diff options
274 files changed, 10152 insertions, 2202 deletions
@@ -467,3 +467,5 @@ fe4f7c5e9fd27e09d03deb1cc9ab3e5093f6309e 3.6.3-release  bf6d453046011a11de2643fac610cc5258650f82 3.6.5-release  ae457ece77001767ae9613148c495e7b98cc0f4a 3.6.7-release  d40c66e410741de7e90b1ed6dac28dd8a2d7e1f6 3.6.8-release +70eda3721d36df3e00730629c42a1304e5bc65b8 3.6.9-release +5b54b36862ff8bc3b6935673c9d1c1f22ee8d521 3.6.10-release diff --git a/BuildParams b/BuildParams index 9752e5298d..31e7e841ad 100755 --- a/BuildParams +++ b/BuildParams @@ -27,9 +27,6 @@ Linux.distcc_version =  Linux.gcc_version = /usr/bin/gcc-4.6  Linux.cxx_version = /usr/bin/g++-4.6 -# Setup default sourceid so Windows can pick up the TeamCity override -sourceid = "" -  ################################################################  ####      Examples of how to set the viewer_channel         ####  # @@ -50,6 +47,18 @@ sourceid = ""  ################################################################  viewer_channel = "Second Life Test" +# Setup default packaging parameters. +sourceid = "" +additional_packages = "Amazon Desura B C" +Amazon_sourceid = "1207v_Amazon" +Amazon_viewer_channel_suffix = " Amazon" +Desura_sourceid = "1208_desura" +Desura_viewer_channel_suffix = " Desura" +B_sourceid = "1301_B" +B_viewer_channel_suffix = " B" +C_sourceid = "1302_C" +C_viewer_channel_suffix = " C" +  # Report changes since...  viewer-development.show_changes_since = last_sprint diff --git a/autobuild.xml b/autobuild.xml index bc7e2f716b..6226c2137b 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -1965,11 +1965,11 @@      <key>package_description</key>      <map>        <key>description</key> -      <string>Spell checking dictionaries</string> +      <string>Second Life Viewer</string>        <key>license</key> -      <string>various open</string> +      <string>LGPL</string>        <key>name</key> -      <string>dictionaries</string> +      <string>Second Life Viewer</string>        <key>platforms</key>        <map>          <key>common</key> @@ -38,22 +38,22 @@ build_dir_CYGWIN()  installer_Darwin()  { -  ls -1td "$(build_dir_Darwin ${last_built_variant:-Release})/newview/"*.dmg 2>/dev/null | sed 1q +  ls -1tr "$(build_dir_Darwin ${last_built_variant:-Release})/newview/"*"$additional_package_name"*.dmg 2>/dev/null | sed 1q  }  installer_Linux()  { -  ls -1td "$(build_dir_Linux ${last_built_variant:-Release})/newview/"*.tar.bz2 2>/dev/null | sed 1q +  ls -1tr "$(build_dir_Linux ${last_built_variant:-Release})/newview/"*"$additional_package_name"*.tar.bz2 2>/dev/null | grep -v symbols | sed 1q  }  installer_CYGWIN()  {    v=${last_built_variant:-Release}    d=$(build_dir_CYGWIN $v) -  if [ -r "$d/newview/$v/touched.bat" ] +  if [ -r "$d/newview/$additional_package_name$v/touched.bat" ]    then -    p=$(sed 's:.*=::' "$d/newview/$v/touched.bat") -    echo "$d/newview/$v/$p" +    p=$(sed 's:.*=::' "$d/newview/$additional_package_name$v/touched.bat") +    echo "$d/newview/$additional_package_name$v/$p"    fi  } @@ -355,10 +355,28 @@ then        # Coverity doesn't package, so it's ok, anything else is fail        succeeded=$build_coverity      else +      # Upload base package.        upload_item installer "$package" binary/octet-stream        upload_item quicklink "$package" binary/octet-stream        [ -f $build_dir/summary.json ] && upload_item installer $build_dir/summary.json text/plain +      # Upload additional packages. +      for package_id in $additional_packages +      do +        case $arch in +        CYGWIN) export additional_package_name="$package_id/" ;; +        *) export additional_package_name=$package_id ;; +        esac +        package=$(installer_$arch) +        if [ x"$package" != x ] +        then +          upload_item installer "$package" binary/octet-stream +        else +          record_failure "Failed to upload $package_id package." +        fi +      done +      export additional_package_name="" +        case "$last_built_variant" in        Release)          # Upload crash reporter files diff --git a/doc/contributions.txt b/doc/contributions.txt index 931211f622..99527c0587 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -175,8 +175,11 @@ Ansariel Hiller  	STORM-1685  	STORM-1713  	STORM-1899 +	STORM-1932 +	STORM-1933  	MAINT-2368  	STORM-1931 +	MAINT-2773  Aralara Rajal  Arare Chantilly  	CHUIBUG-191 @@ -304,9 +307,13 @@ Christopher  Organiser  Ciaran Laval  Cinder Roxley      BUG-2326 +    OPEN-185      STORM-1703  	STORM-1948 +    STORM-1888 +    STORM-1958      STORM-1952 +    STORM-1951  Clara Young  Coaldust Numbers      VWR-1095 @@ -652,7 +659,7 @@ Jonathan Yap  	STORM-1809  	STORM-1793  	STORM-1810 -	STORM-1877 +	STORM-1838  	STORM-1892  	STORM-1894  	STORM-1860 @@ -662,8 +669,11 @@ Jonathan Yap  	STORM-1858  	STORM-1862  	STORM-1918 +	STORM-1929  	STORM-1953  	OPEN-161 +	STORM-1953 +	STORM-1957  Kadah Coba  	STORM-1060      STORM-1843 @@ -679,7 +689,9 @@ Kagehi Kohn  Kaimen Takahe  Katharine Berry  	STORM-1900 +    OPEN-149  	STORM-1940 +    OPEN-149  	STORM-1941  Keklily Longfall  Ken Lavender @@ -928,7 +940,9 @@ Nicky Dasmijn  	STORM-1936  	BUG-3605  	CHUIBUG-197 +	OPEN-187  	STORM-1937 +	OPEN-187  Nicky Perian  	OPEN-1  	STORM-1087 @@ -1125,6 +1139,7 @@ Slee Mayo  snowy Sidran  Sovereign Engineer      MAINT-2334 +    OPEN-189  SpacedOut Frye  	VWR-34  	VWR-45 @@ -1293,6 +1308,7 @@ Westley Streeter  Whimsy Winx  Whirly Fizzle  	STORM-1895 +	VWR-29543  	MAINT-873  	STORM-1930  Whoops Babii @@ -1356,6 +1372,7 @@ YongYong Francois  Zak Westminster  Zai Lynch  	VWR-19505 +    STORM-1902  Zana Kohime  Zaren Alexander  Zarkonnen Decosta diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index bdbfc55fa2..410d25ad97 100755 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -63,10 +63,11 @@ add_subdirectory(${VIEWER_PREFIX}test)  # viewer media plugins  add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) -# llplugin testbed code (is this the right way to include it?) -if (LL_TESTS AND NOT LINUX) -  add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) -endif (LL_TESTS AND NOT LINUX) +  # llplugin testbed code (is this the right way to include it?) +  if (LL_TESTS AND NOT LINUX) +    add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) +    add_subdirectory(${VIEWER_PREFIX}test_apps/llfbconnecttest) +  endif (LL_TESTS AND NOT LINUX)  if (LINUX)    add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index af2063ce6d..e4b63dc7cb 100755 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -16,22 +16,26 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n          else (DEFINED ENV{revision})             find_program(MERCURIAL hg) -           if (DEFINED MERCURIAL) +           find_program(WORDCOUNT wc) +           find_program(SED sed) +           if (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)                execute_process( -                 COMMAND ${MERCURIAL} log -r tip --template "{rev}" +                 COMMAND ${MERCURIAL} log -r tip:0 --template '\\n' +                 COMMAND ${WORDCOUNT} -l +                 COMMAND ${SED} "s/ //g"                   OUTPUT_VARIABLE VIEWER_VERSION_REVISION                   OUTPUT_STRIP_TRAILING_WHITESPACE                   )                if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")                   message("Revision (from hg) ${VIEWER_VERSION_REVISION}")                else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$") +                 message("Revision not set (repository not found?); using 0")                   set(VIEWER_VERSION_REVISION 0 ) -                 message("Revision not set, repository not found, using ${VIEWER_VERSION_REVISION}")                endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$") -           else (DEFINED MERCURIAL) +           else (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED) +              message("Revision not set: 'hg', 'wc' or 'sed' not found; using 0")                set(VIEWER_VERSION_REVISION 0) -              message("Revision not set, 'hg' not found (${MERCURIAL}), using ${VIEWER_VERSION_REVISION}") -           endif (DEFINED MERCURIAL) +           endif (DEFINED MERCURIAL AND DEFINED WORDCOUNT AND DEFINED SED)          endif (DEFINED ENV{revision})          message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")      else ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 54049b5545..52b4acbc94 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -224,15 +224,98 @@ def main():      for opt in args:          print "Option:", opt, "=", args[opt] +    # pass in sourceid as an argument now instead of an environment variable +    try: +        args['sourceid'] = os.environ["sourceid"] +    except KeyError: +        args['sourceid'] = "" + +    # Build base package. +    touch = args.get('touch') +    if touch: +        print 'Creating base package' +    args['package_id'] = "" # base package has no package ID      wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)      wm.do(*args['actions']) - +    # Store package file for later if making touched file. +    base_package_file = "" +    if touch: +        print 'Created base package ', wm.package_file +        base_package_file = "" + wm.package_file + +    # handle multiple packages if set +    try: +        additional_packages = os.environ["additional_packages"] +    except KeyError: +        additional_packages = "" +    if additional_packages: +        # Determine destination prefix / suffix for additional packages. +        base_dest_postfix = args['dest'] +        base_dest_prefix = "" +        base_dest_parts = args['dest'].split(os.sep) +        if len(base_dest_parts) > 1: +            base_dest_postfix = base_dest_parts[len(base_dest_parts) - 1] +            base_dest_prefix = base_dest_parts[0] +            i = 1 +            while i < len(base_dest_parts) - 1: +                base_dest_prefix = base_dest_prefix + os.sep + base_dest_parts[i] +                i = i + 1 +        # Determine touched prefix / suffix for additional packages. +        base_touch_postfix = "" +        base_touch_prefix = "" +        if touch: +            base_touch_postfix = touch +            base_touch_parts = touch.split('/') +            if "arwin" in args['platform']: +                if len(base_touch_parts) > 1: +                    base_touch_postfix = base_touch_parts[len(base_touch_parts) - 1] +                    base_touch_prefix = base_touch_parts[0] +                    i = 1 +                    while i < len(base_touch_parts) - 1: +                        base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] +                        i = i + 1 +            else: +                if len(base_touch_parts) > 2: +                    base_touch_postfix = base_touch_parts[len(base_touch_parts) - 2] + '/' + base_touch_parts[len(base_touch_parts) - 1] +                    base_touch_prefix = base_touch_parts[0] +                    i = 1 +                    while i < len(base_touch_parts) - 2: +                        base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] +                        i = i + 1 +        # Store base channel name. +        base_channel_name = args['channel'] +        # Build each additional package. +        package_id_list = additional_packages.split(" ") +        for package_id in package_id_list: +            try: +                args['package_id'] = package_id +                args['channel'] = base_channel_name + os.environ[package_id + "_viewer_channel_suffix"] +                if package_id + "_sourceid" in os.environ: +                    args['sourceid'] = os.environ[package_id + "_sourceid"] +                else: +                    args['sourceid'] = "" +                args['dest'] = base_dest_prefix + os.sep + package_id + os.sep + base_dest_postfix +            except KeyError: +                sys.stderr.write("Failed to create package for package_id: %s" % package_id) +                sys.stderr.flush() +                continue +            if touch: +                print 'Creating additional package for ', package_id, ' in ', args['dest'] +            wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args) +            wm.do(*args['actions']) +            if touch: +                print 'Created additional package ', wm.package_file, ' for ', package_id +                faketouch = base_touch_prefix + '/' + package_id + '/' + base_touch_postfix +                fp = open(faketouch, 'w') +                fp.write('set package_file=%s\n' % wm.package_file) +                fp.close() +          # Write out the package file in this format, so that it can easily be called      # and used in a .bat file - yeah, it sucks, but this is the simplest...      touch = args.get('touch')      if touch:          fp = open(touch, 'w') -        fp.write('set package_file=%s\n' % wm.package_file) +        fp.write('set package_file=%s\n' % base_package_file)          fp.close()          print 'touched', touch      return 0 diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 8276ec836a..f962485284 100755 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -506,6 +506,8 @@ namespace  		LLSD::array_iterator beginArray() { return mData.begin(); }  		LLSD::array_iterator endArray() { return mData.end(); } +		LLSD::reverse_array_iterator rbeginArray() { return mData.rbegin(); } +		LLSD::reverse_array_iterator rendArray() { return mData.rend(); }  		virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); }  		virtual LLSD::array_const_iterator endArray() const { return mData.end(); } @@ -947,6 +949,9 @@ LLSD::array_iterator		LLSD::endArray()		{ return makeArray(impl).endArray(); }  LLSD::array_const_iterator	LLSD::beginArray() const{ return safe(impl).beginArray(); }  LLSD::array_const_iterator	LLSD::endArray() const	{ return safe(impl).endArray(); } +LLSD::reverse_array_iterator	LLSD::rbeginArray()		{ return makeArray(impl).rbeginArray(); } +LLSD::reverse_array_iterator	LLSD::rendArray()		{ return makeArray(impl).rendArray(); } +  namespace llsd  { diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 5eb69059ac..a3792c1f9d 100755 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -320,11 +320,15 @@ public:  		typedef std::vector<LLSD>::iterator			array_iterator;  		typedef std::vector<LLSD>::const_iterator	array_const_iterator; -		 +		typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator; +  		array_iterator			beginArray();  		array_iterator			endArray();  		array_const_iterator	beginArray() const;  		array_const_iterator	endArray() const; + +		reverse_array_iterator	rbeginArray(); +		reverse_array_iterator	rendArray();  	//@}  	/** @name Type Testing */ diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 0730b2ed8b..bb17725c9c 100755 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -114,6 +114,9 @@ static const F32 MEM_INFO_THROTTLE = 20;  static const F32 MEM_INFO_WINDOW = 10*60;  #if LL_WINDOWS +// We cannot trust GetVersionEx function on Win8.1 , we should check this value when creating OS string +static const U32 WINNT_WINBLUE = 0x0603; +  #ifndef DLLVERSIONINFO  typedef struct _DllVersionInfo  { @@ -214,6 +217,26 @@ static bool regex_search_no_exc(const S& string, M& match, const R& regex)      }  } +#if LL_WINDOWS +// GetVersionEx should not works correct with Windows 8.1 and the later version. We need to check this case  +static bool	check_for_version(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) +{ +    OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; +    DWORDLONG        const dwlConditionMask = VerSetConditionMask( +        VerSetConditionMask( +        VerSetConditionMask( +            0, VER_MAJORVERSION, VER_GREATER_EQUAL), +               VER_MINORVERSION, VER_GREATER_EQUAL), +               VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + +    osvi.dwMajorVersion = wMajorVersion; +    osvi.dwMinorVersion = wMinorVersion; +    osvi.wServicePackMajor = wServicePackMajor; + +    return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; +} +#endif +  LLOSInfo::LLOSInfo() :  	mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")	  @@ -222,6 +245,7 @@ LLOSInfo::LLOSInfo() :  #if LL_WINDOWS  	OSVERSIONINFOEX osvi;  	BOOL bOsVersionInfoEx; +	BOOL bShouldUseShellVersion = false;  	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.  	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); @@ -284,10 +308,18 @@ LLOSInfo::LLOSInfo() :  				}  				else if(osvi.dwMinorVersion == 2)  				{ -					if(osvi.wProductType == VER_NT_WORKSTATION) -						mOSStringSimple = "Microsoft Windows 8 "; +					if (check_for_version(HIBYTE(WINNT_WINBLUE), LOBYTE(WINNT_WINBLUE), 0)) +					{ +						mOSStringSimple = "Microsoft Windows 8.1 "; +						bShouldUseShellVersion = true; // GetVersionEx failed, going to use shell version +					}  					else -						mOSStringSimple = "Windows Server 2012 "; +					{ +						if(osvi.wProductType == VER_NT_WORKSTATION) +							mOSStringSimple = "Microsoft Windows 8 "; +						else +							mOSStringSimple = "Windows Server 2012 "; +					}  				}  				///get native system info if available.. @@ -354,9 +386,8 @@ LLOSInfo::LLOSInfo() :  			}  			else  			{ -				tmpstr = llformat("%s (Build %d)", -								  csdversion.c_str(), -								  (osvi.dwBuildNumber & 0xffff)); +				tmpstr = !bShouldUseShellVersion ?  llformat("%s (Build %d)", csdversion.c_str(), (osvi.dwBuildNumber & 0xffff)): +					llformat("%s (Build %d)", csdversion.c_str(), shell32_build);  			}  			mOSString = mOSStringSimple + tmpstr; @@ -392,7 +423,7 @@ LLOSInfo::LLOSInfo() :  	std::string compatibility_mode;  	if(got_shell32_version)  	{ -		if(osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) +		if((osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) && !bShouldUseShellVersion)  		{  			compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",   											shell32_major, diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h deleted file mode 100644 index 6a5ff314e4..0000000000 --- a/indra/llcommon/llversionviewer.h +++ /dev/null @@ -1,41 +0,0 @@ -/**  - * @file llversionviewer.h - * @brief - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVERSIONVIEWER_H -#define LL_LLVERSIONVIEWER_H - -const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 6; -const S32 LL_VERSION_BUILD = 0; - -const char * const LL_CHANNEL = "Second Life Developer"; - -#if LL_DARWIN -const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; -#endif - -#endif diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 37c603348e..5eb5fb442d 100755 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -414,117 +414,6 @@ BOOL LLParcel::allowTerraformBy(const LLUUID &agent_id) const  } -bool LLParcel::isAgentBlockedFromParcel(LLParcel* parcelp, -                                        const LLUUID& agent_id, -                                        const uuid_vec_t& group_ids, -                                        const BOOL is_agent_identified, -                                        const BOOL is_agent_transacted, -                                        const BOOL is_agent_ageverified) -{ -    S32 current_group_access = parcelp->blockAccess(agent_id, LLUUID::null, is_agent_identified, is_agent_transacted, is_agent_ageverified); -    S32 count; -    bool is_allowed = (current_group_access == BA_ALLOWED) ? true: false; -    LLUUID group_id; -     -    count = group_ids.size(); -    for (int i = 0; i < count && !is_allowed; i++) -    { -        group_id = group_ids[i]; -        current_group_access = parcelp->blockAccess(agent_id, group_id, is_agent_identified, is_agent_transacted, is_agent_ageverified); -         -        if (current_group_access == BA_ALLOWED) is_allowed = true; -    } -     -    return !is_allowed; -} - -BOOL LLParcel::isAgentBanned(const LLUUID& agent_id) const -{ -	// Test ban list -	if (mBanList.find(agent_id) != mBanList.end()) -	{ -		return TRUE; -	} -     -    return FALSE; -} - -S32 LLParcel::blockAccess(const LLUUID& agent_id, const LLUUID& group_id, -                          const BOOL is_agent_identified, -                          const BOOL is_agent_transacted, -                          const BOOL is_agent_ageverified) const -{ -    // Test ban list -    if (isAgentBanned(agent_id)) -    { -        return BA_BANNED; -    } -     -    // Always allow owner on (unless he banned himself, useful for -    // testing). We will also allow estate owners/managers in if they  -    // are not explicitly banned. -    if (agent_id == mOwnerID) -    { -        return BA_ALLOWED; -    } -     -    // Special case when using pass list where group access is being restricted but not  -    // using access list.	 In this case group members are allowed only if they buy a pass. -    // We return BA_NOT_IN_LIST if not in list -    BOOL passWithGroup = getParcelFlag(PF_USE_PASS_LIST) && !getParcelFlag(PF_USE_ACCESS_LIST)  -    && getParcelFlag(PF_USE_ACCESS_GROUP) && !mGroupID.isNull() && group_id == mGroupID; -     -     -    // Test group list -    if (getParcelFlag(PF_USE_ACCESS_GROUP) -        && !mGroupID.isNull() -        && group_id == mGroupID -        && !passWithGroup) -    { -        return BA_ALLOWED; -    } -     -    // Test access list -    if (getParcelFlag(PF_USE_ACCESS_LIST) || passWithGroup ) -    { -        if (mAccessList.find(agent_id) != mAccessList.end()) -        { -            return BA_ALLOWED; -        } -         -        return BA_NOT_ON_LIST;  -    } -     -    // If we're not doing any other limitations, all users -    // can enter, unless -    if (		 !getParcelFlag(PF_USE_ACCESS_GROUP) -                 && !getParcelFlag(PF_USE_ACCESS_LIST)) -    {  -        //If the land is group owned, and you are in the group, bypass these checks -        if(getIsGroupOwned() && group_id == mGroupID) -        { -            return BA_ALLOWED; -        } -         -        // Test for "payment" access levels -        // Anonymous - No Payment Info on File -        if(getParcelFlag(PF_DENY_ANONYMOUS) && !is_agent_identified && !is_agent_transacted) -        { -            return BA_NO_ACCESS_LEVEL; -        } -        // AgeUnverified - Not Age Verified -        if(getParcelFlag(PF_DENY_AGEUNVERIFIED) && !is_agent_ageverified) -        { -			return BA_NOT_AGE_VERIFIED; -        } -     -        return BA_ALLOWED; -    } -     -    return BA_NOT_IN_GROUP; -     -} -  void LLParcel::setArea(S32 area, S32 sim_object_limit)  { diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 0279e8bef9..c4363a48df 100755 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -527,23 +527,6 @@ public:  	// Can this agent change the shape of the land?  	BOOL	allowTerraformBy(const LLUUID &agent_id) const; -	// Returns 0 if access is OK, otherwise a BA_ return code above. -	S32	 blockAccess(const LLUUID& agent_id,  -			const LLUUID& group_id,  -			const BOOL is_agent_identified,  -			const BOOL is_agent_transacted, -			const BOOL is_agent_ageverified) const; - -	// Only checks if the agent is explicitly banned from this parcel -	BOOL isAgentBanned(const LLUUID& agent_id) const; - -	static bool isAgentBlockedFromParcel(LLParcel* parcelp,  -									const LLUUID& agent_id, -									const uuid_vec_t& group_ids, -									const BOOL is_agent_identified, -									const BOOL is_agent_transacted, -									const BOOL is_agent_ageverified); -  	bool	operator==(const LLParcel &rhs) const;  	// Calculate rent - area * rent * discount rate diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2b865b4a8e..f74c934b21 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -166,7 +166,8 @@ void calc_tangent_from_triangle(  	F32 rd = s1*t2-s2*t1; -	float r = ((rd*rd) > FLT_EPSILON) ? 1.0F / rd : 1024.f; //some made up large ratio for division by zero +	float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) +											    : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero  	llassert(llfinite(r));  	llassert(!llisnan(r)); @@ -6789,7 +6790,8 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe  		F32 rd = s1*t2-s2*t1; -		float r = ((rd*rd) > FLT_EPSILON) ? 1.0F / rd : 1024.f; //some made up large ratio for division by zero +		float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) +													 : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero  		llassert(llfinite(r));  		llassert(!llisnan(r)); diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index b047f86e6e..8c8c315808 100755 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -50,7 +50,7 @@ class LLColor4  		LLColor4(F32 r, F32 g, F32 b);		// Initializes LLColor4 to (r, g, b, 1)  		LLColor4(F32 r, F32 g, F32 b, F32 a);		// Initializes LLColor4 to (r. g, b, a)  		LLColor4(U32 clr);							// Initializes LLColor4 to (r=clr>>24, etc)) -		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) +		LLColor4(const F32 *vec);			// Initializes LLColor4 to (vec[0]. vec[1], vec[2], vec[3])  		LLColor4(const LLColor3 &vec, F32 a = 1.f);	// Initializes LLColor4 to (vec, a)  		explicit LLColor4(const LLSD& sd);  		explicit LLColor4(const LLColor4U& color4u);  // "explicit" to avoid automatic conversion diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 6110b035dc..11648717ad 100755 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -217,7 +217,8 @@ static void request(  	Injector* body_injector,  	LLCurl::ResponderPtr responder,  	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS, -	const LLSD& headers = LLSD() +	const LLSD& headers = LLSD(), +	bool follow_redirects = true      )  {  	if (!LLHTTPClient::hasPump()) @@ -231,7 +232,7 @@ static void request(  	}  	LLPumpIO::chain_t chain; -	LLURLRequest* req = new LLURLRequest(method, url); +	LLURLRequest* req = new LLURLRequest(method, url, follow_redirects);  	if(!req->isValid())//failed  	{  		if (responder) @@ -334,7 +335,8 @@ void LLHTTPClient::getByteRange(  	S32 bytes,  	ResponderPtr responder,  	const LLSD& hdrs, -	const F32 timeout) +	const F32 timeout, +	bool follow_redirects /* = true */)  {  	LLSD headers = hdrs;  	if(offset > 0 || bytes > 0) @@ -342,37 +344,42 @@ void LLHTTPClient::getByteRange(  		std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);  		headers["Range"] = range;  	} -    request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); +    request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);  }  void LLHTTPClient::head(  	const std::string& url,  	ResponderPtr responder,  	const LLSD& headers, -	const F32 timeout) +	const F32 timeout, +	bool follow_redirects /* = true */)  { -	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers); +	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);  } -void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) +void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout, +					   bool follow_redirects /* = true */)  { -	request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); +	request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);  } -void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) +void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, +								 const F32 timeout, bool follow_redirects /* = true */)  { -	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers); +	request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);  } -void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout) +void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout, +								 bool follow_redirects /* = true */)  { -	getHeaderOnly(url, responder, LLSD(), timeout); +	getHeaderOnly(url, responder, LLSD(), timeout, follow_redirects);  } -void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, const F32 timeout) +void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, +					   const F32 timeout, bool follow_redirects /* = true */)  {  	LLURI uri;  	uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); -	get(uri.asString(), responder, headers, timeout); +	get(uri.asString(), responder, headers, timeout, follow_redirects);  }  // A simple class for managing data returned from a curl http request. diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index a7236ba169..5de257a4f6 100755 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -63,10 +63,15 @@ public:  		const std::string& url,  		ResponderPtr,  		const LLSD& headers = LLSD(), -		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, +		bool follow_redirects = true); +	static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, +							 const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, +							 bool follow_redirects = true); +	static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), +					const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true); +	static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), +					const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);  	static void put(  		const std::string& url, @@ -74,8 +79,10 @@ public:  		ResponderPtr,  		const LLSD& headers = LLSD(),  		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +	static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, +							  bool follow_redirects = true); +	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, +							  const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);  	static void post(  		const std::string& url, diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index db4a38ea9e..f7118f8ccf 100755 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -126,7 +126,7 @@ enum EInstantMessage  	IM_LURE_ACCEPTED = 23,  	IM_LURE_DECLINED = 24,  	IM_GODLIKE_LURE_USER = 25, -	IM_YET_TO_BE_USED = 26, +	IM_TELEPORT_REQUEST = 26,  	// IM that notifie of a new group election.  	// Name is name of person who called vote. diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index de9e2fe294..683065357d 100755 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -150,16 +150,19 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)  	return VERBS[action];  } -LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) : -	mAction(action) +LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, bool follow_redirects /* = true */) : +	mAction(action), +	mFollowRedirects(follow_redirects)  {  	initialize();  }  LLURLRequest::LLURLRequest(  	LLURLRequest::ERequestAction action, -	const std::string& url) : -	mAction(action) +	const std::string& url, +	bool follow_redirects /* = true */) : +	mAction(action), +	mFollowRedirects(follow_redirects)  {  	initialize();  	setURL(url); @@ -479,12 +482,18 @@ bool LLURLRequest::configure()  	case HTTP_HEAD:  		mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);  		mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1); -		mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1); +		if (mFollowRedirects) +		{ +			mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1); +		}  		rv = true;  		break;  	case HTTP_GET:  		mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1); -		mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1); +		if (mFollowRedirects) +		{ +			mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1); +		}  		// Set Accept-Encoding to allow response compression  		mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, ""); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 44d358d906..20d6e30d17 100755 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -95,7 +95,7 @@ public:  	 *  	 * @param action One of the ERequestAction enumerations.  	 */ -	LLURLRequest(ERequestAction action); +	LLURLRequest(ERequestAction action, bool follow_redirects = true);  	/**   	 * @brief Constructor. @@ -103,7 +103,7 @@ public:  	 * @param action One of the ERequestAction enumerations.  	 * @param url The url of the request. It should already be encoded.  	 */ -	LLURLRequest(ERequestAction action, const std::string& url); +	LLURLRequest(ERequestAction action, const std::string& url, bool follow_redirects = true);  	/**   	 * @brief Destructor. @@ -219,10 +219,11 @@ protected:  	};  	EState mState;  	ERequestAction mAction; +	bool mFollowRedirects;  	LLURLRequestDetail* mDetail;  	LLIOPipe::ptr_t mCompletionCallback; -	 S32 mRequestTransferedBytes; -	 S32 mResponseTransferedBytes; +	S32 mRequestTransferedBytes; +	S32 mResponseTransferedBytes;  	static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param); diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp index 82017ab3fa..9f4d65e723 100755 --- a/indra/llplugin/llplugincookiestore.cpp +++ b/indra/llplugin/llplugincookiestore.cpp @@ -87,6 +87,16 @@ std::string LLPluginCookieStore::Cookie::getKey() const  	return result;  } +std::string LLPluginCookieStore::Cookie::getDomain() const +{ +	std::string result; +	if(mDomainEnd > mDomainStart) +	{ +		result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart); +	} +	return result; +} +  bool LLPluginCookieStore::Cookie::parse(const std::string &host)  {  	bool first_field = true; @@ -662,3 +672,21 @@ void LLPluginCookieStore::removeCookie(const std::string &key)  	}  } +void LLPluginCookieStore::removeCookiesByDomain(const std::string &domain) +{ +	cookie_map_t::iterator iter = mCookies.begin(); +	while(iter != mCookies.end()) +	{  +		if(iter->second->getDomain() == domain) +		{ +            cookie_map_t::iterator doErase = iter; +            iter++; +			delete doErase->second; +			mCookies.erase(doErase); +		} +        else +        { +            iter++; +        } +	} +} diff --git a/indra/llplugin/llplugincookiestore.h b/indra/llplugin/llplugincookiestore.h index 91289d38a5..a2fdeab647 100755 --- a/indra/llplugin/llplugincookiestore.h +++ b/indra/llplugin/llplugincookiestore.h @@ -67,6 +67,8 @@ public:  	// quote or unquote a string as per the definition of 'quoted-string' in rfc2616  	static std::string quoteString(const std::string &s);  	static std::string unquoteString(const std::string &s); + +	void removeCookiesByDomain(const std::string &domain);  private: @@ -79,6 +81,7 @@ private:  		// Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map.  		std::string getKey() const; +		std::string getDomain() const;  		const std::string &getCookie() const { return mCookie; };  		bool isSessionCookie() const { return mDate.isNull(); }; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index b82b370d6e..fe8110904d 100755 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -364,35 +364,55 @@ void LLRenderTarget::release()  		sBytesAllocated -= mResX*mResY*4;  	} -	else if (mUseDepth && mFBO) -	{ //detach shared depth buffer +	else if (mFBO) +	{  		glBindFramebuffer(GL_FRAMEBUFFER, mFBO); -		if (mStencil) -		{ //attached as a renderbuffer -			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); -			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); -			mStencil = false; + +		if (mUseDepth) +		{ //detach shared depth buffer +			if (mStencil) +			{ //attached as a renderbuffer +				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); +				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); +				mStencil = false; +			} +			else +			{ //attached as a texture +				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); +			} +			mUseDepth = false;  		} -		else -		{ //attached as a texture -			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); +	} + +	// Detach any extra color buffers (e.g. SRGB spec buffers) +	// +	if (mFBO && (mTex.size() > 1)) +	{		 +		S32 z; +		for (z = mTex.size() - 1; z >= 1; z--) +		{ +			sBytesAllocated -= mResX*mResY*4; +			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0); +			stop_glerror(); +			LLImageGL::deleteTextures(1, &mTex[z]);  		} -		mUseDepth = false;  	}  	if (mFBO)  	{  		glDeleteFramebuffers(1, (GLuint *) &mFBO); +		stop_glerror();  		mFBO = 0;  	}  	if (mTex.size() > 0)  	{ -		sBytesAllocated -= mResX*mResY*4*mTex.size(); -		LLImageGL::deleteTextures(mTex.size(), &mTex[0]); +		sBytesAllocated -= mResX*mResY*4; +		LLImageGL::deleteTextures(1, &mTex[0]); +	} +  		mTex.clear();  		mInternalFormat.clear(); -	}  	mResX = mResY = 0; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 34a08603fa..589ceac501 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -75,6 +75,7 @@ set(llui_SOURCE_FILES      llmultislider.cpp      llmultisliderctrl.cpp      llnotifications.cpp +    llnotificationslistener.cpp      llnotificationsutil.cpp      llpanel.cpp      llprogressbar.cpp @@ -128,6 +129,7 @@ set(llui_SOURCE_FILES      llviewmodel.cpp      llview.cpp      llviewquery.cpp +    llviewereventrecorder.cpp      llwindowshade.cpp      llxuiparser.cpp      ) @@ -183,6 +185,7 @@ set(llui_HEADER_FILES      llmultislider.h      llnotificationptr.h      llnotifications.h +    llnotificationslistener.h      llnotificationsutil.h      llnotificationtemplate.h      llnotificationvisibilityrule.h @@ -240,6 +243,7 @@ set(llui_HEADER_FILES      llviewinject.h      llviewmodel.h      llview.h +    llviewereventrecorder.h      llviewquery.h      llwindowshade.h      llxuiparser.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 44f2c1efe9..50ac511d18 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -49,6 +49,7 @@  #include "lluictrlfactory.h"  #include "llhelp.h"  #include "lldockablefloater.h" +#include "llviewereventrecorder.h"  static LLDefaultChildRegistry::Register<LLButton> r("button"); @@ -443,6 +444,8 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)  		 */  		LLUICtrl::handleMouseDown(x, y, mask); +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); +  		if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD());  		mMouseDownTimer.start(); @@ -473,6 +476,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)  		 * by calling LLUICtrl::mMouseUpSignal(x, y, mask);  		 */  		LLUICtrl::handleMouseUp(x, y, mask); +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());   		// Regardless of where mouseup occurs, handle callback  		if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index e67f39b21b..3f13691a30 100755 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -62,8 +62,8 @@ public:  	virtual void	draw();  	virtual	void	onCommit(); -	/*virtual*/ void	onFocusReceived(); -	/*virtual*/ void	onFocusLost(); +    /*virtual*/ void	onFocusReceived(); +    /*virtual*/ void	onFocusLost();  	void enableSingleLineMode(bool single_line_mode);  	boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index d4e14d9419..56be52f69a 100755 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -534,6 +534,13 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)  	}  } +void LLComboBox::setLeftTextPadding(S32 pad) +{ +	S32 left_pad, right_pad; +	mTextEntry->getTextPadding(&left_pad, &right_pad); +	mTextEntry->setTextPadding(pad, right_pad); +} +  void* LLComboBox::getCurrentUserdata()  {  	LLScrollListItem* item = mList->getFirstSelected(); diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 64dbaea306..1e04fb0866 100755 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -190,6 +190,8 @@ public:  	virtual BOOL	operateOnAll(EOperation op);  	//======================================================================== + +	void			setLeftTextPadding(S32 pad);  	void*			getCurrentUserdata(); diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 625fb8e870..49cfb2255e 100755 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -50,6 +50,8 @@ const LLCommandId LLCommandId::null = LLCommandId("null command");  LLCommand::Params::Params()  	: available_in_toybox("available_in_toybox", false)  	, icon("icon") +	, hover_icon_unselected("hover_icon_unselected") +	, hover_icon_selected("hover_icon_selected")  	, label_ref("label_ref")  	, name("name")  	, tooltip_ref("tooltip_ref") @@ -71,6 +73,8 @@ LLCommand::LLCommand(const LLCommand::Params& p)  	: mIdentifier(p.name)  	, mAvailableInToybox(p.available_in_toybox)  	, mIcon(p.icon) +	, mHoverIconUnselected(p.hover_icon_unselected) +	, mHoverIconSelected(p.hover_icon_selected)  	, mLabelRef(p.label_ref)  	, mName(p.name)  	, mTooltipRef(p.tooltip_ref) diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index ff5a8a3257..9f276f712d 100755 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -96,6 +96,9 @@ public:  		Mandatory<std::string>	name;  		Mandatory<std::string>	tooltip_ref; +		Optional<std::string>   hover_icon_selected; +		Optional<std::string>   hover_icon_unselected; +  		Mandatory<std::string>	execute_function;  		Optional<LLSD>			execute_parameters; @@ -124,6 +127,8 @@ public:  	const std::string& labelRef() const { return mLabelRef; }  	const std::string& name() const { return mName; }  	const std::string& tooltipRef() const { return mTooltipRef; } +	const std::string& hoverIconUnselected() const {return mHoverIconUnselected; } +	const std::string& hoverIconSelected() const {return mHoverIconSelected; }  	const std::string& executeFunctionName() const { return mExecuteFunction; }  	const LLSD& executeParameters() const { return mExecuteParameters; } @@ -150,6 +155,8 @@ private:  	std::string mLabelRef;  	std::string mName;  	std::string mTooltipRef; +	std::string mHoverIconUnselected; +	std::string mHoverIconSelected;  	std::string mExecuteFunction;  	LLSD        mExecuteParameters; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 273ceb4038..6e6bcd6ab5 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -29,7 +29,7 @@  // mini-map floater, etc.  #include "linden_common.h" - +#include "llviewereventrecorder.h"  #include "llfloater.h"  #include "llfocusmgr.h" @@ -509,8 +509,8 @@ LLFloater::~LLFloater()  	if( gFocusMgr.childHasKeyboardFocus(this))  	{ -		// Just in case we might still have focus here, release it. -		releaseFocus(); +	// Just in case we might still have focus here, release it. +	releaseFocus();  	}  	// This is important so that floaters with persistent rects (i.e., those @@ -642,7 +642,10 @@ void LLFloater::handleVisibilityChange ( BOOL new_visibility )  void LLFloater::openFloater(const LLSD& key)  { -	llinfos << "Opening floater " << getName() << llendl; +    llinfos << "Opening floater " << getName() << " full path: " << getPathname() << llendl; + +	LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), true,"floater"); // Last param is event subtype or empty string +  	mKey = key; // in case we need to open ourselves again  	if (getSoundFlags() != SILENT  @@ -696,6 +699,7 @@ void LLFloater::openFloater(const LLSD& key)  void LLFloater::closeFloater(bool app_quitting)  {  	llinfos << "Closing floater " << getName() << llendl; +	LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), false,"floater"); // Last param is event subtype or empty string  	if (app_quitting)  	{  		LLFloater::sQuitting = true; @@ -1335,7 +1339,7 @@ void LLFloater::setFocus( BOOL b )  	{  		return;  	} -	LLUICtrl* last_focus = gFocusMgr.getLastFocusForGroup(this); +	LLView* last_focus = gFocusMgr.getLastFocusForGroup(this);  	// a descendent already has focus  	BOOL child_had_focus = hasFocus(); @@ -1543,6 +1547,17 @@ BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)  }  // virtual +BOOL LLFloater::handleMouseUp(S32 x, S32 y, MASK mask) +{ +	lldebugs << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +	BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); +	} +	return handled; +} + +// virtual  BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)  {  	if( mMinimized ) @@ -1562,7 +1577,11 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)  	else  	{  		bringToFront( x, y ); -		return LLPanel::handleMouseDown( x, y, mask ); +		BOOL handled = LLPanel::handleMouseDown( x, y, mask );  +		if (handled) { +			LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());  +		} +		return handled;  	}  } @@ -1802,7 +1821,7 @@ void LLFloater::onClickClose( LLFloater* self )  	self->onClickCloseBtn();  } -void	LLFloater::onClickCloseBtn() +void LLFloater::onClickCloseBtn(bool app_quitting)  {  	closeFloater(false);  } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 59448530d9..75715ef296 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -289,6 +289,7 @@ public:  	S32				getHeaderHeight() const { return mHeaderHeight; }  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);  	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);  	virtual BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask); @@ -389,7 +390,7 @@ protected:  	void			destroy(); // Don't call this directly.  You probably want to call closeFloater() -	virtual	void	onClickCloseBtn(); +	virtual	void	onClickCloseBtn(bool app_quitting = false);  	virtual void	updateTitleButtons(); diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 724d190307..f03c8d444b 100755 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -469,7 +469,7 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)  	mAppHasFocus = focus;   } -LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const +LLView* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const  {  	if (subtree_root)  	{ @@ -477,7 +477,7 @@ LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const  		if (found_it != mImpl->mFocusHistory.end())  		{  			// found last focus for this subtree -			return static_cast<LLUICtrl*>(found_it->second.get()); +			return found_it->second.get();  		}  	}  	return NULL; diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 25ae1d2579..1c7326260c 100755 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -97,7 +97,7 @@ public:  	void			triggerFocusFlash();  	BOOL			getAppHasFocus() const { return mAppHasFocus; }  	void			setAppHasFocus(BOOL focus); -	LLUICtrl*		getLastFocusForGroup(LLView* subtree_root) const; +	LLView*		getLastFocusForGroup(LLView* subtree_root) const;  	void			clearLastFocusForGroup(LLView* subtree_root);  	// If setKeyboardFocus(NULL) is called, and there is a non-NULL default diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index cf449217f5..f32a52e6c6 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -185,7 +185,7 @@ LLFolderView::LLFolderView(const Params& p)  	mAutoOpenCandidate = NULL;  	mAutoOpenTimer.stop();  	mKeyboardSelection = FALSE; -	mIndentation = p.folder_indentation; +	mIndentation = 	getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0;    	//clear label  	// go ahead and render root folder as usual @@ -1613,7 +1613,7 @@ void LLFolderView::update()  	{  		getFolderViewModel()->getFilter().clearModified();  	} -     +  	// automatically show matching items, and select first one if we had a selection  	if (mNeedsAutoSelect)  	{ @@ -1653,13 +1653,13 @@ void LLFolderView::update()    BOOL is_visible = isInVisibleChain(); -  // Puts folders/items in proper positions +  //Puts folders/items in proper positions    // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849)    // It also handles the open/close folder animation -  if (is_visible) +  if ( is_visible )    {      sanitizeSelection(); -    if (needsArrange()) +    if( needsArrange() )      {        S32 height = 0;        S32 width = 0; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 6c147ccc12..aa2343226c 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -307,7 +307,12 @@ std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const  // addToFolder() returns TRUE if it succeeds. FALSE otherwise  void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	folder->addItem(this); +	folder->addItem(this);  + +	// Compute indentation since parent folder changed +	mIndentation = (getParentFolder()) +		? getParentFolder()->getIndentation() + mLocalIndentation +		: 0;   } @@ -521,7 +526,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )  BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )  { -	static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::sSettingGroups["config"],"DragAndDropDistanceThreshold"); +	static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::sSettingGroups["config"],"DragAndDropDistanceThreshold", 3);  	mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); @@ -940,6 +945,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )  void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)  {  	folder->addFolder(this); + +	// Compute indentation since parent folder changed +	mIndentation = (getParentFolder()) +		? getParentFolder()->getIndentation() + mLocalIndentation +		: 0;   }  static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); @@ -1109,7 +1119,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )  BOOL LLFolderViewFolder::needsArrange()  { -	return mLastArrangeGeneration < getRoot()->getArrangeGeneration();  +	return mLastArrangeGeneration < getRoot()->getArrangeGeneration();  }  // Passes selection information on to children and record selection diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 8c2be44904..ff85b0ad09 100755 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -34,7 +34,7 @@  #include "llui.h"  #include "llwindow.h"  #include "llkeyboard.h" - +#include "llmenugl.h"  // static  std::list<LLModalDialog*> LLModalDialog::sModalStack; @@ -161,6 +161,18 @@ void LLModalDialog::setVisible( BOOL visible )  BOOL LLModalDialog::handleMouseDown(S32 x, S32 y, MASK mask)  { +	LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); +	if (popup_menu != NULL) +	{ +		S32 mx, my; +		LLUI::getMousePositionScreen(&mx, &my); +		LLRect menu_screen_rc = popup_menu->calcScreenRect(); +		if(!menu_screen_rc.pointInRect(mx, my)) +		{ +			LLMenuGL::sMenuContainer->hideMenus(); +		} +	} +  	if (mModal)  	{  		if (!LLFloater::handleMouseDown(x, y, mask)) @@ -173,16 +185,34 @@ BOOL LLModalDialog::handleMouseDown(S32 x, S32 y, MASK mask)  	{  		LLFloater::handleMouseDown(x, y, mask);  	} + +  	return TRUE;  }  BOOL LLModalDialog::handleHover(S32 x, S32 y, MASK mask)		 -{  +{  	if( childrenHandleHover(x, y, mask) == NULL )  	{  		getWindow()->setCursor(UI_CURSOR_ARROW); -		lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;		 +		lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;  	} + +	LLView* popup_menu = LLMenuGL::sMenuContainer->getVisibleMenu(); +	if (popup_menu != NULL) +	{ +		S32 mx, my; +		LLUI::getMousePositionScreen(&mx, &my); +		LLRect menu_screen_rc = popup_menu->calcScreenRect(); +		if(menu_screen_rc.pointInRect(mx, my)) +		{ +			S32 local_x = mx - popup_menu->getRect().mLeft; +			S32 local_y = my - popup_menu->getRect().mBottom; +			popup_menu->handleHover(local_x, local_y, mask); +			gFocusMgr.setMouseCapture(NULL); +		} +	} +  	return TRUE;  } @@ -210,6 +240,7 @@ BOOL LLModalDialog::handleDoubleClick(S32 x, S32 y, MASK mask)  BOOL LLModalDialog::handleRightMouseDown(S32 x, S32 y, MASK mask)  { +	LLMenuGL::sMenuContainer->hideMenus();  	childrenHandleRightMouseDown(x, y, mask);  	return TRUE;  } diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 3186c5460a..5c288c3f03 100755 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1206,6 +1206,7 @@ LLNotifications::LLNotifications()  :	LLNotificationChannelBase(LLNotificationFilters::includeEverything),  	mIgnoreAllNotifications(false)  { +        mListener.reset(new LLNotificationsListener(*this));  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));  } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 3b620084ee..6ac4a98806 100755 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -98,6 +98,8 @@  #include "llrefcount.h"  #include "llsdparam.h" +#include "llnotificationslistener.h" +  class LLAvatarName;  typedef enum e_notification_priority  { @@ -978,6 +980,8 @@ private:  	bool mIgnoreAllNotifications; +	boost::scoped_ptr<LLNotificationsListener> mListener; +  	std::vector<LLNotificationChannelPtr> mDefaultChannels;  }; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp new file mode 100644 index 0000000000..9e8e943ee6 --- /dev/null +++ b/indra/llui/llnotificationslistener.cpp @@ -0,0 +1,359 @@ +/** + * @file   llnotificationslistener.cpp + * @author Brad Kittenbrink + * @date   2009-07-08 + * @brief  Implementation for llnotificationslistener. + *  + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llnotificationslistener.h" +#include "llnotifications.h" +#include "llnotificationtemplate.h" +#include "llsd.h" +#include "llui.h" + +LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : +    LLEventAPI("LLNotifications", +               "LLNotifications listener to (e.g.) pop up a notification"), +    mNotifications(notifications) +{ +    add("requestAdd", +        "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" +        "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", +        &LLNotificationsListener::requestAdd); +    /*    add("listChannels", +        "Post to [\"reply\"] a map of info on existing channels", +        &LLNotificationsListener::listChannels, +        LLSD().with("reply", LLSD())); +    */ +    add("listChannelNotifications", +        "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", +        &LLNotificationsListener::listChannelNotifications, +        LLSD().with("reply", LLSD()).with("channel", LLSD())); +    add("respond", +        "Respond to notification [\"uuid\"] with data in [\"response\"]", +        &LLNotificationsListener::respond, +        LLSD().with("uuid", LLSD())); +    add("cancel", +        "Cancel notification [\"uuid\"]", +        &LLNotificationsListener::cancel, +        LLSD().with("uuid", LLSD())); +    add("ignore", +        "Ignore future notification [\"name\"]\n" +        "(from <notification name= > in notifications.xml)\n" +        "according to boolean [\"ignore\"].\n" +        "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" +        "Note that ignored notifications are not forwarded unless intercepted before\n" +        "the \"Ignore\" channel.", +        &LLNotificationsListener::ignore); +    add("forward", +        "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" +        "according to boolean [\"forward\"]. When enabled, only types matching\n" +        "[\"types\"] are forwarded, as follows:\n" +        "omitted or undefined: forward all notifications\n" +        "string: forward only the specific named [sig]type\n" +        "array of string: forward any notification matching any named [sig]type.\n" +        "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" +        "notification.", +        &LLNotificationsListener::forward, +        LLSD().with("channel", LLSD())); +} + +// This is here in the .cpp file so we don't need the definition of class +// Forwarder in the header file. +LLNotificationsListener::~LLNotificationsListener() +{ +} + +void LLNotificationsListener::requestAdd(const LLSD& event_data) const +{ +	if(event_data.has("reply")) +	{ +		mNotifications.add(event_data["name"],  +						   event_data["substitutions"],  +						   event_data["payload"], +						   boost::bind(&LLNotificationsListener::NotificationResponder,  +									   this,  +									   event_data["reply"].asString(),  +									   _1, _2 +									   ) +						   ); +	} +	else +	{ +		mNotifications.add(event_data["name"],  +						   event_data["substitutions"],  +						   event_data["payload"]); +	} +} + +void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,  +										const LLSD& notification,  +										const LLSD& response) const +{ +	LLSD reponse_event; +	reponse_event["notification"] = notification; +	reponse_event["response"] = response; +	LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); +} +/* +void LLNotificationsListener::listChannels(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    for (LLNotifications:: + + + +    for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), +                                                     cmend(mNotifications.mChannels.end()); +         cmi != cmend; ++cmi) +    { +        LLSD channelInfo; +        channelInfo["parent"] = cmi->second->getParentChannelName(); +        response[cmi->first] = channelInfo; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} +*/ +void LLNotificationsListener::listChannelNotifications(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); +    if (channel) +    { +        LLSD notifications(LLSD::emptyArray()); +        for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); +             ni != nend; ++ni) +        { +            notifications.append(asLLSD(*ni)); +        } +        response["notifications"] = notifications; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::respond(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        notification->respond(params["response"]); +    } +} + +void LLNotificationsListener::cancel(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        mNotifications.cancel(notification); +    } +} + +void LLNotificationsListener::ignore(const LLSD& params) const +{ +    // Calling a method named "ignore", but omitting its "ignore" Boolean +    // argument, should by default cause something to be ignored. Explicitly +    // pass ["ignore"] = false to cancel ignore. +    bool ignore = true; +    if (params.has("ignore")) +    { +        ignore = params["ignore"].asBoolean(); +    } +    // This method can be used to affect either a single notification name or +    // all future notifications. The two use substantially different mechanisms. +    if (params["name"].isDefined()) +    { +        // ["name"] was passed: ignore just that notification +		LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); +		if (templatep) +		{ +			templatep->mForm->setIgnored(ignore); +		} +    } +    else +    { +        // no ["name"]: ignore all future notifications +        mNotifications.setIgnoreAllNotifications(ignore); +    } +} + +class LLNotificationsListener::Forwarder: public LLEventTrackable +{ +    LOG_CLASS(LLNotificationsListener::Forwarder); +public: +    Forwarder(LLNotifications& llnotifications, const std::string& channel): +        mNotifications(llnotifications), +        mRespond(false) +    { +        // Connect to the specified channel on construction. Because +        // LLEventTrackable is a base, we should automatically disconnect when +        // destroyed. +        LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); +        if (channelptr) +        { +            // Insert our processing as a "passed filter" listener. This way +            // we get to run before all the "changed" listeners, and we get to +            // swipe it (hide it from the other listeners) if desired. +            channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1)); +        } +    } + +    void setPumpName(const std::string& name) { mPumpName = name; } +    void setTypes(const LLSD& types) { mTypes = types; } +    void setRespond(bool respond) { mRespond = respond; } + +private: +    bool handle(const LLSD& notification) const; +    bool matchType(const LLSD& filter, const std::string& type) const; + +    LLNotifications& mNotifications; +    std::string mPumpName; +    LLSD mTypes; +    bool mRespond; +}; + +void LLNotificationsListener::forward(const LLSD& params) +{ +    std::string channel(params["channel"]); +    // First decide whether we're supposed to start forwarding or stop it. +    // Default to true. +    bool forward = true; +    if (params.has("forward")) +    { +        forward = params["forward"].asBoolean(); +    } +    if (! forward) +    { +        // This is a request to stop forwarding notifications on the specified +        // channel. The rest of the params don't matter. +        // Because mForwarders contains scoped_ptrs, erasing the map entry +        // DOES delete the heap Forwarder object. Because Forwarder derives +        // from LLEventTrackable, destroying it disconnects it from the +        // channel. +        mForwarders.erase(channel); +        return; +    } +    // From here on, we know we're being asked to start (or modify) forwarding +    // on the specified channel. Find or create an appropriate Forwarder. +    ForwarderMap::iterator +        entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); +    if (! entry->second) +    { +        entry->second.reset(new Forwarder(mNotifications, channel)); +    } +    // Now, whether this Forwarder is brand-new or not, update it with the new +    // request info. +    Forwarder& fwd(*entry->second); +    fwd.setPumpName(params["pump"]); +    fwd.setTypes(params["types"]); +    fwd.setRespond(params["respond"]); +} + +bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const +{ +    LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; +    if (notification["sigtype"].asString() == "delete") +    { +        LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; +        // let other listeners see the "delete" operation +        return false; +    } +    LLNotificationPtr note(mNotifications.find(notification["id"])); +    if (! note) +    { +        LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; +        return false; +    } +    if (! matchType(mTypes, note->getType())) +    { +        LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; +        // We're not supposed to intercept this particular notification. Let +        // other listeners process it. +        return false; +    } +    LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; +    // This is a notification we care about. Forward it through specified +    // LLEventPump. +    LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); +    // Are we also being asked to auto-respond? +    if (mRespond) +    { +        LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; +        note->respond(LLSD::emptyMap()); +        // Did that succeed in removing the notification? Only cancel() if +        // it's still around -- otherwise we get an LL_ERRS crash! +        note = mNotifications.find(notification["id"]); +        if (note) +        { +            LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; +            mNotifications.cancel(note); +        } +    } +    // If we've auto-responded to this notification, then it's going to be +    // deleted. Other listeners would get the change operation, try to look it +    // up and be baffled by lookup failure. So when we auto-respond, suppress +    // this notification: don't pass it to other listeners. +    return mRespond; +} + +bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const +{ +    // Decide whether this notification matches filter: +    // undefined: forward all notifications +    if (filter.isUndefined()) +    { +        return true; +    } +    // array of string: forward any notification matching any named type +    if (filter.isArray()) +    { +        for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); +             ti != tend; ++ti) +        { +            if (ti->asString() == type) +            { +                return true; +            } +        } +        // Didn't match any entry in the array +        return false; +    } +    // string: forward only the specific named type +    return (filter.asString() == type); +} + +LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) +{ +    LLSD notificationInfo(note->asLLSD()); +    // For some reason the following aren't included in LLNotification::asLLSD(). +    notificationInfo["summary"] = note->summarize(); +    notificationInfo["id"]      = note->id(); +    notificationInfo["type"]    = note->getType(); +    notificationInfo["message"] = note->getMessage(); +    notificationInfo["label"]   = note->getLabel(); +    return notificationInfo; +} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h new file mode 100644 index 0000000000..f9f7641de6 --- /dev/null +++ b/indra/llui/llnotificationslistener.h @@ -0,0 +1,69 @@ +/** + * @file   llnotificationslistener.h + * @author Brad Kittenbrink + * @date   2009-07-08 + * @brief  Wrap subset of LLNotifications API in event API for test scripts. + *  + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLNOTIFICATIONSLISTENER_H +#define LL_LLNOTIFICATIONSLISTENER_H + +#include "lleventapi.h" +#include "llnotificationptr.h" +#include <boost/shared_ptr.hpp> +#include <map> +#include <string> + +class LLNotifications; +class LLSD; + +class LLNotificationsListener : public LLEventAPI +{ +public: +    LLNotificationsListener(LLNotifications & notifications); +    ~LLNotificationsListener(); + +private: +    void requestAdd(LLSD const & event_data) const; + +	void NotificationResponder(const std::string& replypump,  +							   const LLSD& notification,  +							   const LLSD& response) const; + +    void listChannels(const LLSD& params) const; +    void listChannelNotifications(const LLSD& params) const; +    void respond(const LLSD& params) const; +    void cancel(const LLSD& params) const; +    void ignore(const LLSD& params) const; +    void forward(const LLSD& params); + +    static LLSD asLLSD(LLNotificationPtr); + +    class Forwarder; +    typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; +    ForwarderMap mForwarders; +	LLNotifications & mNotifications; +}; + +#endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index cbcce0ece5..238eae21c2 100755 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -519,7 +519,7 @@ bool LLScrollContainer::addChild(LLView* view, S32 tab_group)  void LLScrollContainer::updateScroll()  { -	if (!mScrolledView) +	if (!getVisible() || !mScrolledView)  	{  		return;  	} diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index fd98155704..6fd2bb1b36 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -27,7 +27,7 @@  #include "linden_common.h"  #include "lltabcontainer.h" - +#include "llviewereventrecorder.h"  #include "llfocusmgr.h"  #include "lllocalcliprect.h"  #include "llrect.h" @@ -193,12 +193,15 @@ LLTabContainer::TabParams::TabParams()  :	tab_top_image_unselected("tab_top_image_unselected"),  	tab_top_image_selected("tab_top_image_selected"),  	tab_top_image_flash("tab_top_image_flash"), +	tab_top_image_hovered("tab_top_image_hovered"),  	tab_bottom_image_unselected("tab_bottom_image_unselected"),  	tab_bottom_image_selected("tab_bottom_image_selected"),  	tab_bottom_image_flash("tab_bottom_image_flash"), +	tab_bottom_image_hovered("tab_bottom_image_hovered"),  	tab_left_image_unselected("tab_left_image_unselected"),  	tab_left_image_selected("tab_left_image_selected"), -	tab_left_image_flash("tab_left_image_flash") +	tab_left_image_flash("tab_left_image_flash"), +	tab_left_image_hovered("tab_left_image_hovered")  {}  LLTabContainer::Params::Params() @@ -218,7 +221,8 @@ LLTabContainer::Params::Params()  	open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false),  	tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),  	use_ellipses("use_ellipses"), -	font_halign("halign") +	font_halign("halign"), +	use_highlighting_on_hover("use_highlighting_on_hover",false)  {}  LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) @@ -254,7 +258,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)  	mCustomIconCtrlUsed(p.use_custom_icon_ctrl),  	mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop),  	mTabIconCtrlPad(p.tab_icon_ctrl_pad), -	mUseTabEllipses(p.use_ellipses) +	mUseTabEllipses(p.use_ellipses), +	mUseHighlightingOnHover(p.use_highlighting_on_hover)  {  	static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); @@ -578,6 +583,11 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )  			tab_button->setFocus(TRUE);  		}  	} +	if (handled) { +		// Note: May need to also capture local coords right here ? +		LLViewerEventRecorder::instance().update_xui(getPathname( )); +	} +  	return handled;  } @@ -629,30 +639,33 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )  	BOOL handled = FALSE;  	BOOL has_scroll_arrows = (getMaxScrollPos() > 0)  && !getTabsHidden(); +	S32 local_x = x - getRect().mLeft; +	S32 local_y = y - getRect().mBottom; +  	if (has_scroll_arrows)  	{  		if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft; -			S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom; +			local_x = x - mJumpPrevArrowBtn->getRect().mLeft; +			local_y = y - mJumpPrevArrowBtn->getRect().mBottom;  			handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  		else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x,	y))  		{ -			S32	local_x	= x	- mJumpNextArrowBtn->getRect().mLeft; -			S32	local_y	= y	- mJumpNextArrowBtn->getRect().mBottom; +			local_x	= x	- mJumpNextArrowBtn->getRect().mLeft; +			local_y	= y	- mJumpNextArrowBtn->getRect().mBottom;  			handled = mJumpNextArrowBtn->handleMouseUp(local_x,	local_y, mask);  		}  		else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mPrevArrowBtn->getRect().mLeft; -			S32 local_y = y - mPrevArrowBtn->getRect().mBottom; +			local_x = x - mPrevArrowBtn->getRect().mLeft; +			local_y = y - mPrevArrowBtn->getRect().mBottom;  			handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  		else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))  		{ -			S32 local_x = x - mNextArrowBtn->getRect().mLeft; -			S32 local_y = y - mNextArrowBtn->getRect().mBottom; +			local_x = x - mNextArrowBtn->getRect().mLeft; +			local_y = y - mNextArrowBtn->getRect().mBottom;  			handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);  		}  	} @@ -676,6 +689,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )  		}  		gFocusMgr.setMouseCapture(NULL);  	} +	if (handled) { +		// Note: may need to capture local coords here +		LLViewerEventRecorder::instance().update_xui(getPathname( )); +	}  	return handled;  } @@ -891,18 +908,30 @@ void LLTabContainer::update_images(LLTabTuple* tuple, TabParams params, LLTabCon  			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_top_image_unselected));  			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_top_image_selected));  			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_top_image_flash)); +			if(mUseHighlightingOnHover) +			{ +				tuple->mButton->setImageHoverUnselected(static_cast<LLUIImage*>(params.tab_top_image_hovered)); +			}  		}  		else if (pos == LLTabContainer::BOTTOM)  		{  			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_unselected));  			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_bottom_image_selected));  			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_bottom_image_flash)); +			if(mUseHighlightingOnHover) +			{ +				tuple->mButton->setImageHoverUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_hovered)); +			}  		}  		else if (pos == LLTabContainer::LEFT)  		{  			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_left_image_unselected));  			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_left_image_selected));  			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_left_image_flash)); +			if(mUseHighlightingOnHover) +			{ +				tuple->mButton->setImageHoverUnselected(static_cast<LLUIImage*>(params.tab_left_image_hovered)); +			}  		}  	}  } @@ -1059,21 +1088,21 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)  		if (mIsVertical)  		{ -			p.name(std::string("vert tab button")); -			p.image_unselected(mMiddleTabParams.tab_left_image_unselected); -			p.image_selected(mMiddleTabParams.tab_left_image_selected); -			p.follows.flags = p.follows.flags() | FOLLOWS_TOP; +		  p.name("vtab_"+std::string(child->getName())); +		  p.image_unselected(mMiddleTabParams.tab_left_image_unselected); +		  p.image_selected(mMiddleTabParams.tab_left_image_selected); +		  p.follows.flags = p.follows.flags() | FOLLOWS_TOP;  		}  		else -		{ -			p.name(std::string(child->getName()) + " tab"); -			p.visible(false); -			p.image_unselected(tab_img); -			p.image_selected(tab_selected_img); -			p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); -			// Try to squeeze in a bit more text -			p.pad_left( mLabelPadLeft ); -			p.pad_right(2); +		  {  +		    p.name("htab_"+std::string(child->getName())); +		    p.visible(false); +		    p.image_unselected(tab_img); +		    p.image_selected(tab_selected_img); +		    p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); +		    // Try to squeeze in a bit more text +		    p.pad_left( mLabelPadLeft ); +		    p.pad_right(2);  		}  		// *TODO : It seems wrong not to use p in both cases considering the way p is initialized diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 57862fc626..7e7d4ac6e6 100755 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -62,12 +62,15 @@ public:  		Optional<LLUIImage*>				tab_top_image_unselected,  											tab_top_image_selected,  											tab_top_image_flash, +											tab_top_image_hovered,  											tab_bottom_image_unselected,  											tab_bottom_image_selected,  											tab_bottom_image_flash, +											tab_bottom_image_hovered,  											tab_left_image_unselected,  											tab_left_image_selected, -											tab_left_image_flash;		 +											tab_left_image_flash, +											tab_left_image_hovered;  		TabParams();  	}; @@ -114,6 +117,11 @@ public:  		 */  		Optional<S32>						tab_icon_ctrl_pad; +		/** +		 *  This variable is used to found out should we highlight tab button on hover +		*/ +		Optional<bool>						use_highlighting_on_hover; +  		Params();  	}; @@ -307,6 +315,7 @@ private:  	bool							mOpenTabsOnDragAndDrop;  	S32								mTabIconCtrlPad;  	bool							mUseTabEllipses; +	bool                            mUseHighlightingOnHover;  };  #endif  // LL_TABCONTAINER_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cc171661ce..5ec4cf4fe5 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1029,7 +1029,7 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)  BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)  {  	LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); -	if (cur_segment && cur_segment->handleMouseUp(x, y, mask)) +	if (hasMouseCapture() && cur_segment && cur_segment->handleMouseUp(x, y, mask))  	{  		// Did we just click on a link?  		if (mURLClickSignal diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 11cfa1d263..d175204e6d 100755 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -60,10 +60,13 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)  	if (!handled && mClickedCallback)  	{ +		handled = TRUE; +	} + +	if (handled) +	{  		// Route future Mouse messages here preemptively.  (Release on mouse up.)  		gFocusMgr.setMouseCapture( this ); - -		handled = TRUE;  	}  	return handled; @@ -71,7 +74,7 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)  BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)  { -	BOOL	handled = FALSE; +	BOOL	handled = LLTextBase::handleMouseUp(x, y, mask);  	if (getSoundFlags() & MOUSE_UP)  	{ @@ -93,10 +96,6 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)  			handled = TRUE;  		}  	} -	else -	{ -		handled = LLTextBase::handleMouseUp(x, y, mask); -	}  	return handled;  } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 0c16e06109..62140dd9d6 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -666,6 +666,14 @@ void LLTextEditor::selectAll()  	updatePrimary();  } +void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos) +{ +	setCursorPos(prev_cursor_pos); +	startSelection(); +	setCursorPos(next_cursor_pos); +	endSelection(); +} +  BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL	handled = FALSE; @@ -713,7 +721,6 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)  				setCursorAtLocalPos( x, y, true );  				startSelection();  			} -			gFocusMgr.setMouseCapture( this );  		}  		handled = TRUE; @@ -722,6 +729,10 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)  	// Delay cursor flashing  	resetCursorBlink(); +	if (handled && !gFocusMgr.getMouseCapture()) +	{ +		gFocusMgr.setMouseCapture( this ); +	}  	return handled;  } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 32b543ec0e..d3b7bc0eb7 100755 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -144,6 +144,8 @@ public:  	virtual void	selectAll();  	virtual BOOL	canSelectAll()	const; +	void 			selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); +  	virtual bool	canLoadOrSaveToFile();  	void			selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 928e82cb8c..6bfe113933 100755 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -928,6 +928,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)  	button_p.label = LLTrans::getString(commandp->labelRef());  	button_p.tool_tip = LLTrans::getString(commandp->tooltipRef());  	button_p.image_overlay = LLUI::getUIImage(commandp->icon()); +	button_p.image_hover_unselected = LLUI::getUIImage(commandp->hoverIconUnselected()); +	button_p.image_hover_selected = LLUI::getUIImage(commandp->hoverIconSelected());  	button_p.button_flash_enable = commandp->isFlashingAllowed();  	button_p.overwriteFrom(mButtonParams[mButtonType]);  	LLToolBarButton* button = LLUICtrlFactory::create<LLToolBarButton>(button_p); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 0a0e0e164e..0bc4424a8c 100755 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -405,11 +405,6 @@ public:  					  const std::string& comment = "Declared In Code")  	:	LLCachedControl<T>(LLUI::getControlControlGroup(name), name, default_value, comment)  	{} - -	// This constructor will signal an error if the control doesn't exist in the control group -	LLUICachedControl(const std::string& name) -	:	LLCachedControl<T>(LLUI::getControlControlGroup(name), name) -	{}  };  namespace LLInitParam diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index b9c843e931..1722bf27bd 100755 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -29,7 +29,7 @@  #define LLUICTRL_CPP  #include "lluictrl.h" - +#include "llviewereventrecorder.h"  #include "llfocusmgr.h"  #include "llpanel.h"  #include "lluictrlfactory.h" @@ -308,22 +308,40 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)  //virtual   BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask)  { + +	lldebugs << "LLUICtrl::handleMouseDown calling	LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +    	BOOL handled  = LLView::handleMouseDown(x,y,mask); +	  	if (mMouseDownSignal)  	{  		(*mMouseDownSignal)(this,x,y,mask);  	} +	lldebugs << "LLUICtrl::handleMousedown - handled is returning as: " << handled << "	  " << llendl; +	 +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname()); +	}  	return handled;  }  //virtual  BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask)  { + +	lldebugs << "LLUICtrl::handleMouseUp calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; +  	BOOL handled  = LLView::handleMouseUp(x,y,mask); +	if (handled) { +		LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname());  +	}  	if (mMouseUpSignal)  	{  		(*mMouseUpSignal)(this,x,y,mask);  	} + +	lldebugs << "LLUICtrl::handleMouseUp - handled for xui " << getPathname() << "  -  is returning as: " << handled << "   " << llendl; +  	return handled;  } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 3613a40e2c..20015dca1a 100755 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -48,7 +48,9 @@  #include "lluictrlfactory.h"  #include "lltooltip.h"  #include "llsdutil.h" - +#include "llsdserialize.h" +#include "llviewereventrecorder.h" +#include "llkeyboard.h"  // for ui edit hack  #include "llbutton.h"  #include "lllineeditor.h" @@ -642,13 +644,27 @@ void LLView::setVisible(BOOL visible)  // virtual  void LLView::handleVisibilityChange ( BOOL new_visibility )  { +	BOOL old_visibility;  	BOOST_FOREACH(LLView* viewp, mChildList)  	{  		// only views that are themselves visible will have their overall visibility affected by their ancestors -		if (viewp->getVisible()) +		old_visibility=viewp->getVisible(); + +		if (old_visibility!=new_visibility) +		{ +			LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget"); +		} + +		if (old_visibility)  		{  			viewp->handleVisibilityChange ( new_visibility );  		} + +		// Consider changing returns to confirm success and know which widget grabbed it +		// For now assume success and log at highest xui possible  +		// NOTE we log actual state - which may differ if it somehow failed to set visibility +		lldebugs << "LLView::handleVisibilityChange	 - now: " << getVisible()  << " xui: " << viewp->getPathname() << " name: " << viewp->getName() << llendl; +		  	}  } @@ -697,6 +713,7 @@ bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y)  		&& getEnabled();  } +// This is NOT event recording related  void LLView::logMouseEvent()  {  	if (sDebugMouseHandling) @@ -743,7 +760,14 @@ LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDA  		if ((viewp->*method)( local_x, local_y, extra )  			|| (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y )))  		{ +			lldebugs << "LLView::childrenHandleMouseEvent calling updatemouseeventinfo - local_x|global x  "<< local_x << " " << x	<< "local/global y " << local_y << " " << y << llendl; +			lldebugs << "LLView::childrenHandleMouseEvent  getPathname for viewp result: " << viewp->getPathname() << "for this view: " << getPathname() << llendl; + +			LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());  + +			// This is NOT event recording related  			viewp->logMouseEvent(); +  			return viewp;  		}  	} @@ -766,6 +790,7 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)  		if (viewp->handleToolTip(local_x, local_y, mask)   			|| viewp->blockMouseEvent(local_x, local_y))  		{ +			// This is NOT event recording related  			viewp->logMouseEvent();  			return viewp;  		} @@ -824,6 +849,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)  		if (viewp->handleHover(local_x, local_y, mask)  			|| viewp->blockMouseEvent(local_x, local_y))  		{ +			// This is NOT event recording related  			viewp->logMouseEvent();  			return viewp;  		} @@ -907,10 +933,12 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)  		if (!handled)  		{ +			// For event logging we don't care which widget handles it +			// So we capture the key at the end of this function once we know if it was handled  			handled = handleKeyHere( key, mask ); -			if (handled && LLView::sDebugKeys) +			if (handled)  			{ -				llinfos << "Key handled by " << getName() << llendl; +				llwarns << "Key handled by " << getName() << llendl;  			}  		}  	} @@ -958,6 +986,11 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)  		handled = mParentView->handleUnicodeChar(uni_char, FALSE);  	} +	if (handled) +	{ +		LLViewerEventRecorder::instance().logKeyUnicodeEvent(uni_char); +	} +	  	return handled;  } @@ -987,12 +1020,16 @@ BOOL LLView::hasMouseCapture()  BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseUp( x, y, mask ) != NULL; +	LLView* r = childrenHandleMouseUp( x, y, mask ); + +	return (r!=NULL);  }  BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseDown( x, y, mask ) != NULL; +	LLView* r= childrenHandleMouseDown(x, y, mask ); + +	return (r!=NULL);  }  BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -1065,7 +1102,7 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)  LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)  { -	return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask); +	return	childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask);  }  LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask) diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp new file mode 100644 index 0000000000..a352f621eb --- /dev/null +++ b/indra/llui/llviewereventrecorder.cpp @@ -0,0 +1,296 @@ +/** + * @file llviewereventrecorder.cpp + * @brief Viewer event recording and playback support for mouse and keyboard events + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + *  + * Copyright (c) 2013, 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 "llviewereventrecorder.h" +#include "llui.h" +#include "llleap.h" + +LLViewerEventRecorder::LLViewerEventRecorder() { + +  clear(UNDEFINED); + +  // Remove any previous event log file +  std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old"); +  LLFile::remove(old_log_ui_events_to_llsd_file); +   + +  mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd"); +  LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file); + +} + + +bool LLViewerEventRecorder::displayViewerEventRecorderMenuItems() { +  return LLUI::sSettingGroups["config"]->getBOOL("ShowEventRecorderMenuItems"); +} + + +void LLViewerEventRecorder::setEventLoggingOn() { +  if (! mLog.is_open()) { +    mLog.open(mLogFilename, llofstream::out); +  } +  logEvents=true;  +  lldebugs << "LLViewerEventRecorder::setEventLoggingOn event logging turned on" << llendl; +} + +void LLViewerEventRecorder::setEventLoggingOff() { +  logEvents=false; +  mLog.flush(); +  mLog.close(); +  lldebugs << "LLViewerEventRecorder::setEventLoggingOff event logging turned off" << llendl; +} + + + LLViewerEventRecorder::~LLViewerEventRecorder() { +  if (mLog.is_open()) { +      mLog.close(); +    } +} + +void LLViewerEventRecorder::clear_xui() { +  xui.clear(); +} + +void LLViewerEventRecorder::clear(S32 r) { + +  xui.clear(); + +  local_x=r; +  local_y=r; + +  global_x=r; +  global_y=r; +     + +} + +void LLViewerEventRecorder::setMouseLocalCoords(S32 x, S32 y) { +  local_x=x; +  local_y=y; +} + +void LLViewerEventRecorder::setMouseGlobalCoords(S32 x, S32 y) { +  global_x=x; +  global_y=y; +} + +void LLViewerEventRecorder::updateMouseEventInfo(S32 local_x, S32 local_y, S32 global_x, S32 global_y, std::string mName) { + +  LLView * target_view = LLUI::resolvePath(LLUI::getRootView(), xui); +  if (! target_view) { +    lldebugs << "LLViewerEventRecorder::updateMouseEventInfo - xui path on file at moment is NOT valid - so DO NOT record these local coords" << llendl; +    return; +  } +  lldebugs << "LLViewerEventRecorder::updateMouseEventInfo b4 updatemouseeventinfo - local_x|global x   "<< this->local_x << " " << this->global_x  << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; + + +  if (this->local_x < 1 && this->local_y<1 && local_x && local_y) { +    this->local_x=local_x; +    this->local_y=local_y; +  } +  this->global_x=global_x; +  this->global_y=global_y; + +  // ONLY record deepest xui path for hierarchy searches - or first/only xui for floaters/panels reached via mouse captor - and llmousehandler +  if (mName!="" &&  mName!="/" && xui=="") {  +    //	xui=std::string("/")+mName+xui;  +    //xui=mName+xui;  +    xui = mName; // TODO review confirm we never call with partial path - also cAN REMOVE CHECK FOR "" - ON OTHER HAND IT'S PRETTY HARMLESS +  } + +  lldebugs << "LLViewerEventRecorder::updateMouseEventInfo after updatemouseeventinfo - local_x|global x   "<< this->local_x << " " << this->global_x  << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; +} + +void LLViewerEventRecorder::logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype) { + +  LLSD  event=LLSD::emptyMap(); + +  event.insert("event",LLSD(std::string("visibility"))); + +  if (visibility) { +    event.insert("visibility",LLSD(true)); +  } else { +    event.insert("visibility",LLSD(false)); +  } + +  if (event_subtype!="") { +    event.insert("event_subtype", LLSD(event_subtype)); +  } + +  if(name!="") { +    event.insert("name",LLSD(name)); +  } + +  if (xui!="") { +    event.insert("path",LLSD(xui)); +  } + +  event.insert("timestamp",LLSD(LLDate::now().asString()));  +  recordEvent(event); +} + + +std::string LLViewerEventRecorder::get_xui() { +  return xui; +} +void LLViewerEventRecorder::update_xui(std::string xui) { +  if (xui!="" && this->xui=="" ) { +    lldebugs << "LLViewerEventRecorder::update_xui to " << xui << llendl; +    this->xui=xui; +  } else { +    lldebugs << "LLViewerEventRecorder::update_xui called with empty string" << llendl; +  } +} + +void LLViewerEventRecorder::logKeyEvent(KEY key, MASK mask) { + +  // NOTE: Event recording only logs keydown events - the viewer itself hides keyup events at a fairly low level in the code and does not appear to care about them anywhere + +  LLSD event = LLSD::emptyMap(); + +  event.insert("event",LLSD("type")); + +  // keysym ...or +  // keycode...or +  // char +  event.insert("keysym",LLSD(LLKeyboard::stringFromKey(key))); + +  // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps +  // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might +  // break the test script and it would be useful to have more context to make these sorts of edits safer +  +  // TODO  replace this with a call which extracts to an array of names of masks (just like vita expects during playback) +  // This is looking more and more like an object is a good idea, for this part a handy method call to setMask(mask) would be nice :-) +  // call the func - llkeyboard::llsdStringarrayFromMask + +  LLSD key_mask=LLSD::emptyArray(); + +  if (mask & MASK_CONTROL)     { key_mask.append(LLSD("CTL")); }  // Mac command key - has code of 0x1  in llcommon/indra_contstants +  if (mask & MASK_ALT)         { key_mask.append(LLSD("ALT")); } +  if (mask & MASK_SHIFT)       { key_mask.append(LLSD("SHIFT")); } +  if (mask & MASK_MAC_CONTROL) { key_mask.append(LLSD("MAC_CONTROL")); } + +  event.insert("mask",key_mask);  +  event.insert("timestamp",LLSD(LLDate::now().asString()));  + +  // Although vita has keyDown and keyUp requests it does not have type as a high-level concept  +  // (maybe it should) - instead it has a convenience method that generates the keydown and keyup events  +  // Here  we will use  "type" as  our event type + +  lldebugs << "LLVIewerEventRecorder::logKeyEvent Serialized LLSD for event " << event.asString() << "\n" << llendl; + + +  //lldebugs  << "[VITA] key_name: "  << LLKeyboard::stringFromKey(key) << "mask: "<< mask  << "handled by " << getName() << llendl; +  lldebugs  << "LLVIewerEventRecorder::logKeyEvent  key_name: "  << LLKeyboard::stringFromKey(key) << "mask: "<< mask  << llendl; + + +  recordEvent(event); + +} + +void LLViewerEventRecorder::playbackRecording() { + +  LLSD LeapCommand; + +  // ivita sets this on startup, it also sends commands to the viewer to make start, stop, and playback menu items visible in viewer +  LeapCommand =LLUI::sSettingGroups["config"]->getLLSD("LeapPlaybackEventsCommand"); +   +  lldebugs << "[VITA] launching playback - leap command is: " << LLSDXMLStreamer(LeapCommand) << llendl; +  LLLeap::create("", LeapCommand, false); // exception=false +   +} + + +void LLViewerEventRecorder::recordEvent(LLSD event) { +  lldebugs << "LLViewerEventRecorder::recordEvent event written to log: " << LLSDXMLStreamer(event) << llendl; +  mLog << event << std::endl; +   +} +void LLViewerEventRecorder::logKeyUnicodeEvent(llwchar uni_char) { +  if (! logEvents) return; + +  // Note: keyUp is not captured since the viewer seems to not care about keyUp events + +  LLSD event=LLSD::emptyMap(); + +  event.insert("timestamp",LLSD(LLDate::now().asString())); + +   +  // keysym ...or +  // keycode...or +  // char + +  lldebugs << "Wrapped in conversion to wstring " <<  wstring_to_utf8str(LLWString( 1, uni_char)) << "\n" << llendl; +   +  event.insert("char", +	       LLSD(  wstring_to_utf8str(LLWString( 1,uni_char))  ) +	       );  + +  // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps +  // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might +  // break the test script and it would be useful to have more context to make these sorts of edits safer + +  // TODO need to consider mask keys too? Doesn't seem possible - at least not easily at this point + +  event.insert("event",LLSD("keyDown"));  + +  lldebugs  << "[VITA] unicode key: " << uni_char   << llendl; +  lldebugs  << "[VITA] dumpxml " << LLSDXMLStreamer(event) << "\n" << llendl; + + +  recordEvent(event); + +} + +void LLViewerEventRecorder::logMouseEvent(std::string button_state,std::string button_name) +{ +  if (! logEvents) return;  + +  LLSD  event=LLSD::emptyMap(); + +  event.insert("event",LLSD(std::string("mouse"+ button_state))); +  event.insert("button",LLSD(button_name)); +  if (xui!="") { +    event.insert("path",LLSD(xui)); +  } + +  if (local_x>0 && local_y>0) { +    event.insert("local_x",LLSD(local_x)); +    event.insert("local_y",LLSD(local_y)); +  } + +  if (global_x>0 && global_y>0) { +    event.insert("global_x",LLSD(global_x)); +    event.insert("global_y",LLSD(global_y)); +  } +  event.insert("timestamp",LLSD(LLDate::now().asString()));  +  recordEvent(event); + + +  clear(UNDEFINED); +    + +} diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h new file mode 100644 index 0000000000..72ca643ced --- /dev/null +++ b/indra/llui/llviewereventrecorder.h @@ -0,0 +1,103 @@ +/** + * @file llviewereventrecorder.h + * @brief Viewer event recording and playback support for mouse and keyboard events + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + *  + * Copyright (c) 2013, 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_VIEWER_EVENT_RECORDER +#define LL_VIEWER_EVENT_RECORDER + + +#include "linden_common.h"  + +#include "lldir.h"  +#include "llsd.h"   +#include "llfile.h" +#include "llvfile.h" +#include "lldate.h" +#include "llsdserialize.h" +#include "llkeyboard.h" +#include "llstring.h" + +#include <sstream> + +#include "llsingleton.h" // includes llerror which we need here so we can skip the include here + +class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder> +{ + + public: + +  LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton +  ~LLViewerEventRecorder(); + + +  void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y,  std::string mName); +  void setMouseLocalCoords(S32 x,S32 y); +  void setMouseGlobalCoords(S32 x,S32 y); + +  void logMouseEvent(std::string button_state, std::string button_name ); +  void logKeyEvent(KEY key, MASK mask); +  void logKeyUnicodeEvent(llwchar uni_char); + +  void logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype); + +  void clear_xui(); +  std::string get_xui(); +  void update_xui(std::string xui); + +  bool getLoggingStatus(); +  void setEventLoggingOn(); +  void setEventLoggingOff(); + +  void playbackRecording(); + +  bool displayViewerEventRecorderMenuItems(); + + + protected: +  // On if we wish to log events at the moment - toggle via Develop/Recorder submenu +  bool logEvents; + +  std::string mLogFilename; +  llofstream  mLog;  + + + private: + +  // Mouse event info  +  S32 global_x; +  S32 global_y; +  S32 local_x; +  S32 local_y; + +  // XUI path of UI element +  std::string xui; + +  // Actually write the event out to llsd log file +  void recordEvent(LLSD event); + +  void clear(S32 r);  + +  static const S32 UNDEFINED=-1; +}; +#endif diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 9712ae1d91..eadff8a6b4 100755 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -122,6 +122,7 @@ void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S3  void LLWindowCallbacks::handleFocus(LLWindow *window)  { +	 LL_WARNS("COCOA") << "Called handleFocus proto" << LL_ENDL;  }  void LLWindowCallbacks::handleFocusLost(LLWindow *window) diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 2cae6f3f72..81b25601a9 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -25,6 +25,9 @@   * $/LicenseInfo$   */ +#ifndef LL_LLWINDOWMACOSX_OBJC_H +#define LL_LLWINDOWMACOSX_OBJC_H +  #include <map>  #include <vector> @@ -144,3 +147,5 @@ NSWindowRef getMainAppWindow();  GLViewRef getGLView();  unsigned int getModifiers(); + +#endif // LL_LLWINDOWMACOSX_OBJC_H diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 56472e6b45..11c0b51086 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -331,7 +331,16 @@ void callMouseExit()  void callWindowFocus()  { -	gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); +   if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) +	{ +		gWindowImplementation->getCallbacks()->handleFocus (gWindowImplementation); +	} +	else +	{ +		LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL; +	} + +  }  void callWindowUnfocus() @@ -1300,6 +1309,8 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca  	OSMessageBox(text, caption, type);  } +			// Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature  +			// it is handled at a very low-level  const char* cursorIDToName(int id)  {  	switch (id) diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 16f2290787..97fad7feb0 100755 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -391,7 +391,7 @@ LLControlVariable* LLControlGroup::declareControl(const std::string& name, eCont  		}  		else  		{ -			llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl; +			LL_WARNS("Settings") << "Control named " << name << " already exists, ignoring new declaration." << LL_ENDL;  		}   		return existing_control;  	} @@ -630,14 +630,14 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  	if (!xml_controls.parseFile(filename))  	{ -		llwarns << "Unable to open control file " << filename << llendl; +		LL_WARNS("Settings") << "Unable to open control file " << filename << LL_ENDL;  		return 0;  	}  	LLXmlTreeNode* rootp = xml_controls.getRoot();  	if (!rootp || !rootp->hasAttribute("version"))  	{ -		llwarns << "No valid settings header found in control file " << filename << llendl; +		LL_WARNS("Settings") << "No valid settings header found in control file " << filename << LL_ENDL;  		return 0;  	} @@ -650,7 +650,7 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  	// Check file version  	if (version != CURRENT_VERSION)  	{ -		llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl; +		LL_INFOS("Settings") << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << LL_ENDL;  		return 0;  	} @@ -668,7 +668,7 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require  			if (!name.empty())  			{  				//read in to end of line -				llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl; +				LL_WARNS("Settings") << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << LL_ENDL;  			}  			child_nodep = rootp->getNextChild();  			continue; @@ -822,7 +822,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only  		LLControlVariable* control = iter->second;  		if (!control)  		{ -			llwarns << "Tried to save invalid control: " << iter->first << llendl; +			LL_WARNS("Settings") << "Tried to save invalid control: " << iter->first << LL_ENDL;  		}  		else if( control->shouldSave(nondefault_only) )  		{ @@ -838,12 +838,12 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only  	{  		LLSDSerialize::toPrettyXML(settings, file);  		file.close(); -		llinfos << "Saved to " << filename << llendl; +		LL_INFOS("Settings") << "Saved to " << filename << LL_ENDL;  	}  	else  	{          // This is a warning because sometime we want to use settings files which can't be written... -		llwarns << "Unable to open settings file: " << filename << llendl; +		LL_WARNS("Settings") << "Unable to open settings file: " << filename << LL_ENDL;  		return 0;  	}  	return num_saved; @@ -856,14 +856,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  	infile.open(filename);  	if(!infile.is_open())  	{ -		llwarns << "Cannot find file " << filename << " to load." << llendl; +		LL_WARNS("Settings") << "Cannot find file " << filename << " to load." << LL_ENDL;  		return 0;  	}  	if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(settings, infile))  	{  		infile.close(); -		llwarns << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << llendl; +		LL_WARNS("Settings") << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << LL_ENDL;  		return loadFromFileLegacy(filename, TRUE, TYPE_STRING);  	} @@ -976,6 +976,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v  		++validitems;  	} +	LL_DEBUGS("Settings") << "Loaded " << validitems << " settings from " << filename << LL_ENDL;  	return validitems;  } @@ -1012,7 +1013,7 @@ void main()  	BOOL_CONTROL baz;  	U32 count = gGlobals.loadFromFile("controls.ini"); -	llinfos << "Loaded " << count << " controls" << llendl; +	LL_INFOS("Settings") << "Loaded " << count << " controls" << LL_ENDL;  	// test insertion  	foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f); @@ -1273,19 +1274,19 @@ LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const st  		LLColor4 color(sd);  		if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)  		{ -			llwarns << "Color " << control_name << " red value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " red value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)  		{ -			llwarns << "Color " << control_name << " green value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " green value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)  		{ -			llwarns << "Color " << control_name << " blue value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " blue value out of range: " << color << LL_ENDL;  		}  		else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)  		{ -			llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl; +			LL_WARNS("Settings") << "Color " << control_name << " alpha value out of range: " << color << LL_ENDL;  		}  		return LLColor4(sd); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index e1f9be80dd..f46d21408b 100755 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -408,16 +408,6 @@ public:  		}  	} -	LLCachedControl(LLControlGroup& group, -					const std::string& name) -	{ -		mCachedControlPtr = LLControlCache<T>::getInstance(name); -		if (mCachedControlPtr.isNull()) -		{ -			mCachedControlPtr = new LLControlCache<T>(group, name); -		} -	} -  	operator const T&() const { return mCachedControlPtr->getValue(); }  	operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }  	const T& operator()() { return mCachedControlPtr->getValue(); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d3835a5b2a..1fea6dea9f 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -191,6 +191,7 @@ set(viewer_SOURCE_FILES      llexpandabletextbox.cpp      llexternaleditor.cpp      llface.cpp +    llfacebookconnect.cpp      llfasttimerview.cpp      llfavoritesbar.cpp      llfeaturemanager.cpp @@ -273,6 +274,7 @@ set(viewer_SOURCE_FILES      llfloatersettingsdebug.cpp      llfloatersidepanelcontainer.cpp      llfloatersnapshot.cpp +    llfloatersocial.cpp      llfloatersounddevices.cpp      llfloaterspellchecksettings.cpp      llfloatertelehub.cpp @@ -508,6 +510,7 @@ set(viewer_SOURCE_FILES      llsidetraypanelcontainer.cpp      llsky.cpp      llslurl.cpp +    llsnapshotlivepreview.cpp      llspatialpartition.cpp      llspeakers.cpp      llspeakingindicatormanager.cpp @@ -776,6 +779,7 @@ set(viewer_HEADER_FILES      llexpandabletextbox.h      llexternaleditor.h      llface.h +    llfacebookconnect.h      llfasttimerview.h      llfavoritesbar.h      llfeaturemanager.h @@ -858,6 +862,7 @@ set(viewer_HEADER_FILES      llfloatersettingsdebug.h      llfloatersidepanelcontainer.h      llfloatersnapshot.h +    llfloatersocial.h      llfloatersounddevices.h      llfloaterspellchecksettings.h      llfloatertelehub.h @@ -1082,6 +1087,7 @@ set(viewer_HEADER_FILES      llsidetraypanelcontainer.h      llsky.h      llslurl.h +    llsnapshotlivepreview.h      llspatialpartition.h      llspeakers.h      llspeakingindicatormanager.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index cff2619cfb..e8b6c77dc9 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.6.9 +3.6.11 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 4659673333..ce878f156b 100755 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -3,6 +3,8 @@    <command name="aboutland"             available_in_toybox="true"             icon="Command_AboutLand_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_AboutLand_Label"             tooltip_ref="Command_AboutLand_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -13,6 +15,8 @@    <command name="appearance"               available_in_toybox="true"             icon="Command_Appearance_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Appearance_Label"             tooltip_ref="Command_Appearance_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -23,6 +27,8 @@    <command name="avatar"             available_in_toybox="true"             icon="Command_Avatar_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Avatar_Label"             tooltip_ref="Command_Avatar_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -33,6 +39,8 @@    <command name="build"             available_in_toybox="true"             icon="Command_Build_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Build_Label"             tooltip_ref="Command_Build_Tooltip"             execute_function="Build.Toggle" @@ -46,6 +54,8 @@             available_in_toybox="true"  		   is_flashing_allowed="true"             icon="Command_Chat_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Chat_Label"             tooltip_ref="Command_Conversations_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -56,6 +66,8 @@    <command name="compass"             available_in_toybox="false"             icon="Command_Compass_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Compass_Label"             tooltip_ref="Command_Compass_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -66,6 +78,8 @@    <command name="destinations"             available_in_toybox="true"             icon="Command_Destinations_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Destinations_Label"             tooltip_ref="Command_Destinations_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -76,6 +90,8 @@    <command name="gestures"             available_in_toybox="true"             icon="Command_Gestures_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Gestures_Label"             tooltip_ref="Command_Gestures_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -86,6 +102,8 @@    <command name="howto"             available_in_toybox="true"             icon="Command_HowTo_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_HowTo_Label"             tooltip_ref="Command_HowTo_Tooltip"             execute_function="Help.ToggleHowTo" @@ -94,6 +112,8 @@    <command name="inventory"             available_in_toybox="true"             icon="Command_Inventory_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Inventory_Label"             tooltip_ref="Command_Inventory_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -104,6 +124,8 @@    <command name="map"             available_in_toybox="true"             icon="Command_Map_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Map_Label"             tooltip_ref="Command_Map_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -114,6 +136,8 @@    <command name="marketplace"             available_in_toybox="false"             icon="Command_Marketplace_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Marketplace_Label"             tooltip_ref="Command_Marketplace_Tooltip"             execute_function="Avatar.OpenMarketplace" @@ -121,6 +145,8 @@    <command name="minimap"             available_in_toybox="true"             icon="Command_MiniMap_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_MiniMap_Label"             tooltip_ref="Command_MiniMap_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -131,6 +157,8 @@    <command name="move"             available_in_toybox="true"             icon="Command_Move_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Move_Label"             tooltip_ref="Command_Move_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -141,6 +169,8 @@    <command name="outbox"             available_in_toybox="false"             icon="Command_Outbox_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Outbox_Label"             tooltip_ref="Command_Outbox_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -151,6 +181,8 @@    <command name="people"             available_in_toybox="true"             icon="Command_People_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_People_Label"             tooltip_ref="Command_People_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -161,6 +193,8 @@    <command name="picks"             available_in_toybox="true"             icon="Command_Picks_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Picks_Label"             tooltip_ref="Command_Picks_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -171,6 +205,8 @@    <command name="places"             available_in_toybox="true"             icon="Command_Places_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Places_Label"             tooltip_ref="Command_Places_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -181,6 +217,8 @@    <command name="preferences"             available_in_toybox="true"             icon="Command_Preferences_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Preferences_Label"             tooltip_ref="Command_Preferences_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -191,6 +229,8 @@    <command name="profile"             available_in_toybox="true"             icon="Command_Profile_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Profile_Label"             tooltip_ref="Command_Profile_Tooltip"             execute_function="Avatar.ToggleMyProfile" @@ -199,6 +239,8 @@    <command name="search"             available_in_toybox="true"             icon="Command_Search_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Search_Label"             tooltip_ref="Command_Search_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -209,6 +251,8 @@    <command name="snapshot"             available_in_toybox="true"             icon="Command_Snapshot_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Snapshot_Label"             tooltip_ref="Command_Snapshot_Tooltip"             execute_function="Floater.ToggleOrBringToFront" @@ -216,9 +260,21 @@             is_running_function="Floater.IsOpen"             is_running_parameters="snapshot"             /> +  <command name="social" +           available_in_toybox="true" +           icon="Command_Social_Icon" +           label_ref="Command_Social_Label" +           tooltip_ref="Command_Social_Tooltip" +           execute_function="Floater.ToggleOrBringToFront" +           execute_parameters="social" +           is_running_function="Floater.IsOpen" +           is_running_parameters="social" +           />    <command name="speak"             available_in_toybox="true"             icon="Command_Speak_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_Speak_Label"             tooltip_ref="Command_Speak_Tooltip"             execute_function="Agent.PressMicrophone" @@ -233,6 +289,8 @@    <command name="view"             available_in_toybox="true"             icon="Command_View_Icon" +           hover_icon_unselected="Command_Highlighting_Icon" +           hover_icon_selected="Command_Highlighting_Selected_Icon"             label_ref="Command_View_Label"             tooltip_ref="Command_View_Tooltip"             execute_function="Floater.ToggleOrBringToFront" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0e9266dad4..2ce7363c28 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4941,6 +4941,16 @@        <key>Value</key>        <array />      </map> +    <key>LeapPlaybackEventsCommand</key> +    <map> +      <key>Comment</key> +      <string>Command line to use leap to launch playback of event recordings</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>LLSD</string> +      <key>Value</key> +    </map>      <key>LSLFindCaseInsensitivity</key>          <map>          <key>Comment</key> @@ -5932,6 +5942,17 @@        <key>Value</key>        <real>1.6</real>      </map> +    <key>MaxPersistentNotifications</key> +    <map> +      <key>Comment</key> +      <string>Maximum amount of persistent notifications</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <real>250</real> +    </map>      <key>MaxSelectDistance</key>      <map>        <key>Comment</key> @@ -9840,7 +9861,7 @@      <key>RenderUseVAO</key>      <map>        <key>Comment</key> -      <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string> +      <string>[EXPERIMENTAL] Use GL Vertex Array Objects.</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -10476,6 +10497,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>ShowEventRecorderMenuItems</key> +    <map> +      <key>Comment</key> +      <string>Whether or not Event Recorder menu choices - Start / Stop event recording should appear in the (currently) Develop menu</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>ShowGestureButton</key>      <map>        <key>Comment</key> @@ -13116,6 +13148,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>SocialPhotoResolution</key> +    <map> +      <key>Comment</key> +      <string>Default resolution when sharing photo using the social floater</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>[i800,i600]</string> +    </map>        <key>sourceid</key>      <map>        <key>Comment</key> @@ -13334,7 +13377,7 @@        <key>Type</key>        <string>String</string>        <key>Value</key> -      <string>-1</string> +      <string>0</string>      </map>      <key>VivoxDebugSIPURIHostName</key>      <map> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 636caf5ef3..500151c935 100755 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -77,6 +77,17 @@          <key>Value</key>              <integer>412</integer>      </map> +    <key>ConversationsParticipantListCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of Nearby chat participant list</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>true</integer> +    </map>         <key>InstantMessageLogPath</key>          <map>          <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index bc63d07d72..c98e7d1cd3 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -33,8 +33,8 @@ mat4 getSkinnedTransform()  	mat4 ret;  	int i = int(floor(weight.x));  	float x = fract(weight.x); -		 -	ret[0] = mix(matrixPalette[i+0], matrixPalette[i+1], x); +	 +	ret[0] = mix(matrixPalette[i+0], matrixPalette[i+1],  x);  	ret[1] = mix(matrixPalette[i+15],matrixPalette[i+16], x);  	ret[2] = mix(matrixPalette[i+30],matrixPalette[i+31], x);  	ret[3] = vec4(0,0,0,1); diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index efd0d03965..12996cf0d6 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -34,14 +34,17 @@ mat4 getObjectSkinnedTransform()  	vec4 w = fract(weight4);  	vec4 index = floor(weight4); -	 + +		 index = min(index, vec4(31.0)); +		 index = max(index, vec4( 0.0)); +  	float scale = 1.0/(w.x+w.y+w.z+w.w);  	w *= scale; -	 -	mat4 mat = matrixPalette[int(index.x)]*w.x; -	mat += matrixPalette[int(index.y)]*w.y; -	mat += matrixPalette[int(index.z)]*w.z; -	mat += matrixPalette[int(index.w)]*w.w; + +	mat4 mat  = matrixPalette[int(index.x)]*w.x; +		 mat += matrixPalette[int(index.y)]*w.y; +		 mat += matrixPalette[int(index.z)]*w.z; +		 mat += matrixPalette[int(index.w)]*w.w;  	return mat;  } diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml index 29c019719d..86f9912815 100755 --- a/indra/newview/app_settings/toolbars.xml +++ b/indra/newview/app_settings/toolbars.xml @@ -6,6 +6,7 @@      <command name="speak"/>      <command name="destinations"/>      <command name="people"/> +    <command name="social"/>      <command name="profile"/>      <command name="move"/>      <command name="view"/> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 49f77e6c34..325707bbf1 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1092,11 +1092,19 @@ const LLVector3d &LLAgent::getPositionGlobal() const  //-----------------------------------------------------------------------------  const LLVector3 &LLAgent::getPositionAgent()  { -	if (isAgentAvatarValid() && !gAgentAvatarp->mDrawable.isNull()) +	if (isAgentAvatarValid())  	{ -		mFrameAgent.setOrigin(gAgentAvatarp->getRenderPosition());	 +		if(gAgentAvatarp->mDrawable.isNull()) +		{ +			mFrameAgent.setOrigin(gAgentAvatarp->getPositionAgent()); +		} +		else +		{ +			mFrameAgent.setOrigin(gAgentAvatarp->getRenderPosition()); +		}  	} +  	return mFrameAgent.getOrigin();  } diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp index b9ec304b7e..3410a37890 100755 --- a/indra/newview/llagentui.cpp +++ b/indra/newview/llagentui.cpp @@ -112,6 +112,11 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const  		case LOCATION_FORMAT_NORMAL:  			buffer = llformat("%s", region_name.c_str());  			break; +		case LOCATION_FORMAT_NORMAL_COORDS: +			buffer = llformat("%s (%d, %d, %d)", +				region_name.c_str(), +				pos_x, pos_y, pos_z); +			break;  		case LOCATION_FORMAT_NO_COORDS:  			buffer = llformat("%s%s%s",  				region_name.c_str(), @@ -143,6 +148,11 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const  		case LOCATION_FORMAT_NORMAL:  			buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());  			break; +		case LOCATION_FORMAT_NORMAL_COORDS: +			buffer = llformat("%s (%d, %d, %d)", +				parcel_name.c_str(), +				pos_x, pos_y, pos_z); +			break;  		case LOCATION_FORMAT_NO_MATURITY:  			buffer = llformat("%s, %s (%d, %d, %d)",  				parcel_name.c_str(), diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h index dda5dc1fd1..bb48dad14c 100755 --- a/indra/newview/llagentui.h +++ b/indra/newview/llagentui.h @@ -35,6 +35,7 @@ public:  	enum ELocationFormat  	{  		LOCATION_FORMAT_NORMAL,			// Parcel +		LOCATION_FORMAT_NORMAL_COORDS,	// Parcel (x, y, z)  		LOCATION_FORMAT_LANDMARK,		// Parcel, Region  		LOCATION_FORMAT_NO_MATURITY,	// Parcel, Region (x, y, z)  		LOCATION_FORMAT_NO_COORDS,		// Parcel, Region - Maturity diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 1edbbe2a2e..fa810aac76 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1538,7 +1538,11 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  	std::set<LLUUID> requested_item_ids;  	std::set<LLUUID> current_item_ids;  	for (S32 i=0; i<obj_item_array.count(); i++) -		requested_item_ids.insert(obj_item_array[i].get()->getLinkedUUID()); +	{ +		const LLUUID & requested_id = obj_item_array[i].get()->getLinkedUUID(); +		//llinfos << "Requested attachment id " << requested_id << llendl; +		requested_item_ids.insert(requested_id); +	}  	// Build up list of objects to be removed and items currently attached.  	llvo_vec_t objects_to_remove; @@ -1555,17 +1559,28 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  			if (objectp)  			{  				LLUUID object_item_id = objectp->getAttachmentItemID(); + +				bool remove_attachment = true;  				if (requested_item_ids.find(object_item_id) != requested_item_ids.end()) -				{ -					// Object currently worn, was requested. +				{	// Object currently worn, was requested to keep it  					// Flag as currently worn so we won't have to add it again. -					current_item_ids.insert(object_item_id); +					remove_attachment = false;  				} -				else +				else if (objectp->isTempAttachment()) +				{	// Check if we should keep this temp attachment +					remove_attachment = LLAppearanceMgr::instance().shouldRemoveTempAttachment(objectp->getID()); +				} + +				if (remove_attachment)  				{ -					// object currently worn, not requested. +					// llinfos << "found object to remove, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << llendl;  					objects_to_remove.push_back(objectp);  				} +				else +				{ +					// llinfos << "found object to keep, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << llendl; +					current_item_ids.insert(object_item_id); +				}  			}  		}  	} diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index fd9236c8b3..da1609297e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3415,21 +3415,50 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)  		llwarns << "called with empty list, nothing to do" << llendl;  	}  	for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it) -			{ +	{  		const LLUUID& id_to_remove = *it;  		const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove);  		removeCOFItemLinks(linked_item_id); -			} -	updateAppearanceFromCOF(); +		addDoomedTempAttachment(linked_item_id);  	} +	updateAppearanceFromCOF(); +}  void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)  {  	LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);  	removeCOFItemLinks(linked_item_id); +	addDoomedTempAttachment(linked_item_id);  	updateAppearanceFromCOF();  } + +// Adds the given item ID to mDoomedTempAttachmentIDs iff it's a temp attachment +void LLAppearanceMgr::addDoomedTempAttachment(const LLUUID& id_to_remove) +{ +	LLViewerObject * attachmentp = gAgentAvatarp->findAttachmentByID(id_to_remove); +	if (attachmentp && +		attachmentp->isTempAttachment()) +	{	// If this is a temp attachment and we want to remove it, record the ID  +		// so it will be deleted when attachments are synced up with COF +		mDoomedTempAttachmentIDs.insert(id_to_remove); +		//llinfos << "Will remove temp attachment id " << id_to_remove << llendl; +	} +} + +// Find AND REMOVES the given UUID from mDoomedTempAttachmentIDs +bool LLAppearanceMgr::shouldRemoveTempAttachment(const LLUUID& item_id) +{ +	doomed_temp_attachments_t::iterator iter = mDoomedTempAttachmentIDs.find(item_id); +	if (iter != mDoomedTempAttachmentIDs.end()) +	{ +		mDoomedTempAttachmentIDs.erase(iter); +		return true; +	} +	return false; +} + +  bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body)  {  	if (!item || !item->isWearableType()) return false; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 46252afbde..5ec80f1cf0 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -142,6 +142,9 @@ public:  	void removeAllClothesFromAvatar();  	void removeAllAttachmentsFromAvatar(); +	// Special handling of temp attachments, which are not in the COF +	bool shouldRemoveTempAttachment(const LLUUID& item_id); +  	//has the current outfit changed since it was loaded?  	bool isOutfitDirty() { return mOutfitIsDirty; } @@ -239,6 +242,12 @@ private:  	std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; +	// Set of temp attachment UUIDs that should be removed +	typedef std::set<LLUUID> doomed_temp_attachments_t; +	doomed_temp_attachments_t	mDoomedTempAttachmentIDs; + +	void addDoomedTempAttachment(const LLUUID& id_to_remove); +  	//////////////////////////////////////////////////////////////////////////////////  	// Item-specific convenience functions   public: diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f67142d1ed..539d186441 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -223,6 +223,10 @@  #include "llmachineid.h"  #include "llmainlooprepeater.h" + +#include "llviewereventrecorder.h" + +  // *FIX: These extern globals should be cleaned up.  // The globals either represent state/config/resource-storage of either   // this app, or another 'component' of the viewer. App globals should be  @@ -696,6 +700,7 @@ LLAppViewer::LLAppViewer() :  LLAppViewer::~LLAppViewer()  {  	delete mSettingsLocationList; +	LLViewerEventRecorder::instance().~LLViewerEventRecorder();  	LLLoginInstance::instance().setUpdaterService(0); @@ -2250,13 +2255,13 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  		BOOST_FOREACH(const SettingsFile& file, group.files)  		{ -			llinfos << "Attempting to load settings for the group " << file.name() -			    << " - from location " << location_key << llendl; +			LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name() +			    << " - from location " << location_key << LL_ENDL;  			LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);  			if(!settings_group)  			{ -				llwarns << "No matching settings group for name " << file.name() << llendl; +				LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;  				continue;  			} @@ -2285,7 +2290,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  			if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))  			{	// success! -				llinfos << "Loaded settings file " << full_settings_path << llendl; +				LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;  			}  			else  			{	// failed to load @@ -2299,7 +2304,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,  					// only complain if we actually have a filename at this point  					if (!full_settings_path.empty())  					{ -						llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl; +						LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;  					}  				}  			} @@ -2395,8 +2400,6 @@ bool LLAppViewer::initConfiguration()  	gSavedSettings.setString("ClientSettingsFile",           gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); -	gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel()); -  #ifndef	LL_RELEASE_FOR_DOWNLOAD  	// provide developer build only overrides for these control variables that are not  	// persisted to settings.xml @@ -2460,8 +2463,8 @@ bool LLAppViewer::initConfiguration()  			gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,   										   clp.getOption("settings")[0]);		  		gSavedSettings.setString("ClientSettingsFile", user_settings_filename); -		llinfos	<< "Using command line specified settings filename: "  -			<< user_settings_filename << llendl; +		LL_INFOS("Settings")	<< "Using command line specified settings filename: "  +			<< user_settings_filename << LL_ENDL;  	}  	// - load overrides from user_settings  @@ -2477,8 +2480,8 @@ bool LLAppViewer::initConfiguration()  	{  		std::string session_settings_filename = clp.getOption("sessionsettings")[0];		  		gSavedSettings.setString("SessionSettingsFile", session_settings_filename); -		llinfos	<< "Using session settings filename: "  -			<< session_settings_filename << llendl; +		LL_INFOS("Settings")	<< "Using session settings filename: "  +			<< session_settings_filename << LL_ENDL;  	}  	loadSettingsFromDirectory("Session"); @@ -2486,8 +2489,8 @@ bool LLAppViewer::initConfiguration()  	{  		std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];		  		gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename); -		llinfos	<< "Using user session settings filename: "  -			<< user_session_settings_filename << llendl; +		LL_INFOS("Settings") << "Using user session settings filename: "  +			<< user_session_settings_filename << LL_ENDL;  	}  	loadSettingsFromDirectory("UserSession"); @@ -2575,9 +2578,13 @@ bool LLAppViewer::initConfiguration()          }      } +    if  (clp.hasOption("logevents")) { +	LLViewerEventRecorder::instance().setEventLoggingOn(); +    } +  	std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));  	if(! CmdLineChannel.empty()) -	{ +    {  		LLVersionInfo::resetChannel(CmdLineChannel);  	} @@ -2589,16 +2596,16 @@ bool LLAppViewer::initConfiguration()  		LLFastTimer::sLog = TRUE;  		LLFastTimer::sLogName = std::string("performance");		  	} - +	  	std::string test_name(gSavedSettings.getString("LogMetrics"));  	if (! test_name.empty()) -	{ -		LLFastTimer::sMetricLog = TRUE ; + 	{ + 		LLFastTimer::sMetricLog = TRUE ;  		// '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test  		// In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)  		llinfos << "'--logmetrics' argument : " << test_name << llendl; -		LLFastTimer::sLogName = test_name; - 	} +			LLFastTimer::sLogName = test_name; +		}  	if (clp.hasOption("graphicslevel"))  	{ @@ -2607,14 +2614,14 @@ bool LLAppViewer::initConfiguration()  		// that value for validity.  		U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");  		if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel)) -		{ +        {  			// graphicslevel is valid: save it and engage it later. Capture  			// the requested value separately from the settings variable  			// because, if this is the first run, LLViewerWindow's constructor  			// will call LLFeatureManager::applyRecommendedSettings(), which  			// overwrites this settings variable!  			mForceGraphicsLevel = graphicslevel; -		} +        }  	}  	LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); @@ -2645,16 +2652,32 @@ bool LLAppViewer::initConfiguration()      // What can happen is that someone can use IE (or potentially       // other browsers) and do the rough equivalent of command       // injection and steal passwords. Phoenix. SL-55321 +	LLSLURL start_slurl;  	std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));  	if(! CmdLineLoginLocation.empty()) -	{ -		LLSLURL start_slurl(CmdLineLoginLocation); +    { +		start_slurl = CmdLineLoginLocation;  		LLStartUp::setStartSLURL(start_slurl);  		if(start_slurl.getType() == LLSLURL::LOCATION)   		{    			LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid()); +    } +    } + +	//RN: if we received a URL, hand it off to the existing instance. +	// don't call anotherInstanceRunning() when doing URL handoff, as +	// it relies on checking a marker file which will not work when running +	// out of different directories + +	if (start_slurl.isValid() && +		(gSavedSettings.getBOOL("SLURLPassToOtherInstance"))) +	{ +		if (sendURLToOtherInstance(start_slurl.getSLURLString())) +		{ +			// successfully handed off URL to existing instance, exit +			return false;  		} -	} +    }  	const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");  	if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) @@ -2795,7 +2818,7 @@ bool LLAppViewer::initConfiguration()  		LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;  		LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));  	} -	else if ((clp.hasOption("login") || clp.hasOption("autologin")) +	else if (   (   clp.hasOption("login") || clp.hasOption("autologin"))  			 && gSavedSettings.getString("CmdLineLoginLocation").empty())  	{  		// If automatic login from command line with --login switch @@ -3179,7 +3202,7 @@ bool LLAppViewer::initWindow()  		LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);  		gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);  	} - +			  	// Set this flag in case we crash while initializing GL  	gSavedSettings.setBOOL("RenderInitError", TRUE);  	gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 3cf3c739d9..80a80f4298 100755 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -172,21 +172,20 @@ void ll_nvapi_init(NvDRSSessionHandle hSession)  			nvapi_error(status);  			return;  		} + +        // (5) Now we apply (or save) our changes to the system +        status = NvAPI_DRS_SaveSettings(hSession); +        if (status != NVAPI_OK)  +        { +            nvapi_error(status); +            return; +        }  	}  	else if (status != NVAPI_OK)  	{  		nvapi_error(status);  		return;  	} - -	 - -	// (5) Now we apply (or save) our changes to the system -	status = NvAPI_DRS_SaveSettings(hSession); -	if (status != NVAPI_OK)  -	{ -		nvapi_error(status); -	}  }  //#define DEBUGGING_SEH_FILTER 1 diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp index 1d72397cbc..dd9354fe3a 100755 --- a/indra/newview/llautoreplace.cpp +++ b/indra/newview/llautoreplace.cpp @@ -39,7 +39,7 @@ void LLAutoReplace::autoreplaceCallback(S32& replacement_start, S32& replacement  	replacement_length = 0;  	replacement_string.clear(); -	static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); +	static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace", 0);  	if (perform_autoreplace)  	{  		S32 word_end = cursor_pos - 1; @@ -679,7 +679,7 @@ bool LLAutoReplaceSettings::decreaseListPriority(std::string listName)  std::string LLAutoReplaceSettings::replaceWord(const std::string currentWord)  {  	std::string returnedWord = currentWord; // in case no replacement is found -	static LLCachedControl<bool> autoreplace_enabled(gSavedSettings, "AutoReplace"); +	static LLCachedControl<bool> autoreplace_enabled(gSavedSettings, "AutoReplace", false);  	if ( autoreplace_enabled )  	{  		LL_DEBUGS("AutoReplace")<<"checking '"<<currentWord<<"'"<< LL_ENDL; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index b513a52ff7..70cc48f12b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -73,6 +73,8 @@  #include "llcallingcard.h"  #include "llslurl.h"			// IDEVO  #include "llsidepanelinventory.h" +#include "llavatarname.h" +#include "llagentui.h"  // static  void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -391,6 +393,72 @@ void LLAvatarActions::pay(const LLUUID& id)  	}  } +void LLAvatarActions::teleport_request_callback(const LLSD& notification, const LLSD& response) +{ +	S32 option; +	if (response.isInteger())  +	{ +		option = response.asInteger(); +	} +	else +	{ +		option = LLNotificationsUtil::getSelectedOption(notification, response); +	} + +	if (0 == option) +	{ +		LLMessageSystem* msg = gMessageSystem; + +		msg->newMessageFast(_PREHASH_ImprovedInstantMessage); +		msg->nextBlockFast(_PREHASH_AgentData); +		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + +		msg->nextBlockFast(_PREHASH_MessageBlock); +		msg->addBOOLFast(_PREHASH_FromGroup, FALSE); +		msg->addUUIDFast(_PREHASH_ToAgentID, notification["substitutions"]["uuid"] ); +		msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); +		msg->addU8Fast(_PREHASH_Dialog, IM_TELEPORT_REQUEST); +		msg->addUUIDFast(_PREHASH_ID, LLUUID::null); +		msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + +		std::string name; +		LLAgentUI::buildFullname(name); + +		msg->addStringFast(_PREHASH_FromAgentName, name); +		msg->addStringFast(_PREHASH_Message, response["message"]); +		msg->addU32Fast(_PREHASH_ParentEstateID, 0); +		msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); +		msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + +		gMessageSystem->addBinaryDataFast( +				_PREHASH_BinaryBucket, +				EMPTY_BINARY_BUCKET, +				EMPTY_BINARY_BUCKET_SIZE); + +		gAgent.sendReliableMessage(); +	} +} + +// static +void LLAvatarActions::teleportRequest(const LLUUID& id) +{ +	LLSD notification; +	notification["uuid"] = id; +	LLAvatarName av_name; +	if (!LLAvatarNameCache::get(id, &av_name)) +	{ +		// unlikely ... they just picked this name from somewhere... +		LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::teleportRequest, id)); +		return; // reinvoke this when the name resolves +	} +	notification["NAME"] = av_name.getCompleteName(); + +	LLSD payload; + +	LLNotificationsUtil::add("TeleportRequestPrompt", notification, payload, teleport_request_callback); +} +  // static  void LLAvatarActions::kick(const LLUUID& id)  { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 6e1198cd09..403414558e 100755 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -111,6 +111,12 @@ public:  	static void pay(const LLUUID& id);  	/** +	 * Request teleport from other avatar +	 */ +	static void teleportRequest(const LLUUID& id); +	static void teleport_request_callback(const LLSD& notification, const LLSD& response); + +	/**  	 * Share items with the avatar.  	 */  	static void share(const LLUUID& id); diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 9e3225a264..77d734cbfe 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -336,7 +336,7 @@ void LLAvatarRenderInfoAccountant::idle()  		sRenderInfoReportTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS);  	} -	static LLCachedControl<U32> render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions"); +	static LLCachedControl<U32> render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions", 0);  	static U32 prev_render_auto_mute_functions = (U32) -1;  	if (prev_render_auto_mute_functions != render_auto_mute_functions)  	{ diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index 066cb71677..ac41b26a34 100755 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -41,10 +41,14 @@ static const LLBlockListNameTypeComparator	NAME_TYPE_COMPARATOR;  LLBlockList::LLBlockList(const Params& p)  :	LLFlatListViewEx(p),   	mSelectedItem(NULL), - 	mDirty(true) + 	mDirty(true), +	mShouldAddAll(true), +	mActionType(NONE), +	mMuteListSize(0)  {  	LLMuteList::getInstance()->addObserver(this); +	mMuteListSize = LLMuteList::getInstance()->getMutes().size();  	// Set up context menu.  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -73,6 +77,41 @@ LLBlockList::~LLBlockList()  	LLMuteList::getInstance()->removeObserver(this);  } +void LLBlockList::createList() +{ +	std::vector<LLMute> mutes = LLMuteList::instance().getMutes(); +	std::vector<LLMute>::const_iterator mute_it = mutes.begin(); + +	for (; mute_it != mutes.end(); ++mute_it) +	{ +		addNewItem(&*mute_it); +	} +} + +BlockListActionType LLBlockList::getCurrentMuteListActionType() +{ +	BlockListActionType type = NONE; +	U32 curSize = LLMuteList::getInstance()->getMutes().size(); +	if( curSize > mMuteListSize) +		type = ADD; +	else if(curSize < mMuteListSize) +		type = REMOVE; + +	return type; +} + +void LLBlockList::onChangeDetailed(const LLMute &mute) +{ +	mActionType = getCurrentMuteListActionType(); + +	mCurItemId = mute.mID; +	mCurItemName = mute.mName; +	mCurItemType = mute.mType; +	mCurItemFlags = mute.mFlags; + +	refresh(); +} +  BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); @@ -88,6 +127,16 @@ BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask)  	return handled;  } +void LLBlockList::removeListItem(const LLMute* mute) +{ +	removeItemByUUID(mute->mID); +} + +void LLBlockList::hideListItem(LLBlockedListItem* item, bool show) +{ +	item->setVisible(show); +} +  void LLBlockList::setNameFilter(const std::string& filter)  {  	std::string filter_upper = filter; @@ -136,28 +185,56 @@ void LLBlockList::refresh()  	bool have_filter = !mNameFilter.empty();  	// save selection to restore it after list rebuilt -	LLUUID selected = getSelectedUUID(); +	LLUUID selected = getSelectedUUID(), next_selected; -	// calling refresh may be initiated by removing currently selected item -	// so select next item and save the selection to restore it after list rebuilt -	if (!selectNextItemPair(false, true)) +	if(mShouldAddAll)	// creating list of blockers  	{ -		selectNextItemPair(true, true); +		clear(); +		createList(); +		mShouldAddAll = false; +	} +	else +	{ +		// handle remove/add functionality +		LLMute mute(mCurItemId, mCurItemName, mCurItemType, mCurItemFlags); +		if(mActionType == ADD) +		{ +			addNewItem(&mute); +		} +		else if(mActionType == REMOVE) +		{ +			if(selected == mute.mID) +			{ +				// we are going to remove currently selected item, so select next item and save the selection to restore it +				if (!selectNextItemPair(false, true)) +				{ +					selectNextItemPair(true, true); +				} +				next_selected = getSelectedUUID(); +			} +			removeListItem(&mute); +		} +		mActionType = NONE;  	} -	LLUUID next_selected = getSelectedUUID(); - -	clear(); - -	std::vector<LLMute> mutes = LLMuteList::instance().getMutes(); -	std::vector<LLMute>::const_iterator mute_it = mutes.begin(); -	for (; mute_it != mutes.end(); ++mute_it) +	// handle filter functionality +	if(have_filter || (!have_filter && !mPrevNameFilter.empty()))  	{ -		if (have_filter && !findInsensitive(mute_it->mName, mNameFilter)) -			continue; +		// we should update visibility of our items if previous filter was not empty +		std::vector < LLPanel* > allItems; +		getItems(allItems); +		std::vector < LLPanel* >::iterator it = allItems.begin(); -		addNewItem(&*mute_it); +		for(; it != allItems.end() ; ++it) +		{ +			LLBlockedListItem * curItem = dynamic_cast<LLBlockedListItem *> (*it); +			if(curItem) +			{ +				hideListItem(curItem, findInsensitive(curItem->getName(), mNameFilter)); +			} +		}  	} +	mPrevNameFilter = mNameFilter;  	if (getItemPair(selected))  	{ @@ -169,6 +246,7 @@ void LLBlockList::refresh()  		// previously selected item was removed, so select next item  		selectItemPair(getItemPair(next_selected), true);  	} +	mMuteListSize = LLMuteList::getInstance()->getMutes().size();  	// Sort the list.  	sort(); diff --git a/indra/newview/llblocklist.h b/indra/newview/llblocklist.h index 1a215710f4..b1ea7e98e5 100755 --- a/indra/newview/llblocklist.h +++ b/indra/newview/llblocklist.h @@ -34,6 +34,8 @@  class LLBlockedListItem;  class LLMute; +enum BlockListActionType {NONE, ADD, REMOVE}; +  /**   * List of blocked avatars and objects.   * This list represents contents of the LLMuteList. @@ -56,7 +58,8 @@ public:  	LLToggleableMenu*	getContextMenu() const { return mContextMenu.get(); }  	LLBlockedListItem*	getBlockedItem() const; -	virtual void onChange() { refresh(); } +	virtual void onChange() { } +	virtual void onChangeDetailed(const LLMute& );  	virtual void draw();  	void setNameFilter(const std::string& filter); @@ -67,18 +70,32 @@ public:  private:  	void addNewItem(const LLMute* mute); +	void removeListItem(const LLMute* mute); +	void hideListItem(LLBlockedListItem* item, bool show);  	void setDirty(bool dirty = true) { mDirty = dirty; }  	bool findInsensitive(std::string haystack, const std::string& needle_upper);  	bool isActionEnabled(const LLSD& userdata);  	void onCustomAction (const LLSD& userdata); +	void createList(); - +	BlockListActionType getCurrentMuteListActionType(); +	  	LLHandle<LLToggleableMenu>	mContextMenu;  	LLBlockedListItem*			mSelectedItem;  	std::string 				mNameFilter;  	bool 						mDirty; +	bool						mShouldAddAll; +	BlockListActionType			mActionType; +	U32							mMuteListSize; + +	// This data is used to save information about item that currently changed(added or removed)  +	LLUUID						mCurItemId; +	std::string					mCurItemName; +	LLMute::EType 				mCurItemType; +	U32							mCurItemFlags; +	std::string					mPrevNameFilter;  }; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 43a733f918..ae0ac57e76 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -60,6 +60,8 @@  #include "llstring.h"  #include "llurlaction.h"  #include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "llmutelist.h"  static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); @@ -181,6 +183,18 @@ public:  		{  			LLAvatarActions::startIM(getAvatarId());  		} +		else if (level == "teleport") +		{ +			LLAvatarActions::offerTeleport(getAvatarId()); +		} +		else if (level == "voice_call") +		{ +			LLAvatarActions::startCall(getAvatarId()); +		} +		else if (level == "chat_history") +		{ +			LLAvatarActions::viewChatHistory(getAvatarId()); +		}  		else if (level == "add")  		{  			LLAvatarActions::requestFriendshipDialog(getAvatarId(), mFrom); @@ -189,13 +203,75 @@ public:  		{  			LLAvatarActions::removeFriendDialog(getAvatarId());  		} +		else if (level == "invite_to_group") +		{ +			LLAvatarActions::inviteToGroup(getAvatarId()); +		} +		else if (level == "zoom_in") +		{ +			handle_zoom_to_object(getAvatarId()); +		} +		else if (level == "map") +		{ +			LLAvatarActions::showOnMap(getAvatarId()); +		} +		else if (level == "share") +		{ +			LLAvatarActions::share(getAvatarId()); +		} +		else if (level == "pay") +		{ +			LLAvatarActions::pay(getAvatarId()); +		} +		else if(level == "block_unblock") +		{ +			mute(getAvatarId(), LLMute::flagVoiceChat); +		} +		else if(level == "mute_unmute") +		{ +			mute(getAvatarId(), LLMute::flagTextChat); +		} +	} + +	bool onAvatarIconContextMenuItemChecked(const LLSD& userdata) +	{ +		std::string level = userdata.asString(); + +		if (level == "is_blocked") +		{ +			return LLMuteList::getInstance()->isMuted(getAvatarId(), LLMute::flagVoiceChat); +		} +		if (level == "is_muted") +		{ +			return LLMuteList::getInstance()->isMuted(getAvatarId(), LLMute::flagTextChat); +		} +		return false; +	} + +	void mute(const LLUUID& participant_id, U32 flags) +	{ +		BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); +		std::string name; +		gCacheName->getFullName(participant_id, name); +		LLMute mute(participant_id, name, LLMute::AGENT); + +		if (!is_muted) +		{ +			LLMuteList::getInstance()->add(mute, flags); +		} +		else +		{ +			LLMuteList::getInstance()->remove(mute, flags); +		}  	}  	BOOL postBuild()  	{  		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;  		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); +		registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));  		registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));  		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -460,7 +536,7 @@ protected:  		if(menu)  		{ -			bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; +			bool is_friend = LLAvatarActions::isFriend(mAvatarID);  			menu->setItemEnabled("Add Friend", !is_friend);  			menu->setItemEnabled("Remove Friend", is_friend); @@ -470,13 +546,34 @@ protected:  				menu->setItemEnabled("Add Friend", false);  				menu->setItemEnabled("Send IM", false);  				menu->setItemEnabled("Remove Friend", false); +				menu->setItemEnabled("Offer Teleport",false); +				menu->setItemEnabled("Voice Call", false); +				menu->setItemEnabled("Invite Group", false); +				menu->setItemEnabled("Zoom In", false); +				menu->setItemEnabled("Share", false); +				menu->setItemEnabled("Pay", false); +				menu->setItemEnabled("Block Unblock", false); +				menu->setItemEnabled("Mute Text", false);  			} - -			if (mSessionID == LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, mAvatarID)) +			else  			{ -				menu->setItemVisible("Send IM", false); +				LLUUID currentSessionID = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, mAvatarID); +				if (mSessionID == currentSessionID) +				{ +					menu->setItemVisible("Send IM", false); +				} +				menu->setItemEnabled("Offer Teleport", LLAvatarActions::canOfferTeleport(mAvatarID)); +				menu->setItemEnabled("Voice Call", LLAvatarActions::canCall()); + +				// We should only show 'Zoom in' item in a nearby chat +				bool should_show_zoom = !LLIMModel::getInstance()->findIMSession(currentSessionID); +				menu->setItemVisible("Zoom In", should_show_zoom && gObjectList.findObject(mAvatarID));	 +				menu->setItemEnabled("Block Unblock", LLAvatarActions::canBlock(mAvatarID)); +				menu->setItemEnabled("Mute Text", LLAvatarActions::canBlock(mAvatarID));  			} +			menu->setItemEnabled("Chat History", LLLogChat::isTranscriptExist(mAvatarID)); +			menu->setItemEnabled("Map", (LLAvatarTracker::instance().isBuddyOnline(mAvatarID) && is_agent_mappable(mAvatarID)) || gAgent.isGodlike() );  			menu->buildDrawLabels();  			menu->updateParent(LLMenuGL::sMenuContainer);  			LLMenuGL::showPopup(this, menu, x, y); @@ -968,25 +1065,42 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	// notify processing  	if (chat.mNotifId.notNull())  	{ -		LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); -		if (notification != NULL) +		bool create_toast = true; +		for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances()) +			, tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti)  		{ -			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( +			LLToastNotifyPanel& panel = *ti; +			LLIMToastNotifyPanel * imtoastp = dynamic_cast<LLIMToastNotifyPanel *>(&panel); +			const std::string& notification_name = panel.getNotificationName(); +			if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled() && imtoastp) +			{ +				create_toast = false; +				break; +			} +		} + +		if (create_toast) +		{ +			LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); +			if (notification != NULL) +			{ +				LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel(  					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor); -			//Prepare the rect for the view -			LLRect target_rect = mEditor->getDocumentView()->getRect(); -			// squeeze down the widget by subtracting padding off left and right -			target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); -			target_rect.mRight -= mRightWidgetPad; -			notify_box->reshape(target_rect.getWidth(),	notify_box->getRect().getHeight()); -			notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); - -			LLInlineViewSegment::Params params; -			params.view = notify_box; -			params.left_pad = mLeftWidgetPad; -			params.right_pad = mRightWidgetPad; -			mEditor->appendWidget(params, "\n", false); +				//Prepare the rect for the view +				LLRect target_rect = mEditor->getDocumentView()->getRect(); +				// squeeze down the widget by subtracting padding off left and right +				target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); +				target_rect.mRight -= mRightWidgetPad; +				notify_box->reshape(target_rect.getWidth(),	notify_box->getRect().getHeight()); +				notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); + +				LLInlineViewSegment::Params params; +				params.view = notify_box; +				params.left_pad = mLeftWidgetPad; +				params.right_pad = mRightWidgetPad; +				mEditor->appendWidget(params, "\n", false); +			}  		}  	} @@ -1016,7 +1130,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		if (square_brackets)  		{  			message += "]"; -	} +		}  		mEditor->appendText(message, prependNewLineState, body_message_params);  		prependNewLineState = false; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 88884042d4..131aea9da3 100755 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -220,18 +220,25 @@ void LLNotificationChiclet::setCounter(S32 counter)  bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )  { -	if (notification->getName() == "ScriptDialog") +	bool displayNotification; +	if (   (notification->getName() == "ScriptDialog") // special case for scripts +		// if there is no toast window for the notification, filter it +		|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID())) +		)  	{ -		return false; +		displayNotification = false;  	} - -	if( !(notification->canLogToIM() && notification->hasFormElements()) -		&& (!notification->getPayload().has("give_inventory_notification") -			|| notification->getPayload()["give_inventory_notification"])) +	else if( !(notification->canLogToIM() && notification->hasFormElements()) +			&& (!notification->getPayload().has("give_inventory_notification") +				|| notification->getPayload()["give_inventory_notification"]))  	{ -		return true; +		displayNotification = true;  	} -	return false; +	else +	{ +		displayNotification = false; +	} +	return displayNotification;  }  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 5ab108b39f..44212298cf 100755 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -313,6 +313,10 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)  	{  		LLAvatarActions::offerTeleport(selected_conversation_participant_id);  	} +	else if ("request_teleport" == command_name) +	{ +		LLAvatarActions::teleportRequest(selected_conversation_participant_id); +	}  	else if("add_friend" == command_name)  	{  		if (!LLAvatarActions::isFriend(selected_conversation_participant_id)) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 192a594c9d..affa24f78c 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -132,6 +132,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9faa12b2ee..82d3fe74c0 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -267,6 +267,23 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )      //This node (conversation) was selected and a child (participant) was not      if(result && getRoot())      { + +		if(getRoot()->getCurSelectedItem() == this) +		{ +			LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); +			LLUUID session_id = item? item->getUUID() : LLUUID(); + +			LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +			if (im_container->isConversationsPaneCollapsed() && im_container->getSelectedSession() == session_id) +			{ +				im_container->collapseMessagesPane(!im_container->isMessagesPaneCollapsed()); +			} +			else +			{ +				im_container->collapseMessagesPane(false); +			} + +		}  		selectConversationItem();      } @@ -318,7 +335,6 @@ void LLConversationViewSession::selectConversationItem()  		LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");  		im_container->flashConversationItemWidget(session_id,false);  		im_container->selectConversationPair(session_id, false); -		im_container->collapseMessagesPane(false);  	}  } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 6c5d229dba..e27dc279f4 100755 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -382,9 +382,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)  			bool is_particle_or_hud_particle = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE  													  || group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; -			bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. -				// All particle systems seem to come off the wire with texture entries which claim that they glow.  This is probably a bug in the data.  Suppress. -				!is_particle_or_hud_particle; +			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow.  			static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");  			LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 369273bca6..ae62be0ad0 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1386,7 +1386,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		}  	} -	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);  #ifdef GL_TRANSFORM_FEEDBACK_BUFFER  	if (use_transform_feedback && @@ -1526,7 +1526,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		}  		glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); -  		gGL.popMatrix();  		if (cur_shader) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 66b5f13740..c9037ce1eb 100755 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -194,7 +194,8 @@ public:  	void		setSize(S32 numVertices, S32 num_indices = 0, bool align = false); -	BOOL		genVolumeBBoxes(const LLVolume &volume, S32 f,const LLMatrix4& mat, BOOL global_volume = FALSE); +	BOOL		genVolumeBBoxes(const LLVolume &volume, S32 f, +									const LLMatrix4& mat_vert_in, BOOL global_volume = FALSE);  	void		init(LLDrawable* drawablep, LLViewerObject* objp);  	void		destroy(); diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp new file mode 100644 index 0000000000..9a20ce8f1b --- /dev/null +++ b/indra/newview/llfacebookconnect.cpp @@ -0,0 +1,582 @@ +/**  + * @file llfacebookconnect.h + * @author Merov, Cho, Gil + * @brief Connection to Facebook Service + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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 "llfacebookconnect.h" + +#include "llagent.h" +#include "llcallingcard.h"			// for LLAvatarTracker +#include "llcommandhandler.h" +#include "llhttpclient.h" +#include "llnotificationsutil.h" +#include "llurlaction.h" +#include "llimagepng.h" +#include "llimagejpeg.h" +#include "lltrans.h" +#include "llevents.h" +#include "llviewerregion.h" + +#include "llfloaterwebcontent.h" +#include "llfloaterreg.h" + +boost::scoped_ptr<LLEventPump> LLFacebookConnect::sStateWatcher(new LLEventStream("FacebookConnectState")); +boost::scoped_ptr<LLEventPump> LLFacebookConnect::sInfoWatcher(new LLEventStream("FacebookConnectInfo")); +boost::scoped_ptr<LLEventPump> LLFacebookConnect::sContentWatcher(new LLEventStream("FacebookConnectContent")); + +// Local functions +void log_facebook_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description) +{ +    // Note: 302 (redirect) is *not* an error that warrants logging +    if (status != 302) +    { +		LL_WARNS("FacebookConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL; +    } +} + +void toast_user_for_success() +{ +	LLSD args; +    args["MESSAGE"] = LLTrans::getString("facebook_post_success"); +    LLNotificationsUtil::add("FacebookConnect", args); +} + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookConnectHandler : public LLCommandHandler +{ +public: +	LLFacebookConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { } +     +	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) +	{ +		if (tokens.size() > 0) +		{ +			if (tokens[0].asString() == "connect") +			{ +				// this command probably came from the fbc_web browser, so close it +				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); +				if (fbc_web) +				{ +					fbc_web->closeFloater(); +				} + +				// connect to facebook +				if (query_map.has("code")) +				{ +                    LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state")); +				} +				return true; +			} +		} +		return false; +	} +}; +LLFacebookConnectHandler gFacebookConnectHandler; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookConnectResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookConnectResponder); +public: +	 +    LLFacebookConnectResponder() +    { +        LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS); +    } +     +	virtual void completed(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (isGoodStatus(status)) +		{ +			LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL; +			 +            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED); +		} +		else if (status != 302) +		{ +            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED); +            log_facebook_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description")); +		} +	} +     +    void completedHeader(U32 status, const std::string& reason, const LLSD& content) +    { +        if (status == 302) +        { +            LLFacebookConnect::instance().openFacebookWeb(content["location"]); +        } +    } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookShareResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookShareResponder); +public: +     +	LLFacebookShareResponder() +	{ +		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTING); +	} +	 +	virtual void completed(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (isGoodStatus(status)) +		{ +            toast_user_for_success(); +			LL_DEBUGS("FacebookConnect") << "Post successful. content: " << content << LL_ENDL; +			 +			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED); +		} +		else if (status == 404) +		{ +			LLFacebookConnect::instance().connectToFacebook(); +		} +		else +		{ +            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POST_FAILED); +            log_facebook_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description")); +		} +	} +     +    void completedHeader(U32 status, const std::string& reason, const LLSD& content) +    { +        if (status == 302) +        { +            LLFacebookConnect::instance().openFacebookWeb(content["location"]); +        } +    } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookDisconnectResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookDisconnectResponder); +public: +  +	LLFacebookDisconnectResponder() +	{ +		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECTING); +	} + +	void setUserDisconnected() +	{ +		// Clear data +		LLFacebookConnect::instance().clearInfo(); +		LLFacebookConnect::instance().clearContent(); +		//Notify state change +		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED); +	} + +	virtual void completed(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (isGoodStatus(status))  +		{ +			LL_DEBUGS("FacebookConnect") << "Disconnect successful. content: " << content << LL_ENDL; +			setUserDisconnected(); + +		} +		//User not found so already disconnected +		else if(status == 404) +		{ +			LL_DEBUGS("FacebookConnect") << "Already disconnected. content: " << content << LL_ENDL; +			setUserDisconnected(); +		} +		else +		{ +			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED); +            log_facebook_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description")); +		} +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookConnectedResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookConnectedResponder); +public: +     +	LLFacebookConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect) +    { +		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS); +    } +     +	virtual void completed(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (isGoodStatus(status)) +		{ +			LL_DEBUGS("FacebookConnect") << "Connect successful. content: " << content << LL_ENDL; +             +            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED); +		} +		else +		{ +			// show the facebook login page if not connected yet +			if (status == 404) +			{ +				if (mAutoConnect) +				{ +					LLFacebookConnect::instance().connectToFacebook(); +				} +				else +				{ +					LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED); +				} +			} +            else +            { +                LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED); +				log_facebook_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description")); +            } +		} +	} +     +private: +	bool mAutoConnect; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookInfoResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookInfoResponder); +public: + +	virtual void completed(U32 status, const std::string& reason, const LLSD& info) +	{ +		if (isGoodStatus(status)) +		{ +			llinfos << "Facebook: Info received" << llendl; +			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << info << LL_ENDL; +			LLFacebookConnect::instance().storeInfo(info); +		} +		else +		{ +			log_facebook_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description")); +		} +	} + +	void completedHeader(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (status == 302) +		{ +			LLFacebookConnect::instance().openFacebookWeb(content["location"]); +		} +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +class LLFacebookFriendsResponder : public LLHTTPClient::Responder +{ +	LOG_CLASS(LLFacebookFriendsResponder); +public: + +	virtual void completed(U32 status, const std::string& reason, const LLSD& content) +	{ +		if (isGoodStatus(status)) +		{ +			LL_DEBUGS("FacebookConnect") << "Getting Facebook friends successful. content: " << content << LL_ENDL; +			LLFacebookConnect::instance().storeContent(content); +		} +		else +		{ +            log_facebook_connect_error("Friends", status, reason, content.get("error_code"), content.get("error_description")); +		} +	} + +    void completedHeader(U32 status, const std::string& reason, const LLSD& content) +    { +        if (status == 302) +        { +            LLFacebookConnect::instance().openFacebookWeb(content["location"]); +        } +    } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +LLFacebookConnect::LLFacebookConnect() +:	mConnectionState(FB_NOT_CONNECTED), +	mConnected(false), +	mInfo(), +    mContent(), +	mRefreshInfo(false), +	mRefreshContent(false), +	mReadFromMaster(false) +{ +} + +void LLFacebookConnect::openFacebookWeb(std::string url) +{ +	// Open the URL in an internal browser window without navigation UI +	LLFloaterWebContent::Params p; +    p.url(url).show_chrome(true); +    p.url(url).allow_address_entry(false); +    p.url(url).allow_back_forward_navigation(false); +    p.url(url).trusted_content(true); +	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p); +	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems). +	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event  +	//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus. +	//fbc_web floater contains the "webbrowser" panel.    JIRA: ACME-744 +	gFocusMgr.setKeyboardFocus( floater ); + +	//LLUrlAction::openURLExternal(url); +} + +std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, bool include_read_from_master) +{ +    std::string url(""); +    LLViewerRegion *regionp = gAgent.getRegion(); +    if (regionp) +    { +        url = regionp->getCapability("FacebookConnect"); +        url += route; +     +        if (include_read_from_master && mReadFromMaster) +        { +            url += "?read_from_master=true"; +        } +    } +	return url; +} + +void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state) +{ +	LLSD body; +	if (!auth_code.empty()) +		body["code"] = auth_code; +	if (!auth_state.empty()) +		body["state"] = auth_state; +     +	LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder()); +} + +void LLFacebookConnect::disconnectFromFacebook() +{ +	LLHTTPClient::del(getFacebookConnectURL("/connection"), new LLFacebookDisconnectResponder()); +} + +void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect) +{ +	const bool follow_redirects = false; +	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; +	LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect), +						LLSD(), timeout, follow_redirects); +} + +void LLFacebookConnect::loadFacebookInfo() +{ +	if(mRefreshInfo) +	{ +		const bool follow_redirects = false; +		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; +		LLHTTPClient::get(getFacebookConnectURL("/info", true), new LLFacebookInfoResponder(), +			LLSD(), timeout, follow_redirects); +	} +} + +void LLFacebookConnect::loadFacebookFriends() +{ +	if(mRefreshContent) +	{ +		const bool follow_redirects = false; +		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; +		LLHTTPClient::get(getFacebookConnectURL("/friends", true), new LLFacebookFriendsResponder(), +			LLSD(), timeout, follow_redirects); +	} +} + +void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& image, const std::string& message) +{ +	LLSD body; +	if (!location.empty()) +		body["location"] = location; +	if (!name.empty()) +		body["name"] = name; +	if (!description.empty()) +		body["description"] = description; +	if (!image.empty()) +		body["image"] = image; +	if (!message.empty()) +		body["message"] = message; + +	// Note: we can use that route for different publish action. We should be able to use the same responder. +	LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder()); +} + +void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption) +{ +	LLSD body; +	body["image"] = image_url; +	body["caption"] = caption; +	 +    // Note: we can use that route for different publish action. We should be able to use the same responder. +	LLHTTPClient::post(getFacebookConnectURL("/share/photo", true), body, new LLFacebookShareResponder()); +} + +void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption) +{ +	std::string imageFormat; +	if (dynamic_cast<LLImagePNG*>(image.get())) +	{ +		imageFormat = "png"; +	} +	else if (dynamic_cast<LLImageJPEG*>(image.get())) +	{ +		imageFormat = "jpg"; +	} +	else +	{ +		llwarns << "Image to upload is not a PNG or JPEG" << llendl; +		return; +	} +	 +	// All this code is mostly copied from LLWebProfile::post() +	const std::string boundary = "----------------------------0123abcdefab"; + +	LLSD headers; +	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + +	std::ostringstream body; + +	// *NOTE: The order seems to matter. +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"caption\"\r\n\r\n" +			<< caption << "\r\n"; + +	body	<< "--" << boundary << "\r\n" +			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n" +			<< "Content-Type: image/" << imageFormat << "\r\n\r\n"; + +	// Insert the image data. +	// *FIX: Treating this as a string will probably screw it up ... +	U8* image_data = image->getData(); +	for (S32 i = 0; i < image->getDataSize(); ++i) +	{ +		body << image_data[i]; +	} + +	body <<	"\r\n--" << boundary << "--\r\n"; + +	// postRaw() takes ownership of the buffer and releases it later. +	size_t size = body.str().size(); +	U8 *data = new U8[size]; +	memcpy(data, body.str().data(), size); +	 +    // Note: we can use that route for different publish action. We should be able to use the same responder. +	LLHTTPClient::postRaw(getFacebookConnectURL("/share/photo", true), data, size, new LLFacebookShareResponder(), headers); +} + +void LLFacebookConnect::updateStatus(const std::string& message) +{ +	LLSD body; +	body["message"] = message; +	 +    // Note: we can use that route for different publish action. We should be able to use the same responder. +	LLHTTPClient::post(getFacebookConnectURL("/share/wall", true), body, new LLFacebookShareResponder()); +} + +void LLFacebookConnect::storeInfo(const LLSD& info) +{ +	mInfo = info; +	mRefreshInfo = false; + +	sInfoWatcher->post(info); +} + +const LLSD& LLFacebookConnect::getInfo() const +{ +	return mInfo; +} + +void LLFacebookConnect::clearInfo() +{ +	mInfo = LLSD(); +} + +void LLFacebookConnect::storeContent(const LLSD& content) +{ +    mContent = content; +	mRefreshContent = false; + +	sContentWatcher->post(content); +} + +const LLSD& LLFacebookConnect::getContent() const +{ +    return mContent; +} + +void LLFacebookConnect::clearContent() +{ +    mContent = LLSD(); +} + +void LLFacebookConnect::setDataDirty() +{ +	mRefreshInfo = true; +	mRefreshContent = true; +} + +void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState connection_state) +{ +	if(connection_state == FB_CONNECTED) +	{ +		mReadFromMaster = true; +		setConnected(true); +		setDataDirty(); +	} +	else if(connection_state == FB_NOT_CONNECTED) +	{ +		setConnected(false); +	} +	else if(connection_state == FB_POSTED) +	{ +		mReadFromMaster = false; +	} + +	if (mConnectionState != connection_state) +	{ +		LLSD state_info; +		state_info["enum"] = connection_state; +		sStateWatcher->post(state_info); +	} +	 +	mConnectionState = connection_state; +} + +void LLFacebookConnect::setConnected(bool connected) +{ +	mConnected = connected; +} diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h new file mode 100644 index 0000000000..a77ac24167 --- /dev/null +++ b/indra/newview/llfacebookconnect.h @@ -0,0 +1,106 @@ +/**  + * @file llfacebookconnect.h + * @author Merov, Cho, Gil + * @brief Connection to Facebook Service + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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_LLFACEBOOKCONNECT_H +#define LL_LLFACEBOOKCONNECT_H + +#include "llsingleton.h" +#include "llimage.h" + +class LLEventPump; + +/** + * @class LLFacebookConnect + * + * Manages authentication to, and interaction with, a web service allowing the + * the viewer to get Facebook OpenGraph data. + */ +class LLFacebookConnect : public LLSingleton<LLFacebookConnect> +{ +	LOG_CLASS(LLFacebookConnect); +public: +    enum EConnectionState +	{ +		FB_NOT_CONNECTED = 0, +		FB_CONNECTION_IN_PROGRESS = 1, +		FB_CONNECTED = 2, +		FB_CONNECTION_FAILED = 3, +		FB_POSTING = 4, +		FB_POSTED = 5, +		FB_POST_FAILED = 6, +		FB_DISCONNECTING = 7, +		FB_DISCONNECT_FAILED = 8 +	}; +	 +	void connectToFacebook(const std::string& auth_code = "", const std::string& auth_state = "");	// Initiate the complete FB connection. Please use checkConnectionToFacebook() in normal use. +	void disconnectFromFacebook();																	// Disconnect from the FBC service. +    void checkConnectionToFacebook(bool auto_connect = false);										// Check if an access token is available on the FBC service. If not, call connectToFacebook(). +     +	void loadFacebookInfo(); +    void loadFacebookFriends(); +	void postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& picture, const std::string& message); +    void sharePhoto(const std::string& image_url, const std::string& caption); +	void sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption); +	void updateStatus(const std::string& message); +	 +	void storeInfo(const LLSD& info); +	const LLSD& getInfo() const; +	void clearInfo(); +	void storeContent(const LLSD& content); +    const LLSD& getContent() const; +	void clearContent(); +	void setDataDirty(); +     +    void setConnectionState(EConnectionState connection_state); +	void setConnected(bool connected); +	bool isConnected() { return mConnected; } +	bool isTransactionOngoing() { return ((mConnectionState == FB_CONNECTION_IN_PROGRESS) || (mConnectionState == FB_POSTING) || (mConnectionState == FB_DISCONNECTING)); } +    EConnectionState getConnectionState() { return mConnectionState; } +     +    void openFacebookWeb(std::string url); + +private: +	friend class LLSingleton<LLFacebookConnect>; + +	LLFacebookConnect(); +	~LLFacebookConnect() {}; + 	std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false); +    +    EConnectionState mConnectionState; +	BOOL mConnected; +	LLSD mInfo; +    LLSD mContent; +	bool mRefreshInfo; +	bool mRefreshContent; +	bool mReadFromMaster; +	 +	static boost::scoped_ptr<LLEventPump> sStateWatcher; +	static boost::scoped_ptr<LLEventPump> sInfoWatcher; +	static boost::scoped_ptr<LLEventPump> sContentWatcher; +}; + +#endif // LL_LLFACEBOOKCONNECT_H diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 8e1a1df211..06119620de 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1545,7 +1545,7 @@ void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::  		return ;  	}  } -void	LLFastTimerView::onClickCloseBtn() +void	LLFastTimerView::onClickCloseBtn(bool)  {  	setVisible(false);  } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 5766cfa0b0..1349b1e99c 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -63,7 +63,7 @@ public:  	F64 getTime(const std::string& name);  protected: -	virtual	void	onClickCloseBtn(); +	virtual	void	onClickCloseBtn(bool app_quitting = false);  private:	  	typedef std::vector<std::vector<S32> > bar_positions_t;  	bar_positions_t mBarStart; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index c151b51c23..16eacc9392 100755 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -422,6 +422,19 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)  			L"PNG Images (*.png)\0*.png\0" \  			L"\0";  		break; +	case FFSAVE_TGAPNG: +		if (filename.empty()) +		{ +			wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE);	/*Flawfinder: ignore*/ +			//PNG by default +		} +		mOFN.lpstrDefExt = L"png"; +		mOFN.lpstrFilter = +			L"PNG Images (*.png)\0*.png\0" \ +			L"Targa Images (*.tga)\0*.tga\0" \ +			L"\0"; +		break; +		  	case FFSAVE_JPEG:  		if (filename.empty())  		{ @@ -640,13 +653,16 @@ bool	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena  			creator = "TVOD";  			extension = "wav";  			break; -		  		case FFSAVE_TGA:  			type = "TPIC";  			creator = "prvw";  			extension = "tga";  			break; -		 +		case FFSAVE_TGAPNG: +			type = "PNG"; +			creator = "prvw"; +			extension = "png"; +			break;  		case FFSAVE_BMP:  			type = "BMPf";  			creator = "prvw"; @@ -921,6 +937,22 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer  		g_slist_free (file_list);  	} +	// let's save the extension of the last added file(considering current filter) +	GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget)); +	if(gfilter) +	{ +		std::string filter = gtk_file_filter_get_name(gfilter); + +		if(filter == LLTrans::getString("png_image_files")) +		{ +			picker->mCurrentExtension = ".png"; +		} +		else if(filter == LLTrans::getString("targa_image_files")) +		{ +			picker->mCurrentExtension = ".tga"; +		} +	} +  	// set the default path for this usage context.  	const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));  	if (cur_folder != NULL) @@ -1092,6 +1124,24 @@ static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)  							LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");  } +static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker) +{ +	GtkFileFilter *gfilter_tga = gtk_file_filter_new(); +	GtkFileFilter *gfilter_png = gtk_file_filter_new(); + +	gtk_file_filter_add_pattern(gfilter_tga, "*.tga"); +	gtk_file_filter_add_mime_type(gfilter_png, "image/png"); +	std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)"; +	gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str()); +	gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str()); + +	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), +					gfilter_png); +	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), +					gfilter_tga); +	return caption; +} +  BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )  {  	BOOL rtn = FALSE; @@ -1129,6 +1179,15 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename  				(picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)");  			suggest_ext = ".bmp";  			break; +		case FFSAVE_PNG: +			caption += add_simple_mime_filter_to_gtkchooser +				(picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)"); +			suggest_ext = ".png"; +			break; +		case FFSAVE_TGAPNG: +			caption += add_save_texture_filter_to_gtkchooser(picker); +			suggest_ext = ".png"; +			break;  		case FFSAVE_AVI:  			caption += add_simple_mime_filter_to_gtkchooser  				(picker, "video/x-msvideo", @@ -1181,9 +1240,17 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename  		}  		gtk_widget_show_all(GTK_WIDGET(picker)); +  		gtk_main();  		rtn = (getFileCount() == 1); + +		if(rtn && filter == FFSAVE_TGAPNG) +		{ +			std::string selected_file = mFiles.back(); +			mFiles.pop_back(); +			mFiles.push_back(selected_file + mCurrentExtension); +		}  	}  	gViewerWindow->getWindow()->afterDialog(); diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 0d279f73f3..f0f82c51db 100755 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -107,6 +107,7 @@ public:  		FFSAVE_PNG = 13,  		FFSAVE_JPEG = 14,  		FFSAVE_SCRIPT = 15, +		FFSAVE_TGAPNG = 16  	};  	// open the dialog. This is a modal operation @@ -175,6 +176,8 @@ private:  	// we remember the last path that was accessed for a particular usage  	std::map <std::string, std::string> mContextToPathMap;  	std::string mCurContextName; +	// we also remember the extension of the last added file. +	std::string mCurrentExtension;  #endif  	std::vector<std::string> mFiles; diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 4a85160f95..5041f4689d 100755 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -44,7 +44,8 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i  	mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")),  	mAccountName(session_id[LL_FCP_ACCOUNT_NAME]),  	mCompleteName(session_id[LL_FCP_COMPLETE_NAME]), -	mMutex(NULL) +	mMutex(NULL), +	mShowHistory(false)  {  } @@ -91,12 +92,11 @@ BOOL LLFloaterConversationPreview::postBuild()  	mPageSpinner->setMinValue(1);  	mPageSpinner->set(1);  	mPageSpinner->setEnabled(false); -	mChatHistoryLoaded = false;  	LLLogChat::startChatHistoryThread(file, load_params);  	return LLFloater::postBuild();  } -void LLFloaterConversationPreview::setPages(std::list<LLSD>& messages,const std::string& file_name) +void LLFloaterConversationPreview::setPages(std::list<LLSD>& messages, const std::string& file_name)  {  	if(file_name == mChatHistoryFileName)  	{ @@ -111,34 +111,30 @@ void LLFloaterConversationPreview::setPages(std::list<LLSD>& messages,const std:  		std::string total_page_num = llformat("/ %d", mCurrentPage+1);  		getChild<LLTextBox>("page_num_label")->setValue(total_page_num); -		mChatHistoryLoaded = true; +		mShowHistory = true;  	}  }  void LLFloaterConversationPreview::draw()  { -	if(mChatHistoryLoaded) +	if(mShowHistory)  	{  		showHistory(); -		mChatHistoryLoaded = false; +		mShowHistory = false;  	}  	LLFloater::draw();  }  void LLFloaterConversationPreview::onOpen(const LLSD& key)  { -	if(mChatHistoryLoaded) -	{ -		showHistory(); -	} +	mShowHistory = true;  }  void LLFloaterConversationPreview::showHistory()  { -	// additional protection to avoid changes of mMessages in setPages() +	// additional protection to avoid changes of mMessages in setPages  	LLMutexLock lock(&mMutex); - -	if (!mMessages.size() || mCurrentPage * mPageSize >= mMessages.size()) +	if(!mMessages.size() || mCurrentPage * mPageSize >= mMessages.size())  	{  		return;  	} @@ -147,7 +143,7 @@ void LLFloaterConversationPreview::showHistory()  	std::ostringstream message;  	std::list<LLSD>::const_iterator iter = mMessages.begin();  	std::advance(iter, mCurrentPage * mPageSize); - +	  	for (int msg_num = 0; iter != mMessages.end() && msg_num < mPageSize; ++iter, ++msg_num)  	{  		LLSD msg = *iter; @@ -198,10 +194,11 @@ void LLFloaterConversationPreview::showHistory()  void LLFloaterConversationPreview::onMoreHistoryBtnClick()  {  	mCurrentPage = (int)(mPageSpinner->getValueF32()); -	if (--mCurrentPage < 0) +	if (!mCurrentPage)  	{  		return;  	} -	showHistory(); +	mCurrentPage--; +	mShowHistory = true;  } diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index f8796127ba..b0488f4ff1 100755 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -62,7 +62,7 @@ private:  	std::string		mAccountName;  	std::string		mCompleteName;  	std::string     mChatHistoryFileName; -	bool			mChatHistoryLoaded; +	bool			mShowHistory;  };  #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp index 49da4e64b3..d0f3289769 100755 --- a/indra/newview/llfloatergroupinvite.cpp +++ b/indra/newview/llfloatergroupinvite.cpp @@ -30,6 +30,8 @@  #include "llpanelgroupinvite.h"  #include "lltrans.h"  #include "lldraghandle.h" +#include "llagent.h" +#include "llgroupmgr.h"  class LLFloaterGroupInvite::impl  { @@ -123,6 +125,12 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, uuid_vec_t *agen  	LLFloaterGroupInvite *fgi = get_if_there(impl::sInstances,  											 group_id,  											 (LLFloaterGroupInvite*)NULL); + +	// refresh group information +	gAgent.sendAgentDataUpdateRequest(); +	LLGroupMgr::getInstance()->clearGroupData(group_id); + +  	if (!fgi)  	{  		fgi = new LLFloaterGroupInvite(group_id); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2c3b34e128..b5aa309066 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -101,6 +101,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer()  	gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed());  	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); +	gSavedPerAccountSettings.setBOOL("ConversationsParticipantListCollapsed", !isParticipantListExpanded());  	if (!LLSingleton<LLIMMgr>::destroyed())  	{ @@ -250,6 +251,11 @@ BOOL LLFloaterIMContainer::postBuild()  	// Init the sort order now that the root had been created  	setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); +	//We should expand nearby chat participants list for the new user +	if(gAgent.isFirstLogin() || !gSavedPerAccountSettings.getBOOL("ConversationsParticipantListCollapsed")) +	{ +		expandConversation(); +	}  	// Keep the xml set title around for when we have to overwrite it  	mGeneralTitle = getTitle(); @@ -662,10 +668,10 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  			LLFloater* session_floater = widget->getSessionFloater();  			if (session_floater != nearby_chat)  			{ -				widget->setVisibleIfDetached(visible); -			} +		    widget->setVisibleIfDetached(visible);  		}  	} +	}  	// Now, do the normal multifloater show/hide  	LLMultiFloater::setVisible(visible); @@ -700,13 +706,13 @@ void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& k  	// Only select other sessions  	if (!getSelectedSession().isNull())  	{ -		selectConversationPair(getSelectedSession(), false, take_focus); +    selectConversationPair(getSelectedSession(), false, take_focus);  	}  	if (mInitialized && mIsFirstLaunch)  	{  		collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));  		mIsFirstLaunch = false; -	} +}  }  void LLFloaterIMContainer::updateResizeLimits() @@ -715,6 +721,16 @@ void LLFloaterIMContainer::updateResizeLimits()  	assignResizeLimits();  } +bool LLFloaterIMContainer::isMessagesPaneCollapsed() +{ +	return mMessagesPane->isCollapsed(); +} + +bool LLFloaterIMContainer::isConversationsPaneCollapsed() +{ +	return mConversationsPane->isCollapsed(); +} +  void LLFloaterIMContainer::collapseMessagesPane(bool collapse)  {  	if (mMessagesPane->isCollapsed() == collapse) @@ -784,8 +800,8 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse, bool save_is  		mConversationsPane->setTargetDim(gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"));  	} -	S32 delta_width = -			gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); +	S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth")  +		- mConversationsPane->getMinDim() - mConversationsStack->getPanelSpacing() + 1;  	reshapeFloaterAndSetResizeLimits(collapse, delta_width); @@ -834,7 +850,7 @@ void LLFloaterIMContainer::assignResizeLimits()  	S32 conv_pane_target_width = is_conv_pane_expanded  		? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() ) -		: mConversationsPane->getMinDim(); +			: mConversationsPane->getMinDim();  	S32 msg_pane_min_width  = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;  	S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; @@ -995,7 +1011,7 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order)  			conversation_floater->setSortOrder(order);  		}  	} - +	  	gSavedSettings.setU32("ConversationSortOrder", (U32)order);  } @@ -1080,6 +1096,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec  		{  			LLAvatarActions::offerTeleport(selectedIDS);  		} +		else if ("request_teleport" == command) +		{ +			LLAvatarActions::teleportRequest(selectedIDS.front()); +		}  		else if ("voice_call" == command)  		{  			LLAvatarActions::startCall(userID); @@ -1182,7 +1202,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          }          else if("chat_history" == command)          { -        	if (selectedIDS.size() > 0) +			if (selectedIDS.size() > 0)  			{  				LLAvatarActions::viewChatHistory(selectedIDS.front());  			} @@ -1204,7 +1224,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,      	    {      	      	LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);      	    } -    	} +}      }  } @@ -1235,7 +1255,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)      if (action == "group_profile")      { -    	LLGroupActions::show(mSelectedSession); +        LLGroupActions::show(mSelectedSession);      }      else if (action == "activate_group")      { @@ -2082,6 +2102,19 @@ void LLFloaterIMContainer::expandConversation()  		}  	}  } +bool LLFloaterIMContainer::isParticipantListExpanded() +{ +	bool is_expanded = false; +	if(!mConversationsPane->isCollapsed()) +	{ +		LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession())); +		if (widget) +		{ +			is_expanded = widget->isOpen(); +		} +	} +	return is_expanded; +}  // By default, if torn off session is currently frontmost, LLFloater::isFrontmost() will return FALSE, which can lead to some bugs  // So LLFloater::isFrontmost() is overriden here to check both selected session and the IM floater itself @@ -2098,7 +2131,7 @@ BOOL LLFloaterIMContainer::isFrontmost()  // For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation.  // This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater. -void LLFloaterIMContainer::onClickCloseBtn() +void LLFloaterIMContainer::onClickCloseBtn(bool app_quitting/* = false*/)  {  	// Always unminimize before trying to close.  	// Most of the time the user will never see this state. @@ -2107,7 +2140,7 @@ void LLFloaterIMContainer::onClickCloseBtn()  		LLMultiFloater::setMinimized(FALSE);  	} -	LLFloater::closeFloater(); +	LLFloater::closeFloater(app_quitting);  }  void LLFloaterIMContainer::closeHostedFloater() @@ -2154,7 +2187,7 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)  	if(app_quitting)  	{  		closeAllConversations(); -		onClickCloseBtn(); +		onClickCloseBtn(app_quitting);  	}  	else  	{ diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 36da457cac..f6d973b9b3 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -90,6 +90,8 @@ public:  	static void onCurrentChannelChanged(const LLUUID& session_id);  	void collapseMessagesPane(bool collapse); +	bool isMessagesPaneCollapsed(); +	bool isConversationsPaneCollapsed();  	// Callbacks  	static void idle(void* user_data); @@ -134,7 +136,7 @@ private:  	void onStubCollapseButtonClicked();  	void processParticipantsStyleUpdate();  	void onSpeakButtonClicked(); -	/*virtual*/ void onClickCloseBtn(); +	/*virtual*/ void onClickCloseBtn(bool app_quitting = false);  	/*virtual*/ void closeHostedFloater();  	void collapseConversationsPane(bool collapse, bool save_is_allowed=true); @@ -172,6 +174,7 @@ private:  	void toggleAllowTextChat(const LLUUID& participant_uuid);  	void toggleMute(const LLUUID& participant_id, U32 flags);  	void openNearbyChat(); +	bool isParticipantListExpanded();  	LLButton* mExpandCollapseBtn;  	LLButton* mStubCollapseBtn; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 3d77ea4f0b..323e84751f 100755 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -308,7 +308,8 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)  }  // virtual -void LLFloaterIMNearbyChat::onClickCloseBtn() +void LLFloaterIMNearbyChat::onClickCloseBtn(bool) +  {  	if (!isTornOff())  	{ @@ -493,11 +494,11 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()  			if (!rest_of_match.empty())  			{  				mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part -  				// Select to end of line, starting from the character  				// after the last one the user typed. -				mInputEditor->selectNext(rest_of_match, false); +				mInputEditor->selectByCursorPosition(utf8_out_str.size()-rest_of_match.size(),utf8_out_str.size());  			} +  		}  		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))  		{ diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 05b48cccb0..f0daacd6a9 100755 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -95,7 +95,7 @@ protected:  	void onChatFontChange(LLFontGL* fontp);  	/*virtual*/ void onTearOffClicked(); -	/*virtual*/ void onClickCloseBtn(); +	/*virtual*/ void onClickCloseBtn(bool app_qutting = false);  	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel);  	EChatType processChatTypeTriggers(EChatType type, std::string &str); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 5cb9df5625..14e1a486d3 100755 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -112,7 +112,7 @@ void LLFloaterIMSession::onTearOffClicked()  }  // virtual -void LLFloaterIMSession::onClickCloseBtn() +void LLFloaterIMSession::onClickCloseBtn(bool)  {  	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index a0e0171b34..d6718843ca 100755 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -141,7 +141,7 @@ private:  	/*virtual*/ void refresh();      /*virtual*/ void onTearOffClicked(); -	/*virtual*/ void onClickCloseBtn(); +	/*virtual*/ void onClickCloseBtn(bool app_qutting);  	// Update the window title and input field help text  	/*virtual*/ void updateSessionName(const std::string& name); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 6ef4d8717d..2b9c216e54 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2097,7 +2097,6 @@ void LLPanelLandOptions::refresh()  // virtual  void LLPanelLandOptions::draw()  { -	refreshSearch();	// Is this necessary?  JC  	LLPanel::draw();  } @@ -2111,9 +2110,8 @@ void LLPanelLandOptions::refreshSearch()  		mCheckShowDirectory->set(FALSE);  		mCheckShowDirectory->setEnabled(FALSE); -		// *TODO:Translate -		const std::string& none_string = LLParcel::getCategoryUIString(LLParcel::C_NONE); -		mCategoryCombo->setSimple(none_string); +		const std::string& none_string = LLParcel::getCategoryString(LLParcel::C_NONE); +		mCategoryCombo->setValue(none_string);  		mCategoryCombo->setEnabled(FALSE);  		return;  	} @@ -2140,10 +2138,9 @@ void LLPanelLandOptions::refreshSearch()  	mCheckShowDirectory	->set(show_directory);  	// Set by string in case the order in UI doesn't match the order by index. -	// *TODO:Translate  	LLParcel::ECategory cat = parcel->getCategory(); -	const std::string& category_string = LLParcel::getCategoryUIString(cat); -	mCategoryCombo->setSimple(category_string); +	const std::string& category_string = LLParcel::getCategoryString(cat); +	mCategoryCombo->setValue(category_string);  	std::string tooltip;  	bool enable_show_directory = false; @@ -2377,7 +2374,7 @@ void LLPanelLandAccess::refresh()  	{  		BOOL use_access_list = parcel->getParcelFlag(PF_USE_ACCESS_LIST);  		BOOL use_group = parcel->getParcelFlag(PF_USE_ACCESS_GROUP); -		BOOL public_access = !use_access_list && !use_group; +		BOOL public_access = !use_access_list;  		getChild<LLUICtrl>("public_access")->setValue(public_access );  		getChild<LLUICtrl>("GroupCheck")->setValue(use_group ); @@ -2544,7 +2541,11 @@ void LLPanelLandAccess::refresh_ui()  	getChildView("HoursSpin")->setEnabled(FALSE);  	getChildView("AccessList")->setEnabled(FALSE);  	getChildView("BannedList")->setEnabled(FALSE); -	 +	getChildView("add_allowed")->setEnabled(FALSE); +	getChildView("remove_allowed")->setEnabled(FALSE); +	getChildView("add_banned")->setEnabled(FALSE); +	getChildView("remove_banned")->setEnabled(FALSE); +  	LLParcel *parcel = mParcel->getParcel();  	if (parcel)  	{ @@ -2582,7 +2583,6 @@ void LLPanelLandAccess::refresh_ui()  			{  				getChildView("Only Allow")->setToolTip(std::string());  			} -			getChildView("GroupCheck")->setEnabled(FALSE);  			getChildView("PassCheck")->setEnabled(FALSE);  			getChildView("pass_combo")->setEnabled(FALSE);  			getChildView("AccessList")->setEnabled(FALSE); @@ -2592,11 +2592,7 @@ void LLPanelLandAccess::refresh_ui()  			getChildView("limit_payment")->setEnabled(FALSE);  			getChildView("limit_age_verified")->setEnabled(FALSE); -			std::string group_name; -			if (gCacheName->getGroupName(parcel->getGroupID(), group_name)) -			{			 -				getChildView("GroupCheck")->setEnabled(can_manage_allowed); -			} +  			BOOL group_access = getChild<LLUICtrl>("GroupCheck")->getValue().asBoolean();  			BOOL sell_passes = getChild<LLUICtrl>("PassCheck")->getValue().asBoolean();  			getChildView("PassCheck")->setEnabled(can_manage_allowed); @@ -2607,6 +2603,11 @@ void LLPanelLandAccess::refresh_ui()  				getChildView("HoursSpin")->setEnabled(can_manage_allowed);  			}  		} +		std::string group_name; +		if (gCacheName->getGroupName(parcel->getGroupID(), group_name)) +		{ +			getChildView("GroupCheck")->setEnabled(can_manage_allowed); +		}  		getChildView("AccessList")->setEnabled(can_manage_allowed);  		S32 allowed_list_count = parcel->mAccessList.size();  		getChildView("add_allowed")->setEnabled(can_manage_allowed && allowed_list_count < PARCEL_MAX_ACCESS_LIST); @@ -2652,17 +2653,6 @@ void LLPanelLandAccess::onCommitPublicAccess(LLUICtrl *ctrl, void *userdata)  	{  		return;  	} - -	// If we disabled public access, enable group access by default (if applicable) -	BOOL public_access = self->getChild<LLUICtrl>("public_access")->getValue().asBoolean(); -	if (public_access == FALSE) -	{ -		std::string group_name; -		if (gCacheName->getGroupName(parcel->getGroupID(), group_name)) -		{ -			self->getChild<LLUICtrl>("GroupCheck")->setValue(public_access ? FALSE : TRUE); -		} -	}  	onCommitAny(ctrl, userdata);  } @@ -2697,7 +2687,6 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)  	if (public_access)  	{  		use_access_list = FALSE; -		use_access_group = FALSE;  		limit_payment = self->getChild<LLUICtrl>("limit_payment")->getValue().asBoolean();  		limit_age_verified = self->getChild<LLUICtrl>("limit_age_verified")->getValue().asBoolean();  	} diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 1969435ba1..87ae36716d 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -618,9 +618,12 @@ void LLFloaterPreference::cancel()  	// hide translation settings floater  	LLFloaterReg::hideInstance("prefs_translation"); -	// hide translation settings floater +	// hide autoreplace settings floater  	LLFloaterReg::hideInstance("prefs_autoreplace"); +	// hide spellchecker settings folder +	LLFloaterReg::hideInstance("prefs_spellchecker"); +	  	// cancel hardware menu  	LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings");  	if (hardware_settings) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 50c013a49d..66bf49331b 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1734,7 +1734,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)  			LLSD args;  			args["NUM_ADDED"] = llformat("%d",ids.size());  			args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); -			args["LIST_TYPE"] = "Allowed Residents"; +			args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");  			args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);  			LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);  			delete change_info; @@ -1750,7 +1750,7 @@ void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)  			LLSD args;  			args["NUM_ADDED"] = llformat("%d",ids.size());  			args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); -			args["LIST_TYPE"] = "Banned Residents"; +			args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");  			args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);  			LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);  			delete change_info; @@ -2815,9 +2815,10 @@ bool LLDispatchSetEstateAccess::operator()(  		} -		std::string msg = llformat("Banned residents: (%d, max %d)", -									totalBannedAgents, -									ESTATE_MAX_ACCESS_IDS); +		LLStringUtil::format_map_t args; +		args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents); +		args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); +		std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);  		panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));  		if (banned_agent_name_list) @@ -2837,9 +2838,10 @@ bool LLDispatchSetEstateAccess::operator()(  	if (access_flags & ESTATE_ACCESS_MANAGERS)  	{ -		std::string msg = llformat("Estate Managers: (%d, max %d)", -									num_estate_managers, -									ESTATE_MAX_MANAGERS); +		LLStringUtil::format_map_t args; +		args["[ESTATEMANAGERS]"] = llformat("%d", num_estate_managers); +		args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); +		std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);  		panel->getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));  		LLNameListCtrl* estate_manager_name_list = diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5f9556a870..c5248719e9 100755 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -57,7 +57,7 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key)  	getChild<LLPanel>(sMainPanelName)->onOpen(key);  } -void LLFloaterSidePanelContainer::onClickCloseBtn() +void LLFloaterSidePanelContainer::onClickCloseBtn(bool)  {  	LLPanelOutfitEdit* panel_outfit_edit =  		dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 491723471f..65ec8f604e 100755 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -51,7 +51,7 @@ public:  	/*virtual*/ void onOpen(const LLSD& key); -	/*virtual*/ void onClickCloseBtn(); +	/*virtual*/ void onClickCloseBtn(bool app_quitting = false);  	LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index d8d62e5bbb..ea385d7baf 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -28,60 +28,23 @@  #include "llfloatersnapshot.h" -#include "llfloaterreg.h" - -// Viewer includes  #include "llagent.h" -#include "llagentcamera.h" -#include "llcallbacklist.h" -#include "llcriticaldamp.h" -#include "llfloaterperms.h" -#include "llui.h" -#include "llfocusmgr.h" -#include "llbutton.h" +#include "llfacebookconnect.h" +#include "llfloaterreg.h" +#include "llfloatersocial.h" +#include "llcheckboxctrl.h"  #include "llcombobox.h" -#include "lleconomy.h" -#include "lllandmarkactions.h" -#include "llpanelsnapshot.h" +#include "llpostcard.h" +#include "llresmgr.h"		// LLLocale +#include "llsdserialize.h"  #include "llsidetraypanelcontainer.h" -#include "llsliderctrl.h" +#include "llsnapshotlivepreview.h"  #include "llspinctrl.h"  #include "llviewercontrol.h" -#include "lluictrlfactory.h" -#include "llviewerstats.h" -#include "llviewercamera.h" -#include "llviewerwindow.h" -#include "llviewermenufile.h"	// upload_new_resource() -#include "llcheckboxctrl.h" -#include "llslurl.h"  #include "lltoolfocus.h"  #include "lltoolmgr.h" -#include "llwebsharing.h" -#include "llworld.h" -#include "llagentui.h" - -// Linden library includes -#include "llfontgl.h" -#include "llsys.h" -#include "llrender.h" -#include "v3dmath.h" -#include "llmath.h" -#include "lldir.h" -#include "llsdserialize.h" -#include "llgl.h" -#include "llglheaders.h" -#include "llimagejpeg.h" -#include "llimagepng.h" -#include "llimagebmp.h" -#include "llimagej2c.h" -#include "lllocalcliprect.h" -#include "llnotificationsutil.h" -#include "llpostcard.h" -#include "llresmgr.h"		// LLLocale -#include "llvfile.h" -#include "llvfs.h"  #include "llwebprofile.h" -#include "llwindow.h" +#include "llwebsharing.h"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs @@ -91,949 +54,12 @@ LLSnapshotFloaterView* gSnapshotFloaterView = NULL;  const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; -F32 SHINE_TIME = 0.5f; -F32 SHINE_WIDTH = 0.6f; -F32 SHINE_OPACITY = 0.3f; -F32 FALL_TIME = 0.6f; -S32 BORDER_WIDTH = 6; -  const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte  const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512  static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view"); -///---------------------------------------------------------------------------- -/// Class LLSnapshotLivePreview  -///---------------------------------------------------------------------------- -class LLSnapshotLivePreview : public LLView -{ -	LOG_CLASS(LLSnapshotLivePreview); -public: -	enum ESnapshotType -	{ -		SNAPSHOT_POSTCARD, -		SNAPSHOT_TEXTURE, -		SNAPSHOT_LOCAL, -		SNAPSHOT_WEB -	}; - - -	struct Params : public LLInitParam::Block<Params, LLView::Params> -	{ -		Params() -		{ -			name = "snapshot_live_preview"; -			mouse_opaque = false; -		} -	}; - - -	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p); -	~LLSnapshotLivePreview(); - -	/*virtual*/ void draw(); -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); -	 -	void setSize(S32 w, S32 h); -	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; } -	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; } -	void getSize(S32& w, S32& h) const; -	S32 getWidth() const { return mWidth[mCurImageIndex]; } -	S32 getHeight() const { return mHeight[mCurImageIndex]; } -	S32 getDataSize() const { return mDataSize; } -	void setMaxImageSize(S32 size) ; -	S32  getMaxImageSize() {return mMaxImageSize ;} -	 -	ESnapshotType getSnapshotType() const { return mSnapshotType; } -	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } -	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; } -	BOOL isSnapshotActive() { return mSnapshotActive; } -	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; } -	S32  getThumbnailWidth() const { return mThumbnailWidth ; } -	S32  getThumbnailHeight() const { return mThumbnailHeight ; } -	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; } -	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;} -	LLViewerTexture* getCurrentImage(); -	F32 getImageAspect(); -	F32 getAspect() ; -	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; } -	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; } -	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; } -	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } -	 -	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } -	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } -	void setSnapshotQuality(S32 quality); -	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } -	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); -	void saveWeb(); -	void saveTexture(); -	BOOL saveLocal(); - -	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; } -	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; } - -	/// Sets size of preview thumbnail image and thhe surrounding rect. -	BOOL setThumbnailImageSize() ; -	void generateThumbnailImage(BOOL force_update = FALSE) ; -	void resetThumbnailImage() { mThumbnailImage = NULL ; } -	void drawPreviewRect(S32 offset_x, S32 offset_y) ; - -	// Returns TRUE when snapshot generated, FALSE otherwise. -	static BOOL onIdle( void* snapshot_preview ); - -	// callback for region name resolve -	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z); - -private: -	LLColor4					mColor; -	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen. -	LLRect						mImageRect[2]; -	S32							mWidth[2]; -	S32							mHeight[2]; -	BOOL						mImageScaled[2]; -	S32                         mMaxImageSize ; -	 -	//thumbnail image -	LLPointer<LLViewerTexture>	mThumbnailImage ; -	S32                         mThumbnailWidth ; -	S32                         mThumbnailHeight ; -	LLRect                      mPreviewRect ; -	BOOL                        mThumbnailUpdateLock ; -	BOOL                        mThumbnailUpToDate ; - -	S32							mCurImageIndex; -	LLPointer<LLImageRaw>		mPreviewImage; -	LLPointer<LLImageRaw>		mPreviewImageEncoded; -	LLPointer<LLImageFormatted>	mFormattedImage; -	LLFrameTimer				mSnapshotDelayTimer; -	S32							mShineCountdown; -	LLFrameTimer				mShineAnimTimer; -	F32							mFlashAlpha; -	BOOL						mNeedsFlash; -	LLVector3d					mPosTakenGlobal; -	S32							mSnapshotQuality; -	S32							mDataSize; -	ESnapshotType				mSnapshotType; -	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat; -	BOOL						mSnapshotUpToDate; -	LLFrameTimer				mFallAnimTimer; -	LLVector3					mCameraPos; -	LLQuaternion				mCameraRot; -	BOOL						mSnapshotActive; -	LLViewerWindow::ESnapshotType mSnapshotBufferType; - -public: -	static std::set<LLSnapshotLivePreview*> sList; -	BOOL                        mKeepAspectRatio ; -}; - -std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList; - -LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)  -:	LLView(p), -	mColor(1.f, 0.f, 0.f, 0.5f),  -	mCurImageIndex(0), -	mPreviewImage(NULL), -	mThumbnailImage(NULL) , -	mThumbnailWidth(0), -	mThumbnailHeight(0), -	mPreviewImageEncoded(NULL), -	mFormattedImage(NULL), -	mShineCountdown(0), -	mFlashAlpha(0.f), -	mNeedsFlash(TRUE), -	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")), -	mDataSize(0), -	mSnapshotType(SNAPSHOT_POSTCARD), -	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), -	mSnapshotUpToDate(FALSE), -	mCameraPos(LLViewerCamera::getInstance()->getOrigin()), -	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), -	mSnapshotActive(FALSE), -	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR) -{ -	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); -	mSnapshotDelayTimer.setTimerExpirySec(0.0f); -	mSnapshotDelayTimer.start(); -// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); -	sList.insert(this); -	setFollowsAll(); -	mWidth[0] = gViewerWindow->getWindowWidthRaw(); -	mWidth[1] = gViewerWindow->getWindowWidthRaw(); -	mHeight[0] = gViewerWindow->getWindowHeightRaw(); -	mHeight[1] = gViewerWindow->getWindowHeightRaw(); -	mImageScaled[0] = FALSE; -	mImageScaled[1] = FALSE; - -	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; -	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; -	mThumbnailUpdateLock = FALSE ; -	mThumbnailUpToDate   = FALSE ; -} - -LLSnapshotLivePreview::~LLSnapshotLivePreview() -{ -	// delete images -	mPreviewImage = NULL; -	mPreviewImageEncoded = NULL; -	mFormattedImage = NULL; - -// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); -	sList.erase(this); -} - -void LLSnapshotLivePreview::setMaxImageSize(S32 size)  -{ -	if(size < MAX_SNAPSHOT_IMAGE_SIZE) -	{ -		mMaxImageSize = size; -	} -	else -	{ -		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; -	} -} - -LLViewerTexture* LLSnapshotLivePreview::getCurrentImage() -{ -	return mViewerImage[mCurImageIndex]; -} - -F32 LLSnapshotLivePreview::getAspect() -{ -	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); -	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - -	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) -	{ -		return image_aspect_ratio; -	} -	else -	{ -		return window_aspect_ratio; -	} -} - -F32 LLSnapshotLivePreview::getImageAspect() -{ -	if (!getCurrentImage()) -	{ -		return 0.f; -	} - -	return getAspect() ;	 -} - -void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)  -{ -	// Invalidate current image. -	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl; -	if (getSnapshotUpToDate()) -	{ -		S32 old_image_index = mCurImageIndex; -		mCurImageIndex = (mCurImageIndex + 1) % 2;  -		setSize(mWidth[old_image_index], mHeight[old_image_index]); -		mFallAnimTimer.start();		 -	} -	mSnapshotUpToDate = FALSE; 		 - -	// Update snapshot source rect depending on whether we keep the aspect ratio. -	LLRect& rect = mImageRect[mCurImageIndex]; -	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0); - -	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); -	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - -	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) -	{ -		if (image_aspect_ratio > window_aspect_ratio) -		{ -			// trim off top and bottom -			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);  -			rect.mBottom += (getRect().getHeight() - new_height) / 2; -			rect.mTop -= (getRect().getHeight() - new_height) / 2; -		} -		else if (image_aspect_ratio < window_aspect_ratio) -		{ -			// trim off left and right -			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);  -			rect.mLeft += (getRect().getWidth() - new_width) / 2; -			rect.mRight -= (getRect().getWidth() - new_width) / 2; -		} -	} - -	// Stop shining animation. -	mShineAnimTimer.stop(); - -	// Update snapshot if requested. -	if (new_snapshot) -	{ -		mSnapshotDelayTimer.start(); -		mSnapshotDelayTimer.setTimerExpirySec(delay); -		LLFloaterSnapshot::preUpdate(); -	} - -	// Update thumbnail if requested. -	if(new_thumbnail) -	{ -		mThumbnailUpToDate = FALSE ; -	} -} - -void LLSnapshotLivePreview::setSnapshotQuality(S32 quality) -{ -	llclamp(quality, 0, 100); -	if (quality != mSnapshotQuality) -	{ -		mSnapshotQuality = quality; -		gSavedSettings.setS32("SnapshotQuality", quality); -		mSnapshotUpToDate = FALSE; -	} -} - -void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) -{ -	F32 line_width ;  -	glGetFloatv(GL_LINE_WIDTH, &line_width) ; -	glLineWidth(2.0f * line_width) ; -	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ; -	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y, -				mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ; -	glLineWidth(line_width) ; - -	//draw four alpha rectangles to cover areas outside of the snapshot image -	if(!mKeepAspectRatio) -	{ -		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ; -		S32 dwl = 0, dwr = 0 ; -		if(mThumbnailWidth > mPreviewRect.getWidth()) -		{ -			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ; -			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ; - -			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y, -				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; -			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y, -				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; -		} - -		if(mThumbnailHeight > mPreviewRect.getHeight()) -		{ -			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ; -			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y , -				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ; - -			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ; -			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh, -				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ; -		} -	} -} - -//called when the frame is frozen. -void LLSnapshotLivePreview::draw() -{ -	if (getCurrentImage() && -	    mPreviewImageEncoded.notNull() && -	    getSnapshotUpToDate()) -	{ -		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f); -		gl_rect_2d(getRect(), bg_color); -		const LLRect& rect = getImageRect(); -		LLRect shadow_rect = rect; -		shadow_rect.stretch(BORDER_WIDTH); -		gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10); - -		LLColor4 image_color(1.f, 1.f, 1.f, 1.f); -		gGL.color4fv(image_color.mV); -		gGL.getTexUnit(0)->bind(getCurrentImage()); -		// calculate UV scale -		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f); -		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f); -		gGL.pushMatrix(); -		{ -			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f); -			gGL.begin(LLRender::QUADS); -			{ -				gGL.texCoord2f(uv_width, uv_height); -				gGL.vertex2i(rect.getWidth(), rect.getHeight() ); - -				gGL.texCoord2f(0.f, uv_height); -				gGL.vertex2i(0, rect.getHeight() ); - -				gGL.texCoord2f(0.f, 0.f); -				gGL.vertex2i(0, 0); - -				gGL.texCoord2f(uv_width, 0.f); -				gGL.vertex2i(rect.getWidth(), 0); -			} -			gGL.end(); -		} -		gGL.popMatrix(); - -		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha); -		gl_rect_2d(getRect()); -		if (mNeedsFlash) -		{ -			if (mFlashAlpha < 1.f) -			{ -				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f)); -			} -			else -			{ -				mNeedsFlash = FALSE; -			} -		} -		else -		{ -			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f)); -		} - -		// Draw shining animation if appropriate. -		if (mShineCountdown > 0) -		{ -			mShineCountdown--; -			if (mShineCountdown == 0) -			{ -				mShineAnimTimer.start(); -			} -		} -		else if (mShineAnimTimer.getStarted()) -		{ -			lldebugs << "Drawing shining animation" << llendl; -			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME); -			 -			// draw "shine" effect -			LLLocalClipRect clip(getLocalRect()); -			{ -				// draw diagonal stripe with gradient that passes over screen -				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f))); -				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH); -				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH); -				S32 y1 = 0; -				S32 y2 = gViewerWindow->getWindowHeightScaled(); - -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				gGL.begin(LLRender::QUADS); -				{ -					gGL.color4f(1.f, 1.f, 1.f, 0.f); -					gGL.vertex2i(x1, y1); -					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2); -					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); -					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); -					gGL.vertex2i(x2, y1); - -					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); -					gGL.vertex2i(x2, y1); -					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); -					gGL.color4f(1.f, 1.f, 1.f, 0.f); -					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2); -					gGL.vertex2i(x3, y1); -				} -				gGL.end(); -			} - -			// if we're at the end of the animation, stop -			if (shine_interp >= 1.f) -			{ -				mShineAnimTimer.stop(); -			} -		} -	} - -	// draw framing rectangle -	{ -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		gGL.color4f(1.f, 1.f, 1.f, 1.f); -		const LLRect& outline_rect = getImageRect(); -		gGL.begin(LLRender::QUADS); -		{ -			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); -			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); -			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); -			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); - -			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); -			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); -			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); -			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); - -			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); -			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); -			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); -			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); - -			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); -			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); -			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); -			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); -		} -		gGL.end(); -	} - -	// draw old image dropping away -	if (mFallAnimTimer.getStarted()) -	{ -		S32 old_image_index = (mCurImageIndex + 1) % 2; -		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME) -		{ -			lldebugs << "Drawing fall animation" << llendl; -			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME; -			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f); -			LLColor4 image_color(1.f, 1.f, 1.f, alpha); -			gGL.color4fv(image_color.mV); -			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]); -			// calculate UV scale -			// *FIX get this to work with old image -			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull(); -			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f; -			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f; -			gGL.pushMatrix(); -			{ -				LLRect& rect = mImageRect[old_image_index]; -				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f); -				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f); -				gGL.begin(LLRender::QUADS); -				{ -					gGL.texCoord2f(uv_width, uv_height); -					gGL.vertex2i(rect.getWidth(), rect.getHeight() ); - -					gGL.texCoord2f(0.f, uv_height); -					gGL.vertex2i(0, rect.getHeight() ); - -					gGL.texCoord2f(0.f, 0.f); -					gGL.vertex2i(0, 0); -					gGL.texCoord2f(uv_width, 0.f); -					gGL.vertex2i(rect.getWidth(), 0); -				} -				gGL.end(); -			} -			gGL.popMatrix(); -		} -	} -} - -/*virtual*/  -void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent) -{ -	LLRect old_rect = getRect(); -	LLView::reshape(width, height, called_from_parent); -	if (old_rect.getWidth() != width || old_rect.getHeight() != height) -	{ -		lldebugs << "window reshaped, updating thumbnail" << llendl; -		updateSnapshot(FALSE, TRUE); -	} -} - -BOOL LLSnapshotLivePreview::setThumbnailImageSize() -{ -	if(getWidth() < 10 || getHeight() < 10) -	{ -		return FALSE ; -	} -	S32 window_width = gViewerWindow->getWindowWidthRaw() ; -	S32 window_height = gViewerWindow->getWindowHeightRaw() ; - -	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); - -	// UI size for thumbnail -	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h. -	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect(); -	S32 max_width = thumbnail_rect.getWidth(); -	S32 max_height = thumbnail_rect.getHeight(); - -	if (window_aspect_ratio > (F32)max_width / max_height) -	{ -		// image too wide, shrink to width -		mThumbnailWidth = max_width; -		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio); -	} -	else -	{ -		// image too tall, shrink to height -		mThumbnailHeight = max_height; -		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio); -	} -	 -	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height) -	{ -		return FALSE ;//if the window is too small, ignore thumbnail updating. -	} - -	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ; -	if(!mKeepAspectRatio) -	{ -		F32 ratio_x = (F32)getWidth() / window_width ; -		F32 ratio_y = (F32)getHeight() / window_height ; - -		//if(getWidth() > window_width || -		//	getHeight() > window_height ) -		{ -			if(ratio_x > ratio_y) -			{ -				top = (S32)(top * ratio_y / ratio_x) ; -			} -			else -			{ -				right = (S32)(right * ratio_x / ratio_y) ; -			}			 -		} -		//else -		//{ -		//	right = (S32)(right * ratio_x) ; -		//	top = (S32)(top * ratio_y) ; -		//} -		left = (S32)((mThumbnailWidth - right) * 0.5f) ; -		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ; -		top += bottom ; -		right += left ; -	} -	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ; - -	return TRUE ; -} - -void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) -{	 -	if(mThumbnailUpdateLock) //in the process of updating -	{ -		return ; -	} -	if(getThumbnailUpToDate() && !force_update)//already updated -	{ -		return ; -	} -	if(getWidth() < 10 || getHeight() < 10) -	{ -		return ; -	} - -	////lock updating -	mThumbnailUpdateLock = TRUE ; - -	if(!setThumbnailImageSize()) -	{ -		mThumbnailUpdateLock = FALSE ; -		mThumbnailUpToDate = TRUE ; -		return ; -	} - -	if(mThumbnailImage) -	{ -		resetThumbnailImage() ; -	}		 - -	LLPointer<LLImageRaw> raw = new LLImageRaw; -	if(!gViewerWindow->thumbnailSnapshot(raw, -							mThumbnailWidth, mThumbnailHeight, -							gSavedSettings.getBOOL("RenderUIInSnapshot"), -							FALSE, -							mSnapshotBufferType) )								 -	{ -		raw = NULL ; -	} - -	if(raw) -	{ -		raw->expandToPowerOfTwo(); -		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		 -		mThumbnailUpToDate = TRUE ; -	} - -	//unlock updating -	mThumbnailUpdateLock = FALSE ;		 -} - - -// Called often. Checks whether it's time to grab a new snapshot and if so, does it. -// Returns TRUE if new snapshot generated, FALSE otherwise. -//static  -BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) -{ -	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; -	if (previewp->getWidth() == 0 || previewp->getHeight() == 0) -	{ -		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl; -		return FALSE; -	} - -	// If we're in freeze-frame mode and camera has moved, update snapshot. -	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); -	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); -	if (gSavedSettings.getBOOL("FreezeTime") &&  -		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)) -	{ -		previewp->mCameraPos = new_camera_pos; -		previewp->mCameraRot = new_camera_rot; -		// request a new snapshot whenever the camera moves, with a time delay -		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); -		lldebugs << "camera moved, updating thumbnail" << llendl; -		previewp->updateSnapshot( -			autosnap, // whether a new snapshot is needed or merely invalidate the existing one -			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image. -			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true. -	} - -	// see if it's time yet to snap the shot and bomb out otherwise. -	previewp->mSnapshotActive =  -		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired()) -		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active -	if ( ! previewp->mSnapshotActive) -	{ -		return FALSE; -	} - -	// time to produce a snapshot -	previewp->setThumbnailImageSize(); - -	lldebugs << "producing snapshot" << llendl; -	if (!previewp->mPreviewImage) -	{ -		previewp->mPreviewImage = new LLImageRaw; -	} - -	if (!previewp->mPreviewImageEncoded) -	{ -		previewp->mPreviewImageEncoded = new LLImageRaw; -	} - -	previewp->setVisible(FALSE); -	previewp->setEnabled(FALSE); -	 -	previewp->getWindow()->incBusyCount(); -	previewp->setImageScaled(FALSE); - -	// grab the raw image and encode it into desired format -	if(gViewerWindow->rawSnapshot( -							previewp->mPreviewImage, -							previewp->getWidth(), -							previewp->getHeight(), -							previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), -							previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, -							gSavedSettings.getBOOL("RenderUIInSnapshot"), -							FALSE, -							previewp->mSnapshotBufferType, -							previewp->getMaxImageSize())) -	{ -		previewp->mPreviewImageEncoded->resize( -			previewp->mPreviewImage->getWidth(),  -			previewp->mPreviewImage->getHeight(),  -			previewp->mPreviewImage->getComponents()); - -		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) -		{ -			lldebugs << "Encoding new image of format J2C" << llendl; -			LLPointer<LLImageJ2C> formatted = new LLImageJ2C; -			LLPointer<LLImageRaw> scaled = new LLImageRaw( -				previewp->mPreviewImage->getData(), -				previewp->mPreviewImage->getWidth(), -				previewp->mPreviewImage->getHeight(), -				previewp->mPreviewImage->getComponents()); -		 -			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); -			previewp->setImageScaled(TRUE); -			if (formatted->encode(scaled, 0.f)) -			{ -				previewp->mDataSize = formatted->getDataSize(); -				formatted->decode(previewp->mPreviewImageEncoded, 0); -			} -		} -		else -		{ -			// delete any existing image -			previewp->mFormattedImage = NULL; -			// now create the new one of the appropriate format. -			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat(); -			lldebugs << "Encoding new image of format " << format << llendl; - -			switch(format) -			{ -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: -				previewp->mFormattedImage = new LLImagePNG();  -				break; -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: -				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality);  -				break; -			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: -				previewp->mFormattedImage = new LLImageBMP();  -				break; -			} -			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0)) -			{ -				previewp->mDataSize = previewp->mFormattedImage->getDataSize(); -				// special case BMP to copy instead of decode otherwise decode will crash. -				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) -				{ -					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage); -				} -				else -				{ -					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0); -				} -			} -		} - -		LLPointer<LLImageRaw> scaled = new LLImageRaw( -			previewp->mPreviewImageEncoded->getData(), -			previewp->mPreviewImageEncoded->getWidth(), -			previewp->mPreviewImageEncoded->getHeight(), -			previewp->mPreviewImageEncoded->getComponents()); -		 -		if(!scaled->isBufferInvalid()) -		{ -			// leave original image dimensions, just scale up texture buffer -			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) -			{ -				// go ahead and shrink image to appropriate power of 2 for display -				scaled->biasedScaleToPowerOfTwo(1024); -				previewp->setImageScaled(TRUE); -			} -			else -			{ -				// expand image but keep original image data intact -				scaled->expandToPowerOfTwo(1024, FALSE); -			} - -			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); -			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; -			gGL.getTexUnit(0)->bind(curr_preview_image); -			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) -			{ -				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); -			} -			else -			{ -				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); -			} -			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - -			previewp->mSnapshotUpToDate = TRUE; -			previewp->generateThumbnailImage(TRUE) ; - -			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); -			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame -		} -	} -	previewp->getWindow()->decBusyCount(); -	// only show fullscreen preview when in freeze frame mode -	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); -	previewp->mSnapshotDelayTimer.stop(); -	previewp->mSnapshotActive = FALSE; - -	if(!previewp->getThumbnailUpToDate()) -	{ -		previewp->generateThumbnailImage() ; -	} -	lldebugs << "done creating snapshot" << llendl; -	LLFloaterSnapshot::postUpdate(); - -	return TRUE; -} - -void LLSnapshotLivePreview::setSize(S32 w, S32 h) -{ -	lldebugs << "setSize(" << w << ", " << h << ")" << llendl; -	setWidth(w); -	setHeight(h); -} - -void LLSnapshotLivePreview::getSize(S32& w, S32& h) const -{ -	w = getWidth(); -	h = getHeight(); -} - -void LLSnapshotLivePreview::saveTexture() -{ -	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl; -	// gen a new uuid for this asset -	LLTransactionID tid; -	tid.generate(); -	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); -		 -	LLPointer<LLImageJ2C> formatted = new LLImageJ2C; -	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(), -												  mPreviewImage->getWidth(), -												  mPreviewImage->getHeight(), -												  mPreviewImage->getComponents()); -	 -	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); -	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl; - -	if (formatted->encode(scaled, 0.0f)) -	{ -		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); -		std::string pos_string; -		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); -		std::string who_took_it; -		LLAgentUI::buildFullname(who_took_it); -		LLAssetStorage::LLStoreAssetCallback callback = NULL; -		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); -		void *userdata = NULL; -		upload_new_resource(tid,	// tid -				    LLAssetType::AT_TEXTURE, -				    "Snapshot : " + pos_string, -				    "Taken by " + who_took_it + " at " + pos_string, -				    0, -				    LLFolderType::FT_SNAPSHOT_CATEGORY, -				    LLInventoryType::IT_SNAPSHOT, -				    PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload -				    LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads -				    LLFloaterPerms::getEveryonePerms(), -				    "Snapshot : " + pos_string, -				    callback, expected_upload_cost, userdata); -		gViewerWindow->playSnapshotAnimAndSound(); -	} -	else -	{ -		LLNotificationsUtil::add("ErrorEncodingSnapshot"); -		llwarns << "Error encoding snapshot" << llendl; -	} - -	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); -	 -	mDataSize = 0; -} - -BOOL LLSnapshotLivePreview::saveLocal() -{ -	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); - -	if(success) -	{ -		gViewerWindow->playSnapshotAnimAndSound(); -	} -	return success; -} - -void LLSnapshotLivePreview::saveWeb() -{ -	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep! -	// Needs to pass on ownership of the image. -	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); -	if(!jpg) -	{ -		llwarns << "Formatted image not a JPEG" << llendl; -		return; -	} - -	LLSD metadata; -	metadata["description"] = getChild<LLLineEditor>("description")->getText(); - -	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(), -		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4)); - -	gViewerWindow->playSnapshotAnimAndSound(); -} - -void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z) -{ -	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString(); - -	LLWebSharing::instance().shareSnapshot(snapshot, metadata); -}  ///----------------------------------------------------------------------------  /// Class LLFloaterSnapshot::Impl @@ -2037,7 +1063,7 @@ BOOL LLFloaterSnapshot::postBuild()  	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));  	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); - +	  	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));  	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); @@ -2070,6 +1096,9 @@ BOOL LLFloaterSnapshot::postBuild()  	impl.updateControls(this);  	impl.updateLayout(this); + +	previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); +  	return TRUE;  } @@ -2235,7 +1264,9 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)  void LLFloaterSnapshot::update()  {  	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); -	if (!inst) +	LLFloaterSocial* floater_social  = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");  + +	if (!inst && !floater_social)  		return;  	BOOL changed = FALSE; @@ -2245,7 +1276,8 @@ void LLFloaterSnapshot::update()  	{  		changed |= LLSnapshotLivePreview::onIdle(*iter);  	} -	if(changed) +     +	if (inst && changed)  	{  		lldebugs << "changed" << llendl;  		inst->impl.updateControls(inst); diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index afe135fa40..82af8c7a9d 100755 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -27,7 +27,6 @@  #ifndef LL_LLFLOATERSNAPSHOT_H  #define LL_LLFLOATERSNAPSHOT_H -#include "llimage.h"  #include "llfloater.h"  class LLSpinCtrl; diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp new file mode 100644 index 0000000000..2a74c8e3ea --- /dev/null +++ b/indra/newview/llfloatersocial.cpp @@ -0,0 +1,920 @@ +/**  +* @file llfloatersocial.cpp +* @brief Implementation of llfloatersocial +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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 "llfloatersocial.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfacebookconnect.h" +#include "llfloaterreg.h" +#include "lliconctrl.h" +#include "llresmgr.h"		// LLLocale +#include "llsdserialize.h" +#include "llloadingindicator.h" +#include "llplugincookiestore.h" +#include "llslurl.h" +#include "lltrans.h" +#include "llsnapshotlivepreview.h" +#include "llviewerregion.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" + +static LLRegisterPanelClassWrapper<LLSocialStatusPanel> t_panel_status("llsocialstatuspanel"); +static LLRegisterPanelClassWrapper<LLSocialPhotoPanel> t_panel_photo("llsocialphotopanel"); +static LLRegisterPanelClassWrapper<LLSocialCheckinPanel> t_panel_checkin("llsocialcheckinpanel"); +static LLRegisterPanelClassWrapper<LLSocialAccountPanel> t_panel_account("llsocialaccountpanel"); + +const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte +const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/"; +const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png"; +const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare"; +const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare"; + +std::string get_map_url() +{ +    LLVector3d center_agent; +    if (gAgent.getRegion()) +    { +        center_agent = gAgent.getRegion()->getCenterGlobal(); +    } +    int x_pos = center_agent[0] / 256.0; +    int y_pos = center_agent[1] / 256.0; +    std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos); +    return map_url; +} + +/////////////////////////// +//LLSocialStatusPanel////// +/////////////////////////// + +LLSocialStatusPanel::LLSocialStatusPanel() : +	mMessageTextEditor(NULL), +	mPostButton(NULL), +    mCancelButton(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLSocialStatusPanel::onSend, this)); +} + +BOOL LLSocialStatusPanel::postBuild() +{ +	mMessageTextEditor = getChild<LLUICtrl>("status_message"); +	mPostButton = getChild<LLUICtrl>("post_status_btn"); +	mCancelButton = getChild<LLUICtrl>("cancel_status_btn"); + +	return LLPanel::postBuild(); +} + +void LLSocialStatusPanel::draw() +{ +    if (mMessageTextEditor && mPostButton && mCancelButton) +	{ +        bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); +        std::string message = mMessageTextEditor->getValue().asString(); +        mMessageTextEditor->setEnabled(no_ongoing_connection); +        mCancelButton->setEnabled(no_ongoing_connection); +        mPostButton->setEnabled(no_ongoing_connection && !message.empty()); +    } + +	LLPanel::draw(); +} + +void LLSocialStatusPanel::onSend() +{ +	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); // just in case it is already listening +	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialStatusPanel", boost::bind(&LLSocialStatusPanel::onFacebookConnectStateChange, this, _1)); +		 +	// Connect to Facebook if necessary and then post +	if (LLFacebookConnect::instance().isConnected()) +	{ +		sendStatus(); +	} +	else +	{ +		LLFacebookConnect::instance().checkConnectionToFacebook(true); +	} +} + +bool LLSocialStatusPanel::onFacebookConnectStateChange(const LLSD& data) +{ +	switch (data.get("enum").asInteger()) +	{ +		case LLFacebookConnect::FB_CONNECTED: +			sendStatus(); +			break; + +		case LLFacebookConnect::FB_POSTED: +			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); +			clearAndClose(); +			break; +	} + +	return false; +} + +void LLSocialStatusPanel::sendStatus() +{ +	std::string message = mMessageTextEditor->getValue().asString(); +	if (!message.empty()) +	{ +		LLFacebookConnect::instance().updateStatus(message); +	} +} + +void LLSocialStatusPanel::clearAndClose() +{ +	mMessageTextEditor->setValue(""); + +	LLFloater* floater = getParentByType<LLFloater>(); +	if (floater) +	{ +		floater->closeFloater(); +	} +} + +/////////////////////////// +//LLSocialPhotoPanel/////// +/////////////////////////// + +LLSocialPhotoPanel::LLSocialPhotoPanel() : +mSnapshotPanel(NULL), +mResolutionComboBox(NULL), +mRefreshBtn(NULL), +mWorkingLabel(NULL), +mThumbnailPlaceholder(NULL), +mCaptionTextBox(NULL), +mLocationCheckbox(NULL), +mPostButton(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLSocialPhotoPanel::onSend, this)); +	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this)); +} + +LLSocialPhotoPanel::~LLSocialPhotoPanel() +{ +	if(mPreviewHandle.get()) +	{ +		mPreviewHandle.get()->die(); +	} +} + +BOOL LLSocialPhotoPanel::postBuild() +{ +	setVisibleCallback(boost::bind(&LLSocialPhotoPanel::onVisibilityChange, this, _2)); +	 +	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel"); +	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); +	mResolutionComboBox->setCommitCallback(boost::bind(&LLSocialPhotoPanel::updateResolution, this, TRUE)); +	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); +    mWorkingLabel = getChild<LLUICtrl>("working_lbl"); +	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); +	mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); +	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb"); +	mPostButton = getChild<LLUICtrl>("post_photo_btn"); +	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); + +	return LLPanel::postBuild(); +} + +void LLSocialPhotoPanel::draw() +{  +	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); + +    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) +    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); +    mCancelButton->setEnabled(no_ongoing_connection); +    mCaptionTextBox->setEnabled(no_ongoing_connection); +    mResolutionComboBox->setEnabled(no_ongoing_connection); +    mRefreshBtn->setEnabled(no_ongoing_connection); +    mLocationCheckbox->setEnabled(no_ongoing_connection); +     +    // Display the preview if one is available +	if (previewp && previewp->getThumbnailImage()) +	{ +		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); +		const S32 thumbnail_w = previewp->getThumbnailWidth(); +		const S32 thumbnail_h = previewp->getThumbnailHeight(); + +		// calc preview offset within the preview rect +		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ; +		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; + +		// calc preview offset within the floater rect +        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater. +        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity. +        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time. +		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1; +		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39; +         +		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>()); +         +		gGL.matrixMode(LLRender::MM_MODELVIEW); +		// Apply floater transparency to the texture unless the floater is focused. +		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); +		LLColor4 color = LLColor4::white; +		gl_draw_scaled_image(offset_x, offset_y,  +			thumbnail_w, thumbnail_h, +			previewp->getThumbnailImage(), color % alpha); + +		previewp->drawPreviewRect(offset_x, offset_y) ; +	} + +    // Update the visibility of the working (computing preview) label +    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate())); +     +    // Enable Post if we have a preview to send and no on going connection being processed +    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate())); +     +    // Draw the rest of the panel on top of it +	LLPanel::draw(); +} + +LLSnapshotLivePreview* LLSocialPhotoPanel::getPreviewView() +{ +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); +	return previewp; +} + +void LLSocialPhotoPanel::onVisibilityChange(const LLSD& new_visibility) +{ +	bool visible = new_visibility.asBoolean(); +	if (visible) +	{ +		if (mPreviewHandle.get()) +		{ +			LLSnapshotLivePreview* preview = getPreviewView(); +			if(preview) +			{ +				lldebugs << "opened, updating snapshot" << llendl; +				preview->updateSnapshot(TRUE); +			} +		} +		else +		{ +			LLRect full_screen_rect = getRootView()->getRect(); +			LLSnapshotLivePreview::Params p; +			p.rect(full_screen_rect); +			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); +			mPreviewHandle = previewp->getHandle();	 + +			previewp->setSnapshotType(previewp->SNAPSHOT_WEB); +			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); +			//previewp->setSnapshotQuality(98); +			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); + +			updateControls(); +		} +	} +} + +void LLSocialPhotoPanel::onClickNewSnapshot() +{ +	LLSnapshotLivePreview* previewp = getPreviewView(); +	if (previewp) +	{ +		//setStatus(Impl::STATUS_READY); +		lldebugs << "updating snapshot" << llendl; +		previewp->updateSnapshot(TRUE); +	} +} + +void LLSocialPhotoPanel::onSend() +{ +	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); // just in case it is already listening +	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialPhotoPanel", boost::bind(&LLSocialPhotoPanel::onFacebookConnectStateChange, this, _1)); +	 +	// Connect to Facebook if necessary and then post +	if (LLFacebookConnect::instance().isConnected()) +	{ +		sendPhoto(); +	} +	else +	{ +		LLFacebookConnect::instance().checkConnectionToFacebook(true); +	} +} + +bool LLSocialPhotoPanel::onFacebookConnectStateChange(const LLSD& data) +{ +	switch (data.get("enum").asInteger()) +	{ +		case LLFacebookConnect::FB_CONNECTED: +			sendPhoto(); +			break; + +		case LLFacebookConnect::FB_POSTED: +			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); +			clearAndClose(); +			break; +	} + +	return false; +} + +void LLSocialPhotoPanel::sendPhoto() +{ +	// Get the caption +	std::string caption = mCaptionTextBox->getValue().asString(); + +	// Add the location if required +	bool add_location = mLocationCheckbox->getValue().asBoolean(); +	if (add_location) +	{ +		// Get the SLURL for the location +		LLSLURL slurl; +		LLAgentUI::buildSLURL(slurl); +		std::string slurl_string = slurl.getSLURLString(); + +		// Add query parameters so Google Analytics can track incoming clicks! +		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS; + +		// Add it to the caption (pretty crude, but we don't have a better option with photos) +		if (caption.empty()) +			caption = slurl_string; +		else +			caption = caption + " " + slurl_string; +	} + +	// Get the image +	LLSnapshotLivePreview* previewp = getPreviewView(); +	 +	// Post to Facebook +	LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); + +	updateControls(); +} + +void LLSocialPhotoPanel::clearAndClose() +{ +	mCaptionTextBox->setValue(""); + +	LLFloater* floater = getParentByType<LLFloater>(); +	if (floater) +	{ +		floater->closeFloater(); +	} +} + +void LLSocialPhotoPanel::updateControls() +{ +	LLSnapshotLivePreview* previewp = getPreviewView(); +	BOOL got_bytes = previewp && previewp->getDataSize() > 0; +	BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); +	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + +	// *TODO: Separate maximum size for Web images from postcards +	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; + +	LLLocale locale(LLLocale::USER_LOCALE); +	std::string bytes_string; +	if (got_snap) +	{ +		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); +	} + +	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string +	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown"); +	getChild<LLUICtrl>("file_size_label")->setColor( +		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD  +		&& got_bytes +		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); + +	updateResolution(FALSE); +} + +void LLSocialPhotoPanel::updateResolution(BOOL do_update) +{ +	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); + +	std::string sdstring = combobox->getSelectedValue(); +	LLSD sdres; +	std::stringstream sstream(sdstring); +	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + +	S32 width = sdres[0]; +	S32 height = sdres[1]; + +	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); +	if (previewp && combobox->getCurrentIndex() >= 0) +	{ +		S32 original_width = 0 , original_height = 0 ; +		previewp->getSize(original_width, original_height) ; + +		if (width == 0 || height == 0) +		{ +			// take resolution from current window size +			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; +			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); +		} +		else +		{ +			// use the resolution from the selected pre-canned drop-down choice +			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; +			previewp->setSize(width, height); +		} + +		checkAspectRatio(width); + +		previewp->getSize(width, height); +		 +		if(original_width != width || original_height != height) +		{ +			previewp->setSize(width, height); + +			// hide old preview as the aspect ratio could be wrong +			lldebugs << "updating thumbnail" << llendl; +			 +			previewp->updateSnapshot(FALSE, TRUE); +			if(do_update) +			{ +				lldebugs << "Will update controls" << llendl; +				updateControls(); +                LLSocialPhotoPanel::onClickNewSnapshot(); +			} +		} +		 +	} +} + +void LLSocialPhotoPanel::checkAspectRatio(S32 index) +{ +	LLSnapshotLivePreview *previewp = getPreviewView() ; + +	BOOL keep_aspect = FALSE; + +	if (0 == index) // current window size +	{ +		keep_aspect = TRUE; +	} +	else // predefined resolution +	{ +		keep_aspect = FALSE; +	} + +	if (previewp) +	{ +		previewp->mKeepAspectRatio = keep_aspect; +	} +} + +LLUICtrl* LLSocialPhotoPanel::getRefreshBtn() +{ +	return mRefreshBtn; +} + +//////////////////////// +//LLSocialCheckinPanel// +//////////////////////// + +LLSocialCheckinPanel::LLSocialCheckinPanel() : +    mMapUrl(""), +    mReloadingMapTexture(false) +{ +	mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLSocialCheckinPanel::onSend, this)); +} + +BOOL LLSocialCheckinPanel::postBuild() +{ +    // Keep pointers to widgets so we don't traverse the UI hierarchy too often +	mPostButton = getChild<LLUICtrl>("post_place_btn"); +	mCancelButton = getChild<LLUICtrl>("cancel_place_btn"); +	mMessageTextEditor = getChild<LLUICtrl>("place_caption"); +    mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator"); +    mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder"); +    mMapDefault = getChild<LLIconCtrl>("map_default"); +    mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb"); +     +	return LLPanel::postBuild(); +} + +void LLSocialCheckinPanel::draw() +{ +    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); +    mPostButton->setEnabled(no_ongoing_connection); +    mCancelButton->setEnabled(no_ongoing_connection); +    mMessageTextEditor->setEnabled(no_ongoing_connection); +    mMapCheckBox->setEnabled(no_ongoing_connection); + +    std::string map_url = get_map_url(); +    // Did we change location? +    if (map_url != mMapUrl) +    { +        mMapUrl = map_url; +        // Load the map tile +        mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +        mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP); +        mReloadingMapTexture = true; +        // In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox +        mMapLoadingIndicator->setVisible(true); +        mMapPlaceholder->setVisible(false); +    } +    // Are we done loading the map tile? +    if (mReloadingMapTexture && mMapTexture->isFullyLoaded()) +    { +        // Don't do it again next time around +        mReloadingMapTexture = false; +        // Convert the map texture to the appropriate image object +        LLPointer<LLUIImage> ui_image = new LLUIImage(mMapUrl, mMapTexture); +        // Load the map widget with the correct map tile image +        mMapPlaceholder->setImage(ui_image); +        // Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value +        mMapLoadingIndicator->setVisible(false); +        mMapPlaceholder->setVisible(true); +    } +    // Show the default icon if that's the checkbox value (the real one...) +    // This will hide/show the loading indicator and/or tile underneath +    mMapDefault->setVisible(!(mMapCheckBox->get())); + +	LLPanel::draw(); +} + +void LLSocialCheckinPanel::onSend() +{ +	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); // just in case it is already listening +	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialCheckinPanel", boost::bind(&LLSocialCheckinPanel::onFacebookConnectStateChange, this, _1)); +	 +	// Connect to Facebook if necessary and then post +	if (LLFacebookConnect::instance().isConnected()) +	{ +		sendCheckin(); +	} +	else +	{ +		LLFacebookConnect::instance().checkConnectionToFacebook(true); +	} +} + +bool LLSocialCheckinPanel::onFacebookConnectStateChange(const LLSD& data) +{ +	switch (data.get("enum").asInteger()) +	{ +		case LLFacebookConnect::FB_CONNECTED: +			sendCheckin(); +			break; + +		case LLFacebookConnect::FB_POSTED: +			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); +			clearAndClose(); +			break; +	} + +	return false; +} + +void LLSocialCheckinPanel::sendCheckin() +{ +	// Get the location SLURL +	LLSLURL slurl; +	LLAgentUI::buildSLURL(slurl); +	std::string slurl_string = slurl.getSLURLString(); + +	// Use a valid http:// URL if the scheme is secondlife://  +	LLURI slurl_uri(slurl_string); +	if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) +	{ +		slurl_string = DEFAULT_CHECKIN_LOCATION_URL; +	} + +	// Add query parameters so Google Analytics can track incoming clicks! +	slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; +     +	// Get the region name +	std::string region_name = gAgent.getRegion()->getName(); +     +	// Get the region description +	std::string description; +	LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent()); +     +	// Optionally add the region map view +	bool add_map_view = mMapCheckBox->getValue().asBoolean(); +    std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL); +     +	// Get the caption +	std::string caption = mMessageTextEditor->getValue().asString(); + +	// Post to Facebook +	LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption); +} + +void LLSocialCheckinPanel::clearAndClose() +{ +	mMessageTextEditor->setValue(""); + +	LLFloater* floater = getParentByType<LLFloater>(); +	if (floater) +	{ +		floater->closeFloater(); +	} +} + +/////////////////////////// +//LLSocialAccountPanel////// +/////////////////////////// + +LLSocialAccountPanel::LLSocialAccountPanel() :  +mAccountCaptionLabel(NULL), +mAccountNameLabel(NULL), +mPanelButtons(NULL), +mConnectButton(NULL), +mDisconnectButton(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLSocialAccountPanel::onConnect, this)); +	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLSocialAccountPanel::onDisconnect, this)); + +	setVisibleCallback(boost::bind(&LLSocialAccountPanel::onVisibilityChange, this, _2)); +} + +BOOL LLSocialAccountPanel::postBuild() +{ +	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); +	mAccountNameLabel = getChild<LLTextBox>("account_name_label"); +	mPanelButtons = getChild<LLUICtrl>("panel_buttons"); +	mConnectButton = getChild<LLUICtrl>("connect_btn"); +	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); + +	return LLPanel::postBuild(); +} + +void LLSocialAccountPanel::draw() +{ +	LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + +	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress +	bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; +	mDisconnectButton->setEnabled(!disconnecting); + +	//Disable the 'connect' button when a connection is in progress +	bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; +	mConnectButton->setEnabled(!connecting); + +	LLPanel::draw(); +} + +void LLSocialAccountPanel::onVisibilityChange(const LLSD& new_visibility) +{ +	bool visible = new_visibility.asBoolean(); + +	if(visible) +	{ +		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel"); +		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectStateChange, this, _1)); + +		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel"); +		LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectInfoChange, this)); + +		//Connected +		if(LLFacebookConnect::instance().isConnected()) +		{ +			showConnectedLayout(); +		} +		//Check if connected (show disconnected layout in meantime) +		else +		{ +			showDisconnectedLayout(); +		} +        if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || +            (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) +        { +            LLFacebookConnect::instance().checkConnectionToFacebook(); +        } +	} +	else +	{ +		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel"); +		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel"); +	} +} + +bool LLSocialAccountPanel::onFacebookConnectStateChange(const LLSD& data) +{ +	if(LLFacebookConnect::instance().isConnected()) +	{ +		//In process of disconnecting so leave the layout as is +		if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) +		{ +			showConnectedLayout(); +		} +	} +	else +	{ +		showDisconnectedLayout(); +	} + +	return false; +} + +bool LLSocialAccountPanel::onFacebookConnectInfoChange() +{ +	LLSD info = LLFacebookConnect::instance().getInfo(); +	std::string clickable_name; + +	//Strings of format [http://www.somewebsite.com Click Me] become clickable text +	if(info.has("link") && info.has("name")) +	{ +		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; +	} + +	mAccountNameLabel->setText(clickable_name); + +	return false; +} + +void LLSocialAccountPanel::showConnectButton() +{ +	if(!mConnectButton->getVisible()) +	{ +		mConnectButton->setVisible(TRUE); +		mDisconnectButton->setVisible(FALSE); +	} +} + +void LLSocialAccountPanel::hideConnectButton() +{ +	if(mConnectButton->getVisible()) +	{ +		mConnectButton->setVisible(FALSE); +		mDisconnectButton->setVisible(TRUE); +	} +} + +void LLSocialAccountPanel::showDisconnectedLayout() +{ +	mAccountCaptionLabel->setText(getString("facebook_disconnected")); +	mAccountNameLabel->setText(std::string("")); +	showConnectButton(); +} + +void LLSocialAccountPanel::showConnectedLayout() +{ +	LLFacebookConnect::instance().loadFacebookInfo(); + +	mAccountCaptionLabel->setText(getString("facebook_connected")); +	hideConnectButton(); +} + +void LLSocialAccountPanel::onConnect() +{ +	LLFacebookConnect::instance().checkConnectionToFacebook(true); + +	//Clear only the facebook browser cookies so that the facebook login screen appears +	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  +} + +void LLSocialAccountPanel::onDisconnect() +{ +	LLFacebookConnect::instance().disconnectFromFacebook(); + +	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");  +} + +//////////////////////// +//LLFloaterSocial/////// +//////////////////////// + +LLFloaterSocial::LLFloaterSocial(const LLSD& key) : LLFloater(key), +    mSocialPhotoPanel(NULL), +    mStatusErrorText(NULL), +    mStatusLoadingText(NULL), +    mStatusLoadingIndicator(NULL) +{ +	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterSocial::onCancel, this)); +} + +void LLFloaterSocial::onCancel() +{ +    closeFloater(); +} + +BOOL LLFloaterSocial::postBuild() +{ +    // Keep tab of the Photo Panel +	mSocialPhotoPanel = static_cast<LLSocialPhotoPanel*>(getChild<LLUICtrl>("panel_social_photo")); +    // Connection status widgets +    mStatusErrorText = getChild<LLTextBox>("connection_error_text"); +    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text"); +    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator"); +	return LLFloater::postBuild(); +} + +// static +void LLFloaterSocial::preUpdate() +{ +	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); +	if (instance) +	{ +		//Will set file size text to 'unknown' +		instance->mSocialPhotoPanel->updateControls(); +	} +} + +// static +void LLFloaterSocial::postUpdate() +{ +	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); +	if (instance) +	{ +		//Will set the file size text +		instance->mSocialPhotoPanel->updateControls(); + +		// The refresh button is initially hidden. We show it after the first update, +		// i.e. after snapshot is taken +		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn(); + +		if (!refresh_button->getVisible()) +		{ +			refresh_button->setVisible(true); +		} +		 +	} +} + +void LLFloaterSocial::draw() +{ +    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator) +    { +        mStatusErrorText->setVisible(false); +        mStatusLoadingText->setVisible(false); +        mStatusLoadingIndicator->setVisible(false); +        LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); +        std::string status_text; +         +        switch (connection_state) +        { +        case LLFacebookConnect::FB_NOT_CONNECTED: +            // No status displayed when first opening the panel and no connection done +        case LLFacebookConnect::FB_CONNECTED: +            // When successfully connected, no message is displayed +        case LLFacebookConnect::FB_POSTED: +            // No success message to show since we actually close the floater after successful posting completion +            break; +        case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS: +            // Connection loading indicator +            mStatusLoadingText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookConnecting"); +            mStatusLoadingText->setValue(status_text); +            mStatusLoadingIndicator->setVisible(true); +            break; +        case LLFacebookConnect::FB_POSTING: +            // Posting indicator +            mStatusLoadingText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookPosting"); +            mStatusLoadingText->setValue(status_text); +            mStatusLoadingIndicator->setVisible(true); +			break; +        case LLFacebookConnect::FB_CONNECTION_FAILED: +            // Error connecting to the service +            mStatusErrorText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookErrorConnecting"); +            mStatusErrorText->setValue(status_text); +            break; +        case LLFacebookConnect::FB_POST_FAILED: +            // Error posting to the service +            mStatusErrorText->setVisible(true); +            status_text = LLTrans::getString("SocialFacebookErrorPosting"); +            mStatusErrorText->setValue(status_text); +            break; +		case LLFacebookConnect::FB_DISCONNECTING: +			// Disconnecting loading indicator +			mStatusLoadingText->setVisible(true); +			status_text = LLTrans::getString("SocialFacebookDisconnecting"); +			mStatusLoadingText->setValue(status_text); +			mStatusLoadingIndicator->setVisible(true); +			break; +		case LLFacebookConnect::FB_DISCONNECT_FAILED: +			// Error disconnecting from the service +			mStatusErrorText->setVisible(true); +			status_text = LLTrans::getString("SocialFacebookErrorDisconnecting"); +			mStatusErrorText->setValue(status_text); +			break; +        } +    } +	LLFloater::draw(); +} + diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h new file mode 100644 index 0000000000..bbe07c9704 --- /dev/null +++ b/indra/newview/llfloatersocial.h @@ -0,0 +1,165 @@ +/**  +* @file   llfloatersocial.h +* @brief  Header file for llfloatersocial +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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_LLFLOATERSOCIAL_H +#define LL_LLFLOATERSOCIAL_H + +#include "llfloater.h" +#include "lltextbox.h" +#include "llviewertexture.h" + +class LLIconCtrl; +class LLCheckBoxCtrl; +class LLSnapshotLivePreview; + +class LLSocialStatusPanel : public LLPanel +{ +public: +    LLSocialStatusPanel(); +	BOOL postBuild(); +	void draw(); +    void onSend(); +	bool onFacebookConnectStateChange(const LLSD& data); + +	void sendStatus(); +	void clearAndClose(); + +private: +	LLUICtrl* mMessageTextEditor; +	LLUICtrl* mPostButton; +	LLUICtrl* mCancelButton; +}; + +class LLSocialPhotoPanel : public LLPanel +{ +public: +	LLSocialPhotoPanel(); +	~LLSocialPhotoPanel(); + +	BOOL postBuild(); +	void draw(); + +	LLSnapshotLivePreview* getPreviewView(); +	void onVisibilityChange(const LLSD& new_visibility); +	void onClickNewSnapshot(); +	void onSend(); +	bool onFacebookConnectStateChange(const LLSD& data); + +	void sendPhoto(); +	void clearAndClose(); + +	void updateControls(); +	void updateResolution(BOOL do_update); +	void checkAspectRatio(S32 index); +	LLUICtrl* getRefreshBtn(); + +private: +	LLHandle<LLView> mPreviewHandle; + +	LLUICtrl * mSnapshotPanel; +	LLUICtrl * mResolutionComboBox; +	LLUICtrl * mRefreshBtn; +	LLUICtrl * mWorkingLabel; +	LLUICtrl * mThumbnailPlaceholder; +	LLUICtrl * mCaptionTextBox; +	LLUICtrl * mLocationCheckbox; +	LLUICtrl * mPostButton; +	LLUICtrl* mCancelButton; +}; + +class LLSocialCheckinPanel : public LLPanel +{ +public: +    LLSocialCheckinPanel(); +	BOOL postBuild(); +	void draw(); +    void onSend(); +	bool onFacebookConnectStateChange(const LLSD& data); + +	void sendCheckin(); +	void clearAndClose(); + +private: +    std::string mMapUrl; +    LLPointer<LLViewerFetchedTexture> mMapTexture; +	LLUICtrl* mPostButton; +	LLUICtrl* mCancelButton; +	LLUICtrl* mMessageTextEditor; +    LLUICtrl* mMapLoadingIndicator; +    LLIconCtrl* mMapPlaceholder; +    LLIconCtrl* mMapDefault; +    LLCheckBoxCtrl* mMapCheckBox; +    bool mReloadingMapTexture; +}; + +class LLSocialAccountPanel : public LLPanel +{ +public: +	LLSocialAccountPanel(); +	BOOL postBuild(); +	void draw(); + +private: +	void onVisibilityChange(const LLSD& new_visibility); +	bool onFacebookConnectStateChange(const LLSD& data); +	bool onFacebookConnectInfoChange(); +	void onConnect(); +	void onUseAnotherAccount(); +	void onDisconnect(); + +	void showConnectButton(); +	void hideConnectButton(); +	void showDisconnectedLayout(); +	void showConnectedLayout(); + +	LLTextBox * mAccountCaptionLabel; +	LLTextBox * mAccountNameLabel; +	LLUICtrl * mPanelButtons; +	LLUICtrl * mConnectButton; +	LLUICtrl * mDisconnectButton; +}; + + +class LLFloaterSocial : public LLFloater +{ +public: +	LLFloaterSocial(const LLSD& key); +	BOOL postBuild(); +	void draw(); +	void onCancel(); + +	static void preUpdate(); +	static void postUpdate(); + +private: +	LLSocialPhotoPanel* mSocialPhotoPanel; +    LLTextBox* mStatusErrorText; +    LLTextBox* mStatusLoadingText; +    LLUICtrl*  mStatusLoadingIndicator; +}; + +#endif // LL_LLFLOATERSOCIAL_H + diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3fe2518de6..76b73fcf29 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -29,6 +29,7 @@  #include "llcombobox.h"  #include "lliconctrl.h"  #include "llfloaterreg.h" +#include "llfacebookconnect.h"  #include "lllayoutstack.h"  #include "llpluginclassmedia.h"  #include "llprogressbar.h" @@ -46,7 +47,8 @@ LLFloaterWebContent::_Params::_Params()  	id("id"),  	window_class("window_class", "web_content"),  	show_chrome("show_chrome", true), -	allow_address_entry("allow_address_entry", true), +    allow_address_entry("allow_address_entry", true), +    allow_back_forward_navigation("allow_back_forward_navigation", true),  	preferred_media_size("preferred_media_size"),  	trusted_content("trusted_content", false),  	show_page_title("show_page_title", true) @@ -65,7 +67,11 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )  	mBtnReload(NULL),  	mBtnStop(NULL),  	mUUID(params.id()), -	mShowPageTitle(params.show_page_title) +	mShowPageTitle(params.show_page_title), +    mAllowNavigation(true), +    mCurrentURL(""), +    mDisplayURL(""), +    mSecureURL(false)  {  	mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));  	mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); @@ -97,7 +103,7 @@ BOOL LLFloaterWebContent::postBuild()  	// cache image for secure browsing  	mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); - +      	// initialize the URL history using the system URL History manager  	initializeURLHistory(); @@ -243,6 +249,7 @@ void LLFloaterWebContent::open_media(const Params& p)  	getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);  	getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);  	bool address_entry_enabled = p.allow_address_entry && !p.trusted_content; +    mAllowNavigation = p.allow_back_forward_navigation;  	getChildView("address")->setEnabled(address_entry_enabled);  	getChildView("popexternal")->setEnabled(address_entry_enabled); @@ -287,6 +294,16 @@ void LLFloaterWebContent::onOpen(const LLSD& key)  //virtual  void LLFloaterWebContent::onClose(bool app_quitting)  { +    // If we close the web browsing window showing the facebook login, we need to signal to this object that the connection will not happen +    LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web"); +    if (fbc_web == this) +    { +        if (!LLFacebookConnect::instance().isConnected()) +        { +            LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED); +        } +    } +      	LLViewerMedia::proxyWindowClosed(mUUID);  	destroy();  } @@ -295,8 +312,11 @@ void LLFloaterWebContent::onClose(bool app_quitting)  void LLFloaterWebContent::draw()  {  	// this is asynchronous so we need to keep checking -	mBtnBack->setEnabled( mWebBrowser->canNavigateBack() ); -	mBtnForward->setEnabled( mWebBrowser->canNavigateForward() ); +	mBtnBack->setEnabled( mWebBrowser->canNavigateBack() && mAllowNavigation); +	mBtnForward->setEnabled( mWebBrowser->canNavigateForward() && mAllowNavigation); + +    // Show/hide the lock icon +    mSecureLockIcon->setVisible(mSecureURL && !mAddressCombo->hasFocus());  	LLFloater::draw();  } @@ -342,19 +362,8 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent  		// 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); -		} +			mAddressCombo->setLeftTextPadding(22); +			mAddressCombo->setLeftTextPadding(2);  	}  	else if(event == MEDIA_EVENT_CLOSE_REQUEST)  	{ @@ -397,15 +406,40 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent  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 ); +    if (!url.empty()) +    { +        if (!mCurrentURL.empty()) +        { +            // Clean up the current browsing list to show true URL +            mAddressCombo->remove(mDisplayURL); +            mAddressCombo->add(mCurrentURL); +        } + +        // Update current URL +        mCurrentURL = url; +        LLStringUtil::trim(mCurrentURL); + +        // Serialize url history into the system URL History manager +        LLURLHistory::removeURL("browser", mCurrentURL); +        LLURLHistory::addURL("browser", mCurrentURL); + +		// Check if this is a secure URL +		static const std::string secure_prefix = std::string("https://"); +		std::string prefix = mCurrentURL.substr(0, secure_prefix.length()); +		LLStringUtil::toLower(prefix); +        mSecureURL = (prefix == secure_prefix); +         +        // Hack : we move the text a bit to make space for the lock icon in the secure URL case +		mDisplayURL = (mSecureURL ? "      " + mCurrentURL : mCurrentURL); + +        // Clean up browsing list (prevent dupes) and add/select the new URL to it +        mAddressCombo->remove(mCurrentURL); +        mAddressCombo->add(mDisplayURL); +        mAddressCombo->selectByValue(mDisplayURL); + +        // Set the focus back to the web page. When setting the url, there's no point to leave the focus anywhere else. +		mWebBrowser->setFocus(TRUE); +    }  }  void LLFloaterWebContent::onClickForward() @@ -449,6 +483,7 @@ 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(); +    LLStringUtil::trim(url);  	if ( url.length() > 0 )  	{  		mWebBrowser->navigateTo( url, "text/html"); @@ -460,6 +495,7 @@ 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(); +    LLStringUtil::trim(url);  	if ( url.length() > 0 )  	{  		LLWeb::loadURLExternal( url ); diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 86b5a5e00b..f22940cd07 100755 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -55,6 +55,7 @@ public:  								id;  		Optional<bool>			show_chrome,  								allow_address_entry, +                                allow_back_forward_navigation,  								trusted_content,  								show_page_title;  		Optional<LLRect>		preferred_media_size; @@ -106,9 +107,12 @@ protected:  	LLView*			mBtnReload;  	LLView*			mBtnStop; -	std::string		mCurrentURL; +	std::string		mCurrentURL;    // Current URL +	std::string		mDisplayURL;    // URL being displayed in the address bar (can differ by trailing / leading space)  	std::string		mUUID;  	bool			mShowPageTitle; +    bool            mAllowNavigation; +    bool            mSecureURL;     // true when the current url is prefixed "https://"  };  #endif  // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2e53effcac..9ffbd1a675 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -130,10 +130,10 @@ void process_dnd_im(const LLSD& notification)              fromID,               false,               false); //will need slight refactor to retrieve whether offline message or not (assume online for now) -	} +		}  	notify_of_message(data, true); -} +    } @@ -155,22 +155,22 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,  void notify_of_message(const LLSD& msg, bool is_dnd_msg)  { -	std::string user_preferences; +    std::string user_preferences;  	LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID();  	LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID(); -	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); +    LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); -	// do not show notification which goes from agent -	if (gAgent.getID() == participant_id) -	{ -		return; -	} +    // do not show notification which goes from agent +    if (gAgent.getID() == participant_id) +    { +        return; +    } -	// determine state of conversations floater -	enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; +    // determine state of conversations floater +    enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; -	LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +    LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");  	LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);  	bool store_dnd_message = false; // flag storage of a dnd message  	bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus(); @@ -179,23 +179,23 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)  		conversations_floater_status = CLOSED;  	}  	else if (!im_box->hasFocus() && -		!(session_floater && LLFloater::isVisible(session_floater) -		&& !session_floater->isMinimized() && session_floater->hasFocus())) +			    !(session_floater && LLFloater::isVisible(session_floater) +	            && !session_floater->isMinimized() && session_floater->hasFocus()))  	{  		conversations_floater_status = NOT_ON_TOP;  	}  	else if (im_box->getSelectedSession() != session_id)  	{  		conversations_floater_status = ON_TOP; -	} +    }  	else  	{  		conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;  	} -	//  determine user prefs for this session -	if (session_id.isNull()) -	{ +    //  determine user prefs for this session +    if (session_id.isNull()) +    {  		if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT)  		{  			user_preferences = gSavedSettings.getString("NotificationObjectIMOptions"); @@ -206,50 +206,50 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)  		}  		else  		{ -			user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); +    	user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");  			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE))  			{  				make_ui_sound("UISndNewIncomingIMSession"); -			} +    }  		}  	} -	else if(session->isP2PSessionType()) -	{ -		if (LLAvatarTracker::instance().isBuddy(participant_id)) -		{ -			user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); +    else if(session->isP2PSessionType()) +    { +        if (LLAvatarTracker::instance().isBuddy(participant_id)) +        { +        	user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");  			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE))  			{  				make_ui_sound("UISndNewIncomingIMSession");  			} -		} -		else -		{ -			user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); +        } +        else +        { +        	user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");  			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM") == TRUE))  			{  				make_ui_sound("UISndNewIncomingIMSession"); -			} -		} +        } +    }  	} -	else if(session->isAdHocSessionType()) -	{ -		user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); +    else if(session->isAdHocSessionType()) +    { +    	user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");  		if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE))  		{  			make_ui_sound("UISndNewIncomingIMSession"); -		} +    }  	} -	else if(session->isGroupSessionType()) -	{ -		user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); +    else if(session->isGroupSessionType()) +    { +    	user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");  		if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM") == TRUE))  		{  			make_ui_sound("UISndNewIncomingIMSession");  		} -	} +    } -	// actions: +    // actions:      // 0. nothing - exit      if (("noaction" == user_preferences || @@ -287,23 +287,23 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)  				}  			}  		} -		else -		{ +        else +        {  			store_dnd_message = true; -		} +	        } -	} +    } -	// 2. Flash line item -	if ("openconversations" == user_preferences -		|| ON_TOP == conversations_floater_status -		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status) +    // 2. Flash line item +    if ("openconversations" == user_preferences +    		|| ON_TOP == conversations_floater_status +    		|| ("toast" == user_preferences && ON_TOP != conversations_floater_status)  		|| ("flash" == user_preferences && (CLOSED == conversations_floater_status  				 	 	 	 	 	 	|| NOT_ON_TOP == conversations_floater_status))  		|| is_dnd_msg) -	{ -		if(!LLMuteList::getInstance()->isMuted(participant_id)) -		{ +    { +    	if(!LLMuteList::getInstance()->isMuted(participant_id)) +    	{  			if(gAgent.isDoNotDisturb())  			{  				store_dnd_message = true; @@ -318,43 +318,43 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)  				}  				else  				{ -					im_box->flashConversationItemWidget(session_id, true); -				} -			} +    		im_box->flashConversationItemWidget(session_id, true); +    	} +    }  		}  	} -	// 3. Flash FUI button -	if (("toast" == user_preferences || "flash" == user_preferences) && -		(CLOSED == conversations_floater_status +    // 3. Flash FUI button +    if (("toast" == user_preferences || "flash" == user_preferences) && +    		(CLOSED == conversations_floater_status  		|| NOT_ON_TOP == conversations_floater_status)  		&& !is_session_focused  		&& !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened  	{  		if(!LLMuteList::getInstance()->isMuted(participant_id)) -		{ +    {  			if(!gAgent.isDoNotDisturb()) -			{ +    	{  				gToolBarView->flashCommand(LLCommandId("chat"), true, im_box->isMinimized()); -			} +    	}  			else  			{  				store_dnd_message = true;  			} -		} +    }  	} -	// 4. Toast -	if ((("toast" == user_preferences) && +    // 4. Toast +    if ((("toast" == user_preferences) &&  		(ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status) &&  		(!session_floater->isTornOff() || !LLFloater::isVisible(session_floater))) -		|| !session_floater->isMessagePaneExpanded()) +    		    || !session_floater->isMessagePaneExpanded()) -	{ -		//Show IM toasts (upper right toasts) -		// Skip toasting for system messages and for nearby chat -		if(session_id.notNull() && participant_id.notNull()) -		{ +    { +        //Show IM toasts (upper right toasts) +        // Skip toasting for system messages and for nearby chat +        if(session_id.notNull() && participant_id.notNull()) +        {  			if(!is_dnd_msg)  			{  				if(gAgent.isDoNotDisturb()) @@ -363,10 +363,10 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg)  				}  				else  				{ -					LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); -				} -			} -		} +            LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +        } +    } +}  	}  	if (store_dnd_message)  	{ diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e4fc469bb7..80ef506272 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4739,6 +4739,16 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act  			LLAvatarActions::offerTeleport(item->getCreatorUUID());  		}  	} +	else if ("request_lure" == action) +	{ +		LLViewerInventoryItem *item = getItem(); +		if (item && (item->getCreatorUUID() != gAgent.getID()) && +			(!item->getCreatorUUID().isNull())) +		{ +			LLAvatarActions::teleportRequest(item->getCreatorUUID()); +		} +	} +  	else LLItemBridge::performAction(model, action);  } @@ -4825,6 +4835,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		items.push_back(std::string("Send Instant Message Separator"));  		items.push_back(std::string("Send Instant Message"));  		items.push_back(std::string("Offer Teleport...")); +		items.push_back(std::string("Request Teleport..."));  		items.push_back(std::string("Conference Chat"));  		if (!good_card) @@ -4834,6 +4845,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		if (!good_card || !user_online)  		{  			disabled_items.push_back(std::string("Offer Teleport...")); +			disabled_items.push_back(std::string("Request Teleport..."));  			disabled_items.push_back(std::string("Conference Chat"));  		}  	} diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 54522bb7f6..0720d443f8 100755 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -251,6 +251,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags)  			llinfos << "Muting by name " << mute.mName << llendl;  			updateAdd(mute);  			notifyObservers(); +			notifyObserversDetailed(mute);  			return TRUE;  		}  		else @@ -299,6 +300,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags)  				llinfos << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl;  				updateAdd(localmute);  				notifyObservers(); +				notifyObserversDetailed(localmute);  				if(!(localmute.mFlags & LLMute::flagParticles))  				{  					//Kill all particle systems owned by muted task @@ -396,6 +398,7 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags)  		}  		// Must be after erase. +		notifyObserversDetailed(localmute);  		setLoaded();  // why is this here? -MG  	}  	else @@ -409,6 +412,7 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags)  			updateRemove(mute);  			mLegacyMutes.erase(legacy_it);  			// Must be after erase. +			notifyObserversDetailed(mute);  			setLoaded(); // why is this here? -MG  		}  	} @@ -762,3 +766,16 @@ void LLMuteList::notifyObservers()  		it = mObservers.upper_bound(observer);  	}  } + +void LLMuteList::notifyObserversDetailed(const LLMute& mute) +{ +	for (observer_set_t::iterator it = mObservers.begin(); +		it != mObservers.end(); +		) +	{ +		LLMuteListObserver* observer = *it; +		observer->onChangeDetailed(mute); +		// In case onChange() deleted an entry. +		it = mObservers.upper_bound(observer); +	} +} diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 7a70370fe3..3e998b4f0e 100755 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -123,6 +123,7 @@ private:  	void setLoaded();  	void notifyObservers(); +	void notifyObserversDetailed(const LLMute &mute);  	void updateAdd(const LLMute& mute);  	void updateRemove(const LLMute& mute); @@ -173,6 +174,7 @@ class LLMuteListObserver  public:  	virtual ~LLMuteListObserver() { }  	virtual void onChange() = 0; +	virtual void onChangeDetailed(const LLMute& ) { }  }; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index dea90b9042..08b5eaedbb 100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -343,8 +343,11 @@ void LLNetMap::draw()  		// Draw avatars  		for (U32 i = 0; i < avatar_ids.size(); i++)  		{ -			pos_map = globalPosToView(positions[i]);  			LLUUID uuid = avatar_ids[i]; +			// Skip self, we'll draw it later +			if (uuid == gAgent.getID()) continue; + +			pos_map = globalPosToView(positions[i]);  			bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 08c98e4f28..a3b15931c6 100755 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -35,6 +35,9 @@  #include "llnotificationmanager.h"  #include "llnotifications.h"  #include "llscriptfloater.h" +#include "llfacebookconnect.h" +#include "llavatarname.h" +#include "llavatarnamecache.h"  using namespace LLNotificationsUI; @@ -87,7 +90,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  	{  		LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());  	} -	else +	else if (notification->canShowToast())  	{  		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 53deded2f2..1ff0bfd091 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -542,6 +542,13 @@ void LLPanelMainInventory::changed(U32)  	updateItemcountText();  } +void LLPanelMainInventory::setFocusFilterEditor() +{ +	if(mFilterEditor) +	{ +		mFilterEditor->setFocus(true); +	} +}  // virtual  void LLPanelMainInventory::draw() diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 394b004e20..fc8cc67c33 100755 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -82,6 +82,9 @@ public:  	void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);  	void onFilterEdit(const std::string& search_string ); + +	void setFocusFilterEditor(); +  protected:  	//  	// Misc functions diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d7c634d619..f551fc96ee 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -28,6 +28,8 @@  // libs  #include "llavatarname.h" +#include "llconversationview.h" +#include "llfloaterimcontainer.h"  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h"  #include "llmenubutton.h" @@ -48,15 +50,19 @@  #include "llavataractions.h"  #include "llavatarlist.h"  #include "llavatarlistitem.h" +#include "llavatarnamecache.h"  #include "llcallingcard.h"			// for LLAvatarTracker +#include "llcallbacklist.h" +#include "llerror.h" +#include "llfacebookconnect.h"  #include "llfloateravatarpicker.h" -//#include "llfloaterminiinspector.h"  #include "llfriendcard.h"  #include "llgroupactions.h"  #include "llgrouplist.h"  #include "llinventoryobserver.h"  #include "llnetmap.h"  #include "llpanelpeoplemenus.h" +#include "llparticipantlist.h"  #include "llsidetraypanelcontainer.h"  #include "llrecentpeople.h"  #include "llviewercontrol.h"		// for gSavedSettings @@ -64,6 +70,10 @@  #include "llvoiceclient.h"  #include "llworld.h"  #include "llspeakers.h" +#include "llfloaterwebcontent.h" + +#include "llagentui.h" +#include "llslurl.h"  #define FRIEND_LIST_UPDATE_TIMEOUT	0.5  #define NEARBY_LIST_UPDATE_INTERVAL 1 @@ -73,9 +83,9 @@ static const std::string FRIENDS_TAB_NAME	= "friends_panel";  static const std::string GROUP_TAB_NAME		= "groups_panel";  static const std::string RECENT_TAB_NAME	= "recent_panel";  static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars -  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; +  extern S32 gMaxAgentGroups;  /** Comparator for comparing avatar items by last interaction date */ @@ -495,6 +505,7 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(), +		mTryToConnectToFbc(true),  		mTabContainer(NULL),  		mOnlineFriendList(NULL),  		mAllFriendList(NULL), @@ -573,6 +584,7 @@ BOOL LLPanelPeople::postBuild()  	getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); @@ -583,8 +595,11 @@ BOOL LLPanelPeople::postBuild()  	// updater is active only if panel is visible to user.  	friends_tab->setVisibleCallback(boost::bind(&Updater::setActive, mFriendListUpdater, _2));      friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::removePicker, this)); +	friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::updateFacebookList, this, _2)); +  	mOnlineFriendList = friends_tab->getChild<LLAvatarList>("avatars_online");  	mAllFriendList = friends_tab->getChild<LLAvatarList>("avatars_all"); +	mSuggestedFriends = friends_tab->getChild<LLAvatarList>("suggested_friends");  	mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));  	mOnlineFriendList->setShowIcons("FriendsListShowIcons");  	mOnlineFriendList->showPermissions("FriendsListShowPermissions"); @@ -617,6 +632,7 @@ BOOL LLPanelPeople::postBuild()  	mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);  	mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);  	mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); +	mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);  	setSortOrder(mRecentList,		(ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"),	false);  	setSortOrder(mAllFriendList,	(ESortOrder)gSavedSettings.getU32("FriendsSortOrder"),		false); @@ -695,7 +711,7 @@ void LLPanelPeople::updateFriendListHelpText()  	// Seems sometimes all_friends can be empty because of issue with Inventory loading (clear cache, slow connection...)  	// So, lets check all lists to avoid overlapping the text with online list. See EXT-6448. -	bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches(); +	bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches() || mSuggestedFriends->filterHasMatches();  	no_friends_text->setVisible(!any_friend_exists);  	if (no_friends_text->getVisible())  	{ @@ -762,9 +778,40 @@ void LLPanelPeople::updateFriendList()  	mAllFriendList->setDirty(true, !mAllFriendList->filterHasMatches());  	//update trash and other buttons according to a selected item  	updateButtons(); +	updateSuggestedFriendList();  	showFriendsAccordionsIfNeeded();  } +bool LLPanelPeople::updateSuggestedFriendList() +{ +	const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); +	uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); +	suggested_friends.clear(); + +	//Add suggested friends +	LLSD friends = LLFacebookConnect::instance().getContent(); +	for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) +	{ +		LLUUID agent_id = (*i).asUUID(); +		bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false; + +		if(!second_life_buddy) +		{ +			//FB+SL but not SL friend +			if (agent_id.notNull()) +			{ +				suggested_friends.push_back(agent_id); +			} +		} +	} + +	//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) +	mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); +	showFriendsAccordionsIfNeeded(); + +	return false; +} +  void LLPanelPeople::updateNearbyList()  {  	if (!mNearbyList) @@ -788,6 +835,51 @@ void LLPanelPeople::updateRecentList()  	mRecentList->setDirty();  } +bool LLPanelPeople::onConnectedToFacebook(const LLSD& data) +{ +	LLSD::Integer connection_state = data.get("enum").asInteger(); + +	if (connection_state == LLFacebookConnect::FB_CONNECTED) +	{ +		LLFacebookConnect::instance().loadFacebookFriends(); +	} +	else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED) +	{ +		updateSuggestedFriendList(); +	}; + +	return false; +} + +void LLPanelPeople::updateFacebookList(bool visible) +{ +	if (visible) +	{ +		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening +		LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLPanelPeople::updateSuggestedFriendList, this)); + +		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening +		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLPanelPeople::onConnectedToFacebook, this, _1)); + +		if (LLFacebookConnect::instance().isConnected()) +		{ +			LLFacebookConnect::instance().loadFacebookFriends(); +		} +		else if(mTryToConnectToFbc) +		{ +			LLFacebookConnect::instance().checkConnectionToFacebook(); +			mTryToConnectToFbc = false; +		} +     +		updateSuggestedFriendList(); +	} +	else +	{ +		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); +		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); +	} +} +  void LLPanelPeople::updateButtons()  {  	std::string cur_tab		= getActiveTabName(); @@ -993,23 +1085,25 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	{  		// store accordion tabs opened/closed state before any manipulation with accordion tabs  		if (!saved_filter.empty()) -	{ -		notifyChildren(LLSD().with("action","store_state")); -	} +        { +            notifyChildren(LLSD().with("action","store_state")); +        }  		mOnlineFriendList->setNameFilter(filter);  		mAllFriendList->setNameFilter(filter); +		mSuggestedFriends->setNameFilter(filter); -	setAccordionCollapsedByUser("tab_online", false); -	setAccordionCollapsedByUser("tab_all", false); -	showFriendsAccordionsIfNeeded(); +        setAccordionCollapsedByUser("tab_online", false); +        setAccordionCollapsedByUser("tab_all", false); +		setAccordionCollapsedByUser("tab_suggested_friends", false); +        showFriendsAccordionsIfNeeded();  		// restore accordion tabs state _after_ all manipulations  		if(saved_filter.empty()) -	{ -		notifyChildren(LLSD().with("action","restore_state")); -	} -} +        { +            notifyChildren(LLSD().with("action","restore_state")); +        } +    }  	else if (cur_tab == GROUP_TAB_NAME)  	{  		mGroupList->setNameFilter(filter); @@ -1229,7 +1323,7 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)  		mAllFriendList->showPermissions(show_permissions);  		mOnlineFriendList->showPermissions(show_permissions);  	} -} +	}  void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata)  { @@ -1387,6 +1481,7 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded()  		// Expand and show accordions if needed, else - hide them  		showAccordion("tab_online", mOnlineFriendList->filterHasMatches());  		showAccordion("tab_all", mAllFriendList->filterHasMatches()); +		showAccordion("tab_suggested_friends", mSuggestedFriends->filterHasMatches());  		// Rearrange accordions  		LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion"); @@ -1450,4 +1545,5 @@ bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)  	return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));  } +  // EOF diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 4740964dee..c7141f36ee 100755 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -22,7 +22,7 @@   *    * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$ - */ + */   #ifndef LL_LLPANELPEOPLE_H  #define LL_LLPANELPEOPLE_H @@ -30,6 +30,7 @@  #include <llpanel.h>  #include "llcallingcard.h" // for avatar tracker +#include "llfloaterwebcontent.h"  #include "llvoiceclient.h"  class LLAvatarList; @@ -55,6 +56,8 @@ public:  	// when voice is available  	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); +    bool mTryToConnectToFbc; +  	// internals  	class Updater; @@ -73,8 +76,10 @@ private:  	// methods indirectly called by the updaters  	void					updateFriendListHelpText();  	void					updateFriendList(); +	bool					updateSuggestedFriendList();  	void					updateNearbyList();  	void					updateRecentList(); +	void					updateFacebookList(bool visible);  	bool					isItemsFreeOfFriends(const uuid_vec_t& uuids); @@ -121,6 +126,8 @@ private:  	void					onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param); +	bool					onConnectedToFacebook(const LLSD& data); +  	void					setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);  	void					setAccordionCollapsedByUser(const std::string& name, bool collapsed);  	bool					isAccordionCollapsedByUser(LLUICtrl* acc_tab); @@ -129,6 +136,7 @@ private:  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mOnlineFriendList;  	LLAvatarList*			mAllFriendList; +	LLAvatarList*			mSuggestedFriends;  	LLAvatarList*			mNearbyList;  	LLAvatarList*			mRecentList;  	LLGroupList*			mGroupList; @@ -140,6 +148,7 @@ private:  	Updater*				mFriendListUpdater;  	Updater*				mNearbyListUpdater;  	Updater*				mRecentListUpdater; +	Updater*				mFacebookListUpdater;  	Updater*				mButtonsUpdater;      LLHandle< LLFloater >	mPicker;  }; diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 49f7361c4a..6979ae06e0 100755 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -47,6 +47,7 @@ namespace LLPanelPeopleMenus  PeopleContextMenu gPeopleContextMenu;  NearbyPeopleContextMenu gNearbyPeopleContextMenu; +SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;  //== PeopleContextMenu =============================================================== @@ -74,6 +75,7 @@ LLContextMenu* PeopleContextMenu::createMenu()  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id));  		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id)); +		registrar.add("Avatar.TeleportRequest",	boost::bind(&PeopleContextMenu::requestTeleport,		this));  		registrar.add("Avatar.Calllog",			boost::bind(&LLAvatarActions::viewChatHistory,			id));  		enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2)); @@ -125,6 +127,7 @@ void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); @@ -255,6 +258,13 @@ bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)  	return false;  } +void PeopleContextMenu::requestTeleport() +{ +	// boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(), +	// so we have to use a wrapper. +	LLAvatarActions::teleportRequest(mUUIDs.front()); +} +  void PeopleContextMenu::offerTeleport()  {  	// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(), @@ -284,6 +294,7 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)  		items.push_back(std::string("view_profile"));  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport")); +		items.push_back(std::string("request_teleport"));  		items.push_back(std::string("voice_call"));  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history")); @@ -301,4 +312,36 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)      hide_context_entries(menu, items, disabled_items);  } +//== SuggestedFriendsContextMenu =============================================================== + +LLContextMenu* SuggestedFriendsContextMenu::createMenu() +{ +	// set up the callbacks for all of the avatar menu items +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +	LLContextMenu* menu; + +	// Set up for one person selected menu +	const LLUUID& id = mUUIDs.front(); +	registrar.add("Avatar.Profile",			boost::bind(&LLAvatarActions::showProfile,				id)); +	registrar.add("Avatar.AddFriend",		boost::bind(&LLAvatarActions::requestFriendshipDialog,	id)); + +	// create the context menu from the XUI +	menu = createFromFile("menu_people_nearby.xml"); +	buildContextMenu(*menu, 0x0); + +	return menu; +} + +void SuggestedFriendsContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags) +{  +	menuentry_vec_t items; +	menuentry_vec_t disabled_items; + +	items.push_back(std::string("view_profile")); +	items.push_back(std::string("add_friend")); + +	hide_context_entries(menu, items, disabled_items); +} +  } // namespace LLPanelPeopleMenus diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index 0a1dcef303..945382ebc5 100755 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -47,6 +47,7 @@ private:  	bool enableContextMenuItem(const LLSD& userdata);  	bool checkContextMenuItem(const LLSD& userdata);  	void offerTeleport(); +	void requestTeleport();  };  /** @@ -58,8 +59,21 @@ protected:  	/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);  }; +/** + * Menu used in the suggested friends list. + */ +class SuggestedFriendsContextMenu : public PeopleContextMenu +{ +public: +	/*virtual*/ LLContextMenu * createMenu(); + +protected: +	/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags); +}; +  extern PeopleContextMenu gPeopleContextMenu;  extern NearbyPeopleContextMenu gNearbyPeopleContextMenu; +extern SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;  } // namespace LLPanelPeopleMenus diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 76d38f067d..9504f22a1d 100755 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -94,7 +94,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :  	mZoomObjectFace(0),  	mVolumeSliderVisible(0),  	mWindowShade(NULL), -	mHideImmediately(false) +	mHideImmediately(false), +    mSecureURL(false)  {  	mCommitCallbackRegistrar.add("MediaCtrl.Close",		boost::bind(&LLPanelPrimMediaControls::onClickClose, this));  	mCommitCallbackRegistrar.add("MediaCtrl.Back",		boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -345,7 +346,7 @@ void LLPanelPrimMediaControls::updateShape()  		// Disable zoom if HUD  		mZoomCtrl->setEnabled(!is_hud);  		mUnzoomCtrl->setEnabled(!is_hud); -		mSecureLockIcon->setVisible(false); +        mSecureURL = false;  		mCurrentURL = media_impl->getCurrentMediaURL();  		mBackCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate); @@ -382,7 +383,7 @@ void LLPanelPrimMediaControls::updateShape()  			mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible());  			mWhitelistIcon->setVisible(false); -			mSecureLockIcon->setVisible(false); +            mSecureURL = false;  			if (mMediaPanelScroll)  			{  				mMediaPanelScroll->setVisible(false); @@ -416,7 +417,7 @@ void LLPanelPrimMediaControls::updateShape()  				mMediaPlaySliderCtrl->setEnabled(true);  			} -			// video vloume +			// video volume  			if(volume <= 0.0)  			{  				mMuteBtn->setToggleState(true); @@ -492,10 +493,8 @@ void LLPanelPrimMediaControls::updateShape()  			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(has_focus); -			} +            mSecureURL = has_focus && (test_prefix == prefix); +            mCurrentURL = (mSecureURL ? "      " + mCurrentURL : mCurrentURL);  			if(mCurrentURL!=mPreviousURL)  			{ @@ -746,6 +745,9 @@ void LLPanelPrimMediaControls::draw()  			clearFaceOnFade();  		}  	} + +    // Show/hide the lock icon for secure browsing +    mSecureLockIcon->setVisible(mSecureURL && !mMediaAddress->hasFocus());  	// Build rect for icon area in coord system of this panel  	// Assumes layout_stack is a direct child of this panel diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index eeb433e306..6d2eb3430e 100755 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -191,6 +191,7 @@ private:  	bool mUpdateSlider;  	bool mClearFaceOnFade;  	bool mHideImmediately; +    bool mSecureURL;  	LLMatrix4 mLastCameraMat;  	EZoomLevel mCurrentZoom; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index c53760bca1..ee6893907e 100755 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -27,6 +27,7 @@  #include "llviewerprecompiledheaders.h"  #include "llavatarnamecache.h" +#include "llerror.h"  #include "llimview.h"  #include "llfloaterimcontainer.h"  #include "llparticipantlist.h" @@ -401,6 +402,8 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)  	adjustParticipant(avatar_id);  } +static LLFastTimer::DeclareTimer FTM_FOLDERVIEW_TEST("add test avatar agents"); +  void LLParticipantList::adjustParticipant(const LLUUID& speaker_id)  {  	LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id); diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 076c3e0235..d8fc2bee32 100755 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -77,6 +77,14 @@ void LLPersistentNotificationStorage::saveNotifications()  		}  		data.append(notification->asLLSD(true)); +		if (data.size() >= gSavedSettings.getS32("MaxPersistentNotifications")) +		{ +			llwarns << "Too many persistent notifications." +					<< " Saved " << gSavedSettings.getS32("MaxPersistentNotifications") << " of " << history_channel->size() +					<< " persistent notifications." << llendl; +			break; +		} +  	}  	writeNotifications(output); @@ -97,7 +105,6 @@ void LLPersistentNotificationStorage::loadNotifications()  	}  	mLoaded = true; -  	LLSD input;  	if (!readNotifications(input) ||input.isUndefined())  	{ @@ -115,9 +122,9 @@ void LLPersistentNotificationStorage::loadNotifications()  		findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));  	LLNotifications& instance = LLNotifications::instance(); - -	for (LLSD::array_const_iterator notification_it = data.beginArray(); -		notification_it != data.endArray(); +	S32 processed_notifications = 0; +	for (LLSD::reverse_array_iterator notification_it = data.rbeginArray(); +		notification_it != data.rendArray();  		++notification_it)  	{  		LLSD notification_params = *notification_it; @@ -136,8 +143,16 @@ void LLPersistentNotificationStorage::loadNotifications()  			// hide saved toasts so they don't confuse the user  			notification_channel->hideToast(notification->getID());  		} +		++processed_notifications; +		if (processed_notifications >= gSavedSettings.getS32("MaxPersistentNotifications")) +		{ +			llwarns << "Too many persistent notifications." +					<< " Processed " << gSavedSettings.getS32("MaxPersistentNotifications") << " of " << data.size() << " persistent notifications." << llendl; +		    break; +		}  	} - +	LLNotifications::instance().getChannel("Persistent")-> +			connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));  	LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;  } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 91a98792eb..1ed48a978f 100755 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -36,6 +36,7 @@  #include "llfilepicker.h"  #include "llfloaterreg.h"  #include "llimagetga.h" +#include "llimagepng.h"  #include "llinventory.h"  #include "llnotificationsutil.h"  #include "llresmgr.h" @@ -261,7 +262,7 @@ void LLPreviewTexture::saveAs()  	LLFilePicker& file_picker = LLFilePicker::instance();  	const LLInventoryItem* item = getItem() ; -	if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA, item ? LLDir::getScrubbedFileName(item->getName()) : LLStringUtil::null) ) +	if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGAPNG, item ? LLDir::getScrubbedFileName(item->getName()) : LLStringUtil::null) )  	{  		// User canceled or we failed to acquire save file.  		return; @@ -358,14 +359,27 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,  	if( self && final && success )  	{ -		LLPointer<LLImageTGA> image_tga = new LLImageTGA; -		if( !image_tga->encode( src ) ) +		const U32 ext_length = 3; +		std::string extension = self->mSaveFileName.substr( self->mSaveFileName.length() - ext_length); + +		// We only support saving in PNG or TGA format +		LLPointer<LLImageFormatted> image; +		if(extension == "png") +		{ +			image = new LLImagePNG; +		} +		else if(extension == "tga") +		{ +			image = new LLImageTGA; +		} + +		if( image && !image->encode( src, 0 ) )  		{  			LLSD args;  			args["FILE"] = self->mSaveFileName;  			LLNotificationsUtil::add("CannotEncodeFile", args);  		} -		else if( !image_tga->save( self->mSaveFileName ) ) +		else if( image && !image->save( self->mSaveFileName ) )  		{  			LLSD args;  			args["FILE"] = self->mSaveFileName; diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp index 09e799e4f7..cbd8bee9d5 100755 --- a/indra/newview/llsceneview.cpp +++ b/indra/newview/llsceneview.cpp @@ -51,7 +51,7 @@ LLSceneView::LLSceneView(const LLRect& rect)  	setCanClose(true);  } -void LLSceneView::onClickCloseBtn() +void LLSceneView::onClickCloseBtn(bool)  {  	setVisible(false);  } diff --git a/indra/newview/llsceneview.h b/indra/newview/llsceneview.h index 2a3a14bbee..1fceecb9e1 100755 --- a/indra/newview/llsceneview.h +++ b/indra/newview/llsceneview.h @@ -38,7 +38,7 @@ public:  	virtual void draw();  protected: -	virtual void onClickCloseBtn(); +	virtual void onClickCloseBtn(bool app_qutting = false);  }; diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 928d26646b..c4d5450e2b 100755 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -207,6 +207,7 @@ LLSD _basic_constraints_ext(X509* cert)  			}  		} +		BASIC_CONSTRAINTS_free( bs );  	}  	return result;  } @@ -268,6 +269,8 @@ LLSD _ext_key_usage_ext(X509* cert)  				ASN1_OBJECT_free(usage);  			}  		} + +		EXTENDED_KEY_USAGE_free( eku );  	}  	return result;  } @@ -280,6 +283,8 @@ LLSD _subject_key_identifier_ext(X509 *cert)  	if(skeyid)  	{  		result = cert_string_from_octet_string(skeyid); + +		ASN1_OCTET_STRING_free( skeyid );  	}  	return result;  } @@ -300,6 +305,9 @@ LLSD _authority_key_identifier_ext(X509* cert)  		{  			result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);  		}	 + + +		AUTHORITY_KEYID_free( akeyid );  	}  	// we ignore the issuer name in the authority key identifier, we check the issue name via @@ -1049,6 +1057,8 @@ void LLBasicCertificateStore::validate(int validation_policy,  		throw LLInvalidCertificate((*current_cert));			  	}  	std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); +	X509_free( cert_x509 ); +	cert_x509 = NULL;  	t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash);  	if(cache_entry != mTrustedCertCache.end())  	{ diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 8915bb2fef..cbf43dbb93 100755 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -397,7 +397,7 @@ void LLSidepanelInventory::onToggleInboxBtn()  void LLSidepanelInventory::onOpen(const LLSD& key)  {  	LLFirstUse::newInventory(false); - +	mPanelMainInventory->setFocusFilterEditor();  #if AUTO_EXPAND_INBOX  	// Expand the inbox if we have fresh items  	LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL); diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index ad7c939728..9be6d0c5f1 100755 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -1170,6 +1170,10 @@ void LLSidepanelTaskInfo::doClickAction(U8 click_action)  			// Warn, but do it anyway.  			LLNotificationsUtil::add("ClickActionNotPayable");  		} +		else +		{ +			handle_give_money_dialog(); +		}  	}  	LLSelectMgr::getInstance()->selectionSetClickAction(click_action);  } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp new file mode 100644 index 0000000000..7532ebfc57 --- /dev/null +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -0,0 +1,874 @@ +/**  +* @file llsnapshotlivepreview.cpp +* @brief Implementation of llsnapshotlivepreview +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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 "llagent.h" +#include "llagentcamera.h" +#include "llagentui.h" +#include "llcombobox.h" +#include "lleconomy.h" +#include "llfloaterperms.h" +#include "llfloaterreg.h" +#include "llfloatersocial.h" +#include "llimagebmp.h" +#include "llimagej2c.h" +#include "llimagejpeg.h" +#include "llimagepng.h" +#include "lllandmarkactions.h" +#include "lllocalcliprect.h" +#include "llnotificationsutil.h" +#include "llslurl.h" +#include "llsnapshotlivepreview.h" +#include "lltoolfocus.h" +#include "llviewercontrol.h" +#include "llviewermenufile.h"	// upload_new_resource() +#include "llviewerstats.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llwebsharing.h" +#include "llwindow.h" +#include "llworld.h" + +const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; + +F32 SHINE_TIME = 0.5f; +F32 SHINE_WIDTH = 0.6f; +F32 SHINE_OPACITY = 0.3f; +F32 FALL_TIME = 0.6f; +S32 BORDER_WIDTH = 6; + +const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 + +std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList; + +LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)  +	:	LLView(p), +	mColor(1.f, 0.f, 0.f, 0.5f),  +	mCurImageIndex(0), +	mPreviewImage(NULL), +	mThumbnailImage(NULL) , +	mThumbnailWidth(0), +	mThumbnailHeight(0), +	mPreviewImageEncoded(NULL), +	mFormattedImage(NULL), +	mShineCountdown(0), +	mFlashAlpha(0.f), +	mNeedsFlash(TRUE), +	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")), +	mDataSize(0), +	mSnapshotType(SNAPSHOT_POSTCARD), +	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), +	mSnapshotUpToDate(FALSE), +	mCameraPos(LLViewerCamera::getInstance()->getOrigin()), +	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), +	mSnapshotActive(FALSE), +	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR) +{ +	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); +	mSnapshotDelayTimer.setTimerExpirySec(0.0f); +	mSnapshotDelayTimer.start(); +	// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); +	sList.insert(this); +	setFollowsAll(); +	mWidth[0] = gViewerWindow->getWindowWidthRaw(); +	mWidth[1] = gViewerWindow->getWindowWidthRaw(); +	mHeight[0] = gViewerWindow->getWindowHeightRaw(); +	mHeight[1] = gViewerWindow->getWindowHeightRaw(); +	mImageScaled[0] = FALSE; +	mImageScaled[1] = FALSE; + +	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; +	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; +	mThumbnailUpdateLock = FALSE ; +	mThumbnailUpToDate   = FALSE ; +} + +LLSnapshotLivePreview::~LLSnapshotLivePreview() +{ +	// delete images +	mPreviewImage = NULL; +	mPreviewImageEncoded = NULL; +	mFormattedImage = NULL; + +	// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); +	sList.erase(this); +} + +void LLSnapshotLivePreview::setMaxImageSize(S32 size)  +{ +	if(size < MAX_SNAPSHOT_IMAGE_SIZE) +	{ +		mMaxImageSize = size; +	} +	else +	{ +		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; +	} +} + +LLViewerTexture* LLSnapshotLivePreview::getCurrentImage() +{ +	return mViewerImage[mCurImageIndex]; +} + +F32 LLSnapshotLivePreview::getAspect() +{ +	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); +	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); + +	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) +	{ +		return image_aspect_ratio; +	} +	else +	{ +		return window_aspect_ratio; +	} +} + +F32 LLSnapshotLivePreview::getImageAspect() +{ +	if (!getCurrentImage()) +	{ +		return 0.f; +	} + +	return getAspect() ;	 +} + +void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)  +{ +	// Invalidate current image. +	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl; +	if (getSnapshotUpToDate()) +	{ +		S32 old_image_index = mCurImageIndex; +		mCurImageIndex = (mCurImageIndex + 1) % 2;  +		setSize(mWidth[old_image_index], mHeight[old_image_index]); +		mFallAnimTimer.start();		 +	} +	mSnapshotUpToDate = FALSE; 		 + +	// Update snapshot source rect depending on whether we keep the aspect ratio. +	LLRect& rect = mImageRect[mCurImageIndex]; +	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0); + +	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight()); +	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); + +	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) +	{ +		if (image_aspect_ratio > window_aspect_ratio) +		{ +			// trim off top and bottom +			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);  +			rect.mBottom += (getRect().getHeight() - new_height) / 2; +			rect.mTop -= (getRect().getHeight() - new_height) / 2; +		} +		else if (image_aspect_ratio < window_aspect_ratio) +		{ +			// trim off left and right +			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);  +			rect.mLeft += (getRect().getWidth() - new_width) / 2; +			rect.mRight -= (getRect().getWidth() - new_width) / 2; +		} +	} + +	// Stop shining animation. +	mShineAnimTimer.stop(); + +	// Update snapshot if requested. +	if (new_snapshot) +	{ +		mSnapshotDelayTimer.start(); +		mSnapshotDelayTimer.setTimerExpirySec(delay); +		LLFloaterSnapshot::preUpdate(); +		LLFloaterSocial::preUpdate(); +	} + +	// Update thumbnail if requested. +	if(new_thumbnail) +	{ +		mThumbnailUpToDate = FALSE ; +	} +} + +void LLSnapshotLivePreview::setSnapshotQuality(S32 quality) +{ +	llclamp(quality, 0, 100); +	if (quality != mSnapshotQuality) +	{ +		mSnapshotQuality = quality; +		gSavedSettings.setS32("SnapshotQuality", quality); +		mSnapshotUpToDate = FALSE; +	} +} + +void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) +{ +	F32 line_width ;  +	glGetFloatv(GL_LINE_WIDTH, &line_width) ; +	glLineWidth(2.0f * line_width) ; +	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ; +	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y, +		mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ; +	glLineWidth(line_width) ; + +	//draw four alpha rectangles to cover areas outside of the snapshot image +	if(!mKeepAspectRatio) +	{ +		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ; +		S32 dwl = 0, dwr = 0 ; +		if(mThumbnailWidth > mPreviewRect.getWidth()) +		{ +			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ; +			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ; + +			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y, +				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; +			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y, +				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; +		} + +		if(mThumbnailHeight > mPreviewRect.getHeight()) +		{ +			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ; +			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y , +				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ; + +			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ; +			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh, +				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ; +		} +	} +} + +//called when the frame is frozen. +void LLSnapshotLivePreview::draw() +{ +	if (getCurrentImage() && +		mPreviewImageEncoded.notNull() && +		getSnapshotUpToDate()) +	{ +		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f); +		gl_rect_2d(getRect(), bg_color); +		const LLRect& rect = getImageRect(); +		LLRect shadow_rect = rect; +		shadow_rect.stretch(BORDER_WIDTH); +		gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10); + +		LLColor4 image_color(1.f, 1.f, 1.f, 1.f); +		gGL.color4fv(image_color.mV); +		gGL.getTexUnit(0)->bind(getCurrentImage()); +		// calculate UV scale +		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f); +		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f); +		gGL.pushMatrix(); +		{ +			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f); +			gGL.begin(LLRender::QUADS); +			{ +				gGL.texCoord2f(uv_width, uv_height); +				gGL.vertex2i(rect.getWidth(), rect.getHeight() ); + +				gGL.texCoord2f(0.f, uv_height); +				gGL.vertex2i(0, rect.getHeight() ); + +				gGL.texCoord2f(0.f, 0.f); +				gGL.vertex2i(0, 0); + +				gGL.texCoord2f(uv_width, 0.f); +				gGL.vertex2i(rect.getWidth(), 0); +			} +			gGL.end(); +		} +		gGL.popMatrix(); + +		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha); +		gl_rect_2d(getRect()); +		if (mNeedsFlash) +		{ +			if (mFlashAlpha < 1.f) +			{ +				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f)); +			} +			else +			{ +				mNeedsFlash = FALSE; +			} +		} +		else +		{ +			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f)); +		} + +		// Draw shining animation if appropriate. +		if (mShineCountdown > 0) +		{ +			mShineCountdown--; +			if (mShineCountdown == 0) +			{ +				mShineAnimTimer.start(); +			} +		} +		else if (mShineAnimTimer.getStarted()) +		{ +			lldebugs << "Drawing shining animation" << llendl; +			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME); + +			// draw "shine" effect +			LLLocalClipRect clip(getLocalRect()); +			{ +				// draw diagonal stripe with gradient that passes over screen +				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f))); +				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH); +				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH); +				S32 y1 = 0; +				S32 y2 = gViewerWindow->getWindowHeightScaled(); + +				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +				gGL.begin(LLRender::QUADS); +				{ +					gGL.color4f(1.f, 1.f, 1.f, 0.f); +					gGL.vertex2i(x1, y1); +					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2); +					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); +					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); +					gGL.vertex2i(x2, y1); + +					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY); +					gGL.vertex2i(x2, y1); +					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2); +					gGL.color4f(1.f, 1.f, 1.f, 0.f); +					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2); +					gGL.vertex2i(x3, y1); +				} +				gGL.end(); +			} + +			// if we're at the end of the animation, stop +			if (shine_interp >= 1.f) +			{ +				mShineAnimTimer.stop(); +			} +		} +	} + +	// draw framing rectangle +	{ +		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +		gGL.color4f(1.f, 1.f, 1.f, 1.f); +		const LLRect& outline_rect = getImageRect(); +		gGL.begin(LLRender::QUADS); +		{ +			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); +			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); +			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); +			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); + +			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); +			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); +			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); +			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); + +			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop); +			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom); +			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); +			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); + +			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom); +			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop); +			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); +			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH); +		} +		gGL.end(); +	} + +	// draw old image dropping away +	if (mFallAnimTimer.getStarted()) +	{ +		S32 old_image_index = (mCurImageIndex + 1) % 2; +		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME) +		{ +			lldebugs << "Drawing fall animation" << llendl; +			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME; +			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f); +			LLColor4 image_color(1.f, 1.f, 1.f, alpha); +			gGL.color4fv(image_color.mV); +			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]); +			// calculate UV scale +			// *FIX get this to work with old image +			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull(); +			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f; +			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f; +			gGL.pushMatrix(); +			{ +				LLRect& rect = mImageRect[old_image_index]; +				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f); +				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f); +				gGL.begin(LLRender::QUADS); +				{ +					gGL.texCoord2f(uv_width, uv_height); +					gGL.vertex2i(rect.getWidth(), rect.getHeight() ); + +					gGL.texCoord2f(0.f, uv_height); +					gGL.vertex2i(0, rect.getHeight() ); + +					gGL.texCoord2f(0.f, 0.f); +					gGL.vertex2i(0, 0); + +					gGL.texCoord2f(uv_width, 0.f); +					gGL.vertex2i(rect.getWidth(), 0); +				} +				gGL.end(); +			} +			gGL.popMatrix(); +		} +	} +} + +/*virtual*/  +void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent) +{ +	LLRect old_rect = getRect(); +	LLView::reshape(width, height, called_from_parent); +	if (old_rect.getWidth() != width || old_rect.getHeight() != height) +	{ +		lldebugs << "window reshaped, updating thumbnail" << llendl; +		updateSnapshot(FALSE, TRUE); +	} +} + +BOOL LLSnapshotLivePreview::setThumbnailImageSize() +{ +	if(getWidth() < 10 || getHeight() < 10) +	{ +		return FALSE ; +	} +	S32 window_width = gViewerWindow->getWindowWidthRaw() ; +	S32 window_height = gViewerWindow->getWindowHeightRaw() ; + +	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); + +	// UI size for thumbnail +	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h. +	const LLRect& thumbnail_rect = mThumbnailPlaceholderRect; +	S32 max_width = thumbnail_rect.getWidth(); +	S32 max_height = thumbnail_rect.getHeight(); + +	if (window_aspect_ratio > (F32)max_width / max_height) +	{ +		// image too wide, shrink to width +		mThumbnailWidth = max_width; +		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio); +	} +	else +	{ +		// image too tall, shrink to height +		mThumbnailHeight = max_height; +		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio); +	} + +	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height) +	{ +		return FALSE ;//if the window is too small, ignore thumbnail updating. +	} + +	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ; +	if(!mKeepAspectRatio) +	{ +		F32 ratio_x = (F32)getWidth() / window_width ; +		F32 ratio_y = (F32)getHeight() / window_height ; + +		//if(getWidth() > window_width || +		//	getHeight() > window_height ) +		{ +			if(ratio_x > ratio_y) +			{ +				top = (S32)(top * ratio_y / ratio_x) ; +			} +			else +			{ +				right = (S32)(right * ratio_x / ratio_y) ; +			}			 +		} +		//else +		//{ +		//	right = (S32)(right * ratio_x) ; +		//	top = (S32)(top * ratio_y) ; +		//} +		left = (S32)((mThumbnailWidth - right) * 0.5f) ; +		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ; +		top += bottom ; +		right += left ; +	} +	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ; + +	return TRUE ; +} + +void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) +{	 +	if(mThumbnailUpdateLock) //in the process of updating +	{ +		return ; +	} +	if(getThumbnailUpToDate() && !force_update)//already updated +	{ +		return ; +	} +	if(getWidth() < 10 || getHeight() < 10) +	{ +		return ; +	} + +	////lock updating +	mThumbnailUpdateLock = TRUE ; + +	if(!setThumbnailImageSize()) +	{ +		mThumbnailUpdateLock = FALSE ; +		mThumbnailUpToDate = TRUE ; +		return ; +	} + +	if(mThumbnailImage) +	{ +		resetThumbnailImage() ; +	}		 + +	LLPointer<LLImageRaw> raw = new LLImageRaw; +	if(!gViewerWindow->thumbnailSnapshot(raw, +		mThumbnailWidth, mThumbnailHeight, +		gSavedSettings.getBOOL("RenderUIInSnapshot"), +		FALSE, +		mSnapshotBufferType) )								 +	{ +		raw = NULL ; +	} + +	if(raw) +	{ +		raw->expandToPowerOfTwo(); +		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		 +		mThumbnailUpToDate = TRUE ; +	} + +	//unlock updating +	mThumbnailUpdateLock = FALSE ;		 +} + + +// Called often. Checks whether it's time to grab a new snapshot and if so, does it. +// Returns TRUE if new snapshot generated, FALSE otherwise. +//static  +BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) +{ +	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; +	if (previewp->getWidth() == 0 || previewp->getHeight() == 0) +	{ +		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl; +		return FALSE; +	} + +	// If we're in freeze-frame mode and camera has moved, update snapshot. +	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); +	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); +	if (gSavedSettings.getBOOL("FreezeTime") &&  +		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)) +	{ +		previewp->mCameraPos = new_camera_pos; +		previewp->mCameraRot = new_camera_rot; +		// request a new snapshot whenever the camera moves, with a time delay +		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); +		lldebugs << "camera moved, updating thumbnail" << llendl; +		previewp->updateSnapshot( +			autosnap, // whether a new snapshot is needed or merely invalidate the existing one +			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image. +			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true. +	} + +	// see if it's time yet to snap the shot and bomb out otherwise. +	previewp->mSnapshotActive =  +		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired()) +		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active +	if ( ! previewp->mSnapshotActive) +	{ +		return FALSE; +	} + +	// time to produce a snapshot +	previewp->setThumbnailImageSize(); + +	lldebugs << "producing snapshot" << llendl; +	if (!previewp->mPreviewImage) +	{ +		previewp->mPreviewImage = new LLImageRaw; +	} + +	if (!previewp->mPreviewImageEncoded) +	{ +		previewp->mPreviewImageEncoded = new LLImageRaw; +	} + +	previewp->setVisible(FALSE); +	previewp->setEnabled(FALSE); + +	previewp->getWindow()->incBusyCount(); +	previewp->setImageScaled(FALSE); + +	// grab the raw image and encode it into desired format +	if(gViewerWindow->rawSnapshot( +		previewp->mPreviewImage, +		previewp->getWidth(), +		previewp->getHeight(), +		previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), +		previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, +		gSavedSettings.getBOOL("RenderUIInSnapshot"), +		FALSE, +		previewp->mSnapshotBufferType, +		previewp->getMaxImageSize())) +	{ +		previewp->mPreviewImageEncoded->resize( +			previewp->mPreviewImage->getWidth(),  +			previewp->mPreviewImage->getHeight(),  +			previewp->mPreviewImage->getComponents()); + +		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) +		{ +			lldebugs << "Encoding new image of format J2C" << llendl; +			LLPointer<LLImageJ2C> formatted = new LLImageJ2C; +			LLPointer<LLImageRaw> scaled = new LLImageRaw( +				previewp->mPreviewImage->getData(), +				previewp->mPreviewImage->getWidth(), +				previewp->mPreviewImage->getHeight(), +				previewp->mPreviewImage->getComponents()); + +			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); +			previewp->setImageScaled(TRUE); +			if (formatted->encode(scaled, 0.f)) +			{ +				previewp->mDataSize = formatted->getDataSize(); +				formatted->decode(previewp->mPreviewImageEncoded, 0); +			} +		} +		else +		{ +			// delete any existing image +			previewp->mFormattedImage = NULL; +			// now create the new one of the appropriate format. +			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat(); +			lldebugs << "Encoding new image of format " << format << llendl; + +			switch(format) +			{ +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: +				previewp->mFormattedImage = new LLImagePNG();  +				break; +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: +				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality);  +				break; +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: +				previewp->mFormattedImage = new LLImageBMP();  +				break; +			} +			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0)) +			{ +				previewp->mDataSize = previewp->mFormattedImage->getDataSize(); +				// special case BMP to copy instead of decode otherwise decode will crash. +				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) +				{ +					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage); +				} +				else +				{ +					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0); +				} +			} +		} + +		LLPointer<LLImageRaw> scaled = new LLImageRaw( +			previewp->mPreviewImageEncoded->getData(), +			previewp->mPreviewImageEncoded->getWidth(), +			previewp->mPreviewImageEncoded->getHeight(), +			previewp->mPreviewImageEncoded->getComponents()); + +		if(!scaled->isBufferInvalid()) +		{ +			// leave original image dimensions, just scale up texture buffer +			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) +			{ +				// go ahead and shrink image to appropriate power of 2 for display +				scaled->biasedScaleToPowerOfTwo(1024); +				previewp->setImageScaled(TRUE); +			} +			else +			{ +				// expand image but keep original image data intact +				scaled->expandToPowerOfTwo(1024, FALSE); +			} + +			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); +			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; +			gGL.getTexUnit(0)->bind(curr_preview_image); +			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) +			{ +				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); +			} +			else +			{ +				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +			} +			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); + +			previewp->mSnapshotUpToDate = TRUE; +			previewp->generateThumbnailImage(TRUE) ; + +			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); +			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame +		} +	} +	previewp->getWindow()->decBusyCount(); +	// only show fullscreen preview when in freeze frame mode +	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); +	previewp->mSnapshotDelayTimer.stop(); +	previewp->mSnapshotActive = FALSE; + +	if(!previewp->getThumbnailUpToDate()) +	{ +		previewp->generateThumbnailImage() ; +	} +	lldebugs << "done creating snapshot" << llendl; +	LLFloaterSnapshot::postUpdate(); +	LLFloaterSocial::postUpdate(); + +	return TRUE; +} + +void LLSnapshotLivePreview::setSize(S32 w, S32 h) +{ +	lldebugs << "setSize(" << w << ", " << h << ")" << llendl; +	setWidth(w); +	setHeight(h); +} + +void LLSnapshotLivePreview::getSize(S32& w, S32& h) const +{ +	w = getWidth(); +	h = getHeight(); +} + +void LLSnapshotLivePreview::saveTexture() +{ +	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl; +	// gen a new uuid for this asset +	LLTransactionID tid; +	tid.generate(); +	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + +	LLPointer<LLImageJ2C> formatted = new LLImageJ2C; +	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(), +		mPreviewImage->getWidth(), +		mPreviewImage->getHeight(), +		mPreviewImage->getComponents()); + +	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); +	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl; + +	if (formatted->encode(scaled, 0.0f)) +	{ +		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); +		std::string pos_string; +		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); +		std::string who_took_it; +		LLAgentUI::buildFullname(who_took_it); +		LLAssetStorage::LLStoreAssetCallback callback = NULL; +		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); +		void *userdata = NULL; +		upload_new_resource(tid,	// tid +			LLAssetType::AT_TEXTURE, +			"Snapshot : " + pos_string, +			"Taken by " + who_took_it + " at " + pos_string, +			0, +			LLFolderType::FT_SNAPSHOT_CATEGORY, +			LLInventoryType::IT_SNAPSHOT, +			PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload +			LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads +			LLFloaterPerms::getEveryonePerms(), +			"Snapshot : " + pos_string, +			callback, expected_upload_cost, userdata); +		gViewerWindow->playSnapshotAnimAndSound(); +	} +	else +	{ +		LLNotificationsUtil::add("ErrorEncodingSnapshot"); +		llwarns << "Error encoding snapshot" << llendl; +	} + +	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); + +	mDataSize = 0; +} + +BOOL LLSnapshotLivePreview::saveLocal() +{ +	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); + +	if(success) +	{ +		gViewerWindow->playSnapshotAnimAndSound(); +	} +	return success; +} + +void LLSnapshotLivePreview::saveWeb() +{ +	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep! +	// Needs to pass on ownership of the image. +	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); +	if(!jpg) +	{ +		llwarns << "Formatted image not a JPEG" << llendl; +		return; +	} + +	LLSD metadata; +	metadata["description"] = getChild<LLLineEditor>("description")->getText(); + +	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(), +		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4)); + +	gViewerWindow->playSnapshotAnimAndSound(); +} + +void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z) +{ +	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString(); + +	LLWebSharing::instance().shareSnapshot(snapshot, metadata); +} diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h new file mode 100644 index 0000000000..fe3d257b02 --- /dev/null +++ b/indra/newview/llsnapshotlivepreview.h @@ -0,0 +1,164 @@ +/**  +* @file   llsnapshotlivepreview.h +* @brief  Header file for llsnapshotlivepreview +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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_LLSNAPSHOTLIVEPREVIEW_H +#define LL_LLSNAPSHOTLIVEPREVIEW_H + +#include "llpanelsnapshot.h" +#include "llviewerwindow.h" + +class LLImageJPEG; + +///---------------------------------------------------------------------------- +/// Class LLSnapshotLivePreview  +///---------------------------------------------------------------------------- +class LLSnapshotLivePreview : public LLView +{ +	LOG_CLASS(LLSnapshotLivePreview); +public: +	enum ESnapshotType +	{ +		SNAPSHOT_POSTCARD, +		SNAPSHOT_TEXTURE, +		SNAPSHOT_LOCAL, +		SNAPSHOT_WEB +	}; + + +	struct Params : public LLInitParam::Block<Params, LLView::Params> +	{ +		Params() +		{ +			name = "snapshot_live_preview"; +			mouse_opaque = false; +		} +	}; + + +	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p); +	~LLSnapshotLivePreview(); + +	/*virtual*/ void draw(); +	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); + +	void setSize(S32 w, S32 h); +	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; } +	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; } +	void getSize(S32& w, S32& h) const; +	S32 getWidth() const { return mWidth[mCurImageIndex]; } +	S32 getHeight() const { return mHeight[mCurImageIndex]; } +	S32 getDataSize() const { return mDataSize; } +	void setMaxImageSize(S32 size) ; +	S32  getMaxImageSize() {return mMaxImageSize ;} + +	ESnapshotType getSnapshotType() const { return mSnapshotType; } +	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } +	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; } +	BOOL isSnapshotActive() { return mSnapshotActive; } +	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; } +	S32  getThumbnailWidth() const { return mThumbnailWidth ; } +	S32  getThumbnailHeight() const { return mThumbnailHeight ; } +	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; } +	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;} +	LLViewerTexture* getCurrentImage(); +	F32 getImageAspect(); +	F32 getAspect() ; +	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; } +	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; } +	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; } +	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } + +	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } +	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } +	void setSnapshotQuality(S32 quality); +	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } +	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); +	void saveWeb(); +	void saveTexture(); +	BOOL saveLocal(); + +	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; } +	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; } + +	/// Sets size of preview thumbnail image and thhe surrounding rect. +	void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; } +	BOOL setThumbnailImageSize() ; +	void generateThumbnailImage(BOOL force_update = FALSE) ; +	void resetThumbnailImage() { mThumbnailImage = NULL ; } +	void drawPreviewRect(S32 offset_x, S32 offset_y) ; + +	// Returns TRUE when snapshot generated, FALSE otherwise. +	static BOOL onIdle( void* snapshot_preview ); + +	// callback for region name resolve +	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z); + +private: +	LLColor4					mColor; +	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen. +	LLRect						mImageRect[2]; +	S32							mWidth[2]; +	S32							mHeight[2]; +	BOOL						mImageScaled[2]; +	S32                         mMaxImageSize ; + +	//thumbnail image +	LLPointer<LLViewerTexture>	mThumbnailImage ; +	S32                         mThumbnailWidth ; +	S32                         mThumbnailHeight ; +	LLRect                      mPreviewRect ; +	BOOL                        mThumbnailUpdateLock ; +	BOOL                        mThumbnailUpToDate ; +	LLRect                      mThumbnailPlaceholderRect; + +	S32							mCurImageIndex; +	LLPointer<LLImageRaw>		mPreviewImage; +	LLPointer<LLImageRaw>		mPreviewImageEncoded; +	LLPointer<LLImageFormatted>	mFormattedImage; +	LLFrameTimer				mSnapshotDelayTimer; +	S32							mShineCountdown; +	LLFrameTimer				mShineAnimTimer; +	F32							mFlashAlpha; +	BOOL						mNeedsFlash; +	LLVector3d					mPosTakenGlobal; +	S32							mSnapshotQuality; +	S32							mDataSize; +	ESnapshotType				mSnapshotType; +	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat; +	BOOL						mSnapshotUpToDate; +	LLFrameTimer				mFallAnimTimer; +	LLVector3					mCameraPos; +	LLQuaternion				mCameraRot; +	BOOL						mSnapshotActive; +	LLViewerWindow::ESnapshotType mSnapshotBufferType; + +public: +	static std::set<LLSnapshotLivePreview*> sList; +	BOOL                        mKeepAspectRatio ; +}; + +#endif // LL_LLSNAPSHOTLIVEPREVIEW_H + diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 00eb0c1ab1..2c83f6d0b7 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1568,7 +1568,7 @@ void LLSpatialGroup::checkOcclusion()  			{  				glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); -				static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); +				static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion", true);  				if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)  				{ //query was issued last frame, wait until it's available diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 1a3add2bfb..626d69aca4 100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -118,6 +118,11 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)  	}  } + LLPanel * LLSysWellWindow::findItemByID(const LLUUID& id) +{ +       return mMessageList->getItemByValue(id); +} +  //---------------------------------------------------------------------------------  //---------------------------------------------------------------------------------  void LLSysWellWindow::initChannel()  diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index cc5c057d8b..71b41476f5 100755 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -55,6 +55,7 @@ public:  	// Operating with items  	void removeItemByID(const LLUUID& id); +	LLPanel * findItemByID(const LLUUID& id);  	// Operating with outfit  	virtual void setVisible(BOOL visible); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index bcb55c4bbe..e5f2ca7e5c 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1270,7 +1270,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == LOAD_FROM_NETWORK)  	{ -		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP"); +		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP", true);  // 		if (mHost != LLHost::invalid) get_url = false;  		if ( use_http && mCanUseHTTP && mUrl.empty())//get http url. @@ -1697,7 +1697,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == DECODE_IMAGE)  	{ -		static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); +		static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false);  		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it  		if (textures_decode_disabled) @@ -1873,9 +1873,9 @@ bool LLTextureFetchWorker::doWork(S32 param)  // virtual  void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)  { -	static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog"); -	static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator"); -	static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic") ; +	static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog", false); +	static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator", false); +	static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic", false) ;  	LLMutexLock lock(&mWorkMutex);										// +Mw @@ -2885,7 +2885,7 @@ void LLTextureFetch::commonUpdate()  //virtual  S32 LLTextureFetch::update(F32 max_time_ms)  { -	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS"); +	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 500.0);  	{  		mNetworkQueueMutex.lock();										// +Mfnq @@ -3108,8 +3108,8 @@ void LLTextureFetch::sendRequestListToSimulators()  // 				llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard  // 						<< " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; -				static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); -				static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); +				static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false); +				static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false);  				if (log_to_viewer_log || log_to_sim)  				{  					mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); @@ -3368,8 +3368,8 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1  	if (packet_num >= (worker->mTotalPackets - 1))  	{ -		static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); -		static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); +		static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false); +		static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false);  		if (log_to_viewer_log || log_to_sim)  		{ diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index d876c9a3f4..448fae48de 100755 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -555,7 +555,7 @@ BOOL LLToast::handleMouseDown(S32 x, S32 y, MASK mask)  		mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y);  	} -	return LLFloater::handleMouseDown(x, y, mask); +	return LLModalDialog::handleMouseDown(x, y, mask);  }  //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 3f75f8da5e..6083210080 100755 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -492,7 +492,7 @@ void LLToastAlertPanel::draw()  	}  	static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow"); -	static LLUICachedControl<S32> shadow_lines ("DropShadowFloater"); +	static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 5);  	gl_drop_shadow( 0, LLToastPanel::getRect().getHeight(), LLToastPanel::getRect().getWidth(), 0,  		shadow_color, shadow_lines); diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 09ab31df36..bdbd8f1f83 100755 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -93,7 +93,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	if(!mIsGroupMsg)  	{ -		mAvatarName->setValue(p.from); +	mAvatarName->setValue(p.from);  	}  	mTime->setValue(p.time);  	mSessionID = p.session_id; @@ -164,7 +164,7 @@ void LLToastIMPanel::spawnNameToolTip()  	params.background_visible(false);  	if(!mIsGroupMsg)  	{ -		params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); +	params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));  	}  	else  	{ diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 94d07b37ef..3a41bf28b4 100755 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -407,6 +407,28 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )  	}  } +bool LLToastNotifyPanel::isControlPanelEnabled() const +{ +	bool cp_enabled = mControlPanel->getEnabled(); +	bool some_buttons_enabled = false; +	if (cp_enabled) +	{ +		LLView::child_list_const_iter_t child_it = mControlPanel->beginChild(); +		LLView::child_list_const_iter_t child_it_end = mControlPanel->endChild(); +		for(; child_it != child_it_end; ++child_it) +		{ +			LLButton * buttonp = dynamic_cast<LLButton *>(*child_it); +			if (buttonp && buttonp->getEnabled()) +			{ +				some_buttons_enabled = true; +				break; +			} +		} +	} + +	return cp_enabled && some_buttons_enabled; +} +  //////////////////////////////////////////////////////////////////////////  LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index d02171b512..fe7f1cf8f3 100755 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -69,6 +69,8 @@ public:  	virtual void updateNotification() {} +	bool isControlPanelEnabled() const; +  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index a30f841980..e1b764a943 100755 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -53,6 +53,12 @@ std::string LLToastPanel::getTitle()  }  //virtual +const std::string& LLToastPanel::getNotificationName() +{ +	return mNotification->getName(); +} + +//virtual  const LLUUID& LLToastPanel::getID()  {  	return mNotification->id(); diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index e4ab95007e..51630381f2 100755 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -45,6 +45,7 @@ public:  	virtual ~LLToastPanel() = 0;  	virtual std::string getTitle(); +	virtual const std::string& getNotificationName();  	virtual const LLUUID& getID();  	static const S32 MIN_PANEL_HEIGHT; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index ef7d0cd81b..1a137f7129 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -355,7 +355,7 @@ void LLToolDragAndDrop::setDragStart(S32 x, S32 y)  BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y)  { -	static LLCachedControl<S32> drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold"); +	static LLCachedControl<S32> drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold", 3);  	S32 mouse_delta_x = x - mDragStartX;  	S32 mouse_delta_y = y - mDragStartY; diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index dd17068be5..a80b9da13c 100755 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -103,22 +103,29 @@ LLSD LLURLHistory::getURLHistory(const std::string& collection)  // static  void LLURLHistory::addURL(const std::string& collection, const std::string& url)  { -	if(! url.empty()) +	if(!url.empty())  	{ -		sHistorySD[collection].insert(0, url); +        LLURI u(url); +        std::string simplified_url = u.scheme() + "://" + u.authority() + u.path(); +		sHistorySD[collection].insert(0, simplified_url);  		LLURLHistory::limitSize(collection);  	}  }  // static  void LLURLHistory::removeURL(const std::string& collection, const std::string& url)  { -	for(int index = 0; index < sHistorySD[collection].size(); index++) +	if(!url.empty())  	{ -		if(sHistorySD[collection].get(index).asString() == url) -		{ -			sHistorySD[collection].erase(index); -		} -	} +        LLURI u(url); +        std::string simplified_url = u.scheme() + "://" + u.authority() + u.path(); +        for(int index = 0; index < sHistorySD[collection].size(); index++) +        { +            if(sHistorySD[collection].get(index).asString() == simplified_url) +            { +                sHistorySD[collection].erase(index); +            } +        } +    }  }  // static diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c6b28b9e5e..4ce049df03 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -103,6 +103,7 @@  #include "llfloatersettingsdebug.h"  #include "llfloatersidepanelcontainer.h"  #include "llfloatersnapshot.h" +#include "llfloatersocial.h"  #include "llfloatersounddevices.h"  #include "llfloaterspellchecksettings.h"  #include "llfloatertelehub.h" @@ -303,6 +304,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);  	LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);  	LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>); +	LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);  	LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);  	LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);  	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); @@ -311,7 +313,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);  	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);  	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);	 - +	LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);  	LLFloaterUIPreviewUtil::registerFloater();  	LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload"); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index f6e840adcd..aeeb591d55 100755 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -919,7 +919,7 @@ void LLViewerJoystick::moveFlycam(bool reset)  		{  			if (i == X_I || i == Y_I || i == Z_I)  			{ -				static LLCachedControl<F32> build_mode_scale(gSavedSettings,"FlycamBuildModeScale"); +				static LLCachedControl<F32> build_mode_scale(gSavedSettings,"FlycamBuildModeScale", 1.0);  				cur_delta[i] *= build_mode_scale;  			}  		} diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 2fbb3bf868..aa9de076b8 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -687,7 +687,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL  	{  		// it is sufficient to set this value once per call to handlekey  		// without clearing it, as it is only used in the subsequent call to scanKey -		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); +		mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask);  +		// mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress) +		// NOT whether some UI shortcut wishes to handle the keypress +	    	}  	return mKeyHandledByUI[translated_key];  } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 2df028de69..21fb8d519b 100755 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2000,7 +2000,12 @@ void LLViewerMediaImpl::loadURI()  										"<>#%"  										";/?:@&=",  										false); -		llinfos << "Asking media source to load URI: " << uri << llendl; +        { +            // Do not log the query parts +            LLURI u(uri); +            std::string sanitized_uri = (u.query().empty() ? uri : u.scheme() + "://" + u.authority() + u.path()); +            llinfos << "Asking media source to load URI: " << sanitized_uri << llendl; +        }  		mMediaSource->loadURI( uri ); @@ -2567,7 +2572,12 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi  	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)  	{  		// Helpful to have media urls in log file. Shouldn't be spammy. -		llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl; +        { +            // Do not log the query parts +            LLURI u(url); +            std::string sanitized_url = (u.query().empty() ? url : u.scheme() + "://" + u.authority() + u.path()); +            llinfos << "NOT LOADING media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mime_type << llendl; +        }  		// This impl should not be loaded at this time.  		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL; @@ -2582,7 +2592,12 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi  void LLViewerMediaImpl::navigateInternal()  {  	// Helpful to have media urls in log file. Shouldn't be spammy. -	llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl; +    { +        // Do not log the query parts +        LLURI u(mMediaURL); +        std::string sanitized_url = (u.query().empty() ? mMediaURL : u.scheme() + "://" + u.authority() + u.path()); +        llinfos << "media id= " << mTextureId << " url=" << sanitized_url << ", mime_type=" << mMimeType << llendl; +    }  	if(mNavigateSuspended)  	{ @@ -3758,18 +3773,18 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const  	// If it is attached to an avatar and the pref is off, we shouldn't show it  	if (attached_to_another_avatar)  	{ -		static LLCachedControl<bool> show_media_on_others(gSavedSettings, LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); +		static LLCachedControl<bool> show_media_on_others(gSavedSettings, LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING, false);  		return show_media_on_others;  	}  	if (inside_parcel)  	{ -		static LLCachedControl<bool> show_media_within_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); +		static LLCachedControl<bool> show_media_within_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING, true);  		return show_media_within_parcel;  	}  	else   	{ -		static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); +		static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING, true);  		return show_media_outside_parcel;  	} diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9468a2d542..ac2940fcfc 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -40,11 +40,13 @@  #include "llinventorypanel.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" +#include "llviewereventrecorder.h"  // newview includes  #include "llagent.h"  #include "llagentaccess.h"  #include "llagentcamera.h" +#include "llagentui.h"  #include "llagentwearables.h"  #include "llagentpilot.h"  #include "llcompilequeue.h" @@ -52,6 +54,7 @@  #include "lldaycyclemanager.h"  #include "lldebugview.h"  #include "llenvmanager.h" +#include "llfacebookconnect.h"  #include "llfilepicker.h"  #include "llfirstuse.h"  #include "llfloaterbuy.h" @@ -1952,6 +1955,43 @@ class LLAdvancedDropPacket : public view_listener_t  }; +//////////////////// +// EVENT Recorder // +/////////////////// + + +class LLAdvancedViewerEventRecorder : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		std::string command = userdata.asString(); +		if ("start playback" == command) +		{ +			llinfos << "Event Playback starting" << llendl; +			LLViewerEventRecorder::instance().playbackRecording(); +			llinfos << "Event Playback completed" << llendl; +		} +		else if ("stop playback" == command) +		{ +			// Future +		} +		else if ("start recording" == command) +		{ +			LLViewerEventRecorder::instance().setEventLoggingOn(); +			llinfos << "Event recording started" << llendl; +		} +		else if ("stop recording" == command) +		{ +			LLViewerEventRecorder::instance().setEventLoggingOff(); +			llinfos << "Event recording stopped" << llendl; +		}  + +		return true; +	}		 +}; + + +  /////////////////  // AGENT PILOT // @@ -8420,6 +8460,8 @@ void initialize_menus()  	// Don't prepend MenuName.Foo because these can be used in any menu.  	enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); +	enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); +  	view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");  	enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); @@ -8678,6 +8720,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");  	view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");  	view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); +	view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder");  	// Advanced > Debugging  	view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c38af1f990..82131c6675 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -45,6 +45,7 @@  #include "llsd.h"  #include "llsdserialize.h"  #include "llteleportflags.h" +#include "lltoastnotifypanel.h"  #include "lltransactionflags.h"  #include "llvfile.h"  #include "llvfs.h" @@ -2220,7 +2221,7 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t  	case IM_LURE_ACCEPTED:  	case IM_LURE_DECLINED:  	case IM_GODLIKE_LURE_USER: -	case IM_YET_TO_BE_USED: +	case IM_TELEPORT_REQUEST:  	case IM_GROUP_ELECTION_DEPRECATED:  	//IM_GOTO_URL  	//IM_FROM_TASK_AS_ALERT @@ -2988,6 +2989,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  		break;  	case IM_LURE_USER: +	case IM_TELEPORT_REQUEST:  		{  			if (is_muted)  			{  @@ -3010,7 +3012,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				bool canUserAccessDstRegion = true;  				bool doesUserRequireMaturityIncrease = false; -				if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) +				// Do not parse the (empty) lure bucket for TELEPORT_REQUEST +				if (IM_TELEPORT_REQUEST != dialog && parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))  				{  					region_access_str = LLViewerRegion::accessToString(region_access);  					region_access_icn = LLViewerRegion::getAccessIcon(region_access); @@ -3082,12 +3085,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				}  				else  				{ -			    LLNotification::Params params("TeleportOffered"); +					LLNotification::Params params; +					if (IM_LURE_USER == dialog) +					{ +						params.name = "TeleportOffered"; +						params.functor.name = "TeleportOffered"; +					} +					else if (IM_TELEPORT_REQUEST == dialog) +					{ +						params.name = "TeleportRequest"; +						params.functor.name = "TeleportRequest"; +					} +  			    params.substitutions = args;  			    params.payload = payload;  			    LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false);  			} -  			}  		}  		break; @@ -3216,7 +3229,20 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			payload["online"] = (offline == IM_ONLINE);  			payload["sender"] = msg->getSender().getIPandPort(); -			if (is_muted) +			bool add_notification = true; +			for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances()) +				, tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti) +			{ +				LLToastNotifyPanel& panel = *ti; +				const std::string& notification_name = panel.getNotificationName(); +				if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled()) +				{ +					add_notification = false; +					break; +				} +			} + +			if (is_muted && add_notification)  			{  				LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);  			} @@ -3227,18 +3253,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  					send_do_not_disturb_message(msg, from_id);  				}  				args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); -				if(message.empty()) -				{ -					//support for frienship offers from clients before July 2008 -				        LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload); -				} -				else + +				if (add_notification)  				{ -					args["[MESSAGE]"] = message; -				    LLNotification::Params params("OfferFriendship"); -				    params.substitutions = args; -				    params.payload = payload; -				    LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false); +					if(message.empty()) +					{ +						//support for frienship offers from clients before July 2008 +						LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload); +					} +					else +					{ +						args["[MESSAGE]"] = message; +						LLNotification::Params params("OfferFriendship"); +						params.substitutions = args; +						params.payload = payload; +						LLPostponedNotification::add<LLPostponedOfferNotification>(	params, from_id, false); +					}  				}  			}  		} @@ -3804,19 +3834,6 @@ public:  				LLInventoryModel::EXCLUDE_TRASH,  				is_card);  		} -		LLSD args; -		if ( land_items.count() > 0 ) -		{	// Show notification that they can now teleport to landmarks.  Use a random landmark from the inventory -			S32 random_land = ll_rand( land_items.count() - 1 ); -			args["NAME"] = land_items[random_land]->getName(); -			LLNotificationsUtil::add("TeleportToLandmark",args); -		} -		if ( card_items.count() > 0 ) -		{	// Show notification that they can now contact people.  Use a random calling card from the inventory -			S32 random_card = ll_rand( card_items.count() - 1 ); -			args["NAME"] = card_items[random_card]->getName(); -			LLNotificationsUtil::add("TeleportToPerson",args); -		}  		gInventory.removeObserver(this);  		delete this; @@ -4093,18 +4110,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)  		if (isAgentAvatarValid())  		{ -			// Chat the "back" SLURL. (DEV-4907) - -			LLSLURL slurl; -			gAgent.getTeleportSourceSLURL(slurl); -			LLSD substitution = LLSD().with("[T_SLURL]", slurl.getSLURLString()); -			std::string completed_from = LLAgent::sTeleportProgressMessages["completed_from"]; -			LLStringUtil::format(completed_from, substitution); - -			LLSD args; -			args["MESSAGE"] = completed_from; -			LLNotificationsUtil::add("SystemMessageTip", args); -  			// Set the new position  			gAgentAvatarp->setPositionAgent(agent_pos);  			gAgentAvatarp->clearChat(); @@ -6873,6 +6878,51 @@ void send_group_notice(const LLUUID& group_id,  			bin_bucket_size);  } +void send_lures(const LLSD& notification, const LLSD& response) +{ +	std::string text = response["message"].asString(); +	LLSLURL slurl; +	LLAgentUI::buildSLURL(slurl); +	text.append("\r\n").append(slurl.getSLURLString()); + +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_StartLure); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +	msg->nextBlockFast(_PREHASH_Info); +	msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. +	msg->addStringFast(_PREHASH_Message, text); +	for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); +		it != notification["payload"]["ids"].endArray(); +		++it) +	{ +		LLUUID target_id = it->asUUID(); + +		msg->nextBlockFast(_PREHASH_TargetData); +		msg->addUUIDFast(_PREHASH_TargetID, target_id); + +		// Record the offer. +		{ +			std::string target_name; +			gCacheName->getFullName(target_id, target_name);  // for im log filenames +			LLSD args; +			args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();; +	 +			LLSD payload; +				 +			//*TODO please rewrite all keys to the same case, lower or upper +			payload["from_id"] = target_id; +			payload["SUPPRESS_TOAST"] = true; +			LLNotificationsUtil::add("TeleportOfferSent", args, payload); + +			// Add the recepient to the recent people list. +			LLRecentPeople::instance().add(target_id); +		} +	} +	gAgent.sendReliableMessage(); +} +  bool handle_lure_callback(const LLSD& notification, const LLSD& response)  {  	static const unsigned OFFER_RECIPIENT_LIMIT = 250; @@ -6886,50 +6936,12 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  		LLNotificationsUtil::add("TooManyTeleportOffers", args);  		return false;  	} -	 -	std::string text = response["message"].asString(); -	LLSLURL slurl; -	LLAgentUI::buildSLURL(slurl); -	text.append("\r\n").append(slurl.getSLURLString()); +  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	if(0 == option)  	{ -		LLMessageSystem* msg = gMessageSystem; -		msg->newMessageFast(_PREHASH_StartLure); -		msg->nextBlockFast(_PREHASH_AgentData); -		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -		msg->nextBlockFast(_PREHASH_Info); -		msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. -		msg->addStringFast(_PREHASH_Message, text); -		for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); -			it != notification["payload"]["ids"].endArray(); -			++it) -		{ -			LLUUID target_id = it->asUUID(); - -			msg->nextBlockFast(_PREHASH_TargetData); -			msg->addUUIDFast(_PREHASH_TargetID, target_id); - -			// Record the offer. -			{ -				std::string target_name; -				gCacheName->getFullName(target_id, target_name);  // for im log filenames -				LLSD args; -				args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();; -	 -				LLSD payload; -				 -				//*TODO please rewrite all keys to the same case, lower or upper -				payload["from_id"] = target_id; -				LLNotificationsUtil::add("TeleportOfferSent", args, payload); - -				// Add the recepient to the recent people list. -				LLRecentPeople::instance().add(target_id); -			} -		} -		gAgent.sendReliableMessage(); +		send_lures(notification, response);  	}  	return false; @@ -6969,6 +6981,58 @@ void handle_lure(const uuid_vec_t& ids)  	}  } +bool teleport_request_callback(const LLSD& notification, const LLSD& response) +{ +	LLUUID from_id = notification["payload"]["from_id"].asUUID(); +	if(from_id.isNull()) +	{ +		llwarns << "from_id is NULL" << llendl; +		return false; +	} + +	std::string from_name; +	gCacheName->getFullName(from_id, from_name); + +	if(LLMuteList::getInstance()->isMuted(from_id) && !LLMuteList::getInstance()->isLinden(from_name)) +	{ +		return false; +	} + +	S32 option = 0; +	if (response.isInteger())  +	{ +		option = response.asInteger(); +	} +	else +	{ +		option = LLNotificationsUtil::getSelectedOption(notification, response); +	} + +	switch(option) +	{ +	// Yes +	case 0: +		{ +			LLSD dummy_notification; +			dummy_notification["payload"]["ids"][0] = from_id; + +			LLSD dummy_response; +			dummy_response["message"] = response["message"]; + +			send_lures(dummy_notification, dummy_response); +		} +		break; + +	// No +	case 1: +	default: +		break; +	} + +	return false; +} + +static LLNotificationFunctorRegistration teleport_request_callback_reg("TeleportRequest", teleport_request_callback);  void send_improved_im(const LLUUID& to_id,  							const std::string& name, diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7151a0d6ed..1544e66431 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5879,6 +5879,13 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif  	return ;  } +// virtual  +BOOL	LLViewerObject::isTempAttachment() const +{ +	return (mID.notNull() && (mID == mAttachmentItemID)); +} + +  const LLUUID &LLViewerObject::getAttachmentItemID() const  {  	return mAttachmentItemID; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index b035473c74..80bdd628a1 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -171,6 +171,8 @@ public:  	virtual BOOL	isAttachment() const { return FALSE; }  	virtual LLVOAvatar* getAvatar() const;  //get the avatar this object is attached to, or NULL if object is not an attachment  	virtual BOOL	isHUDAttachment() const { return FALSE; } +	virtual BOOL	isTempAttachment() const; +  	virtual void 	updateRadius() {};  	virtual F32 	getVObjRadius() const; // default implemenation is mDrawable->getRadius() diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 66615657d8..b4e287c446 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -954,15 +954,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  			objectp = *idle_iter;  			llassert(objectp->isActive());  			objectp->idleUpdate(agent, world, frame_time); - -			} +		}  		//update flexible objects  		LLVolumeImplFlexible::updateClass();  		//update animated textures -		LLViewerTextureAnim::updateClass(); -			} +		if (gAnimateTextures) +		{ +			LLViewerTextureAnim::updateClass(); +		} +	} diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e9bbcb1097..552df5b1e8 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -232,6 +232,7 @@ public:  		if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder  		{  			LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; +			regionp->failedSeedCapability();  			return ;  		} @@ -301,17 +302,12 @@ public:  		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )  		{ -			llinfos << "BaseCapabilitiesCompleteTracker " << "sim " << regionp->getName() -				<< " sent duplicate seed caps that differs in size - most likely content. "  -				<< (S32) regionp->getRegionImpl()->mCapabilities.size() << " vs " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() -				<< llendl; - +			llinfos<<"BaseCapabilitiesCompleteTracker "<<"Sim sent duplicate seed caps that differs in size - most likely content."<<llendl;			  			//todo#add cap debug versus original check? -			/* -			CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin(); +			/*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin();  			while (iter!=regionp->getRegionImpl()->mCapabilities.end() )  			{ -				llinfos << "BaseCapabilitiesCompleteTracker Original " << iter->first << " " << iter->second<<llendl; +				llinfos<<"BaseCapabilitiesCompleteTracker Original "<<iter->first<<" "<< iter->second<<llendl;  				++iter;  			}  			*/ @@ -399,9 +395,6 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,  	mImpl->mObjectPartition.push_back(new LLBridgePartition());	//PARTITION_BRIDGE  	mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE  	mImpl->mObjectPartition.push_back(NULL);						//PARTITION_NONE - -	mRenderInfoRequestTimer.resetWithExpiry(0.f);		// Set timer to be expired -	setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer, _1));  } @@ -1586,7 +1579,6 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("AgentState");  	capabilityNames.append("AttachmentResources");  	capabilityNames.append("AvatarPickerSearch"); -	capabilityNames.append("AvatarRenderInfo");  	capabilityNames.append("CharacterProperties");  	capabilityNames.append("ChatSessionRequest");  	capabilityNames.append("CopyInventoryFromNotecard"); @@ -1595,6 +1587,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("EnvironmentSettings");  	capabilityNames.append("EstateChangeInfo");  	capabilityNames.append("EventQueueGet"); +	capabilityNames.append("FacebookConnect"); +	//capabilityNames.append("FacebookRedirect");  	if (gSavedSettings.getBOOL("UseHTTPInventory"))  	{ diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 50f0a5f1af..553f6a2d59 100755 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -461,7 +461,7 @@ void LLViewerShaderMgr::setShaders()  		S32 deferred_class = 0;  		S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; -		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); +		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);  		if (!use_transform_feedback)  		{  			transform_class = 0; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 84f66c359f..693eca8a06 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1422,7 +1422,7 @@ void LLViewerFetchedTexture::processTextureStats()  	{  		updateVirtualSize() ; -		static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); +		static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false);  		if (textures_fullres)  		{ @@ -1747,9 +1747,9 @@ bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level)  bool LLViewerFetchedTexture::updateFetch()  { -	static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); -	static LLCachedControl<F32>  sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold"); -	static LLCachedControl<S32>  sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost"); +	static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); +	static LLCachedControl<F32>  sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2); +	static LLCachedControl<S32>  sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3);  	if(textures_decode_disabled)  	{  		return false ; @@ -2828,7 +2828,7 @@ void LLViewerLODTexture::processTextureStats()  {  	updateVirtualSize() ; -	static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); +	static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false);  	if (textures_fullres)  	{ diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 2efe4665fa..783d1f2202 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -500,7 +500,7 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,  												   LLGLenum primary_format,  												   LLHost request_from_host)  { -	static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled"); +	static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled", true);  	LLPointer<LLViewerFetchedTexture> imagep ;  	switch(texture_type) @@ -1373,7 +1373,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)  // static  void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data)  { -	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; +	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;  	LLFastTimer t(FTM_PROCESS_IMAGES); @@ -1445,7 +1445,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d  // static  void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data)  { -	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; +	static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;  	LLFastTimer t(FTM_PROCESS_IMAGES); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bf11bce3da..cb7536edce 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -198,6 +198,8 @@  #include "llagentui.h"  #include "llwearablelist.h" +#include "llviewereventrecorder.h" +  #include "llnotifications.h"  #include "llnotificationsutil.h"  #include "llnotificationmanager.h" @@ -313,7 +315,7 @@ public:  	void update()  	{ -		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; +		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;  		std::string wind_vel_text;  		std::string wind_vector_text; @@ -954,27 +956,18 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK  			{  				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;  			} -			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); -		} -		// Topmost view gets a chance before the hierarchy -		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); -		//if (top_ctrl) -		//{ -		//	S32 local_x, local_y; -		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); -		//		if (top_ctrl->pointInView(local_x, local_y)) -		//		{ -		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	; -		//		} -		//		else -		//		{ -		//		if (down) -		//		{ -		//			gFocusMgr.setTopCtrl(NULL); -		//		} -		//	} -		//} +			BOOL r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);  +			if (r) { + +				lldebugs << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x  "<< local_x << " " << x  << "local/global y " << local_y << " " << y << llendl; + +				LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); +				LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname));  + +			} +			return r; +		}  		// Mark the click as handled and return if we aren't within the root view to avoid spurious bugs  		if( !mRootView->pointInView(x, y) ) @@ -982,27 +975,44 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK  			return TRUE;  		}  		// Give the UI views a chance to process the click -		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ) + +		BOOL r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; +		if (r)   		{ + +			lldebugs << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x  "<< " " << x	<< "global y " << y	 << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << llendl; + +			LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + +			// Clear local coords - this was a click on root window so these are not needed +			// By not including them, this allows the test skeleton generation tool to be smarter when generating code +			// the code generator can be smarter because when local coords are present it can try the xui path with local coords +			// and fallback to global coordinates only if needed.  +			// The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element +			// (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) +			// For this reason it's best to provide hints where possible here by leaving out local coordinates +			LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); +			LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname);  +  			if (LLView::sDebugMouseHandling)  			{ -				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl; -			} +				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui()	<< llendl; +			}   			return TRUE; -		} -		else if (LLView::sDebugMouseHandling) -		{ -			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; -		} +		} else if (LLView::sDebugMouseHandling) +			{ +				llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; +			}  	}  	// Do not allow tool manager to handle mouseclicks if we have disconnected	  	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )  	{ +		LLViewerEventRecorder::instance().clear_xui();   		return TRUE;  	} -	 +	  	// If we got this far on a down-click, it wasn't handled.  	// Up-clicks, though, are always handled as far as the OS is concerned.  	BOOL default_rtn = !down; @@ -1373,7 +1383,8 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)  void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)  {  	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); -	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level); +	gViewerKeyboard.scanKey(key, key_down, key_up, key_level); +	return; // Be clear this function returns nothing  } @@ -2519,6 +2530,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))  		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))  	{ +		lldebugs << "LLviewerWindow::handleKey handle nav keys for nav" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2533,12 +2546,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  			&& keyboard_focus   			&& keyboard_focus->handleKey(key,mask,FALSE))  		{ +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);  			return TRUE;  		}  		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))  			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))  		{ +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);  			return TRUE;  		}  	} @@ -2548,6 +2563,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// if nothing has focus, go to first or last UI element as appropriate  	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))  	{ +		llwarns << "LLviewerWindow::handleKey give floaters first chance at tab key " << llendl;  		if (gMenuHolder) gMenuHolder->hideMenus();  		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode @@ -2562,11 +2578,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		{  			mRootView->focusNextRoot();  		} +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	}  	// hidden edit menu for cut/copy/paste  	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))  	{ +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2606,18 +2624,27 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  		if (keyboard_focus->handleKey(key, mask, FALSE))  		{ + +			lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << llendl; +			LLViewerEventRecorder::instance().logKeyEvent(key,mask);   			return TRUE; +		} else { +			lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned FALSE" << llendl;  		}  	}  	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )  	{ +		lldebugs << "LLviewerWindow::handleKey toolbar handling?" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	}  	// Try for a new-format gesture  	if (LLGestureMgr::instance().triggerGesture(key, mask))  	{ +		lldebugs << "LLviewerWindow::handleKey new gesture feature" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2625,6 +2652,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// don't pass it down to the menus.  	if (gGestureList.trigger(key, mask))  	{ +		lldebugs << "LLviewerWindow::handleKey check gesture trigger" << llendl; +		LLViewerEventRecorder::instance().logKeyEvent(key,mask);  		return TRUE;  	} @@ -2673,7 +2702,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  	// HACK: Numeric keypad <enter> on Mac is Unicode 3  	// HACK: Control-M on Windows is Unicode 13  	if ((uni_char == 13 && mask != MASK_CONTROL) -		|| (uni_char == 3 && mask == MASK_NONE)) +	    || (uni_char == 3 && mask == MASK_NONE) )  	{  		if (mask != MASK_ALT)  		{ @@ -2696,14 +2725,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  			return TRUE;  		} -		//// Topmost view gets a chance before the hierarchy -		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); -		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) ) -		//{ -		//	return TRUE; -		//} - -		return TRUE; +        return TRUE;  	}  	return FALSE; @@ -2712,8 +2734,6 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  void LLViewerWindow::handleScrollWheel(S32 clicks)  { -	LLView::sMouseHandlerMessage.clear(); -  	LLUI::resetMouseIdleTimer();  	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index fe035a0a7f..f5918a0a5f 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -707,7 +707,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mVisualComplexityStale(TRUE),  	mLoadedCallbacksPaused(FALSE),  	mHasPelvisOffset( FALSE ), -	mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")), +	mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)),  	mLastRezzedStatus(-1),  	mIsEditingAppearance(FALSE),  	mUseLocalAppearance(FALSE), @@ -2707,8 +2707,8 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				LLFontGL::getFontSansSerifSmall());  		} -		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); -		static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); +		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames", true); +		static LLUICachedControl<bool> show_usernames("NameTagShowUsernames", true);  		if (LLAvatarName::useDisplayNames())  		{ @@ -2934,7 +2934,7 @@ void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)  LLColor4 LLVOAvatar::getNameTagColor(bool is_friend)  { -	static LLUICachedControl<bool> show_friends("NameTagShowFriends"); +	static LLUICachedControl<bool> show_friends("NameTagShowFriends", false);  	const char* color_name;  	if (show_friends && is_friend)  	{ @@ -2989,7 +2989,7 @@ bool LLVOAvatar::isVisuallyMuted()  	if (!isSelf())  	{ -		static LLCachedControl<U32> render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions"); +		static LLCachedControl<U32> render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions", 0);  		if (render_auto_mute_functions)		// Hacky debug switch for developing feature  		{  			// Priority order (highest priority first) @@ -3001,9 +3001,9 @@ bool LLVOAvatar::isVisuallyMuted()  			//       - AND aren't over the thresholds  			// * otherwise visually mute all other avatars -			static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); -			static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); -			static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit"); +			static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit", 0); +			static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 0.0); +			static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit", 0);  			if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE)  			{	// Always want to see this AV as an impostor @@ -3390,8 +3390,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  			LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV ); -			static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow"); -			static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast"); +			static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); +			static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0);  			F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); @@ -5521,7 +5521,15 @@ void LLVOAvatar::addChild(LLViewerObject *childp)  	LLViewerObject::addChild(childp);  	if (childp->mDrawable)  	{ -		attachObject(childp); +		if (!attachObject(childp)) +		{ +			llwarns << "addChild() failed for "  +					<< childp->getID() +					<< " item " << childp->getAttachmentItemID() +					<< llendl; +			// MAINT-3312 backout +			// mPendingAttachment.push_back(childp); +		}  	}  	else  	{ @@ -5554,8 +5562,27 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi  	if (!attachment)  	{ -		llwarns << "Object attachment point invalid: " << attachmentID << llendl; -		attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest) +		llwarns << "Object attachment point invalid: " << attachmentID  +			<< " trying to use 1 (chest)" +			<< llendl; + +		attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL);	// Arbitrary using 1 (chest) +		if (attachment) +		{ +			llwarns << "Object attachment point invalid: " << attachmentID  +				<< " on object " << viewer_object->getID() +				<< " attachment item " << viewer_object->getAttachmentItemID() +				<< " falling back to 1 (chest)" +				<< llendl; +		} +		else +		{ +			llwarns << "Object attachment point invalid: " << attachmentID  +				<< " on object " << viewer_object->getID() +				<< " attachment item " << viewer_object->getAttachmentItemID() +				<< "Unable to use fallback attachment point 1 (chest)" +				<< llendl; +		}  	}  	return attachment; @@ -5626,13 +5653,22 @@ void LLVOAvatar::lazyAttach()  	for (U32 i = 0; i < mPendingAttachment.size(); i++)  	{ -		if (mPendingAttachment[i]->mDrawable) +		LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i]; +		if (cur_attachment->mDrawable)  		{ -			attachObject(mPendingAttachment[i]); +			if (!attachObject(cur_attachment)) +			{	// Drop it +				llwarns << "attachObject() failed for "  +					<< cur_attachment->getID() +					<< " item " << cur_attachment->getAttachmentItemID() +					<< llendl; +				// MAINT-3312 backout +				//still_pending.push_back(cur_attachment); +			}  		}  		else  		{ -			still_pending.push_back(mPendingAttachment[i]); +			still_pending.push_back(cur_attachment);  		}  	} @@ -5939,6 +5975,28 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const +LLViewerObject *	LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const +{ +	for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin(); +		attachment_points_iter != gAgentAvatarp->mAttachmentPoints.end(); +		++attachment_points_iter) +	{ +		LLViewerJointAttachment* attachment = attachment_points_iter->second; +		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +			 attachment_iter != attachment->mAttachedObjects.end(); +			 ++attachment_iter) +		{ +			LLViewerObject *attached_object = (*attachment_iter); +			if (attached_object && +				attached_object->getID() == target_id) +			{ +				return attached_object; +			} +		} +	} + +	return NULL; +}  // virtual @@ -7877,7 +7935,7 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d  void LLVOAvatar::idleUpdateRenderCost()  { -	static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit"); +	static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit", 0);  	static const U32 ARC_LIMIT = 20000;  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 931e65b3ea..9d45a74ecc 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -731,6 +731,8 @@ public:  	void				cleanupAttachedMesh( LLViewerObject* pVO );  	static LLVOAvatar*  findAvatarFromAttachment(LLViewerObject* obj);  	/*virtual*/ BOOL	isWearingWearableType(LLWearableType::EType type ) const; +	LLViewerObject *	findAttachmentByID( const LLUUID & target_id ) const; +  protected:  	LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);  	void 				lazyAttach(); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index af55c8f741..815965fb0a 100755 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -113,8 +113,8 @@ LLVoiceClient::LLVoiceClient()  	:  	mVoiceModule(NULL),  	m_servicePump(NULL), -	mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled")), -	mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault")), +	mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled", true)), +	mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault", "00000000-0000-0000-0000-000000000000")),  	mPTTDirty(true),  	mPTT(true),  	mUsePTT(true), diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index ff73aa5354..9497041482 100755 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -786,7 +786,6 @@ void LLVivoxVoiceClient::stateMachine()  						{  							loglevel = "0";	// turn logging off completely  						} -						loglevel = "0";	// turn logging off completely  						params.args.add("-ll");  						params.args.add(loglevel);  						params.cwd = gDirUtilp->getAppRODataDir(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d9efd23b43..dfac77857c 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -343,6 +343,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  					}  				}  				mTexAnimMode = 0; +				  				mTextureAnimp->unpackTAMessage(mesgsys, block_num);  			}  			else @@ -693,7 +694,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  		}  	} -	static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); +	static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable", false);  	if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible())  	{ @@ -1036,8 +1037,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  			}  		} - -		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); +		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);  		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject &&  			(!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); @@ -2618,7 +2618,6 @@ void LLVOVolume::setLightTextureID(LLUUID id)  		if (hasLightTexture())  		{  			setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); -			parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);  			mLightTexture = NULL;  		}  	}		 @@ -2636,8 +2635,7 @@ void LLVOVolume::setSpotLightParams(LLVector3 params)  void LLVOVolume::setIsLight(BOOL is_light)  { -	BOOL was_light = getIsLight(); -	if (is_light != was_light) +	if (is_light != getIsLight())  	{  		if (is_light)  		{ @@ -2822,7 +2820,7 @@ void LLVOVolume::updateSpotLightPriority()  bool LLVOVolume::isLightSpotlight() const  {  	LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); -	if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) +	if (params)  	{  		return params->isLightSpotlight();  	} @@ -3752,30 +3750,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  			{  				LLFace* face = mDrawable->getFace(face_hit);				 -				bool ignore_alpha = false; - -				const LLTextureEntry* te = face->getTextureEntry(); -				if (te) -				{ -					LLMaterial* mat = te->getMaterialParams(); -					if (mat) -					{ -						U8 mode = mat->getDiffuseAlphaMode(); - -						if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || -							mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) -						{ -							ignore_alpha = true; -						} -					} -				} -  				if (face && -					(ignore_alpha || -					pick_transparent ||  -					!face->getTexture() ||  -					!face->getTexture()->hasGLTexture() ||  -					face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) +					(pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))))  				{  					local_end = p;  					if (face_hitp != NULL) @@ -4460,6 +4436,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	bool emissive = false; +	 +  	{  		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); @@ -5198,7 +5176,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac  	U32 buffer_usage = group->mBufferUsage; -	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);  	if (use_transform_feedback &&  		gTransformPositionProgram.mProgramObject && //transform shaders are loaded diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 641f338f2c..69255af179 100755 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -148,9 +148,6 @@ public:  		LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl;  		LLWebProfile::reportImageUploadStatus(true);  	} - -private: -	LLPointer<LLImageFormatted> mImagep;  }; @@ -172,7 +169,7 @@ public:  			headers["Cookie"] = LLWebProfile::getAuthCookie();  			const std::string& redir_url = content["location"];  			LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; -			LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); +			LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder(), headers);  		}  		else  		{ diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index 28f959eb71..a8e06511d7 100755 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -265,7 +265,9 @@ void LLWindowListener::getPaths(LLSD const & request)  void LLWindowListener::keyDown(LLSD const & evt)  {  	Response response(LLSD(), evt); -	 +	KEY key = getKEY(evt); +	MASK mask = getMask(evt); +  	if (evt.has("path"))  	{  		std::string path(evt["path"]); @@ -280,8 +282,6 @@ void LLWindowListener::keyDown(LLSD const & evt)  			response.setResponse(target_view->getInfo());  			gFocusMgr.setKeyboardFocus(target_view); -			KEY key = getKEY(evt); -			MASK mask = getMask(evt);  			gViewerKeyboard.handleKey(key, mask, false);  			if(key < 0x80) mWindow->handleUnicodeChar(key, mask);  		} @@ -294,7 +294,8 @@ void LLWindowListener::keyDown(LLSD const & evt)  	}  	else   	{ -		mKbGetter()->handleTranslatedKeyDown(getKEY(evt), getMask(evt)); +		gViewerKeyboard.handleKey(key, mask, false);  +		if(key < 0x80) mWindow->handleUnicodeChar(key, mask);  	}  } diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 7996f8a640..103668d051 100755 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -140,6 +140,7 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host)  {  	llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl;  	LLViewerRegion *regionp = getRegionFromHandle(region_handle); +	std::string seedUrl;  	if (regionp)  	{  		llinfos << "Region exists, removing it " << llendl; @@ -161,6 +162,9 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host)  			llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;  		} +		// Save capabilities seed URL +		seedUrl = regionp->getCapability("Seed"); +  		// Kill the old host, and then we can continue on and add the new host.  We have to kill even if the host  		// matches, because all the agent state for the new camera is completely different.  		removeRegion(old_host); @@ -188,6 +192,11 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host)  		llerrs << "Unable to create new region!" << llendl;  	} +	if ( !seedUrl.empty() ) +	{ +		regionp->setCapability("Seed", seedUrl); +	} +  	mRegionList.push_back(regionp);  	mActiveRegionList.push_back(regionp);  	mCulledRegionList.push_back(regionp); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 5fa380e0e3..bfae142812 100755 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -522,6 +522,17 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&  			tooltip_fmt.setArg("[AREA]",  llformat("%d", extra));  			tooltip_fmt.setArg("[PRICE]", llformat("%d", extra2)); + +			// Check for division by zero +			if (extra != 0) +			{ +				tooltip_fmt.setArg("[SQMPRICE]", llformat("%.1f", (F32)extra2 / (F32)extra)); +			} +			else +			{ +				tooltip_fmt.setArg("[SQMPRICE]",  LLTrans::getString("Unknown")); +			} +  			new_item.setTooltip(tooltip_fmt.getString());  			if (type == MAP_ITEM_LAND_FOR_SALE) diff --git a/indra/newview/skins/default/textures/icons/Facebook.png b/indra/newview/skins/default/textures/icons/Facebook.png Binary files differnew file mode 100644 index 0000000000..8287d56f88 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Facebook.png diff --git a/indra/newview/skins/default/textures/icons/map_placeholder.png b/indra/newview/skins/default/textures/icons/map_placeholder.png Binary files differnew file mode 100644 index 0000000000..31e457aa75 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/map_placeholder.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 54f60f4441..bb891996c9 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -148,10 +148,13 @@ with the same filename but different name    <texture name="Command_Preferences_Icon"  file_name="toolbar_icons/preferences.png"  preload="true" />    <texture name="Command_Profile_Icon"      file_name="toolbar_icons/profile.png"      preload="true" />    <texture name="Command_Search_Icon"       file_name="toolbar_icons/search.png"       preload="true" /> +  <texture name="Command_Social_Icon"       file_name="toolbar_icons/facebook.png"     preload="true" />    <texture name="Command_Snapshot_Icon"     file_name="toolbar_icons/snapshot.png"     preload="true" />    <texture name="Command_Speak_Icon"        file_name="toolbar_icons/speak.png"        preload="true" />    <texture name="Command_View_Icon"         file_name="toolbar_icons/view.png"         preload="true" />    <texture name="Command_Voice_Icon"        file_name="toolbar_icons/nearbyvoice.png"  preload="true" /> +  <texture name="Command_Highlighting_Icon" file_name="toolbar_icons/highlighting.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> +  <texture name="Command_Highlighting_Selected_Icon" file_name="toolbar_icons/highlighting_selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />    <texture name="Caret_Bottom_Icon"         file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />    <texture name="Caret_Right_Icon"          file_name="toolbar_icons/caret_right.png"  preload="true" scale.left="5" scale.top="15" scale.right="28" scale.bottom="1" />    <texture name="Caret_Left_Icon"           file_name="toolbar_icons/caret_left.png"   preload="true" scale.left="1" scale.top="15" scale.right="23" scale.bottom="1" /> @@ -162,6 +165,7 @@ with the same filename but different name    <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> +  <texture name="ComboButton_Hovered" file_name="widgets/ComboButton_Hover.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="Container" file_name="containers/Container.png" preload="false" /> @@ -199,6 +203,8 @@ with the same filename but different name    <texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />    <texture name="Edit_Wrench" file_name="icons/Edit_Wrench.png" preload="false" /> +  <texture name="Facebook_Icon" file_name="icons/Facebook.png" preload="false" /> +    <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />    <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />    <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" /> @@ -323,6 +329,8 @@ with the same filename but different name    <texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" /> +  <texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" /> +        <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />    <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" /> @@ -565,6 +573,7 @@ with the same filename but different name    <texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" />    <texture name="Snapshot_Inventory" file_name="toolbar_icons/inventory.png" preload="false" />    <texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" /> +  <texture name="Snapshot_Facebook" file_name="toolbar_icons/facebook.png" preload="false" />    <texture name="startup_logo"  file_name="windows/startup_logo.png" preload="true" /> diff --git a/indra/newview/skins/default/textures/toolbar_icons/facebook.png b/indra/newview/skins/default/textures/toolbar_icons/facebook.png Binary files differnew file mode 100644 index 0000000000..b960b834dc --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/facebook.png diff --git a/indra/newview/skins/default/textures/toolbar_icons/highlighting.png b/indra/newview/skins/default/textures/toolbar_icons/highlighting.png Binary files differnew file mode 100644 index 0000000000..c227f07513 --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/highlighting.png diff --git a/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png b/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png Binary files differnew file mode 100644 index 0000000000..aa1bb26a56 --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Hover.png b/indra/newview/skins/default/textures/widgets/ComboButton_Hover.png Binary files differnew file mode 100644 index 0000000000..d492b30b40 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/ComboButton_Hover.png diff --git a/indra/newview/skins/default/xui/da/floater_tools.xml b/indra/newview/skins/default/xui/da/floater_tools.xml index 815bde456e..9be129bbf6 100755 --- a/indra/newview/skins/default/xui/da/floater_tools.xml +++ b/indra/newview/skins/default/xui/da/floater_tools.xml @@ -462,10 +462,6 @@  				<combo_box.item label="Rør" name="suction"/>  				<combo_box.item label="Væv" name="weave"/>  			</combo_box> -			<check_box initial_value="falsk" label="Flugt planare overflader" name="checkbox planar align" tool_tip="Flugt teksuter på alle valgte overflader med den sidst valgte overflade. Kræver at planar tekstur-mapning er valgt."/> -			<text name="rpt"> -				Gentagelser / overflade -			</text>  			<spinner label="Vandret (U)" name="TexScaleU"/>  			<check_box label="Vend" name="checkbox flip s"/>  			<spinner label="Lodret (V)" name="TexScaleV"/> diff --git a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml index 72200a07ad..e494b2b755 100755 --- a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml @@ -26,14 +26,14 @@  		<text name="ShadersText">  			Overflader:  		</text> -		<check_box initial_value="sand" label="Gennemsigtig vand" name="TransparentWater"/> +		<check_box initial_value="true" label="Gennemsigtig vand" name="TransparentWater"/>  		<check_box initial_value="true" label="Glatte flader og skin" name="BumpShiny"/> -		<check_box initial_value="sand" label="Lokale lys" name="LocalLights"/> +		<check_box initial_value="true" label="Lokale lys" name="LocalLights"/>  		<check_box initial_value="true" label="Basale flader" name="BasicShaders" tool_tip="Ved at slå dette valg fra, kan det forhindres at visse grafikkort drivere crasher."/>  		<check_box initial_value="true" label="Atmosfæriske flader" name="WindLightUseAtmosShaders"/> -		<check_box initial_value="sand" label="Lys og skygger" name="UseLightShaders"/> -		<check_box initial_value="sand" label=""Ambient Occlusion"" name="UseSSAO"/> -		<check_box initial_value="sand" label="Skarphedsdybde" name="UseDoF"/> +		<check_box initial_value="true" label="Lys og skygger" name="UseLightShaders"/> +		<check_box initial_value="true" label=""Ambient Occlusion"" name="UseSSAO"/> +		<check_box initial_value="true" label="Skarphedsdybde" name="UseDoF"/>  		<text name="shadows_label">  			Skygger:  		</text> diff --git a/indra/newview/skins/default/xui/da/panel_preferences_setup.xml b/indra/newview/skins/default/xui/da/panel_preferences_setup.xml index 479e98817e..7be9a9d555 100755 --- a/indra/newview/skins/default/xui/da/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/da/panel_preferences_setup.xml @@ -26,14 +26,13 @@  		Web:  	</text>  	<radio_group name="use_external_browser"> -		<radio_item label="Benyt min browser(IE, Firefox, Safari)" name="external" tool_tip="Brug systemets standard web browser til hjælp, web links, m.v. Ikke anbefalet hvis du kører i fuld-skærm." value="1"/> +		<radio_item label="Benyt min browser(IE, Firefox, Safari)" name="external" tool_tip="Brug systemets standard web browser til hjælp, web links, m.v. Ikke anbefalet hvis du kører i fuld-skærm." value="true"/>  		<radio_item label="Benyt den indbyggede browser" name="internal" tool_tip="Brug den indbyggede web browser til hjælp, web links m.v. Denne browser åbner et nyt vindue i [APP_NAME]." value=""/>  	</radio_group>  	<check_box initial_value="true" label="Aktivér plugins" name="browser_plugins_enabled"/>  	<check_box initial_value="true" label="Acceptér cookies" name="cookies_enabled"/>  	<check_box initial_value="true" label="Aktivér Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="fra" label="Tilad media browser pop-ups" name="media_popup_enabled"/> -	<check_box initial_value="false" label="Aktivér web proxy" name="web_proxy_enabled"/> +	<check_box initial_value="false" label="Tilad media browser pop-ups" name="media_popup_enabled"/>	  	<text name="Proxy location">  		Proxy placering:  	</text> diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml index 5f5c34a5cf..6634a4bd90 100755 --- a/indra/newview/skins/default/xui/de/floater_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_tools.xml @@ -466,16 +466,11 @@  				<combo_box.item label="Saugen" name="suction"/>  				<combo_box.item label="gewoben" name="weave"/>  			</combo_box> -			<check_box initial_value="falsch" label="Flache Oberflächen ausrichten" name="checkbox planar align" tool_tip="Texturen auf allen ausgewählten Oberflächen an der zuletzt ausgewählten Oberfläche ausrichten. Planar Texture Mapping erforderlich."/> -			<text name="rpt"> -				Wiederholungen / Oberfläche -			</text>  			<spinner label="Horizontal (U)" name="TexScaleU"/>  			<check_box label="Umkehren" name="checkbox flip s"/>  			<spinner label="Vertikal (V)" name="TexScaleV"/>  			<check_box label="Umkehren" name="checkbox flip t"/>  			<spinner label="Rotation˚" name="TexRot"/> -			<spinner label="Wiederholungen / Meter" name="rptctrl"/>  			<button label="Übernehmen" label_selected="Übernehmen" name="button apply"/>  			<text name="tex offset">  				Texture-Versatz diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index c8c20424e1..4268b95370 100755 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1274,7 +1274,7 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 793a6e6fa1..a660e812cc 100755 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1365,7 +1365,7 @@ Only large parcels can be listed in search.                  <combo_box.item                   label="Any Category"                   name="item0" -                 value="any" /> +                 value="none" />                  <combo_box.item                   label="Linden Location"                   name="item1" diff --git a/indra/newview/skins/default/xui/en/floater_fbc_web.xml b/indra/newview/skins/default/xui/en/floater_fbc_web.xml new file mode 100644 index 0000000000..0d35e22a19 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_fbc_web.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater name="floater_fbc_web" +         help_topic="fbc_web" +         width="780" +         height="775" +         save_rect="true" +         single_instance="true" +         reuse_instance="false" +         filename="floater_web_content.xml"/> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1215efb7f9..28c89868bd 100755 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -41,8 +41,8 @@           auto_resize="false"           user_resize="true"                   name="conversations_layout_panel" -         min_dim="38" -         expanded_min_dim="136"> +         min_dim="43" +         expanded_min_dim="140">              <layout_stack               animate="false"                follows="left|top|right" @@ -100,7 +100,7 @@                  <layout_panel                   auto_resize="false"                   name="conversations_pane_buttons_collapsed" -                 width="31"> +                 width="35">                      <button                       follows="right|top"                       height="25" @@ -110,10 +110,10 @@                       image_unselected="Toolbar_Middle_Off"                       layout="topleft"                       top="1" -                     left="0" +                     left="4"                       name="expand_collapse_btn"                       tool_tip="Collapse/Expand this list" -                     width="31" /> +                     width="35" />                  </layout_panel>              </layout_stack>              <panel diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 49d64767cc..853c209bca 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -21,7 +21,11 @@          Sending Email      </string>      <string -     name="profile_progress_str"> +        name="facebook_progress_str"> +        Posting to Facebook +    </string> +    <string +        name="profile_progress_str">          Posting      </string>      <string @@ -33,7 +37,11 @@          Saving to Computer      </string>   	<string - 	 name="profile_succeeded_str"> +        name="facebook_succeeded_str"> + 	    Image uploaded + 	</string> + 	<string +        name="profile_succeeded_str">   	    Image uploaded   	</string>   	<string @@ -49,7 +57,11 @@   	    Saved to Computer!   	</string>   	<string - 	 name="profile_failed_str"> +        name="facebook_failed_str"> + 	    Failed to upload image to your Facebook timeline. + 	</string> + 	<string +        name="profile_failed_str">   	    Failed to upload image to your Profile Feed.   	</string>   	<string diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml new file mode 100644 index 0000000000..b7ff374d5f --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_social.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<floater +  positioning="cascading" +  can_close="true" +  can_resize="false" +  help_topic="floater_social" +  layout="topleft" +  name="floater_social" +  save_rect="true" +  single_instance="true" +  reuse_instance="true" +  title="POST TO FACEBOOK" +  height="482" +  width="304"> +  <panel +   height="482" +   width="304" +   visible="true" +   name="background" +   follows="all" +   top="0" +   left="0"> +   <tab_container +     name="tabs" +     tab_group="1" +     tab_min_width="70" +     tab_height="30" +     tab_position="top" +     top="7" +     height="437" +     halign="center"> +     <panel +       filename="panel_social_status.xml" +       class="llsocialstatuspanel" +       follows="all" +       label="STATUS" +       name="panel_social_status"/> +     <panel +       filename="panel_social_photo.xml" +       class="llsocialphotopanel" +       follows="all" +       label="PHOTO" +       name="panel_social_photo"/> +     <panel +       filename="panel_social_place.xml" +       class="llsocialcheckinpanel" +       follows="all" +       label="CHECK IN" +       name="panel_social_place"/> +     <panel +       filename="panel_social_account.xml" +       class="llsocialaccountpanel" +       follows="all" +       label="ACCOUNT" +       name="panel_social_account"/>      +    </tab_container> +    <panel +     name="connection_status_panel" +     follows="left|bottom|right" +     height="24"> +     <text +      name="connection_error_text" +      type="string" +      follows="left|bottom|right" +      top="5" +      left="9" +      width="250" +      height="20" +      wrap="true" +      halign="left" +      valign="center" +      text_color="DrYellow" +      font="SansSerif"> +      Error +     </text> +     <loading_indicator +      follows="left|bottom|right" +      height="24" +      width="24" +      name="connection_loading_indicator" +      top="2" +      left="9" +      visible="true"/> +     <text +      name="connection_loading_text" +      type="string" +      follows="left|bottom|right" +      top="5" +      left_pad="5" +      width="250" +      height="20" +      wrap="true" +      halign="left" +      valign="center" +      text_color="EmphasisColor" +      font="SansSerif"> +      Loading... +    </text> +  </panel> + </panel> +</floater> 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 cea10adca8..a80440e844 100755 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -125,10 +125,10 @@        <icon          name="media_secure_lock_flag"          height="16" -        follows="top|right" +        follows="top|left"          image_name="Lock2"          layout="topleft" -        left_delta="620" +        left_delta="2"          top_delta="2"          visible="false"           tool_tip="Secured Browsing" diff --git a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml index 50910dff32..77b9095f7c 100755 --- a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml @@ -17,7 +17,7 @@           parameter="profile" />      </menu_item_call>      <menu_item_call -     label="Send IM..." +     label="IM"       layout="topleft"       name="Send IM">          <menu_item_call.on_click @@ -25,7 +25,26 @@           parameter="im" />      </menu_item_call>      <menu_item_call -     label="Add Friend..." +     label="Offer teleport" +     layout="topleft" +     name="Offer Teleport"> +        <on_click function="AvatarIcon.Action" parameter="teleport"/> +    </menu_item_call> +    <menu_item_call +     label="Voice call" +     layout="topleft" +     name="Voice Call"> +        <on_click function="AvatarIcon.Action" parameter="voice_call"/> +    </menu_item_call> +    <menu_item_call +     label="Chat history..." +     layout="topleft" +     name="Chat History"> +        <on_click function="AvatarIcon.Action" parameter="chat_history"/>    +    </menu_item_call> +    <menu_item_separator layout="topleft" name="separator_chat_history"/> +    <menu_item_call +     label="Add friend"       layout="topleft"       name="Add Friend">          <menu_item_call.on_click @@ -33,11 +52,56 @@           parameter="add" />      </menu_item_call>      <menu_item_call -     label="Remove Friend..." +     label="Remove friend"       layout="topleft"       name="Remove Friend">          <menu_item_call.on_click           function="AvatarIcon.Action"           parameter="remove" />      </menu_item_call> +    <menu_item_call +     label="Invite to group..." +     layout="topleft" +     name="Invite Group"> +      <on_click function="AvatarIcon.Action" parameter="invite_to_group" />    +    </menu_item_call> +    <menu_item_separator layout="topleft" name="separator_invite_to_group"/> +    <menu_item_call +     label="Zoom In" +     layout="topleft" +     name="Zoom In"> +      <on_click function="AvatarIcon.Action" parameter="zoom_in" /> +    </menu_item_call> +    <menu_item_call +     label="Map" +     layout="topleft" +     name="Map"> +       <on_click function="AvatarIcon.Action" parameter="map" /> +    </menu_item_call> +    <menu_item_call +     label="Share" +     layout="topleft" +     name="Share"> +       <on_click function="AvatarIcon.Action" parameter="share" /> +    </menu_item_call> +    <menu_item_call +     label="Pay" +     layout="topleft" +     name="Pay"> +       <on_click function="AvatarIcon.Action" parameter="pay" /> +    </menu_item_call> +    <menu_item_check +     label="Block Voice" +     layout="topleft" +     name="Block Unblock"> +       <on_click function="AvatarIcon.Action" parameter="block_unblock" /> +       <on_check function="AvatarIcon.Check" parameter="is_blocked" /> +    </menu_item_check> +    <menu_item_check +     label="Block Text" +     layout="topleft" +     name="Mute Text"> +       <on_click function="AvatarIcon.Action" parameter="mute_unmute" /> +       <on_check function="AvatarIcon.Check" parameter="is_muted" />    +  </menu_item_check>  </menu> diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index b3d28788da..31b1d091ee 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -53,6 +53,13 @@          <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/>      </menu_item_call>      <menu_item_call +     label="Request teleport" +     layout="topleft" +     name="request_teleport"> +        <on_click function="Avatar.DoToSelected" parameter="request_teleport"/> +        <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call       label="Voice call"       layout="topleft"       name="voice_call"> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml index 8796b87955..a1a3afbf68 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -56,6 +56,16 @@        function="Calllog.Enable"        parameter="can_offer_teleport"/>      </menu_item_call> +    <menu_item_call +    label="Request Teleport" +    name="request_teleport"> +      <on_click +       function="Calllog.Action" +       parameter="request_teleport"/> +      <on_enable +      function="Calllog.Enable" +      parameter="can_offer_teleport"/> +    </menu_item_call>      <menu_item_separator />      <menu_item_call       label="Add Friend" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 13dc0b941a..512205ba43 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -591,6 +591,14 @@           parameter="lure" />      </menu_item_call>      <menu_item_call +     label="Request Teleport..." +     layout="topleft" +     name="Request Teleport..."> +        <menu_item_call.on_click +        function="Inventory.DoToSelected" +        parameter="request_lure" /> +    </menu_item_call> +    <menu_item_call       label="Start Conference Chat"       layout="topleft"       name="Conference Chat"> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 3abb5f7bc8..f12226ebeb 100755 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -29,6 +29,15 @@        parameter="can_offer_teleport"/>      </menu_item_call>      <menu_item_call +    label="Request Teleport" +    name="request_teleport"> +      <menu_item_call.on_click +       function="Avatar.TeleportRequest"/> +      <menu_item_call.on_enable +      function="Avatar.EnableItem" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call       label="Voice call"       layout="topleft"       name="voice_call"> @@ -134,5 +143,4 @@           function="Avatar.EnableItem"           parameter="can_block" />      </menu_item_check> -    <menu_item_separator />  </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 2d65052def..95a7839337 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -16,6 +16,14 @@           parameter="agent" />        </menu_item_call>        <menu_item_call +        label="Post to Facebook..." +        name="PostToFacebook"> +        <menu_item_call.on_click +          function="Floater.Toggle" +          parameter="social"/> +      </menu_item_call>       +      <menu_item_separator/> +      <menu_item_call         label="Appearance..."         name="ChangeOutfit">          <menu_item_call.on_click @@ -189,7 +197,7 @@           name="Preferences"           shortcut="control|P">              <menu_item_call.on_click -             function="Floater.Show" +             function="Floater.Toggle"               parameter="preferences" />          </menu_item_call>           <menu_item_call @@ -1297,19 +1305,19 @@       tear_off="true">          <menu_item_call           label="How to..." -         name="How To"> +         name="How To" +         shortcut="F1">              <menu_item_call.on_click               function="Help.ToggleHowTo"               parameter="" />          </menu_item_call>          <menu_item_call -         label="[SECOND_LIFE] Help" -         name="Second Life Help" -         shortcut="F1"> -            <menu_item_call.on_click -             function="ShowHelp" -             parameter="f1_help" /> -        </menu_item_call> +           label="Quickstart" +           name="Quickstart"> +        <menu_item_call.on_click +            function="Advanced.ShowURL" +            parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Quickstart/ta-p/1087919"/> +        </menu_item_call>                <!--        <menu_item_call           label="Tutorial"           name="Tutorial"> @@ -1318,21 +1326,13 @@               parameter="hud" />          </menu_item_call>-->  		<menu_item_separator/> -		 -		<menu_item_call -             label="User’s guide" -             name="User’s guide"> -             <menu_item_call.on_click -                 function="Advanced.ShowURL" -                 parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-User-s-Guide/ta-p/1244857"/> -        </menu_item_call> -        <menu_item_call -             label="Knowledge Base" -             name="Knowledge Base"> -             <menu_item_call.on_click -                 function="Advanced.ShowURL" -                 parameter="http://community.secondlife.com/t5/tkb/communitypage"/> -        </menu_item_call> +      <menu_item_call +           label="Knowledge Base" +           name="Knowledge Base"> +        <menu_item_call.on_click +            function="Advanced.ShowURL" +            parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-User-s-Guide/ta-p/1244857"/> +      </menu_item_call>          <menu_item_call               label="Wiki"               name="Wiki"> @@ -2947,6 +2947,34 @@           label="Recorder"           name="Recorder"           tear_off="true"> +            <menu_item_call visible="false" +             label="Start event recording" +             name="Start event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="start recording" /> +            </menu_item_call> +            <menu_item_call visible="false" +             label="Stop event recording" +             name="Stop event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="stop recording" /> +            </menu_item_call> +            <menu_item_call visible="false" +             label="Playback event recording" +             name="Playback event recording"> +	      <menu_item_call.on_visible +		 function="displayViewerEventRecorderMenuItems" /> +                <menu_item_call.on_click +                 function="Advanced.EventRecorder" +                 parameter="start playback" /> +            </menu_item_call> +              <menu_item_call               label="Start Playback"               name="Start Playback"> @@ -3049,6 +3077,13 @@               parameter="http://google.com"/>            </menu_item_call>            <menu_item_call +           label="FB Connect Test" +           name="FB Connect Test"> +            <menu_item_call.on_click +             function="Advanced.WebContentTest" +             parameter="https://cryptic-ridge-1632.herokuapp.com/"/> +          </menu_item_call> +          <menu_item_call               label="Dump SelectMgr"               name="Dump SelectMgr">                  <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 69b7fe5a75..964deb35a7 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3481,7 +3481,7 @@ or you can install it now.     name="DownloadBackgroundTip"     type="notify">  We have downloaded an update to your [APP_NAME] installation. -Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] +Version [VERSION] [[INFO_URL] Information about this update]      <tag>confirm</tag>      <usetemplate       name="okcancelbuttons" @@ -3493,8 +3493,8 @@ Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update]   icon="alertmodal.tga"   name="DownloadBackgroundDialog"   type="alertmodal"> -We have downloaded an update to your [APP_NAME] installation. -Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] +    We have downloaded an update to your [APP_NAME] installation. +    Version [VERSION] [[INFO_URL] Information about this update]      <tag>confirm</tag>      <usetemplate       name="okcancelbuttons" @@ -4071,6 +4071,27 @@ Join me in [REGION]    <notification     icon="alertmodal.tga" +   name="TeleportRequestPrompt" +   type="alertmodal"> +Request a teleport to [NAME] with the following message +    <tag>confirm</tag> +    <form name="form"> +      <input name="message" type="text"> + +      </input> +      <button +       default="true" +       index="0" +       name="OK" +       text="OK"/> +      <button +       index="1" +       name="Cancel" +       text="Cancel"/> +    </form> +  </notification> +  <notification +   icon="alertmodal.tga"     name="TooManyTeleportOffers"     type="alertmodal">  You attempted to make [OFFERS] teleport offers @@ -6017,6 +6038,13 @@ Please select at least one type of content to search (General, Moderate, or Adul  [MESSAGE]    </notification> + <notification +  icon="notify.tga" +  name="FacebookConnect" +  type="notifytip"> +[MESSAGE] + </notification> +        <notification     icon="notify.tga"     name="PaymentReceived" @@ -6309,13 +6337,22 @@ You can only claim public land in the Region you're in.    <notification     icon="notify.tga"     name="RegionTPAccessBlocked" -   persist="true" +   persist="false"     type="notify">     <tag>fail</tag>      The region you're trying to visit contains content exceeding your current preferences.  You can change your preferences using Me > Preferences > General.    </notification>    <notification +   icon="notify.tga" +   name="RegionAboutToShutdown" +   persist="false" +   type="notify"> +    <tag>fail</tag> +    The region you're trying to enter is about to shut down. +  </notification> +   +  <notification  	icon="notify.tga"  	name="URBannedFromRegion"     persist="true" @@ -6637,7 +6674,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     sound="UISndNewIncomingIMSession">  [NAME_SLURL] has offered to teleport you to their location: -“[MESSAGE]” +"[MESSAGE]”  <icon>[MATURITY_ICON]</icon> - [MATURITY_STR]      <tag>confirm</tag>      <form name="form"> @@ -6702,6 +6739,27 @@ However, this region contains content accessible to adults only.  	Teleport offer sent to [TO_NAME]    </notification> +  <notification +   icon="notify.tga" +   name="TeleportRequest" +   log_to_im="true" +   type="offer"> +[NAME_SLURL] is requesting to be teleported to your location. +[MESSAGE] + +Offer a teleport? +    <tag>confirm</tag> +    <form name="form"> +      <button +       index="0" +       name="Yes" +       text="Yes"/> +      <button +       index="1" +       name="No" +       text="No"/> +    </form> +  </notification>    <notification     icon="notify.tga" @@ -6750,7 +6808,6 @@ However, this region contains content accessible to adults only.     icon="notify.tga"     name="FriendshipOffered"     log_to_im="true"    -   show_toast="false"        type="notify">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6800,7 +6857,6 @@ However, this region contains content accessible to adults only.     icon="notify.tga"     name="FriendshipAcceptedByMe"     log_to_im="true"    -   show_toast="false"     type="notify">      <tag>friendship</tag>  Friendship offer accepted. @@ -6810,7 +6866,6 @@ Friendship offer accepted.     icon="notify.tga"     name="FriendshipDeclinedByMe"     log_to_im="true"    -   show_toast="false"        type="notify">      <tag>friendship</tag>  Friendship offer declined. @@ -6841,7 +6896,7 @@ This will add a bookmark in your inventory so you can quickly IM this Resident.     priority="high"     sound="UISndAlert"     type="notify"> -This region will restart in [MINUTES] minutes. +The region "[NAME]" will restart in [MINUTES] minutes.  If you stay in this region you will be logged out.    </notification> @@ -6851,7 +6906,7 @@ If you stay in this region you will be logged out.     priority="high"     sound="UISndAlert"     type="notify"> -This region will restart in [SECONDS] seconds. +The region "[NAME]" will restart in [SECONDS] seconds.  If you stay in this region you will be logged out.    </notification> @@ -8734,11 +8789,11 @@ You are no longer allowed here and have [EJECT_TIME] seconds to leave.    <notification     icon="alertmodal.tga" -   name="NoEnterServerFull" +   name="NoEnterRegionMaybeFull"     type="notify">     <tag>fail</tag> -You can't enter this region because  -the server is full. +You can't enter region "[NAME]". +It may be full or restarting soon.    </notification>    <notification @@ -9504,6 +9559,14 @@ Not enough script resources available to attach object!    <notification     icon="alertmodal.tga" +   name="CantAttachObjectBeingRemoved" +   type="notify"> +    <tag>fail</tag> +    Cannot attach object because it is already being removed. +  </notification> + +  <notification +   icon="alertmodal.tga"     name="CantDropItemTrialUser"     type="notify">     <tag>fail</tag> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index a054e71e34..4372cf69bf 100755 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -11,7 +11,7 @@       height="20"       default_icon_name="Generic_Person"       layout="topleft" -     left="5" +     left="9"       top="2"       visible="false"       width="20" /> @@ -20,7 +20,7 @@       height="20"       default_icon_name="Generic_Group"       layout="topleft" -     left="5" +     left="9"       top="2"       visible="false"       width="20" /> @@ -29,9 +29,9 @@       height="20"       image_name="Nearby_chat_icon"       layout="topleft" -     left="5" +     left="10"       name="nearby_chat_icon" -     top="2" +     top="3"       visible="false"       width="20"/>      <layout_stack diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 3edeb9aa36..c7edba21f8 100755 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -87,6 +87,7 @@  	         direction="down"  	         height="23"  	         image_overlay="Arrow_Left_Off" +	         image_hover_unselected="PushButton_Over"  	         image_bottom_pad="1"  	         layout="topleft"  	         left="10" @@ -99,6 +100,7 @@  	         direction="down"  	         height="23"  	         image_overlay="Arrow_Right_Off" +	         image_hover_unselected="PushButton_Over"  	         image_bottom_pad="1"  	         layout="topleft"  	         left_pad="0" @@ -111,6 +113,7 @@  	         height="23"  	         image_bottom_pad="1"  	         image_overlay="Home_Off" +	         image_hover_unselected="PushButton_Over"  	         layout="topleft"  	         left_pad="7"  	         name="home_btn" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index ed274d0233..3caf2b3d7e 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -66,7 +66,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       tab_position="top"       top="0"       halign="center" -     right="-5"> +     right="-5" +     use_highlighting_on_hover="true">  <!-- ================================= NEARBY tab =========================== --> @@ -365,6 +366,23 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                           top="0"                           width="307" />                  </accordion_tab> +              <accordion_tab +               layout="topleft" +               height="173" +               name="tab_suggested_friends" +               title="People you may want to friend"> +                <avatar_list +                 ignore_online_status="true" +                 allow_select="true" +                 follows="all" +                 height="173" +                 layout="topleft" +                 left="0" +                 name="suggested_friends" +                 show_permissions_granted="true" +                 top="0" +                 width="307" /> +              </accordion_tab>                            </accordion>              <text               follows="all" @@ -483,7 +501,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M              <text                  type="string"                  length="1" -                follows="all" +                follows="left|top|right"                  height="14"                  layout="topleft"                  right="-10" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index d9067b41c7..8794e3bf95 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -129,6 +129,16 @@     name="tap_tap_hold_to_run"     width="237"     top_pad="0"/> +  <check_box +   control_name="AutomaticFly" +   follows="left|top" +   height="20" +   label="Hold jump or crouch key to start or stop flying" +   layout="topleft" +   left_delta="0" +   name="automatic_fly" +   width="237" +   top_pad="0"/>    <text     follows="left|top"     type="string" @@ -260,4 +270,4 @@       function="Floater.Show"       parameter="pref_joystick" />    </button> -</panel>
\ No newline at end of file +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index 198ccd6e2f..8f90521bb2 100755 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -315,7 +315,18 @@  		<line_editor.commit_callback  			function="MediaCtrl.CommitURL"/>  	  </line_editor> -	  <layout_stack +        <icon +        name="media_secure_lock_flag" +        height="16" +        follows="top|left" +        image_name="Lock2" +        layout="topleft" +        left_delta="2" +        top_delta="2" +        visible="false" +        tool_tip="Secured Browsing" +        width="16" /> +        <layout_stack  		  name="media_address_url_icons"  		  animate="false"  		  follows="top|right" @@ -340,19 +351,6 @@  			  tool_tip="White List enabled"  			  width="16" />  		</layout_panel> -		<layout_panel -			layout="topleft" -			width="16" -			mouse_opaque="false" -			auto_resize="false"> -		  <icon -			  name="media_secure_lock_flag" -			  height="16" -			  image_name="Lock2" -			  layout="topleft" -			  tool_tip="Secured Browsing" -			  width="16" /> -		</layout_panel>  	  </layout_stack>  	</layout_panel>  	<layout_panel diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml index d2f29ade44..61c8c971c2 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -16,11 +16,11 @@     imgoverlay_label_space="10"     label="Post to My Profile Feed"     layout="topleft" -   left="10" +   left_delta="0"     name="save_to_profile_btn"     pad_left="10"     right="-10" -   top="5"> +   top_pad="10">      <button.commit_callback       function="Snapshot.SaveToProfile" />    </button> diff --git a/indra/newview/skins/default/xui/en/panel_social_account.xml b/indra/newview/skins/default/xui/en/panel_social_account.xml new file mode 100644 index 0000000000..d7235396fe --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_social_account.xml @@ -0,0 +1,75 @@ +<panel +	 height="400" +	 width="304" +	 layout="topleft" +   name="panel_social_account"> +  <string +      name="facebook_connected" +      value="You are connected to Facebook as:" /> +  <string +      name="facebook_disconnected" +      value="Not connected to Facebook" /> +  <text +   layout="topleft" +   length="1" +   follows="top|left" +   font="SansSerif" +   height="16" +   left="9" +   name="account_caption_label" +   top="21" +   type="string"> +    Not connected to Facebook. +  </text> +  <text +   layout="topleft" +   top_pad="2" +   length="1" +   follows="top|left" +   font="SansSerif" +   height="16" +   left="9" +   name="account_name_label" +   parse_urls="true" +   type="string"/> +  <panel +    layout="topleft" +    name="panel_buttons" +    height="345" +    left="9"> +    <button +     layout="topleft" +     follows="left|top" +     top_pad="9" +     visible="true" +     height="23" +     label="Connect..." +     name="connect_btn" +     width="210"> +      <commit_callback function="SocialSharing.Connect"/> +    </button> + +    <button +     layout="topleft" +     follows="left|top" +     top_delta="0" +     height="23" +     label="Disconnect" +     name="disconnect_btn" +     width="210" +     visible="false"> +      <commit_callback function="SocialSharing.Disconnect"/> +    </button> +    <text +      layout="topleft" +      length="1" +      follows="top|left" +      height="16" +      left="0" +      name="account_learn_more_label" +      top_pad="20" +      type="string"> +      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook] +    </text> +  </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_social_photo.xml b/indra/newview/skins/default/xui/en/panel_social_photo.xml new file mode 100644 index 0000000000..a55613b52a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_social_photo.xml @@ -0,0 +1,152 @@ +    <panel +      height="400" +      width="304" +      layout="topleft" +      name="panel_social_photo"> +      <layout_stack +	   layout="topleft" +       border_size="0" +       height="392" +       follows="all" +       orientation="vertical" +       name="stack_photo" +       top="8"> +        <layout_panel	 +         name="snapshot_panel" +         height="367"> +            <combo_box +             control_name="SocialPhotoResolution" +             follows="left|top" +             top="6" +             left="9" +             name="resolution_combobox" +             tool_tip="Image resolution" +             height="21" +             width="135"> +              <combo_box.item +               label="Current Window" +               name="CurrentWindow" +               value="[i0,i0]" /> +              <combo_box.item +               label="640x480" +               name="640x480" +               value="[i640,i480]" /> +              <combo_box.item +               label="800x600" +               name="800x600" +               value="[i800,i600]" /> +              <combo_box.item +               label="1024x768" +               name="1024x768" +               value="[i1024,i768]" /> +            </combo_box> +            <text +             follows="left|top" +             font="SansSerifSmall" +             height="14" +             left="208" +             length="1" +             halign="right" +             name="file_size_label" +             top="9" +             type="string" +             width="50"> +              [SIZE] KB +            </text> +            <panel +                height="150" +                width="250" +                visible="true" +                name="thumbnail_placeholder" +                top="33" +                follows="left|top" +                left="9"> +            </panel> +            <button +             follows="left|top" +             height="23" +             label="Refresh" +             left="9" +             top_pad="5" +             name="new_snapshot_btn" +             tool_tip="Click to refresh" +             visible="true" +             width="100" > +             <button.commit_callback +               function="SocialSharing.RefreshPhoto" /> +            </button> +            <text +                follows="left|top" +                font="SansSerif" +                text_color="EmphasisColor" +                height="14" +                top_pad="-19" +                left_pad="-20" +                length="1" +                halign="center" +                name="working_lbl" +                translate="false" +                type="string" +                visible="true" +                width="150"> +                Refreshing... +            </text> +            <text +             length="1" +             follows="top|left|right" +             font="SansSerif" +             height="16" +             left="9" +             name="caption_label" +             top_pad="20" +             type="string"> +              Comment (optional): +            </text> +            <text_editor +             follows="left|top" +             height="87" +             width="250" +             left="9" +             length="1" +             max_length="700" +             name="photo_caption" +             type="string" +             word_wrap="true"> +            </text_editor> +            <check_box +             follows="left|top" +             initial_value="true" +             label="Include location in posting" +             name="add_location_cb" +              left="9" +              height="16" +             top_pad="8"/> +        </layout_panel> +        <layout_panel +          name="photo_button_panel" +          height="25"> +          <button +           follows="left|top" +           top="0" +           left="9" +           height="23" +           label="Post" +           name="post_photo_btn" +           width="100"> +            <button.commit_callback +             function="SocialSharing.SendPhoto" /> +          </button> +          <button +               follows="left|top" +               height="23" +               label="Cancel" +               name="cancel_photo_btn" +               left_pad="15" +               top_delta="0" +               width="100"> +            <button.commit_callback +             function="SocialSharing.Cancel" /> +          </button>           +        </layout_panel>         +      </layout_stack> +    </panel> diff --git a/indra/newview/skins/default/xui/en/panel_social_place.xml b/indra/newview/skins/default/xui/en/panel_social_place.xml new file mode 100644 index 0000000000..13e94f6998 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_social_place.xml @@ -0,0 +1,132 @@ +    <panel +      height="400" +      width="304" +	  layout="topleft" +      name="panel_social_place"> +      <layout_stack +	    layout="topleft" +        border_size="0" +        height="392" +        follows="all" +        orientation="vertical" +        name="stack_place" +        top="8"> +        <layout_panel +          name="place_detail_panel" +          height="181"> +          <text +            length="1" +            follows="top|left|right" +            font="SansSerif" +            height="16" +            left="9" +            name="place_caption_label" +            top="13" +            type="string"> +            Say something about where you are: +          </text> +          <text_editor +            follows="top|left" +            height="150" +            width="250" +            left="9" +            length="1" +            max_length="700" +            name="place_caption" +            type="string" +            word_wrap="true"> +           </text_editor> +          </layout_panel> +          <layout_panel +            name="place_map_panel" +            height="186"> +              <panel +                  follows="left|top" +                  height="128" +                  width="128" +                  background_visible="true" +                  bg_opaque_color="Black" +                  bg_alpha_color="Black" +                  top="20" +                  left="9" +                  visible="true" +                  name="map_border"> +              </panel> +              <loading_indicator +              follows="left|top" +              height="24" +              width="24" +              name="map_loading_indicator" +              top="77" +              left="61" +              visible="true"/> +              <icon +                follows="left|top" +                height="128" +                width="128" +                image_name="Map_Placeholder_Icon" +                layout="topleft" +                top="20" +                left="9" +                visible="true" +                name="map_placeholder"> +              </icon> +              <icon +                  follows="left|top" +                  height="128" +                  width="128" +                  image_name="Map_Placeholder_Icon" +                  layout="topleft" +                  top="20" +                  left="9" +                  visible="true" +                  name="map_default"> +              </icon> +            <check_box +              follows="left|top" +              initial_value="false" +              top_delta="8" +              width="8" +              label="" +              name="add_place_view_cb" +              left_pad="5"/> +            <text +              follows="left|top" +              font="SansSerif" +              height="32" +              width="130" +              word_wrap="true" +              left_pad="12" +              top_delta="-8" +              type="string"> +              Include overhead view of location +            </text> +          </layout_panel> +          <layout_panel +            name="place_button_panel" +            height="25"> +            <button +              follows="left|top" +              top="0" +              left="9" +              height="23" +              label="Post" +              name="post_place_btn" +              width="100"> +              <button.commit_callback +                 function="SocialSharing.SendCheckin" /> +            </button> +            <button +              follows="left|top" +              height="23" +              label="Cancel" +              name="cancel_place_btn" +              left_pad="15" +              top_delta="0" +              width="100"> +              <button.commit_callback +                  function="SocialSharing.Cancel" /> +            </button> +        </layout_panel> +     </layout_stack> +    </panel> diff --git a/indra/newview/skins/default/xui/en/panel_social_status.xml b/indra/newview/skins/default/xui/en/panel_social_status.xml new file mode 100644 index 0000000000..54cfa3f524 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_social_status.xml @@ -0,0 +1,67 @@ +    <panel +	 height="400" +	 width="304" +	 layout="topleft" +     name="panel_social_status"> +     <layout_stack +      layout="topleft" +      border_size="0" +      height="392" +      follows="all" +      orientation="vertical" +      name="stack_status" +      top="8"> +      <layout_panel +       name="status_detail_panel" +       height="367"> +       <text +        length="1" +        follows="top|left|right" +        font="SansSerif" +        height="16" +        left="9" +        name="status_caption_label" +        top="13" +        type="string"> +        What's on your mind? +       </text> +       <text_editor +        follows="left|top" +        height="150" +        width="250" +        left="9" +        length="1" +        max_length="700" +        name="status_message" +        type="string" +        word_wrap="true"> +       </text_editor> +      </layout_panel> +      <layout_panel +       name="status_button_panel" +       height="25"> +       <button +        follows="left|top" +        top="0" +        left="9" +        height="23" +        label="Post" +        name="post_status_btn" +        width="100"> +        <button.commit_callback +          function="SocialSharing.SendStatus" /> +       </button> +       <button +        follows="left|top" +        height="23" +        label="Cancel" +        name="cancel_status_btn" +        left_pad="15" +        top_delta="0" +        width="100"> +        <button.commit_callback +          function="SocialSharing.Cancel" /> +       </button> +      </layout_panel> +     </layout_stack> +    </panel> diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index dd2a0c6627..064ece6e4b 100755 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -113,7 +113,7 @@       image_pressed="Pause_Press"       image_pressed_selected="Play_Press"       is_toggle="true" -     left_pad="15" +     left_pad="5"       top="1"       name="media_toggle_btn"       tool_tip="Start/Stop All Media (Music, Video, Web pages)" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 1c46cec479..7e79d297ef 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -148,6 +148,14 @@ Please try logging in again in a minute.</string>  	<string name="SentToInvalidRegion">You were sent to an invalid region.</string>  	<string name="TestingDisconnect">Testing viewer disconnect</string> +	<!-- Facebook Connect and, eventually, other Social Network --> +	<string name="SocialFacebookConnecting">Connecting to Facebook...</string> +	<string name="SocialFacebookPosting">Posting...</string> +	<string name="SocialFacebookDisconnecting">Disconnecting from Facebook...</string> +	<string name="SocialFacebookErrorConnecting">Problem connecting to Facebook</string> +	<string name="SocialFacebookErrorPosting">Problem posting to Facebook</string> +	<string name="SocialFacebookErrorDisconnecting">Problem disconnecting from Facebook</string> +      	<!-- Tooltip -->  	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->  	<string name="TooltipNoName">(no name)</string> <!-- No name on an object --> @@ -379,7 +387,7 @@ Please try logging in again in a minute.</string>  	<!-- world map -->  	<string name="texture_loading">Loading...</string>  	<string name="worldmap_offline">Offline</string> -	<string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE]</string> +	<string name="worldmap_item_tooltip_format">[AREA] m² L$[PRICE] ([SQMPRICE] L$/m²)</string>  	<string name="worldmap_results_none_found">None found.</string>  	<!-- animations uploading status codes --> @@ -448,6 +456,8 @@ Please try logging in again in a minute.</string>  	<string name="load_file_verb">Load</string>  	<string name="targa_image_files">Targa Images</string>  	<string name="bitmap_image_files">Bitmap Images</string> +	<string name="png_image_files">PNG Images</string> +	<string name="save_texture_image_files">Targa or PNG Images</string>  	<string name="avi_movie_file">AVI Movie File</string>  	<string name="xaf_animation_file">XAF Anim File</string>  	<string name="xml_file">XML File</string> @@ -2185,7 +2195,7 @@ For AI Character: Get the closest navigable point to the point provided.  	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>  	<string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string>  	<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> -	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> +	<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3</string>  	<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>  	<string name="MarketplaceURL_Imports">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports</string>  	<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string> @@ -2464,7 +2474,11 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  		all estates that you manage for [OWNER]  	</string>  	<string name="RegionInfoAllowedResidents">Allowed Residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string> -	<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string> +	<string name="RegionInfoAllowedGroups">Allowed Groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string> +	<string name="RegionInfoEstateManagers">Estate Managers: ([ESTATEMANAGERS], max [MAXMANAGERS])</string> +	<string name="RegionInfoBannedResidents">Banned Residents: ([BANNEDAGENTS], max [MAXBANNED])</string> +	<string name="RegionInfoListTypeAllowedAgents">Allowed Residents</string> +	<string name="RegionInfoListTypeBannedAgents">Banned Residents</string>  	<!-- script limits floater -->  	<string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string> @@ -3427,6 +3441,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].      Drag items from inventory here    </string> +  <string name="facebook_post_success"> +    You posted to Facebook. +  </string>    <string name="no_session_message">      (IM Session Doesn't Exist) @@ -3859,6 +3876,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Profile_Label">Profile</string>    <string name="Command_Search_Label">Search</string>    <string name="Command_Snapshot_Label">Snapshot</string> +  <string name="Command_Social_Label">Facebook</string>    <string name="Command_Speak_Label">Speak</string>    <string name="Command_View_Label">Camera controls</string>    <string name="Command_Voice_Label">Voice settings</string> @@ -3886,6 +3904,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Profile_Tooltip">Edit or view your profile</string>    <string name="Command_Search_Tooltip">Find places, events, people</string>    <string name="Command_Snapshot_Tooltip">Take a picture</string> +  <string name="Command_Social_Tooltip">Post to Facebook</string>    <string name="Command_Speak_Tooltip">Speak with people nearby using your microphone</string>    <string name="Command_View_Tooltip">Changing camera angle</string>    <string name="Command_Voice_Tooltip">Volume controls for calls and people near you in world</string> diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 61ec046649..4ea1aa6efb 100755 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -150,6 +150,7 @@    <combo_button  		name="Location History"                  label="" +                image_hover_unselected="ComboButton_Hovered"                  pad_right="0"/>    <combo_list  	      bg_writeable_color="MenuDefaultBgColor" diff --git a/indra/newview/skins/default/xui/en/widgets/person_tab_view.xml b/indra/newview/skins/default/xui/en/widgets/person_tab_view.xml new file mode 100644 index 0000000000..af5aec2c34 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/person_tab_view.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<person_tab_view +  folder_arrow_image="Folder_Arrow" +  folder_indentation="5" +  item_height="24"  +  item_top_pad="3" +  mouse_opaque="true" +  follows="left|top|right" +  text_pad="6" +  text_pad_left="4" +  text_pad_right="4" +  arrow_size="10" +  max_folder_item_overlap="2"/> diff --git a/indra/newview/skins/default/xui/en/widgets/person_view.xml b/indra/newview/skins/default/xui/en/widgets/person_view.xml new file mode 100644 index 0000000000..46c1b7ff75 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/person_view.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<person_view +  folder_arrow_image="Folder_Arrow" +  folder_indentation="5" +  item_height="24"  +  item_top_pad="3" +  mouse_opaque="true" +  follows="left|top|right" +  icon_pad="4" +  icon_width="20" +  text_pad="6" +  text_pad_left="4" +  text_pad_right="4" +  arrow_size="10" +  max_folder_item_overlap="2"> +    <facebook_icon +      follows="left" +      height="14" +      image_name="Facebook_Icon" +      left="5" +      bottom="6" +      name="facebook_icon" +      tool_tip="Facebook User" +      visible="false" +      width="14" /> +    <avatar_icon +      follows="left" +      layout="topleft" +      height="20" +      default_icon_name="Generic_Person" +      left="5" +      top="2" +      visible="false" +      width="20" /> +    <last_interaction_time_textbox +      layout="topleft" +      follows="right" +      font="SansSerifSmall" +      height="15" +      left_pad="5" +      right="-164" +      name="last_interaction_time_textbox" +      text_color="LtGray_50" +      value="0s" +      visible="false"  +      width="35" /> +    <permission_edit_theirs_icon +      layout="topleft" +      height="16" +      follows="right" +      image_name="Permission_Edit_Objects_Theirs" +      left_pad="3" +      right="-129" +      name="permission_edit_theirs_icon" +      tool_tip="You can edit this friend's objects" +      top="4" +      visible="false"  +      width="16" /> +    <permission_edit_mine_icon +      layout="topleft" +      height="16" +      follows="right" +      image_name="Permission_Edit_Objects_Mine" +      left_pad="3" +      right="-110" +      name="permission_edit_mine_icon" +      tool_tip="This friend can edit, delete or take your objects" +      top="4" +      visible="false"  +      width="16" /> +    <permission_map_icon +      height="16" +      follows="right" +      image_name="Permission_Visible_Map" +      left_pad="3" +      tool_tip="This friend can locate you on the map" +      right="-91" +      name="permission_map_icon" +      visible="false"  +      width="16" /> +    <permission_online_icon +      height="16" +      follows="right" +      image_name="Permission_Visible_Online" +      left_pad="3" +      right="-72" +      name="permission_online_icon" +      tool_tip="This friend can see when you're online" +      visible="false"  +      width="16" /> +    <info_btn +      follows="right" +      height="16" +      image_pressed="Info_Press" +      image_unselected="Info_Over" +      left_pad="3" +      right="-53" +      name="info_btn" +      tool_tip="More info" +      tab_stop="false" +      visible="false"       +      width="16" /> +    <profile_btn +      layout="topleft" +      follows="right" +      height="20" +      image_overlay="Web_Profile_Off" +      left_pad="5" +      right="-28" +      name="profile_btn" +      tab_stop="false" +      tool_tip="View profile" +      top="2" +      visible="false" +      width="20" /> +    <output_monitor +      auto_update="true" +      follows="right" +      draw_border="false" +      height="16" +      right="-3" +      mouse_opaque="true" +      name="speaking_indicator" +      visible="false" +      width="20" /> + </person_view> + diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index 0586119681..9559be214a 100755 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -24,17 +24,26 @@ label_pad_left - padding to the left of tab button labels                 tab_bottom_image_unselected="Toolbar_Left_Off"                 tab_bottom_image_selected="Toolbar_Left_Selected"                 tab_left_image_unselected="SegmentedBtn_Left_Disabled" -               tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/> +               tab_left_image_selected="SegmentedBtn_Left_Selected_Over" +               tab_top_image_hovered="TabTop_Left_Selected" +               tab_button_image_hovered="Toolbar_Left_Selected" +               tab_left_image_hovered="SegmentedBtn_Left_Selected_Over"/>    <middle_tab tab_top_image_unselected="TabTop_Middle_Off"                 tab_top_image_selected="TabTop_Middle_Selected"                 tab_bottom_image_unselected="Toolbar_Middle_Off"                 tab_bottom_image_selected="Toolbar_Middle_Selected"                 tab_left_image_unselected="SegmentedBtn_Left_Disabled" -               tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/> +               tab_left_image_selected="SegmentedBtn_Left_Selected_Over" +               tab_top_image_hovered="TabTop_Middle_Selected" +               tab_button_image_hovered="Toolbar_Middle_Selected" +               tab_left_image_hovered="SegmentedBtn_Left_Selected_Over"/>    <last_tab tab_top_image_unselected="TabTop_Right_Off"                 tab_top_image_selected="TabTop_Right_Selected"                 tab_bottom_image_unselected="Toolbar_Right_Off"                 tab_bottom_image_selected="Toolbar_Right_Selected"                 tab_left_image_unselected="SegmentedBtn_Left_Disabled" -               tab_left_image_selected="SegmentedBtn_Left_Selected_Over"/> +               tab_left_image_selected="SegmentedBtn_Left_Selected_Over" +               tab_top_image_hovered="TabTop_Right_Selected" +               tab_button_image_hovered="Toolbar_Right_Selected" +               tab_left_image_hovered="SegmentedBtn_Left_Selected_Over"/>  </tab_container> diff --git a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml index c351db5eae..c2327c96c4 100755 --- a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml @@ -28,7 +28,7 @@  	<text name="tc label">  		Activar S3TC:  	</text> -	<check_box initial_value="verdadero" label="Activar la compresión de texturas (requiere reiniciar)" name="texture compression" tool_tip="Comprime las texturas de la memoria de vídeo, lo cual permite cargar texturas de una resolución más alta, pero con una cierta pérdida de calidad del color."/> +	<check_box initial_value="true" label="Activar la compresión de texturas (requiere reiniciar)" name="texture compression" tool_tip="Comprime las texturas de la memoria de vídeo, lo cual permite cargar texturas de una resolución más alta, pero con una cierta pérdida de calidad del color."/>  	<slider label="Memoria para texturas (MB):" name="GraphicsCardTextureMemory" tool_tip="Cantidad de memoria asignada a las texturas. Por defecto es la memoria de la tarjeta de vídeo. Reducir esta cantidad puede mejorar el rendimiento, pero también hacer que las texturas se vean borrosas."/>  	<spinner label="Intensidad de la niebla:" name="fog"/>  	<button label="OK" label_selected="OK" name="OK"/> diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml index 15462c3726..32baa5bb7d 100755 --- a/indra/newview/skins/default/xui/es/floater_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_tools.xml @@ -443,16 +443,11 @@  				<combo_box.item label="succión" name="suction"/>  				<combo_box.item label="tejido" name="weave"/>  			</combo_box> -			<check_box initial_value="falso" label="Alinear caras del plano" name="checkbox planar align" tool_tip="Alinear texturas en todas las caras seleccionadas con la última cara seleccionada. Requiere la representación de texturas en el plano."/> -			<text name="rpt"> -				Repeticiones por cara -			</text>  			<spinner label="Horizontal (U)" name="TexScaleU"/>  			<check_box label="Voltear" name="checkbox flip s"/>  			<spinner label="Vertical (V)" name="TexScaleV"/>  			<check_box label="Voltear" name="checkbox flip t"/>  			<spinner label="Rotación" name="TexRot"/> -			<spinner label="Repeticiones / Metro" name="rptctrl"/>  			<button label="Aplicar" label_selected="Aplicar" name="button apply"/>  			<text name="tex offset">  				Desplazar diff --git a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml index 9362f76708..a9eab74e2b 100755 --- a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml @@ -25,14 +25,14 @@  		<text name="ShadersText">  			Shaders:  		</text> -		<check_box initial_value="verdadero" label="Agua transparente" name="TransparentWater"/> +		<check_box initial_value="true" label="Agua transparente" name="TransparentWater"/>  		<check_box initial_value="true" label="Efecto de relieve y brillo" name="BumpShiny"/> -		<check_box initial_value="verdadero" label="Luces locales" name="LocalLights"/> +		<check_box initial_value="true" label="Luces locales" name="LocalLights"/>  		<check_box initial_value="true" label="Shaders básicos" name="BasicShaders" tool_tip="Desactivando esta opción puede prevenir fallos en algunos controladores de la tarjeta gráfica."/>  		<check_box initial_value="true" label="Shaders de la atmósfera" name="WindLightUseAtmosShaders"/> -		<check_box initial_value="verdadero" label="Modelo de iluminación avanzado" name="UseLightShaders"/> -		<check_box initial_value="verdadero" label="Oclusión del ambiente" name="UseSSAO"/> -		<check_box initial_value="verdadero" label="Profundidad del campo" name="UseDoF"/> +		<check_box initial_value="true" label="Modelo de iluminación avanzado" name="UseLightShaders"/> +		<check_box initial_value="true" label="Oclusión del ambiente" name="UseSSAO"/> +		<check_box initial_value="true" label="Profundidad del campo" name="UseDoF"/>  		<text name="shadows_label">  			Sombras:  		</text> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml index f7eaa03d63..508bfbcd32 100755 --- a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml @@ -21,7 +21,7 @@  	<check_box initial_value="true" label="Activar plugins" name="browser_plugins_enabled"/>  	<check_box initial_value="true" label="Aceptar las 'cookies'" name="cookies_enabled"/>  	<check_box initial_value="true" label="Activar Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="falso" label="Permitir las ventanas emergentes en el navegador" name="media_popup_enabled"/> +	<check_box initial_value="false" label="Permitir las ventanas emergentes en el navegador" name="media_popup_enabled"/>  	<text name="Software updates:">  		Actualizaciones de software:  	</text> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_sound.xml b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml index 5cb1654c70..dcd6984715 100755 --- a/indra/newview/skins/default/xui/es/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml @@ -19,7 +19,7 @@  	<check_box label="Activado" name="enable_voice_check"/>  	<check_box label="Permitir la ejecución automática de los media" name="media_auto_play_btn" tool_tip="Marcar esto para permitir la ejecución automática de los media" value="true"/>  	<check_box label="Ejecutar para otros avatares los media anexados" name="media_show_on_others_btn" tool_tip="Al desmarcar esto se esconderán los media anexados a otros avatares cercanos" value="true"/> -	<check_box label="Reproducir sonidos de los gestos" name="gesture_audio_play_btn" tool_tip="Selecciona esta opción para escuchar los sonidos de los gestos" value="verdadero"/> +	<check_box label="Reproducir sonidos de los gestos" name="gesture_audio_play_btn" tool_tip="Selecciona esta opción para escuchar los sonidos de los gestos" value="true"/>  	<text name="voice_chat_settings">  		Configuración del chat de voz  	</text> diff --git a/indra/newview/skins/default/xui/es/panel_tools_texture.xml b/indra/newview/skins/default/xui/es/panel_tools_texture.xml index 7199905a1c..b820880e60 100644 --- a/indra/newview/skins/default/xui/es/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/es/panel_tools_texture.xml @@ -112,5 +112,5 @@  	<spinner label="Grados de rotación" name="shinyRot"/>  	<spinner label="Desplazamiento horizontal" name="shinyOffsetU"/>  	<spinner label="Desplazamiento vertical" name="shinyOffsetV"/> -	<check_box initial_value="falso" label="Alinear caras del plano" name="checkbox planar align" tool_tip="Alinear texturas en todas las caras seleccionadas con la última cara seleccionada. Requiere la representación de texturas en el plano."/> +	<check_box initial_value="false" label="Alinear caras del plano" name="checkbox planar align" tool_tip="Alinear texturas en todas las caras seleccionadas con la última cara seleccionada. Requiere la representación de texturas en el plano."/>  </panel> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 4686d1ed3a..484511a08b 100755 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -1256,7 +1256,7 @@ Intenta iniciar sesión de nuevo en unos instantes.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml index 098f8fc713..bb146556ba 100755 --- a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml @@ -28,7 +28,7 @@  	<text name="tc label">  		Activer S3TC :  	</text> -	<check_box initial_value="vraie" label="Activer la compression des textures (redémarrage requis)" name="texture compression" tool_tip="Comprime les textures en mémoire vidéo afin de permettre de charger des textures de résolution plus élevée au prix d'une certaine qualité de couleur."/> +	<check_box initial_value="true" label="Activer la compression des textures (redémarrage requis)" name="texture compression" tool_tip="Comprime les textures en mémoire vidéo afin de permettre de charger des textures de résolution plus élevée au prix d'une certaine qualité de couleur."/>  	<slider label="Mémoire textures (Mo) :" name="GraphicsCardTextureMemory" tool_tip="Quantité de mémoire à affecter aux textures. Utilise la mémoire de la carte vidéo par défaut. Si vous réduisez ce paramètre, cela peut améliorer les performances, mais les textures risquent d'être floues."/>  	<spinner label="Indice du brouillard :" name="fog"/>  	<button label="OK" label_selected="OK" name="OK"/> diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml index bcc3423862..421e14d51b 100755 --- a/indra/newview/skins/default/xui/fr/floater_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_tools.xml @@ -463,16 +463,11 @@  				<combo_box.item label="Ventouses" name="suction"/>  				<combo_box.item label="Tissage" name="weave"/>  			</combo_box> -			<check_box initial_value="false" label="Aligner les faces Plan" name="checkbox planar align" tool_tip="Aligner les textures sur toutes les faces sélectionnées avec la dernière face sélectionnée. Application de la texture Plan requise."/> -			<text name="rpt"> -				Répétitions / Face -			</text>  			<spinner label="Horizontal (U)" name="TexScaleU"/>  			<check_box label="Inverser" name="checkbox flip s"/>  			<spinner label="Vertical (V)" name="TexScaleV"/>  			<check_box label="Inverser" name="checkbox flip t"/>  			<spinner label="Rotation˚" name="TexRot"/> -			<spinner label="Répétitions / Mètre" name="rptctrl"/>  			<button label="Appliquer" label_selected="Appliquer" name="button apply"/>  			<text name="tex offset">  				Décalage de la texture diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 346fa62351..78d846ff4f 100755 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1274,7 +1274,7 @@ Veuillez réessayer de vous connecter dans une minute.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml index dd59035dd4..468f284ccb 100755 --- a/indra/newview/skins/default/xui/it/floater_tools.xml +++ b/indra/newview/skins/default/xui/it/floater_tools.xml @@ -470,16 +470,11 @@  				<combo_box.item label="Cerchi rialzati" name="suction"/>  				<combo_box.item label="Trama" name="weave"/>  			</combo_box> -			<check_box initial_value="falso" label="Allinea facce planari" name="checkbox planar align" tool_tip="Allinea le texture su tutte le facce selezionate con l’ultima faccia selezionata. È richiesta la mappatura planare delle texture."/> -			<text name="rpt"> -				Ripetizioni / Faccia -			</text>  			<spinner label="Orizzontale (U)" name="TexScaleU"/>  			<check_box label="Inverti" name="checkbox flip s"/>  			<spinner label="Verticale (V)" name="TexScaleV"/>  			<check_box label="Inverti" name="checkbox flip t"/>  			<spinner label="Rotazione˚" name="TexRot"/> -			<spinner label="Ripetizioni / Metro" name="rptctrl"/>  			<button label="Applica" label_selected="Applica" name="button apply"/>  			<text name="tex offset">  				Bilanciamento della texture diff --git a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml index e7483b1ba5..2978c48db6 100755 --- a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml @@ -25,7 +25,7 @@  		<text name="ShadersText">  			Effetti grafici:  		</text> -		<check_box initial_value="vero" label="Acqua trasparente" name="TransparentWater"/> +		<check_box initial_value="true" label="Acqua trasparente" name="TransparentWater"/>  		<check_box initial_value="true" label="Piccoli rilievi e scintillii" name="BumpShiny"/>  		<check_box initial_value="true" label="Luci locali" name="LocalLights"/>  		<check_box initial_value="true" label="Effetti grafici base" name="BasicShaders" tool_tip="Disabilitare questa opzione può evitare che qualche scheda grafica vada in crash."/> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml index 4c190197b4..fcc9661d03 100755 --- a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml @@ -21,7 +21,7 @@  	<check_box initial_value="true" label="Abilita plugin" name="browser_plugins_enabled"/>  	<check_box initial_value="true" label="Accetta cookie" name="cookies_enabled"/>  	<check_box initial_value="true" label="Abilita Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="falso" label="Consenti pop-up nel browser media" name="media_popup_enabled"/> +	<check_box initial_value="false" label="Consenti pop-up nel browser media" name="media_popup_enabled"/>  	<text name="Software updates:">  		Aggiornamenti software:  	</text> diff --git a/indra/newview/skins/default/xui/it/panel_tools_texture.xml b/indra/newview/skins/default/xui/it/panel_tools_texture.xml index 4e515563ac..36ad2980cb 100644 --- a/indra/newview/skins/default/xui/it/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/it/panel_tools_texture.xml @@ -112,5 +112,5 @@  	<spinner label="Gradi di rotazione" name="shinyRot"/>  	<spinner label="Spostamento orizzontale" name="shinyOffsetU"/>  	<spinner label="Spostamento verticale" name="shinyOffsetV"/> -	<check_box initial_value="falso" label="Allinea facce planari" name="checkbox planar align" tool_tip="Allinea le texture su tutte le facce selezionate con l’ultima faccia selezionata. È richiesta la mappatura planare delle texture."/> +	<check_box initial_value="false" label="Allinea facce planari" name="checkbox planar align" tool_tip="Allinea le texture su tutte le facce selezionate con l’ultima faccia selezionata. È richiesta la mappatura planare delle texture."/>  </panel> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 160df911d3..60ed2b0929 100755 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -1265,7 +1265,7 @@ Prova ad accedere nuovamente tra un minuto.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/ja/floater_tools.xml b/indra/newview/skins/default/xui/ja/floater_tools.xml index 4bd6439ad2..5511433ae3 100755 --- a/indra/newview/skins/default/xui/ja/floater_tools.xml +++ b/indra/newview/skins/default/xui/ja/floater_tools.xml @@ -469,16 +469,11 @@  				<combo_box.item label="吸い込み" name="suction"/>  				<combo_box.item label="織目" name="weave"/>  			</combo_box> -			<check_box initial_value="false" label="平面を揃える" name="checkbox planar align" tool_tip="選択面全てのテクスチャを、最後に選択された面に揃えます。 平面テクスチャのマッピングが必要です。"/> -			<text name="rpt"> -				反復 / 面 -			</text>  			<spinner label="水平(U)" name="TexScaleU"/>  			<check_box label="反転" name="checkbox flip s"/>  			<spinner label="垂直(V)" name="TexScaleV"/>  			<check_box label="反転" name="checkbox flip t"/>  			<spinner label="回転˚" name="TexRot"/> -			<spinner label="反復 / メーター" name="rptctrl"/>  			<button label="適用" label_selected="適用" name="button apply"/>  			<text name="tex offset">  				テクスチャのズレ diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index ab2fd461ab..a0f45e5a55 100755 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -1274,7 +1274,7 @@ support@secondlife.com にお問い合わせください。  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml index 9e6fed8387..69d5c23f9c 100755 --- a/indra/newview/skins/default/xui/pl/floater_tools.xml +++ b/indra/newview/skins/default/xui/pl/floater_tools.xml @@ -442,16 +442,11 @@  				<combo_box.item label="Suction" name="suction"/>  				<combo_box.item label="Fali" name="weave"/>  			</combo_box> -			<check_box initial_value="nieprawda" label="Połącz powierzchnie planarne" name="checkbox planar align" tool_tip="Połącz tekstury na wszystkich wybranych powierzchniach z powierzchnią wybraną jako ostatnia. Wymaga planarnego mapowania tekstury."/> -			<text name="rpt"> -				Powtórzenia / Powierzchnia -			</text>  			<spinner label="Poziomo (U)" name="TexScaleU"/>  			<check_box label="Odwróć" name="checkbox flip s"/>  			<spinner label="Pionowo (V)" name="TexScaleV"/>  			<check_box label="Odwróć" name="checkbox flip t"/>  			<spinner label="Powtórzenia˚" name="TexRot"/> -			<spinner label="Powtórzenia / metr" name="rptctrl"/>  			<button label="Zastosuj" label_selected="Zastosuj" name="button apply"/>  			<text name="tex offset">  				Wyrównanie tekstury diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml index f2beef091a..4cd271a141 100755 --- a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml @@ -26,7 +26,7 @@  		<text name="ShadersText">  			Cieniowanie pixeli (shadery):  		</text> -		<check_box initial_value="prawda" label="Przeźroczystość wody" name="TransparentWater"/> +		<check_box initial_value="true" label="Przeźroczystość wody" name="TransparentWater"/>  		<check_box initial_value="true" label="Mapowanie wypukłości i połysk" name="BumpShiny"/>  		<check_box initial_value="true" label="Podstawowe shadery" name="BasicShaders" tool_tip="Wyłączenie tej opcji może naprawić błędy niektórych sterowników graficznych."/>  		<check_box initial_value="true" label="Shadery atmosfery" name="WindLightUseAtmosShaders"/> diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml index fa0a5981a8..b663e18227 100755 --- a/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml @@ -26,14 +26,13 @@  		Internet:  	</text>  	<radio_group name="use_external_browser"> -		<radio_item label="Użyj zewnętrznej przeglądarki (IE, Firefox, Safari)" name="external" tool_tip="Używaj zewnętrznej przeglądarki. Nie jest to rekomendowane w trybie pełnoekranowym." value="1"/> +		<radio_item label="Użyj zewnętrznej przeglądarki (IE, Firefox, Safari)" name="external" tool_tip="Używaj zewnętrznej przeglądarki. Nie jest to rekomendowane w trybie pełnoekranowym." value="true"/>  		<radio_item label="Używaj wbudowanej przeglądarki." name="internal" tool_tip="Używaj wbudowanej przeglądarki. Ta przeglądarka otworzy nowe okno w [APP_NAME]." value=""/>  	</radio_group>  	<check_box initial_value="true" label="Zezwalaj na wtyczki" name="browser_plugins_enabled"/>  	<check_box initial_value="true" label="Akceptuj ciasteczka z Internetu" name="cookies_enabled"/>  	<check_box initial_value="true" label="Zezwalaj na Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="nieprawda" label="Zezwól na wyskakujące okienka przeglądarki mediów" name="media_popup_enabled"/> -	<check_box initial_value="false" label="Używaj serwera proxy" name="web_proxy_enabled"/> +	<check_box initial_value="false" label="Zezwól na wyskakujące okienka przeglądarki mediów" name="media_popup_enabled"/>  	<text name="Proxy location">  		Lokalizacja proxy:  	</text> diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml index 8c245c582e..66c14cdecf 100755 --- a/indra/newview/skins/default/xui/pt/floater_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_tools.xml @@ -463,16 +463,11 @@  				<combo_box.item label="Sulcos" name="suction"/>  				<combo_box.item label="Weave" name="weave"/>  			</combo_box> -			<check_box initial_value="falso" label="Alinhar planares" name="checkbox planar align" tool_tip="Alinhar texturas dos planos selecionados com o plano selecionado por último. Requer mapeamento planar da textura."/> -			<text name="rpt"> -				Repetições / Plano -			</text>  			<spinner label="Horizontal (U)" name="TexScaleU"/>  			<check_box label="Inverter" name="checkbox flip s"/>  			<spinner label="Vertical (V)" name="TexScaleV"/>  			<check_box label="Inverter" name="checkbox flip t"/>  			<spinner label="Rotação˚" name="TexRot"/> -			<spinner label="Repetições/Metro" name="rptctrl"/>  			<button label="Aplicar" label_selected="Aplicar" name="button apply"/>  			<text name="tex offset">  				Offset de textura diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml index 37e8838bf4..756e345cb8 100755 --- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml @@ -26,14 +26,14 @@ rápido  		<text name="ShadersText">  			Sombreadores:  		</text> -		<check_box initial_value="verdadeiro" label="Água transparente" name="TransparentWater"/> +		<check_box initial_value="true" label="Água transparente" name="TransparentWater"/>  		<check_box initial_value="true" label="Bump de Mapeamento e Brilho" name="BumpShiny"/> -		<check_box initial_value="verdadeiro" label="Luzes locais" name="LocalLights"/> +		<check_box initial_value="true" label="Luzes locais" name="LocalLights"/>  		<check_box initial_value="true" label="Sombreadores básicos" name="BasicShaders" tool_tip="Desabilitar esta opção poderá impedir que alguns drivers de placa de vídeo a travem."/>  		<check_box initial_value="true" label="Sombreadores Atmosféricos" name="WindLightUseAtmosShaders"/> -		<check_box initial_value="verdadeiro" label="Modelo avançado de luzes" name="UseLightShaders"/> -		<check_box initial_value="verdadeiro" label="Oclusão ambiental" name="UseSSAO"/> -		<check_box initial_value="verdadeiro" label="Profundidade" name="UseDoF"/> +		<check_box initial_value="true" label="Modelo avançado de luzes" name="UseLightShaders"/> +		<check_box initial_value="true" label="Oclusão ambiental" name="UseSSAO"/> +		<check_box initial_value="true" label="Profundidade" name="UseDoF"/>  		<text name="shadows_label">  			Sombras:  		</text> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml index 887d0cfe98..1279e74e21 100755 --- a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml @@ -21,7 +21,7 @@  	<check_box initial_value="true" label="Habilitar plugins" name="browser_plugins_enabled"/>  	<check_box initial_value="true" label="Aceitar cookies" name="cookies_enabled"/>  	<check_box initial_value="true" label="Habilitar Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="falso" label="Ativar pop-ups no navegador de mídia" name="media_popup_enabled"/> +	<check_box initial_value="false" label="Ativar pop-ups no navegador de mídia" name="media_popup_enabled"/>  	<text name="Software updates:">  		Atualizações de software:  	</text> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml index d910a7b812..fff5fd7005 100755 --- a/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml @@ -19,7 +19,7 @@  	<check_box label="Ativado" name="enable_voice_check"/>  	<check_box label="Autorizar auto-play de mídias" name="media_auto_play_btn" tool_tip="Marque esta opção para auto-executar mídias, se elas quiserem" value="true"/>  	<check_box label="Tocar mídia anexada em outros avatares" name="media_show_on_others_btn" tool_tip="Desmarque esta opção para ocultar mídias anexadas em avatares por perto" value="true"/> -	<check_box label="Tocar áudio de gestos" name="gesture_audio_play_btn" tool_tip="Selecione para ouvir o áudio de gestos" value="verdadeiro"/> +	<check_box label="Tocar áudio de gestos" name="gesture_audio_play_btn" tool_tip="Selecione para ouvir o áudio de gestos" value="true"/>  	<text name="voice_chat_settings">  		Configuração de bate-papo de voz  	</text> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index adc3ee14e0..2eb4c0a02e 100755 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -1220,7 +1220,7 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/ru/floater_auction.xml b/indra/newview/skins/default/xui/ru/floater_auction.xml index d84dc2e941..105c75c919 100755 --- a/indra/newview/skins/default/xui/ru/floater_auction.xml +++ b/indra/newview/skins/default/xui/ru/floater_auction.xml @@ -3,7 +3,7 @@  	<floater.string name="already for sale">  		Нельзя выставить на аукцион участки, которые уже продаются.  	</floater.string> -	<check_box initial_value="истина" label="Включая желтую ограду вокруг выбранного участка" name="fence_check"/> +	<check_box initial_value="true" label="Включая желтую ограду вокруг выбранного участка" name="fence_check"/>  	<button label="Снимок" label_selected="Снимок" name="snapshot_btn"/>  	<button label="Купить может каждый" label_selected="Купить может каждый" name="sell_to_anyone_btn"/>  	<button label="Очистить настройки" label_selected="Очистить настройки" name="reset_parcel_btn"/> diff --git a/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml b/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml index 31fc1c5ed3..304bf97dc1 100755 --- a/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml @@ -39,7 +39,7 @@  	</text>  	<check_box label="Изменять" name="next_owner_modify"/>  	<check_box label="Копировать" name="next_owner_copy"/> -	<check_box initial_value="истина" label="Передать" name="next_owner_transfer" tool_tip="Следующий владелец может отдать или перепродать объект"/> +	<check_box initial_value="true" label="Передать" name="next_owner_transfer" tool_tip="Следующий владелец может отдать или перепродать объект"/>  	<button label="OK" name="ok"/>  	<button label="Применить" name="apply"/>  	<button label="Отмена" name="close"/> diff --git a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml index 43f8c36473..d7da112a27 100755 --- a/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/ru/floater_hardware_settings.xml @@ -24,7 +24,7 @@  	<text name="Enable VBO:">  		Включить VBO:  	</text> -	<check_box initial_value="истина" label="Включить объекты вершинных буферов OpenGL" name="vbo" tool_tip="Включение этого параметра на современном оборудовании даст увеличение производительности.  Однако на старом оборудовании это может привести к сбою приложения."/> +	<check_box initial_value="true" label="Включить объекты вершинных буферов OpenGL" name="vbo" tool_tip="Включение этого параметра на современном оборудовании даст увеличение производительности.  Однако на старом оборудовании это может привести к сбою приложения."/>  	<text name="tc label">  		Включить S3TC:  	</text> diff --git a/indra/newview/skins/default/xui/ru/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/ru/floater_live_lsleditor.xml index d8047fc045..fb6e747592 100755 --- a/indra/newview/skins/default/xui/ru/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/ru/floater_live_lsleditor.xml @@ -10,6 +10,6 @@  		СКРИПТ: [NAME]  	</floater.string>  	<button label="Сброс" label_selected="Сброс" name="Reset"/> -	<check_box initial_value="истина" label="Выполняется" name="running"/> -	<check_box initial_value="истина" label="Моно" name="mono"/> +	<check_box initial_value="true" label="Выполняется" name="running"/> +	<check_box initial_value="true" label="Моно" name="mono"/>  </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_perm_prefs.xml b/indra/newview/skins/default/xui/ru/floater_perm_prefs.xml index a704b87bd1..626f3c9321 100755 --- a/indra/newview/skins/default/xui/ru/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/ru/floater_perm_prefs.xml @@ -8,7 +8,7 @@  		</text>  		<check_box label="изменять" name="next_owner_modify"/>  		<check_box label="копировать" name="next_owner_copy"/> -		<check_box initial_value="истина" label="перепродавать/отдавать" name="next_owner_transfer"/> +		<check_box initial_value="true" label="перепродавать/отдавать" name="next_owner_transfer"/>  	</panel>  	<button label="ОК" label_selected="ОК" name="ok"/>  	<button label="Отмена" label_selected="Отмена" name="cancel"/> diff --git a/indra/newview/skins/default/xui/ru/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/ru/floater_preferences_proxy.xml index 4eecfedf17..13cff2bcbe 100755 --- a/indra/newview/skins/default/xui/ru/floater_preferences_proxy.xml +++ b/indra/newview/skins/default/xui/ru/floater_preferences_proxy.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <floater name="Proxy Settings Floater" title="Настройки прокси-сервера"> -	<check_box initial_value="ложь" label="Использовать HTTP-прокси для веб-страниц" name="web_proxy_enabled"/> +	<check_box initial_value="false" label="Использовать HTTP-прокси для веб-страниц" name="web_proxy_enabled"/>  	<text name="http_proxy_label">  		HTTP-прокси:  	</text> diff --git a/indra/newview/skins/default/xui/ru/floater_settings_debug.xml b/indra/newview/skins/default/xui/ru/floater_settings_debug.xml index 7db014ef53..db78d11e90 100755 --- a/indra/newview/skins/default/xui/ru/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/ru/floater_settings_debug.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <floater name="settings_debug" title="НАСТРОЙКИ ОТЛАДКИ">  	<radio_group name="boolean_combo"> -		<radio_item label="ИСТИНА" name="TRUE" value="истина"/> +		<radio_item label="ИСТИНА" name="TRUE" value="true"/>  		<radio_item label="ЛОЖЬ" name="FALSE" value=""/>  	</radio_group>  	<color_swatch label="Цвет" name="val_color_swatch"/> diff --git a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml index a9a21e7d4a..c9e117362f 100755 --- a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml @@ -19,10 +19,10 @@  	<button label="По умолчанию" label_selected="По умолчанию" name="Default"/>  	<button label="Очистить" label_selected="Очистить" name="Blank"/>  	<button label="Нет" label_selected="Нет" name="None"/> -	<check_box initial_value="истина" label="Применить сейчас" name="apply_immediate_check"/> +	<check_box initial_value="true" label="Применить сейчас" name="apply_immediate_check"/>  	<text name="preview_disabled" value="Просмотр отключен"/>  	<filter_editor label="Фильтровать текстуры" name="inventory search editor"/> -	<check_box initial_value="ложь" label="Показывать папки" name="show_folders_check"/> +	<check_box initial_value="false" label="Показывать папки" name="show_folders_check"/>  	<button label="Добавить" label_selected="Добавить" name="l_add_btn"/>  	<button label="Удалить" label_selected="Удалить" name="l_rem_btn"/>  	<button label="Передать" label_selected="Передать" name="l_upl_btn"/> diff --git a/indra/newview/skins/default/xui/ru/floater_tools.xml b/indra/newview/skins/default/xui/ru/floater_tools.xml index c312f73428..35921d147f 100755 --- a/indra/newview/skins/default/xui/ru/floater_tools.xml +++ b/indra/newview/skins/default/xui/ru/floater_tools.xml @@ -76,8 +76,8 @@  	<text label="Растяжка обеих сторон" name="checkbox uniform label">  		Растяжка обеих сторон  	</text> -	<check_box initial_value="истина" label="Растягивать текстуры" name="checkbox stretch textures"/> -	<check_box initial_value="истина" label="Привязка" name="checkbox snap to grid"/> +	<check_box initial_value="true" label="Растягивать текстуры" name="checkbox stretch textures"/> +	<check_box initial_value="true" label="Привязка" name="checkbox snap to grid"/>  	<combo_box name="combobox grid mode" tool_tip="Выберите тип линейки сетки для размещения объекта">  		<combo_box.item label="Мировая" name="World"/>  		<combo_box.item label="Локальная" name="Local"/> @@ -101,7 +101,7 @@  	<button name="ToolGrass" tool_tip="Трава"/>  	<check_box label="Держать инструмент" name="checkbox sticky"/>  	<check_box label="Копировать выдел." name="checkbox copy selection"/> -	<check_box initial_value="истина" label="Центрир. копию" name="checkbox copy centers"/> +	<check_box initial_value="true" label="Центрир. копию" name="checkbox copy centers"/>  	<check_box label="Повернуть копию" name="checkbox copy rotates"/>  	<radio_group name="land_radio_group">  		<radio_item label="Выбрать землю" name="radio select land"/> @@ -465,16 +465,11 @@  				<combo_box.item label="присоска" name="suction"/>  				<combo_box.item label="переплетение" name="weave"/>  			</combo_box> -			<check_box initial_value="ложь" label="Согласование" name="checkbox planar align" tool_tip="Согласование текстур на всех выбранных граних по последней выбранной грани. Должно быть выбрано наложение по плоскостям."/> -			<text name="rpt"> -				Повторов на грань -			</text>  			<spinner label="По горизонтали (U)" name="TexScaleU"/>  			<check_box label="Разворот" name="checkbox flip s"/>  			<spinner label="По вертикали (V)" name="TexScaleV"/>  			<check_box label="Разворот" name="checkbox flip t"/>  			<spinner label="Вращение˚" name="TexRot"/> -			<spinner label="Повторов на метр" name="rptctrl"/>  			<button label="Применить" label_selected="Применить" name="button apply"/>  			<text name="tex offset">  				Сдвиг текстуры diff --git a/indra/newview/skins/default/xui/ru/floater_world_map.xml b/indra/newview/skins/default/xui/ru/floater_world_map.xml index ef8dfe22ae..7d2acfd9a0 100755 --- a/indra/newview/skins/default/xui/ru/floater_world_map.xml +++ b/indra/newview/skins/default/xui/ru/floater_world_map.xml @@ -35,7 +35,7 @@  		<text name="pg_label">  			Общие  		</text> -		<check_box initial_value="истина" name="events_mature_chk"/> +		<check_box initial_value="true" name="events_mature_chk"/>  		<text name="events_mature_label">  			Умеренные  		</text> diff --git a/indra/newview/skins/default/xui/ru/panel_group_general.xml b/indra/newview/skins/default/xui/ru/panel_group_general.xml index 4d7e1c9fff..ba38dbf89e 100755 --- a/indra/newview/skins/default/xui/ru/panel_group_general.xml +++ b/indra/newview/skins/default/xui/ru/panel_group_general.xml @@ -51,6 +51,6 @@  			<combo_box.item label="Умеренный контент" name="mature"/>  			<combo_box.item label="Общий контент" name="pg"/>  		</combo_box> -		<check_box initial_value="истина" label="Показать в поиске" name="show_in_group_list" tool_tip="Позволить людям видеть эту группу в результатах поиска"/> +		<check_box initial_value="true" label="Показать в поиске" name="show_in_group_list" tool_tip="Позволить людям видеть эту группу в результатах поиска"/>  	</panel>  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_media_settings_general.xml b/indra/newview/skins/default/xui/ru/panel_media_settings_general.xml index 6dc435db20..d52397832c 100755 --- a/indra/newview/skins/default/xui/ru/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/ru/panel_media_settings_general.xml @@ -15,14 +15,14 @@  	</text>  	<text name="current_url" tool_tip="Текущая страница для этого медиа-источника" value=""/>  	<button label="Сброс" name="current_url_reset_btn"/> -	<check_box initial_value="ложь" label="Автоматическое зацикливание" name="auto_loop"/> -	<check_box initial_value="ложь" label="Реакция на первый щелчок" name="first_click_interact"/> -	<check_box initial_value="ложь" label="Автоувеличение" name="auto_zoom"/> -	<check_box initial_value="ложь" label="Автоматическое проигрывание" name="auto_play"/> +	<check_box initial_value="false" label="Автоматическое зацикливание" name="auto_loop"/> +	<check_box initial_value="false" label="Реакция на первый щелчок" name="first_click_interact"/> +	<check_box initial_value="false" label="Автоувеличение" name="auto_zoom"/> +	<check_box initial_value="false" label="Автоматическое проигрывание" name="auto_play"/>  	<text name="media_setting_note">  		Примечание. Жители могут переопределять эту настройку.  	</text> -	<check_box initial_value="ложь" label="Автомасштабирование на объекте" name="auto_scale"/> +	<check_box initial_value="false" label="Автомасштабирование на объекте" name="auto_scale"/>  	<text name="size_label">  		Размер:  	</text> diff --git a/indra/newview/skins/default/xui/ru/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/ru/panel_media_settings_permissions.xml index 680cba9c14..cfb006f346 100755 --- a/indra/newview/skins/default/xui/ru/panel_media_settings_permissions.xml +++ b/indra/newview/skins/default/xui/ru/panel_media_settings_permissions.xml @@ -14,16 +14,16 @@  	<text name="owner_label">  		Владелец  	</text> -	<check_box initial_value="ложь" label="Разрешить навигацию и взаимодействие" name="perms_owner_interact"/> -	<check_box initial_value="ложь" label="Панель управления видна" name="perms_owner_control"/> +	<check_box initial_value="false" label="Разрешить навигацию и взаимодействие" name="perms_owner_interact"/> +	<check_box initial_value="false" label="Панель управления видна" name="perms_owner_control"/>  	<text name="group_label">  		Группа:  	</text> -	<check_box initial_value="ложь" label="Разрешить навигацию и взаимодействие" name="perms_group_interact"/> -	<check_box initial_value="ложь" label="Панель управления видна" name="perms_group_control"/> +	<check_box initial_value="false" label="Разрешить навигацию и взаимодействие" name="perms_group_interact"/> +	<check_box initial_value="false" label="Панель управления видна" name="perms_group_control"/>  	<text name="anyone_label">  		всем  	</text> -	<check_box initial_value="ложь" label="Разрешить навигацию и взаимодействие" name="perms_anyone_interact"/> -	<check_box initial_value="ложь" label="Панель управления видна" name="perms_anyone_control"/> +	<check_box initial_value="false" label="Разрешить навигацию и взаимодействие" name="perms_anyone_interact"/> +	<check_box initial_value="false" label="Панель управления видна" name="perms_anyone_control"/>  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_media_settings_security.xml b/indra/newview/skins/default/xui/ru/panel_media_settings_security.xml index 6b30dc799c..bae491472a 100755 --- a/indra/newview/skins/default/xui/ru/panel_media_settings_security.xml +++ b/indra/newview/skins/default/xui/ru/panel_media_settings_security.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel label="Безопасность" name="Media Settings Security"> -	<check_box initial_value="ложь" label="Разрешить доступ к ссылкам только по шаблону" name="whitelist_enable"/> +	<check_box initial_value="false" label="Разрешить доступ к ссылкам только по шаблону" name="whitelist_enable"/>  	<text name="home_url_fails_some_items_in_whitelist">  		Пункты, не подходящие для домашней страницы, отмечены знаком:  	</text> diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_general.xml b/indra/newview/skins/default/xui/ru/panel_preferences_general.xml index c7a850f78a..62617caed3 100755 --- a/indra/newview/skins/default/xui/ru/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/ru/panel_preferences_general.xml @@ -36,7 +36,7 @@  		<combo_box.item label="Мое последнее место" name="MyLastLocation"/>  		<combo_box.item label="Мой дом" name="MyHome"/>  	</combo_box> -	<check_box initial_value="истина" label="Показывать на экране входа" name="show_location_checkbox"/> +	<check_box initial_value="true" label="Показывать на экране входа" name="show_location_checkbox"/>  	<text name="name_tags_textbox">  		Теги имен:  	</text> diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml index 029e72e137..c93955fcdc 100755 --- a/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml @@ -25,14 +25,14 @@  		<text name="ShadersText">  			Шейдеры:  		</text> -		<check_box initial_value="истина" label="Прозрачность воды" name="TransparentWater"/> -		<check_box initial_value="истина" label="Рельефность и сияние" name="BumpShiny"/> -		<check_box initial_value="истина" label="Локальный свет" name="LocalLights"/> -		<check_box initial_value="истина" label="Базовые шейдеры" name="BasicShaders" tool_tip="Отключение этого параметра может предотвратить зависание некоторых видеокарт"/> -		<check_box initial_value="истина" label="Атмосферные шейдеры" name="WindLightUseAtmosShaders"/> -		<check_box initial_value="истина" label="Расширенная модель освещения" name="UseLightShaders"/> -		<check_box initial_value="истина" label="Объемный свет" name="UseSSAO"/> -		<check_box initial_value="истина" label="Глубина поля" name="UseDoF"/> +		<check_box initial_value="true" label="Прозрачность воды" name="TransparentWater"/> +		<check_box initial_value="true" label="Рельефность и сияние" name="BumpShiny"/> +		<check_box initial_value="true" label="Локальный свет" name="LocalLights"/> +		<check_box initial_value="true" label="Базовые шейдеры" name="BasicShaders" tool_tip="Отключение этого параметра может предотвратить зависание некоторых видеокарт"/> +		<check_box initial_value="true" label="Атмосферные шейдеры" name="WindLightUseAtmosShaders"/> +		<check_box initial_value="true" label="Расширенная модель освещения" name="UseLightShaders"/> +		<check_box initial_value="true" label="Объемный свет" name="UseSSAO"/> +		<check_box initial_value="true" label="Глубина поля" name="UseDoF"/>  		<text name="shadows_label">  			Тени:  		</text> @@ -95,9 +95,9 @@  		<text name="AvatarRenderingText">  			Отрисовка аватара:  		</text> -		<check_box initial_value="истина" label="Плоские аватары" name="AvatarImpostors"/> -		<check_box initial_value="истина" label="Аппаратная отрисовка" name="AvatarVertexProgram"/> -		<check_box initial_value="истина" label="Одежда аватара" name="AvatarCloth"/> +		<check_box initial_value="true" label="Плоские аватары" name="AvatarImpostors"/> +		<check_box initial_value="true" label="Аппаратная отрисовка" name="AvatarVertexProgram"/> +		<check_box initial_value="true" label="Одежда аватара" name="AvatarCloth"/>  		<text name="TerrainDetailText">  			Ландшафт:  		</text> diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml index e9c0c7de10..1741397a84 100755 --- a/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/ru/panel_preferences_setup.xml @@ -18,10 +18,10 @@  		<radio_item label="Использовать мой браузер (IE, Firefox, Safari)" name="external" tool_tip="Будет использоваться браузер, заданный в системе по умолчанию. Не рекомендуется, если [APP_NAME] работает в полноэкранном режиме." value="true"/>  		<radio_item label="Использовать встроенный браузер" name="internal" tool_tip="Для просмотра справки, ссылок на веб-страницы и т. д. будет использоваться встроенный браузер. Этот браузер открывается как новое окно в [APP_NAME]." value=""/>  	</radio_group> -	<check_box initial_value="истина" label="Разрешить плагины" name="browser_plugins_enabled"/> -	<check_box initial_value="истина" label="Принимать файлы cookie" name="cookies_enabled"/> -	<check_box initial_value="истина" label="Разрешить Javascript" name="browser_javascript_enabled"/> -	<check_box initial_value="ложь" label="Разрешить всплывающие окна" name="media_popup_enabled"/> +	<check_box initial_value="true" label="Разрешить плагины" name="browser_plugins_enabled"/> +	<check_box initial_value="true" label="Принимать файлы cookie" name="cookies_enabled"/> +	<check_box initial_value="true" label="Разрешить Javascript" name="browser_javascript_enabled"/> +	<check_box initial_value="false" label="Разрешить всплывающие окна" name="media_popup_enabled"/>  	<text name="Software updates:">  		Обновления ПО:  	</text> diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_sound.xml b/indra/newview/skins/default/xui/ru/panel_preferences_sound.xml index bf673750d2..44f270527c 100755 --- a/indra/newview/skins/default/xui/ru/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/ru/panel_preferences_sound.xml @@ -4,7 +4,7 @@  		среднюю кнопку мыши  	</panel.string>  	<slider label="Общая громкость" name="System Volume"/> -	<check_box initial_value="истина" name="mute_when_minimized"/> +	<check_box initial_value="true" name="mute_when_minimized"/>  	<text name="mute_chb_label">  		Заглушать, когда свернуто  	</text> @@ -17,9 +17,9 @@  	<check_box label="Включено" name="enable_media"/>  	<slider label="Голосовой чат" name="Voice Volume"/>  	<check_box label="Включено" name="enable_voice_check"/> -	<check_box label="Разрешить автовоспроизведение медиа" name="media_auto_play_btn" tool_tip="Установка флажка позволит вам автоматически воспроизводить медиа" value="истина"/> -	<check_box label="Воспроизводить медиа, присоединенные к другому аватару" name="media_show_on_others_btn" tool_tip="Снятие флажка скроет медиа, присоединенные к другому аватару" value="истина"/> -	<check_box label="Сопровождать жесты звуками" name="gesture_audio_play_btn" tool_tip="Установите флажок, чтобы слышать звуки при жестах" value="истина"/> +	<check_box label="Разрешить автовоспроизведение медиа" name="media_auto_play_btn" tool_tip="Установка флажка позволит вам автоматически воспроизводить медиа" value="true"/> +	<check_box label="Воспроизводить медиа, присоединенные к другому аватару" name="media_show_on_others_btn" tool_tip="Снятие флажка скроет медиа, присоединенные к другому аватару" value="true"/> +	<check_box label="Сопровождать жесты звуками" name="gesture_audio_play_btn" tool_tip="Установите флажок, чтобы слышать звуки при жестах" value="true"/>  	<text name="voice_chat_settings">  		Настройки голосового чата  	</text> diff --git a/indra/newview/skins/default/xui/ru/panel_tools_texture.xml b/indra/newview/skins/default/xui/ru/panel_tools_texture.xml index 60717a3d1d..1abf729487 100644 --- a/indra/newview/skins/default/xui/ru/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/ru/panel_tools_texture.xml @@ -112,5 +112,5 @@  	<spinner label="Поворот, градусы" name="shinyRot"/>  	<spinner label="Смещение по горизонтали" name="shinyOffsetU"/>  	<spinner label="Смещение по вертикали" name="shinyOffsetV"/> -	<check_box initial_value="ложь" label="Согласование" name="checkbox planar align" tool_tip="Согласование текстур на всех выбранных гранях по последней выбранной грани. Должно быть выбрано наложение по плоскостям."/> +	<check_box initial_value="false" label="Согласование" name="checkbox planar align" tool_tip="Согласование текстур на всех выбранных гранях по последней выбранной грани. Должно быть выбрано наложение по плоскостям."/>  </panel> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 49ce33ec96..0f71edcee0 100755 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -1271,7 +1271,7 @@ support@secondlife.com.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/tr/floater_tools.xml b/indra/newview/skins/default/xui/tr/floater_tools.xml index 4bf0372a8a..39a3569efa 100755 --- a/indra/newview/skins/default/xui/tr/floater_tools.xml +++ b/indra/newview/skins/default/xui/tr/floater_tools.xml @@ -465,16 +465,11 @@  				<combo_box.item label="vakum" name="suction"/>  				<combo_box.item label="örgü" name="weave"/>  			</combo_box> -			<check_box initial_value="false" label="Planar yüzleri hizala" name="checkbox planar align" tool_tip="Tüm seçili yüzeylerdeki dokuları son seçili yüzdekiyle hizalar. Planar doku eşleştirmesi gerektirir."/> -			<text name="rpt"> -				Tekrarlar / Yüz -			</text>  			<spinner label="Yatay (U)" name="TexScaleU"/>  			<check_box label="Çevir" name="checkbox flip s"/>  			<spinner label="Dikey (V)" name="TexScaleV"/>  			<check_box label="Çevir" name="checkbox flip t"/>  			<spinner label="Döndürme*" name="TexRot"/> -			<spinner label="Tekrarlar / Metre" name="rptctrl"/>  			<button label="Uygula" label_selected="Uygula" name="button apply"/>  			<text name="tex offset">  				Doku Dengeleyicisi diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 5a809ea783..c4b1530b2b 100755 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -1271,7 +1271,7 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/  	</string>  	<string name="MarketplaceURL_CreateStore"> -		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 +		http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.3  	</string>  	<string name="MarketplaceURL_Dashboard">  		https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard diff --git a/indra/newview/skins/default/xui/zh/floater_tools.xml b/indra/newview/skins/default/xui/zh/floater_tools.xml index 33c9ebeaf0..7e6c972f40 100755 --- a/indra/newview/skins/default/xui/zh/floater_tools.xml +++ b/indra/newview/skins/default/xui/zh/floater_tools.xml @@ -465,16 +465,11 @@  				<combo_box.item label="吸附" name="suction"/>  				<combo_box.item label="編織" name="weave"/>  			</combo_box> -			<check_box initial_value="false" label="對齊平面" name="checkbox planar align" tool_tip="以最後所選擇的面為基準,對齊全部所選擇的面上的材質。 這必須使用平面材質映射方式。"/> -			<text name="rpt"> -				重覆次數 / 面 -			</text>  			<spinner label="水平(U)" name="TexScaleU"/>  			<check_box label="翻轉" name="checkbox flip s"/>  			<spinner label="垂直(V)" name="TexScaleV"/>  			<check_box label="翻轉" name="checkbox flip t"/>  			<spinner label="旋轉˚" name="TexRot"/> -			<spinner label="重覆次數 / 公尺" name="rptctrl"/>  			<button label="套用" label_selected="套用" name="button apply"/>  			<text name="tex offset">  				材質位移 diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml b/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml index 0fcc49b203..ab4d9a881d 100755 --- a/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml @@ -15,7 +15,7 @@  		網頁:  	</text>  	<radio_group name="use_external_browser"> -		<radio_item label="使用我的網頁瀏覽器(例如 IE, Firefox, Safari)" name="external" tool_tip="使用系統預設的瀏覽器瀏覽幫助,開啟網頁。全螢幕模式下不建議這麼做。" value="1"/> +		<radio_item label="使用我的網頁瀏覽器(例如 IE, Firefox, Safari)" name="external" tool_tip="使用系統預設的瀏覽器瀏覽幫助,開啟網頁。全螢幕模式下不建議這麼做。" value="true"/>  		<radio_item label="使用內建網頁瀏覽器" name="internal" tool_tip="使用內建的瀏覽器瀏覽幫助,開啟網頁。該瀏覽器將透過 [APP_NAME] 開啟新視窗。" value=""/>  	</radio_group>  	<check_box initial_value="true" label="啟用外掛" name="browser_plugins_enabled"/> diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp index fd9527d631..8ce56326d8 100755 --- a/indra/newview/tests/lltranslate_test.cpp +++ b/indra/newview/tests/lltranslate_test.cpp @@ -308,8 +308,8 @@ void LLCurl::Responder::errorWithContent(U32, std::string const&, LLSD const&) {  void LLCurl::Responder::result(LLSD const&) {}  LLCurl::Responder::~Responder() {} -void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32) {} -void LLHTTPClient::get(const std::string&, LLPointer<LLCurl::Responder>, const LLSD&, const F32) {} +void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32, bool) {} +void LLHTTPClient::get(const std::string&, LLPointer<LLCurl::Responder>, const LLSD&, const F32, bool) {}  LLBufferStream::LLBufferStream(const LLChannelDescriptors& channels, LLBufferArray* buffer)  :	std::iostream(&mStreamBuf), mStreamBuf(channels, buffer) {} diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 19863dd845..894e368427 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -104,26 +104,37 @@ class ViewerManifest(LLManifest):                      self.path("dictionaries")                      self.end_prefix(pkgdir) -                # CHOP-955: If we have "sourceid" in the build process -                # environment, generate it into settings_install.xml. -                try: -                    sourceid = os.environ["sourceid"] -                except KeyError: -                    # no sourceid, no settings_install.xml file -                    pass -                else: -                    if sourceid: -                        # Single-entry subset of the LLSD content of settings.xml -                        content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers', -                                                     Persist=1, -                                                     Type='String', -                                                     Value=sourceid)) -                        # put_in_file(src=) need not be an actual pathname; it -                        # only needs to be non-empty -                        settings_install = self.put_in_file(llsd.format_pretty_xml(content), -                                                            "settings_install.xml", -                                                            src="environment") -                        print "Put sourceid '%s' in %s" % (sourceid, settings_install) +                # CHOP-955: If we have "sourceid" or "viewer_channel" in the +                # build process environment, generate it into +                # settings_install.xml. +                settings_template = dict( +                    sourceid=dict(Comment='Identify referring agency to Linden web servers', +                                  Persist=1, +                                  Type='String', +                                  Value=''), +                    CmdLineChannel=dict(Comment='Command line specified channel name', +                                        Persist=0, +                                        Type='String', +                                        Value='')) +                settings_install = {} +                for key, setting in (("sourceid", "sourceid"), +                                     ("channel", "CmdLineChannel")): +                    if key in self.args: +                        # only set if value is non-empty +                        if self.args[key]: +                            # copy corresponding setting from settings_template +                            settings_install[setting] = settings_template[setting].copy() +                            # then fill in Value +                            settings_install[setting]["Value"] = self.args[key] +                            print "Put %s '%s' in settings_install.xml" % (setting, self.args[key]) + +                # did we actually copy anything into settings_install dict? +                if settings_install: +                    # put_in_file(src=) need not be an actual pathname; it +                    # only needs to be non-empty +                    self.put_in_file(llsd.format_pretty_xml(settings_install), +                                     "settings_install.xml", +                                     src="environment")                  self.end_prefix("app_settings") @@ -611,6 +622,9 @@ class WindowsManifest(ViewerManifest):              installer_file = self.args['installer_name']          else:              installer_file = installer_file % substitution_strings +        if len(self.args['package_id']) > 0: +            installer_file = installer_file.replace(self.args['package_id'], "") +            installer_file = installer_file.replace(".exe", self.args['package_id'] + ".exe")          substitution_strings['installer_file'] = installer_file          tempfile = "secondlife_setup_tmp.nsi" @@ -838,7 +852,9 @@ class DarwinManifest(ViewerManifest):          volname="Second Life Installer"  # DO NOT CHANGE without understanding comment above -        if self.default_channel(): +        if len(self.args['package_id']) > 0: +            imagename = imagename + self.args['package_id'] +        elif self.default_channel():              if not self.default_grid():                  # beta case                  imagename = imagename + '_' + self.args['grid'].upper() @@ -851,7 +867,7 @@ class DarwinManifest(ViewerManifest):          # make sure we don't have stale files laying about          self.remove(sparsename, finalname) -        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { +        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 1000 -layout SPUD' % {                  'sparse':sparsename,                  'vol':volname}) @@ -926,6 +942,7 @@ class DarwinManifest(ViewerManifest):          print "Converting temp disk image to final disk image"          self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname}) +        self.run_command('hdiutil internet-enable -yes %(final)r' % {'final':finalname})          # get rid of the temp file          self.package_file = finalname          self.remove(sparsename) @@ -998,6 +1015,7 @@ class LinuxManifest(ViewerManifest):                      installer_name += '_' + self.args['grid'].upper()              else:                  installer_name += '_' + self.channel_oneword().upper() +        installer_name = installer_name + self.args['package_id']          self.strip_binaries() diff --git a/indra/test_apps/llfbconnecttest/CMakeLists.txt b/indra/test_apps/llfbconnecttest/CMakeLists.txt new file mode 100644 index 0000000000..f56329a010 --- /dev/null +++ b/indra/test_apps/llfbconnecttest/CMakeLists.txt @@ -0,0 +1,304 @@ +# -*- cmake -*- +project(llfbconnecttest) + +include(00-Common) +include(FindOpenGL) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(LLSharedLibs) +include(PluginAPI) +include(LLImage) +include(LLMath) +include(LLMessage) +include(LLRender) +include(LLWindow) +include(Glut) +include(Glui) + +include_directories( +    ${LLPLUGIN_INCLUDE_DIRS} +    ${LLCOMMON_INCLUDE_DIRS} +    ${LLIMAGE_INCLUDE_DIRS} +    ${LLMATH_INCLUDE_DIRS} +    ${LLMESSAGE_INCLUDE_DIRS} +    ${LLRENDER_INCLUDE_DIRS} +    ${LLWINDOW_INCLUDE_DIRS} +) + +if (DARWIN) +    include(CMakeFindFrameworks) +    find_library(COREFOUNDATION_LIBRARY CoreFoundation) +endif (DARWIN) + +### llfbconnecttest + +set(llfbconnecttest_SOURCE_FILES +    llfbconnecttest.cpp +    llfbconnecttest.h +    bookmarks.txt +    ) + +add_executable(llfbconnecttest +    WIN32 +    MACOSX_BUNDLE +    ${llfbconnecttest_SOURCE_FILES} +) + +set_target_properties(llfbconnecttest +    PROPERTIES +    WIN32_EXECUTABLE +    FALSE +) + +target_link_libraries(llfbconnecttest +  ${GLUT_LIBRARY} +  ${GLUI_LIBRARY} +  ${OPENGL_LIBRARIES} +  ${LLPLUGIN_LIBRARIES} +  ${LLMESSAGE_LIBRARIES} +  ${LLCOMMON_LIBRARIES} +  ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +if (DARWIN) +  # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app. +  target_link_libraries(llfbconnecttest +    ${COREFOUNDATION_LIBRARY} +  ) +endif (DARWIN) + +add_dependencies(llfbconnecttest +  stage_third_party_libs +  SLPlugin +  media_plugin_webkit +  ${LLPLUGIN_LIBRARIES} +  ${LLMESSAGE_LIBRARIES} +  ${LLCOMMON_LIBRARIES} +) + +# turn off weird GLUI pragma  +add_definitions(-DGLUI_NO_LIB_PRAGMA) + +if (DARWIN OR LINUX) +  # glui.h contains code that triggers the "overloaded-virtual" warning in gcc.   +  set_source_files_properties(llfbconnecttest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual") +endif (DARWIN OR LINUX) + +# Gather build products of the various dependencies into the build directory for the testbed. + +if (DARWIN) +  # path inside the app bundle where we'll need to copy plugins and other related files +  set(PLUGINS_DESTINATION_DIR +    ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llfbconnecttest.app/Contents/Resources +  ) +   +  # create the Contents/Resources directory +  add_custom_command( +    TARGET llfbconnecttest POST_BUILD +    COMMAND ${CMAKE_COMMAND} +    ARGS +      -E +      make_directory +      ${PLUGINS_DESTINATION_DIR} +    COMMENT "Creating Resources directory in app bundle." +  )  +else (DARWIN) +  set(PLUGINS_DESTINATION_DIR +    ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ +  ) +endif (DARWIN) + +get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) +add_custom_command(TARGET llfbconnecttest POST_BUILD +  COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN}  ${PLUGINS_DESTINATION_DIR} +  DEPENDS ${BUILT_SLPLUGIN} +) + +get_target_property(BUILT_LLCOMMON llcommon LOCATION) +add_custom_command(TARGET llfbconnecttest POST_BUILD +  COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON}  ${PLUGINS_DESTINATION_DIR} +  DEPENDS ${BUILT_LLCOMMON} +) + + +if (DARWIN OR WINDOWS) +  get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION) +  add_custom_command(TARGET llfbconnecttest POST_BUILD +    COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN}  ${PLUGINS_DESTINATION_DIR} +    DEPENDS ${BUILT_WEBKIT_PLUGIN} +  ) +   +  # copy over bookmarks file if llfbconnecttest gets built +  get_target_property(BUILT_LLFBCONNECTTEST llfbconnecttest LOCATION) +  add_custom_command(TARGET llfbconnecttest POST_BUILD +    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/ +    DEPENDS ${BUILT_LLFBCONNECTTEST} +  ) +  # also copy it to the same place as SLPlugin, which is what the mac wants... +  add_custom_command(TARGET llfbconnecttest POST_BUILD +    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR} +    DEPENDS ${BUILT_LLFBCONNECTTEST} +  ) +endif (DARWIN OR WINDOWS) + +if (DARWIN) +  add_custom_command(TARGET llfbconnecttest POST_BUILD +    COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR} +    DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib +  ) +endif (DARWIN) + +if(WINDOWS) +  #******************** +  # Plugin test library deploy +  # +  # Debug config runtime files required for the FB connect test +  set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}") +  set(fbconnecttest_debug_files +    libeay32.dll +    libglib-2.0-0.dll +    libgmodule-2.0-0.dll +    libgobject-2.0-0.dll +    libgthread-2.0-0.dll +    qtcored4.dll +    qtguid4.dll +    qtnetworkd4.dll +    qtopengld4.dll +    qtwebkitd4.dll +    ssleay32.dll +    ) +  copy_if_different( +    ${fbconnecttest_debug_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Debug" +    out_targets +    ${fbconnecttest_debug_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) +   +  # Debug config runtime files required for the FB connect test (Qt image format plugins) +  set(fbconecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/imageformats") +  set(fbconecttest_debug_files +    qgifd4.dll +    qicod4.dll +    qjpegd4.dll +    qmngd4.dll +    qsvgd4.dll +    qtiffd4.dll +    ) +  copy_if_different( +    ${fbconecttest_debug_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats" +    out_targets +    ${fbconecttest_debug_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  # Debug config runtime files required for the FB connect test (Qt codec plugins) +  set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/codecs") +  set(fbconnecttest_debug_files +    qcncodecsd4.dll +    qjpcodecsd4.dll +    qkrcodecsd4.dll +    qtwcodecsd4.dll +    ) +  copy_if_different( +    ${fbconnecttest_debug_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs" +    out_targets +    ${fbconnecttest_debug_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) +  +  # Release & ReleaseDebInfo config runtime files required for the FB connect test +  set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") +  set(fbconnecttest_release_files +    libeay32.dll +    libglib-2.0-0.dll +    libgmodule-2.0-0.dll +    libgobject-2.0-0.dll +    libgthread-2.0-0.dll +    qtcore4.dll +    qtgui4.dll +    qtnetwork4.dll +    qtopengl4.dll +    qtwebkit4.dll +    qtxmlpatterns4.dll +    ssleay32.dll +    ) +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Release" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins) +  set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/imageformats") +  set(fbconnecttest_release_files +    qgif4.dll +    qico4.dll +    qjpeg4.dll +    qmng4.dll +    qsvg4.dll +    qtiff4.dll +    ) +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  # Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins) +  set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/codecs") +  set(fbconnecttest_release_files +    qcncodecs4.dll   +    qjpcodecs4.dll   +    qkrcodecs4.dll   +    qtwcodecs4.dll   +    ) +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) + +  copy_if_different( +    ${fbconnecttest_release_src_dir} +    "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs" +    out_targets +    ${fbconnecttest_release_files} +    ) +  set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets}) +  +   add_custom_target(copy_fbconnecttest_libs ALL +     DEPENDS  +     ${fbconnect_test_targets} +     ) + +  add_dependencies(llfbconnecttest copy_fbconnecttest_libs) + +endif(WINDOWS) + +ll_deploy_sharedlibs_command(llfbconnecttest)  diff --git a/indra/test_apps/llfbconnecttest/bookmarks.txt b/indra/test_apps/llfbconnecttest/bookmarks.txt new file mode 100644 index 0000000000..3995627ea9 --- /dev/null +++ b/indra/test_apps/llfbconnecttest/bookmarks.txt @@ -0,0 +1,4 @@ +# format is description, url (don't put ',' chars in description :) +# if no ',' found, whole line is used for both description and url +Google Home Page,http://www.google.com +Facebook Home Page,http://www.facebook.com diff --git a/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp b/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp new file mode 100644 index 0000000000..483a15c468 --- /dev/null +++ b/indra/test_apps/llfbconnecttest/llfbconnecttest.cpp @@ -0,0 +1,2394 @@ +/** + * @file LLFBConnectTest.cpp + * @brief Facebook Connect Test App + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "llapr.h" +#include "llerrorcontrol.h" + +#include <math.h> +#include <iomanip> +#include <sstream> +#include <ctime> + +#include "llfbconnecttest.h" + +#if __APPLE__ +	#include <GLUT/glut.h> +	#include <CoreFoundation/CoreFoundation.h> +#else +	#define FREEGLUT_STATIC +	#include "GL/freeglut.h" +	#define GLUI_FREEGLUT +#endif + +#if LL_WINDOWS +#pragma warning(disable: 4263) +#pragma warning(disable: 4264) +#endif +#include "glui.h" + + +LLFBConnectTest* gApplication = 0; +static void gluiCallbackWrapper( int control_id ); + +//////////////////////////////////////////////////////////////////////////////// +// +static bool isTexture( GLuint texture ) +{ +	bool result = false; + +	// glIsTexture will sometimes return false for real textures... do this instead. +	if(texture != 0) +		result = true; + +	return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel::mediaPanel() +{ +	mMediaTextureHandle = 0; +	mPickTextureHandle = 0; +	mMediaSource = NULL; +	mPickTexturePixels = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel::~mediaPanel() +{ +	// delete OpenGL texture handles +	if ( isTexture( mPickTextureHandle ) ) +	{ +		std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl; +		glDeleteTextures( 1, &mPickTextureHandle ); +		mPickTextureHandle = 0; +	} + +	if ( isTexture( mMediaTextureHandle ) ) +	{ +		std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl; +		glDeleteTextures( 1, &mMediaTextureHandle ); +		mMediaTextureHandle = 0; +	} + +	if(mPickTexturePixels) +	{ +		delete mPickTexturePixels; +	} + +	if(mMediaSource) +	{ +		delete mMediaSource; +	} + +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLFBConnectTest::LLFBConnectTest( int app_window, int window_width, int window_height ) : +	mVersionMajor( 2 ), +	mVersionMinor( 0 ), +	mVersionPatch( 0 ), +	mMaxPanels( 25 ), +	mViewportAspect( 0 ), +	mAppWindow( app_window ), +	mCurMouseX( 0 ), +	mCurMouseY( 0 ), +	mFuzzyMedia( true ), +	mSelectedPanel( 0 ), +	mDistanceCameraToSelectedGeometry( 0.0f ), +	//mMediaBrowserControlEnableCookies( 0 ), +	mMediaBrowserControlBackButton( 0 ), +	mMediaBrowserControlForwardButton( 0 ), +	//mMediaTimeControlVolume( 100 ), +	//mMediaTimeControlSeekSeconds( 0 ), +	//mGluiMediaTimeControlWindowFlag( true ), +	mGluiMediaBrowserControlWindowFlag( true ), +	mMediaBrowserControlBackButtonFlag( true ), +	mMediaBrowserControlForwardButtonFlag( true ), +	mHomeWebUrl( "https://cryptic-ridge-1632.herokuapp.com/" ) +{ +	// debugging spam +	std::cout << std::endl << "             GLUT version: " << "3.7.6" << std::endl;	// no way to get real version from GLUT +	std::cout << std::endl << "             GLUI version: " << GLUI_Master.get_version() << std::endl; +	std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl; + +	// bookmark title +	mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) ); + +	// insert hardcoded URLs here as required for testing +	//mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) ); + +	// read bookmarks from file. +	// note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory +	//       to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC) +	//		 For example, test_apps\llplugintest and not test_apps\llplugintest\Release +	//		 This may need to be changed for Mac/Linux builds. +	// See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI +	const std::string bookmarks_filename( "bookmarks.txt" ); +	std::ifstream file_handle( bookmarks_filename.c_str() ); +	if ( file_handle.is_open() ) +	{ +		std::cout << "Reading bookmarks for test" << std::endl; +		while( ! file_handle.eof() ) +		{ +			std::string line; +			std::getline( file_handle, line ); +			if ( file_handle.eof() ) +				break; + +			if ( line.substr( 0, 1 ) != "#" ) +			{ +				size_t comma_pos = line.find_first_of( ',' ); +				if ( comma_pos != std::string::npos ) +				{ +					std::string description = line.substr( 0, comma_pos ); +					std::string url = line.substr( comma_pos + 1 ); +					mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) ); +				} +				else +				{ +					mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) ); +				}; +			}; +		}; +		std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl; +	} +	else +	{ +		std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl; +	}; + +	// initialize linden lab APR module +	ll_init_apr(); + +	// Set up llerror logging +	{ +		LLError::initForApplication("."); +		LLError::setDefaultLevel(LLError::LEVEL_INFO); +		//LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG); +	} + +	// lots of randomness in this app +	srand( ( unsigned int )time( 0 ) ); + +	// build GUI +	makeChrome(); + +	// OpenGL initialilzation +	glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); +	glClearDepth( 1.0f ); +	glEnable( GL_DEPTH_TEST ); +	glEnable( GL_COLOR_MATERIAL ); +	glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); +	glDepthFunc( GL_LEQUAL ); +	glEnable( GL_TEXTURE_2D ); +	glDisable( GL_BLEND ); +	glColor3f( 1.0f, 1.0f, 1.0f ); +	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); +	glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + +	// start with a sane view +	resetView(); + +	// initial media panel +	const int num_initial_panels = 1; +	for( int i = 0; i < num_initial_panels; ++i ) +	{ +		//addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); +		addMediaPanel( mHomeWebUrl ); +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLFBConnectTest::~LLFBConnectTest() +{ +	// delete all media panels +	for( int i = 0; i < (int)mMediaPanels.size(); ++i ) +	{ +		remMediaPanel( mMediaPanels[ i ] ); +	}; +	 +	// Stop the plugin read thread if it's running. +	LLPluginProcessParent::setUseReadThread(false); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::reshape( int width, int height ) +{ +	// update viewport (the active window inside the chrome) +	int viewport_x, viewport_y; +	int viewport_height, viewport_width; +	GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height ); +	mViewportAspect = (float)( viewport_width ) / (float)( viewport_height ); +	glViewport( viewport_x, viewport_y, viewport_width, viewport_height ); + +	// save these as we'll need them later +	mWindowWidth = width; +	mWindowHeight = height; + +	// adjust size of URL bar so it doesn't get clipped +	mUrlEdit->set_w( mWindowWidth - 360 ); + +	// GLUI requires this +	if ( glutGetWindow() != mAppWindow ) +		glutSetWindow( mAppWindow ); + +	// trigger re-display +	glutPostRedisplay(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::bindTexture(GLuint texture, GLint row_length, GLint alignment) +{ +	glEnable( GL_TEXTURE_2D ); + +	glBindTexture( GL_TEXTURE_2D, texture ); +	glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length ); +	glPixelStorei( GL_UNPACK_ALIGNMENT, alignment ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLFBConnectTest::checkGLError(const char *name) +{ +	bool result = false; +	GLenum error = glGetError(); + +	if(error != GL_NO_ERROR) +	{ +		// For some reason, glGenTextures is returning GL_INVALID_VALUE... +		std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl; +		result = true; +	} + +	return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +GLfloat LLFBConnectTest::distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z ) +{ +	GLdouble camera_pos_x = 0.0f; +	GLdouble camera_pos_y = 0.0f; +	GLdouble camera_pos_z = 0.0f; + +	GLdouble modelMatrix[16]; +	GLdouble projMatrix[16]; +	GLint viewport[4]; + +	glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); +	glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); +	glGetIntegerv(GL_VIEWPORT, viewport); + +	gluUnProject( +		(viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2, +		0.0, +		modelMatrix, projMatrix, viewport, +		&camera_pos_x, &camera_pos_y, &camera_pos_z ); + +	GLfloat distance = +		sqrt( ( camera_pos_x - point_x ) * ( camera_pos_x - point_x ) + +			  ( camera_pos_y - point_y ) * ( camera_pos_y - point_y ) + +			  ( camera_pos_z - point_z ) * ( camera_pos_z - point_z ) ); + +	return distance; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::drawGeometry( int panel, bool selected ) +{ +	// texture coordinates for each panel +	GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; +	GLfloat opengl_texture_coords[ 8 ] =     { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + +	GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords; + +	// base coordinates for each panel +	GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + +	// calculate posiitons +	const int num_panels = (int)mMediaPanels.size(); +	const int num_rows = (int)sqrt( (float)num_panels ); +	const int num_cols = num_panels / num_rows; +	const int panel_x = ( panel / num_rows ); +	const int panel_y = ( panel % num_rows ); + +	// default spacing is small - make it larger if checkbox set - for testing positional audio +	float spacing = 0.1f; +	//if ( mLargePanelSpacing ) +	//	spacing = 2.0f; + +	const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2; +	const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2; + +	// Adjust for media aspect ratios +	{ +		float aspect = 1.0f; + +		if(mMediaPanels[ panel ]->mMediaHeight != 0) +		{ +			aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight; +		} + +		if(aspect > 1.0f) +		{ +			// media is wider than it is high -- adjust the top and bottom in +			for( int corner = 0; corner < 4; ++corner ) +			{ +				float temp = base_vertex_pos[corner * 2 + 1]; + +				if(temp < 0.5f) +					temp += 0.5 - (0.5f / aspect); +				else +					temp -= 0.5 - (0.5f / aspect); + +				base_vertex_pos[corner * 2 + 1] = temp; +			} +		} +		else if(aspect < 1.0f) +		{ +			// media is higher than it is wide -- adjust the left and right sides in +			for( int corner = 0; corner < 4; ++corner ) +			{ +				float temp = base_vertex_pos[corner * 2]; + +				if(temp < 0.5f) +					temp += 0.5f - (0.5f * aspect); +				else +					temp -= 0.5f - (0.5f * aspect); + +				base_vertex_pos[corner * 2] = temp; +			} +		} +	} + +	glBegin( GL_QUADS ); +	for( int corner = 0; corner < 4; ++corner ) +	{ +		glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] ); +		GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f; +		GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f; + +		glVertex3f( x, y, 0.0f ); +	}; +	glEnd(); + +	// calculate distance to this panel if it's selected +	if ( selected ) +	{ +		GLfloat point_x = base_vertex_pos[ 0 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f; +		GLfloat point_y = base_vertex_pos[ 0 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f; +		GLfloat point_z = 0.0f; +		mDistanceCameraToSelectedGeometry = distanceToCamera( point_x, point_y, point_z ); +	}; +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::startPanelHighlight( float red, float green, float blue, float line_width ) +{ +	glPushAttrib( GL_ALL_ATTRIB_BITS ); +	glEnable( GL_POLYGON_OFFSET_FILL ); +	glPolygonOffset( -2.5f, -2.5f ); +	glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); +	glLineWidth( line_width ); +	glColor3f( red, green, blue ); +	glDisable( GL_TEXTURE_2D ); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::endPanelHighlight() +{ +	glPopAttrib(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::draw( int draw_type ) +{ +	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +	{ +		// drawing pick texture +		if ( draw_type == DrawTypePickTexture ) +		{ +			// only bother with pick if we have something to render +			// Actually, we need to pick even if we're not ready to render. +			// Otherwise you can't select and remove a panel which has gone bad. +			//if ( mMediaPanels[ panel ]->mReadyToRender ) +			{ +				glMatrixMode( GL_TEXTURE ); +				glPushMatrix(); + +				// pick texture is a power of 2 so no need to scale +				glLoadIdentity(); + +				// bind to media texture +				glLoadIdentity(); +				bindTexture( mMediaPanels[ panel ]->mPickTextureHandle ); +				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); +				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + +				// draw geometry using pick texture +				drawGeometry( panel, false ); + +				glMatrixMode( GL_TEXTURE ); +				glPopMatrix(); +			}; +		} +		else +		if ( draw_type == DrawTypeMediaTexture ) +		{ +			bool texture_valid = false; +			bool plugin_exited = false; + +			if(mMediaPanels[ panel ]->mMediaSource) +			{ +				texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid(); +				plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited(); +			} + +			// save texture matrix (changes for each panel) +			glMatrixMode( GL_TEXTURE ); +			glPushMatrix(); + +			// only process texture if the media is ready to draw +			// (we still want to draw the geometry) +			if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid ) +			{ +				// bind to media texture +				bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle ); + +				if ( mFuzzyMedia ) +				{ +					glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); +					glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); +				} +				else +				{ +					glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); +					glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); +				} + +				// scale to fit panel +				glScalef( mMediaPanels[ panel ]->mTextureScaleX, +							mMediaPanels[ panel ]->mTextureScaleY, +								1.0f ); +			}; + +			float intensity = plugin_exited?0.25f:1.0f; + +			// highlight the selected panel +			if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) ) +			{ +				startPanelHighlight( intensity, intensity, 0.0f, 5.0f ); +				drawGeometry( panel, true ); +				endPanelHighlight(); +			} +			else +			// this panel not able to render yet since it +			// doesn't have enough information +			if ( !mMediaPanels[ panel ]->mReadyToRender ) +			{ +				startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f ); +				drawGeometry( panel, false ); +				endPanelHighlight(); +			} +			else +			// just display a border around the media +			{ +				startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f ); +				drawGeometry( panel, false ); +				endPanelHighlight(); +			}; + +			if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid ) +			{ +				// draw visual geometry +				drawGeometry( panel, false ); +			} + +			// restore texture matrix (changes for each panel) +			glMatrixMode( GL_TEXTURE ); +			glPopMatrix(); +		}; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::display() +{ +	// GLUI requires this +	if ( glutGetWindow() != mAppWindow ) +		glutSetWindow( mAppWindow ); + +	// start with a clean slate +	glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); +	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + +	// set up OpenGL view +	glMatrixMode( GL_PROJECTION ); +	glLoadIdentity(); +	glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f ); +	glMatrixMode( GL_MODELVIEW ); +	glLoadIdentity(); +	glTranslatef( 0.0, 0.0, 0.0f ); +	glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] ); +	glMultMatrixf( mViewRotation ); + +	// draw pick texture +	draw( DrawTypePickTexture ); + +	// read colors and get coordinate values +	glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor ); + +	// clear the pick render (otherwise it may depth-fight with the textures rendered later) +	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + +	// draw visible geometry +	draw( DrawTypeMediaTexture ); + +	glutSwapBuffers(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::idle() +{ +//	checkGLError("LLFBConnectTest::idle"); + +	// GLUI requires this +	if ( glutGetWindow() != mAppWindow ) +		glutSetWindow( mAppWindow ); + +	// random creation/destruction of panels enabled? +/* +	const time_t panel_timeout_time = 5; +	if ( mRandomPanelCount ) +	{ +		// time for a change +		static time_t last_panel_time = 0; +		if ( time( NULL ) - last_panel_time > panel_timeout_time ) +		{ +			if ( rand() % 2 == 0 ) +			{ +				if ( mMediaPanels.size() < 16 ) +				{ +					std::cout << "Randomly adding new panel" << std::endl; +					addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); +				}; +			} +			else +			{ +				if ( mMediaPanels.size() > 0 ) +				{ +					std::cout << "Deleting selected panel" << std::endl; +					remMediaPanel( mSelectedPanel ); +				}; +			}; +			time( &last_panel_time ); +		}; +	}; + +	// random selection of bookmarks enabled? +	const time_t bookmark_timeout_time = 5; +	if ( mRandomBookmarks ) +	{ +		// time for a change +		static time_t last_bookmark_time = 0; +		if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time ) +		{ +			// go to a different random bookmark on each panel +			for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +			{ +				std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second; + +				std::cout << "Random: navigating to : " << uri << std::endl; + +				std::string mime_type = mimeTypeFromUrl( uri ); + +				if ( mime_type != mMediaPanels[ panel ]->mMimeType ) +				{ +					replaceMediaPanel( mMediaPanels[ panel ], uri ); +				} +				else +				{ +					mMediaPanels[ panel ]->mMediaSource->loadURI( uri ); +					mMediaPanels[ panel ]->mMediaSource->start(); +				}; +			}; + +			time( &last_bookmark_time ); +		}; +	}; +*/ +	// update UI +	if ( mSelectedPanel ) +	{ +		// set volume based on slider if we have time media +		//if ( mGluiMediaTimeControlWindowFlag ) +		//{ +		//	mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); +		//}; + +		// NOTE: it is absurd that we need cache the state of GLUI controls +		//       but enabling/disabling controls drags framerate from 500+ +		//		 down to 15. Not a problem for plugin system - only this test +		// enable/disable time based UI controls based on type of plugin +		if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) +		{ +			/* +			if ( ! mGluiMediaTimeControlWindowFlag ) +			{ +				mGluiMediaTimeControlWindow->enable(); +				mGluiMediaTimeControlWindowFlag = true; +			}; +			*/ +		} +		else +		{ +			/* +			if ( mGluiMediaTimeControlWindowFlag ) +			{ +				mGluiMediaTimeControlWindow->disable(); +				mGluiMediaTimeControlWindowFlag = false; +			}; +			*/ +		}; + +		// enable/disable browser based UI controls based on type of plugin +		if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() ) +		{ +			if ( ! mGluiMediaBrowserControlWindowFlag ) +			{ +				mGluiMediaBrowserControlWindow->enable(); +				mGluiMediaBrowserControlWindowFlag = true; +			}; +		} +		else +		{ +			if ( mGluiMediaBrowserControlWindowFlag ) +			{ +				mGluiMediaBrowserControlWindow->disable(); +				mGluiMediaBrowserControlWindowFlag = false; +			}; +		}; + +		// enable/disable browser back button depending on browser history +		if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable()  ) +		{ +			if ( ! mMediaBrowserControlBackButtonFlag ) +			{ +				mMediaBrowserControlBackButton->enable(); +				mMediaBrowserControlBackButtonFlag = true; +			}; +		} +		else +		{ +			if ( mMediaBrowserControlBackButtonFlag ) +			{ +				mMediaBrowserControlBackButton->disable(); +				mMediaBrowserControlBackButtonFlag = false; +			}; +		}; + +		// enable/disable browser forward button depending on browser history +		if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable()  ) +		{ +			if ( ! mMediaBrowserControlForwardButtonFlag ) +			{ +				mMediaBrowserControlForwardButton->enable(); +				mMediaBrowserControlForwardButtonFlag = true; +			}; +		} +		else +		{ +			if ( mMediaBrowserControlForwardButtonFlag ) +			{ +				mMediaBrowserControlForwardButton->disable(); +				mMediaBrowserControlForwardButtonFlag = false; +			}; +		}; + +		// NOTE: This is *very* slow and not worth optimising +		updateStatusBar(); +	}; + +	// update all the panels +	for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index ) +	{ +		mediaPanel *panel = mMediaPanels[ panel_index ]; + +		// call plugins idle function so it can potentially update itself +		panel->mMediaSource->idle(); + +		// update each media panel +		updateMediaPanel( panel ); + +		LLRect dirty_rect; +		if ( ! panel->mMediaSource->textureValid() ) +		{ +			//std::cout << "texture invalid, skipping update..." << std::endl; +		} +		else +		if ( panel && +			 ( panel->mMediaWidth != panel->mMediaSource->getWidth() || +			   panel->mMediaHeight != panel->mMediaSource->getHeight() ) ) +		{ +			//std::cout << "Resize in progress, skipping update..." << std::endl; +		} +		else +		if ( panel->mMediaSource->getDirty( &dirty_rect ) ) +		{ +			const unsigned char* pixels = panel->mMediaSource->getBitsData(); +			if ( pixels && isTexture(panel->mMediaTextureHandle)) +			{ +				int x_offset = dirty_rect.mLeft; +				int y_offset = dirty_rect.mBottom; +				int width = dirty_rect.mRight - dirty_rect.mLeft; +				int height = dirty_rect.mTop - dirty_rect.mBottom; + +				if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight)) +				{ +					// Offset the pixels pointer properly +					pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() ); +					pixels += ( x_offset * panel->mMediaSource->getTextureDepth() ); + +					// set up texture +					bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() ); +					if ( mFuzzyMedia ) +					{ +						glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); +						glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); +					} +					else +					{ +						glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); +						glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); +					}; + +					checkGLError("glTexParameteri"); + +					if(panel->mMediaSource->getTextureFormatSwapBytes()) +					{ +						glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); +						checkGLError("glPixelStorei"); +					} + +					// draw portion that changes into texture +					glTexSubImage2D( GL_TEXTURE_2D, 0, +						x_offset, +						y_offset, +						width, +						height, +						panel->mMediaSource->getTextureFormatPrimary(), +						panel->mMediaSource->getTextureFormatType(), +						pixels ); + +					if(checkGLError("glTexSubImage2D")) +					{ +						std::cerr << "    panel ID=" << panel->mId << std::endl; +						std::cerr << "    texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl; +						std::cerr << "    media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl; +						std::cerr << "    dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl; +						std::cerr << "    texture width = " << panel->mMediaSource->getBitsWidth() << std::endl; +						std::cerr << "    format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl; +						std::cerr << "    format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl; +						std::cerr << "    pixels = " << (void*)pixels << std::endl; +					} + +					if(panel->mMediaSource->getTextureFormatSwapBytes()) +					{ +						glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); +						checkGLError("glPixelStorei"); +					} + +					panel->mMediaSource->resetDirty(); + +					panel->mReadyToRender = true; +				} +				else +				{ +					std::cerr << "dirty rect is outside current media size, skipping update" << std::endl; +				} +			}; +		}; +	}; + +	// GLUI requires this +	if ( glutGetWindow() != mAppWindow ) +		glutSetWindow( mAppWindow ); + +	// trigger re-display +	glutPostRedisplay(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::windowPosToTexturePos( int window_x, int window_y, +											   int& media_x, int& media_y, +											   int& id ) +{ +	if ( ! mSelectedPanel ) +	{ +		media_x = 0; +		media_y = 0; +		id = 0; +		return; +	}; + +	// record cursor poisiton for a readback next frame +	mCurMouseX = window_x; +	// OpenGL app == coordinate system this way +	// NOTE: unrelated to settings in plugin - this +	// is just for this app +	mCurMouseY = mWindowHeight - window_y; + +	// extract x (0..1023, y (0..1023) and id (0..15) from RGB components +	unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ]; +	int texture_x = pixel_read_color_bits & 0x3ff; +	int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff; +	id = ( pixel_read_color_bits >> 20 ) & 0x0f; + +	// scale to size of media (1024 because we use 10 bits for X and Y from 24) +	media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f ); +	media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f ); + +	// we assume the plugin uses an inverted coordinate scheme like OpenGL +	// if not, the plugin code inverts the Y coordinate for us - we don't need to +	media_y = mSelectedPanel->mMediaHeight - media_y; + +	if ( media_x > 0 && media_y > 0 ) +	{ +		//std::cout << "      mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id  << std::endl; +		//std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id  << std::endl; +		//std::cout << "      media coords: " << media_x << " x " << media_y << " and id = " << id  << std::endl; +		//std::cout << std::endl; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::selectPanelById( int id ) +{ +	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +	{ +		if ( mMediaPanels[ panel ]->mId == id ) +		{ +			selectPanel(mMediaPanels[ panel ]); +			return; +		}; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::selectPanel( mediaPanel* panel ) +{ +	if( mSelectedPanel == panel ) +		return; + +	// turn off volume before we delete it +	if( mSelectedPanel && mSelectedPanel->mMediaSource ) +	{ +		mSelectedPanel->mMediaSource->setVolume( 0.0f ); +		mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW ); +	}; + +	mSelectedPanel = panel; + +	if( mSelectedPanel && mSelectedPanel->mMediaSource ) +	{ +		//mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); +		mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL ); + +		if(!mSelectedPanel->mStartUrl.empty()) +		{ +			mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) ); +		} +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel*  LLFBConnectTest::findMediaPanel( LLPluginClassMedia* source ) +{ +	mediaPanel *result = NULL; + +	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +	{ +		if ( mMediaPanels[ panel ]->mMediaSource == source ) +		{ +			result = mMediaPanels[ panel ]; +		} +	} + +	return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel* LLFBConnectTest::findMediaPanel( const std::string &target_name ) +{ +	mediaPanel *result = NULL; + +	for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) +	{ +		if ( mMediaPanels[ panel ]->mTarget == target_name ) +		{ +			result = mMediaPanels[ panel ]; +		} +	} + +	return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::navigateToNewURI( std::string uri ) +{ +	if ( uri.length() ) +	{ +		std::string mime_type = mimeTypeFromUrl( uri ); + +		if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) ) +		{ +			std::cout << "MIME type is the same" << std::endl; +			mSelectedPanel->mMediaSource->loadURI( uri ); +			mSelectedPanel->mMediaSource->start(); +			mBookmarkList->do_selection( 0 ); +		} +		else +		{ +			std::cout << "MIME type changed or plugin had exited" << std::endl; +			replaceMediaPanel( mSelectedPanel, uri ); +			mBookmarkList->do_selection( 0 ); +		} +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::initUrlHistory( std::string uris ) +{ +	if ( uris.length() > 0 ) +	{ +		std::cout << "init URL : " << uris << std::endl; +		LLSD historySD; + +		char *cstr, *p; +		cstr = new char[uris.size()+1]; +		strcpy(cstr, uris.c_str()); +		const char *DELIMS = " ,;"; +		p = strtok(cstr, DELIMS); +		while (p != NULL) { +			historySD.insert(0, p); +			p = strtok(NULL, DELIMS); +		} +		mSelectedPanel->mMediaSource->initializeUrlHistory(historySD); +		delete[] cstr; +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::gluiCallback( int control_id ) +{ +	if ( control_id == mIdBookmarks ) +	{ +		std::string uri = mBookmarks[ mSelBookmark ].second; + +		navigateToNewURI( uri ); +	} +	else +    if ( control_id == mIdUrlEdit) +	{ +		std::string uri = mUrlEdit->get_text(); + +		navigateToNewURI( uri ); +	} +/* +	else +	if ( control_id == mIdUrlInitHistoryEdit ) +	{ +		std::string uri = mUrlInitHistoryEdit->get_text(); + +		initUrlHistory( uri ); +	} +	else +	if ( control_id == mIdControlAddPanel ) +	{ +		addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); +	} +	else +	if ( control_id == mIdControlRemPanel ) +	{ +		remMediaPanel( mSelectedPanel ); +	} +	else +	if ( control_id == mIdDisableTimeout ) +	{ +		// Set the "disable timeout" flag for all active plugins. +		for( int i = 0; i < (int)mMediaPanels.size(); ++i ) +		{ +			mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout); +		} +	} +	else +	if ( control_id == mIdUsePluginReadThread ) +	{ +		LLPluginProcessParent::setUseReadThread(mUsePluginReadThread); +	} +	else +	if ( control_id == mIdControlCrashPlugin ) +	{ +		// send message to plugin and ask it to crash +		// (switch out for ReleaseCandidate version :) ) +		if(mSelectedPanel && mSelectedPanel->mMediaSource) +		{ +			mSelectedPanel->mMediaSource->crashPlugin(); +		} +	} +	else +	if ( control_id == mIdControlHangPlugin ) +	{ +		// send message to plugin and ask it to hang +		// (switch out for ReleaseCandidate version :) ) +		if(mSelectedPanel && mSelectedPanel->mMediaSource) +		{ +			mSelectedPanel->mMediaSource->hangPlugin(); +		} +	} +	else +*/ +	if ( control_id == mIdControlExitApp ) +	{ +		// text for exiting plugin system cleanly +		delete this;	// clean up +		exit( 0 ); +	} +/* +	else +	if ( control_id == mIdMediaTimeControlPlay ) +	{ +		if ( mSelectedPanel ) +		{ +			mSelectedPanel->mMediaSource->setLoop( false ); +			mSelectedPanel->mMediaSource->start(); +		}; +	} +	else +	if ( control_id == mIdMediaTimeControlLoop ) +	{ +		if ( mSelectedPanel ) +		{ +			mSelectedPanel->mMediaSource->setLoop( true ); +			mSelectedPanel->mMediaSource->start(); +		}; +	} +	else +	if ( control_id == mIdMediaTimeControlPause ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->pause(); +	} +	else +	if ( control_id == mIdMediaTimeControlStop ) +	{ +		if ( mSelectedPanel ) +		{ +			mSelectedPanel->mMediaSource->stop(); +		}; +	} +	else +	if ( control_id == mIdMediaTimeControlSeek ) +	{ +		if ( mSelectedPanel ) +		{ +			// get value from spinner +			float seconds_to_seek = mMediaTimeControlSeekSeconds; +			mSelectedPanel->mMediaSource->seek( seconds_to_seek ); +			mSelectedPanel->mMediaSource->start(); +		}; +	} +	else +	if ( control_id == mIdMediaTimeControlRewind ) +	{ +		if ( mSelectedPanel ) +		{ +			mSelectedPanel->mMediaSource->setLoop( false ); +			mSelectedPanel->mMediaSource->start(-2.0f); +		}; +	} +	else +	if ( control_id == mIdMediaTimeControlFastForward ) +	{ +		if ( mSelectedPanel ) +		{ +			mSelectedPanel->mMediaSource->setLoop( false ); +			mSelectedPanel->mMediaSource->start(2.0f); +		}; +	} +	else +*/ +	if ( control_id == mIdMediaBrowserControlBack ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->browse_back(); +	} +	else +	if ( control_id == mIdMediaBrowserControlStop ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->browse_stop(); +	} +	else +	if ( control_id == mIdMediaBrowserControlForward ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->browse_forward(); +	} +	else +	if ( control_id == mIdMediaBrowserControlHome ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl ); +	} +	else +	if ( control_id == mIdMediaBrowserControlReload ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->browse_reload( true ); +	} +/* +	else +	if ( control_id == mIdMediaBrowserControlClearCache ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->clear_cache(); +	} +	else +	if ( control_id == mIdMediaBrowserControlClearCookies ) +	{ +		if ( mSelectedPanel ) +			mSelectedPanel->mMediaSource->clear_cookies(); +	} +	else +	if ( control_id == mIdMediaBrowserControlEnableCookies ) +	{ +		if ( mSelectedPanel ) +		{ +			if ( mMediaBrowserControlEnableCookies ) +			{ +				mSelectedPanel->mMediaSource->enable_cookies( true ); +			} +			else +			{ +				mSelectedPanel->mMediaSource->enable_cookies( false ); +			} +		}; +	}; +*/ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::keyboard( int key ) +{ +	//if ( key == 'a' || key == 'A' ) +	//	addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); +	//else +	//if ( key == 'r' || key == 'R' ) +	//	remMediaPanel( mSelectedPanel ); +	//else +	//if ( key == 'd' || key == 'D' ) +	//	dumpPanelInfo(); +	//else +	if ( key == 27 ) +	{ +		std::cout << "Application finished - exiting..." << std::endl; +		delete this; +		exit( 0 ); +	}; + +	mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 , LLSD()); +	mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0, LLSD()); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::mouseButton( int button, int state, int x, int y ) +{ +	if ( button == GLUT_LEFT_BUTTON ) +	{ +		if ( state == GLUT_DOWN ) +		{ +			int media_x, media_y, id; +			windowPosToTexturePos( x, y, media_x, media_y, id ); + +			if ( mSelectedPanel ) +				mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 ); +		} +		else +		if ( state == GLUT_UP ) +		{ +			int media_x, media_y, id; +			windowPosToTexturePos( x, y, media_x, media_y, id ); + +			// only select a panel if we're on a panel +			// (HACK: strictly speaking this rules out clicking on +			// the origin of a panel but that's very unlikely) +			if ( media_x > 0 && media_y > 0 ) +			{ +				selectPanelById( id ); + +				if ( mSelectedPanel ) +					mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 ); +			}; +		}; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::mousePassive( int x, int y ) +{ +	int media_x, media_y, id; +	windowPosToTexturePos( x, y, media_x, media_y, id ); + +	if ( mSelectedPanel ) +		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::mouseMove( int x, int y ) +{ +	int media_x, media_y, id; +	windowPosToTexturePos( x, y, media_x, media_y, id ); + +	if ( mSelectedPanel ) +		mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::makeChrome() +{ +	// IDs used by GLUI +	int start_id = 0x1000; + +	// right side window - geometry manipulators +#if __APPLE__ +	// the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways. +	// Use a separate controls window in this case. +	// GLUI window at right containing manipulation controls and other buttons +	int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4; +	int y = glutGet(GLUT_WINDOW_Y); +	GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y ); +#else +	GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT ); +#endif +	mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation ); +	mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos ); +	mViewTranslationCtrl->set_speed( 0.01f ); +	mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] ); +	mViewScaleCtrl->set_speed( 0.05f ); +	right_glui_window->set_main_gfx_window( mAppWindow ); + +	// right side window - app controls +	/* +	mIdControlAddPanel = start_id++; +	right_glui_window->add_statictext( "" ); +	right_glui_window->add_separator(); +	right_glui_window->add_statictext( "" ); +	right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper ); +	right_glui_window->add_statictext( "" ); +	mIdControlRemPanel = start_id++; +	right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper ); +	right_glui_window->add_statictext( "" ); +	right_glui_window->add_separator(); +	right_glui_window->add_statictext( "" ); +	mIdControlCrashPlugin = start_id++; +	right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper ); +	mIdControlHangPlugin = start_id++; +	right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper ); +	*/ +	right_glui_window->add_statictext( "" ); +	right_glui_window->add_separator(); +	right_glui_window->add_statictext( "" ); +	mIdControlExitApp = start_id++; +	right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper ); + +	//// top window - holds bookmark UI +	mIdBookmarks = start_id++; +	mSelBookmark = 0; +	GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); +	mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper ); +	// only add the first 50 bookmarks - list can be very long sometimes (30,000+) +	// when testing list of media URLs from AGNI for example +	for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each ) +		mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) ); +	glui_window_top->set_main_gfx_window( mAppWindow ); + +	glui_window_top->add_column( false ); +	mIdUrlEdit = start_id++; +	mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper ); +	mUrlEdit->set_w( 600 ); +	//GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); +	//mIdUrlInitHistoryEdit = start_id++; +	//mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):", +	//	GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper ); +	//mUrlInitHistoryEdit->set_w( 800 ); + +	// top window - media controls for "time" media types (e.g. movies) +/* +	mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); +	mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow ); +	mIdMediaTimeControlPlay = start_id++; +	mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper ); +	mGluiMediaTimeControlWindow->add_column( false ); +	mIdMediaTimeControlLoop = start_id++; +	mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper ); +	mGluiMediaTimeControlWindow->add_column( false ); +	mIdMediaTimeControlPause = start_id++; +	mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper ); +	mGluiMediaTimeControlWindow->add_column( false ); + +	GLUI_Button  *button; +	mIdMediaTimeControlRewind = start_id++; +	button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper ); +	button->set_w(30); +	mGluiMediaTimeControlWindow->add_column( false ); +	mIdMediaTimeControlFastForward = start_id++; +	button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper ); +	button->set_w(30); + +	mGluiMediaTimeControlWindow->add_column( true ); + +	mIdMediaTimeControlStop = start_id++; +	mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper ); +	mGluiMediaTimeControlWindow->add_column( false ); +	mIdMediaTimeControlVolume = start_id++; +	GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper); +	spinner->set_float_limits( 0, 100 ); +	mGluiMediaTimeControlWindow->add_column( true ); +	mIdMediaTimeControlSeekSeconds = start_id++; +	spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper); +	spinner->set_float_limits( 0, 200 ); +	spinner->set_w( 32 ); +	spinner->set_speed( 0.025f ); +	mGluiMediaTimeControlWindow->add_column( false ); +	mIdMediaTimeControlSeek = start_id++; +	mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper ); +	mGluiMediaTimeControlWindow->add_column( false ); +*/ + +	// top window - media controls for "browser" media types (e.g. web browser) +	mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); +	mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow ); +	mIdMediaBrowserControlBack = start_id++; +	mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlStop = start_id++; +	mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlForward = start_id++; +	mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlHome = start_id++; +	mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlReload = start_id++; +	mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	/* +	mIdMediaBrowserControlClearCache = start_id++; +	mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlClearCookies = start_id++; +	mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper ); +	mGluiMediaBrowserControlWindow->add_column( false ); +	mIdMediaBrowserControlEnableCookies = start_id++; +	mMediaBrowserControlEnableCookies = 0; +	mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper ); + +	// top window - misc controls +	GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); +	mIdRandomPanelCount = start_id++; +	mRandomPanelCount = 0; +	glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); +	mIdRandomBookmarks = start_id++; +	mRandomBookmarks = 0; +	glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); + +	mIdDisableTimeout = start_id++; +	mDisableTimeout = 0; +	glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); + +	mIdUsePluginReadThread = start_id++; +	mUsePluginReadThread = 0; +	glui_window_misc_control->add_checkbox( "Use plugin read thread", &mUsePluginReadThread, mIdUsePluginReadThread, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); + +	mIdLargePanelSpacing = start_id++; +	mLargePanelSpacing = 0; +	glui_window_misc_control->add_checkbox( "Large Panel Spacing", &mLargePanelSpacing, mIdLargePanelSpacing, gluiCallbackWrapper ); +	glui_window_misc_control->set_main_gfx_window( mAppWindow ); +	glui_window_misc_control->add_column( true ); +*/ +	// bottom window - status +	mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM ); +	mStatusText = mBottomGLUIWindow->add_statictext( "" ); +	mBottomGLUIWindow->set_main_gfx_window( mAppWindow ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::resetView() +{ +	mViewRotationCtrl->reset(); + +	mViewScaleCtrl->set_x( 0.0f ); +	mViewScaleCtrl->set_y( 0.0f ); +	mViewScaleCtrl->set_z( 1.3f ); + +	mViewTranslationCtrl->set_x( 0.0f ); +	mViewTranslationCtrl->set_y( 0.0f ); +	mViewTranslationCtrl->set_z( 0.0f ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels ) +{ +	int pick_texture_width = 1024; +	int pick_texture_height = 1024; +	int pick_texture_depth = 3; +	unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ]; +	for( int y = 0; y < pick_texture_height; ++y ) +	{ +		for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth ) +		{ +			unsigned long bits = 0L; +			bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 ); +			unsigned char r_component = ( bits >> 16 ) & 0xff; +			unsigned char g_component = ( bits >> 8 ) & 0xff; +			unsigned char b_component = bits & 0xff; + +			ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component; +			ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component; +			ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component; +		}; +	}; + +	glGenTextures( 1, texture_handle ); + +	checkGLError("glGenTextures"); +	std::cout << "glGenTextures returned " << *texture_handle << std::endl; + +	bindTexture( *texture_handle ); +	glTexImage2D( GL_TEXTURE_2D, 0, +					GL_RGB, +						pick_texture_width, pick_texture_height, +							0, GL_RGB, GL_UNSIGNED_BYTE, ptr ); + +	*texture_pixels = ptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// +std::string LLFBConnectTest::mimeTypeFromUrl( std::string& url ) +{ +	// default to web +	std::string mime_type = "text/html"; + +	// we may need a more advanced MIME type accessor later :-) +	if ( url.find( ".mov" ) != std::string::npos )	// Movies +		mime_type = "video/quicktime"; +	else +	if ( url.find( ".txt" ) != std::string::npos )	// Apple Text descriptors +		mime_type = "video/quicktime"; +	else +	if ( url.find( ".mp3" ) != std::string::npos )	// Apple Text descriptors +		mime_type = "video/quicktime"; +	else +	if ( url.find( "example://" ) != std::string::npos )	// Example plugin +		mime_type = "example/example"; + +	return mime_type; +} + +//////////////////////////////////////////////////////////////////////////////// +// +std::string LLFBConnectTest::pluginNameFromMimeType( std::string& mime_type ) +{ +#if LL_DARWIN +	std::string plugin_name( "media_plugin_null.dylib" ); +	if ( mime_type == "video/quicktime" ) +		plugin_name = "media_plugin_quicktime.dylib"; +	else +	if ( mime_type == "text/html" ) +		plugin_name = "media_plugin_webkit.dylib"; + +#elif LL_WINDOWS +	std::string plugin_name( "media_plugin_null.dll" ); + +	if ( mime_type == "video/quicktime" ) +		plugin_name = "media_plugin_quicktime.dll"; +	else +	if ( mime_type == "text/html" ) +		plugin_name = "media_plugin_webkit.dll"; +	else +	if ( mime_type == "example/example" ) +		plugin_name = "media_plugin_example.dll"; + +#elif LL_LINUX +	std::string plugin_name( "libmedia_plugin_null.so" ); + +	if ( mime_type == "video/quicktime" ) +		plugin_name = "libmedia_plugin_quicktime.so"; +	else +	if ( mime_type == "text/html" ) +		plugin_name = "libmedia_plugin_webkit.so"; +#endif +	return plugin_name; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel* LLFBConnectTest::addMediaPanel( std::string url ) +{ +	// Get the plugin filename using the URL +	std::string mime_type = mimeTypeFromUrl( url ); +	std::string plugin_name = pluginNameFromMimeType( mime_type ); + +	// create a random size for the new media +	int media_width; +	int media_height; +	getRandomMediaSize( media_width, media_height, mime_type ); +	media_width = 1024; +	media_height = 1536; + +	// make a new plugin +	LLPluginClassMedia* media_source = new LLPluginClassMedia(this); + +	// enable cookies so the FB login works +	media_source->enable_cookies(true); + +	// tell the plugin what size we asked for +	media_source->setSize( media_width, media_height ); + +	// Use the launcher start and initialize the plugin +#if LL_DARWIN || LL_LINUX +	std::string launcher_name( "SLPlugin" ); +#elif LL_WINDOWS +	std::string launcher_name( "SLPlugin.exe" ); +#endif + +	// for this test app, use the cwd as the user data path (ugh). +#if LL_WINDOWS +	std::string user_data_path = ".\\"; +#else +        char cwd[ FILENAME_MAX ]; +	if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) +	{ +		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; +		return NULL; +	} +	std::string user_data_path = std::string( cwd ) + "/"; +#endif +	media_source->setUserDataPath(user_data_path); +	media_source->init( launcher_name, user_data_path, plugin_name, false ); +	//media_source->setDisableTimeout(mDisableTimeout); + +	// make a new panel and save parameters +	mediaPanel* panel = new mediaPanel; +	panel->mMediaSource = media_source; +	panel->mStartUrl = url; +	panel->mMimeType = mime_type; +	panel->mMediaWidth = media_width; +	panel->mMediaHeight = media_height; +	panel->mTextureWidth = 0; +	panel->mTextureHeight = 0; +	panel->mTextureScaleX = 0; +	panel->mTextureScaleY = 0; +	panel->mMediaTextureHandle = 0; +	panel->mPickTextureHandle = 0; +	panel->mAppTextureCoordsOpenGL = false;	// really need an 'undefined' state here too +	panel->mReadyToRender = false; + +	// look through current media panels to find an unused index number +	bool id_exists = true; +	for( int nid = 0; nid < mMaxPanels; ++nid ) +	{ +		// does this id exist already? +		id_exists = false; +		for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid ) +		{ +			if ( nid == mMediaPanels[ pid ]->mId ) +			{ +				id_exists = true; +				break; +			}; +		}; + +		// id wasn't found so we can use it +		if ( ! id_exists ) +		{ +			panel->mId = nid; +			break; +		}; +	}; + +	// if we get here and this flag is set, there is no room for any more panels +	if ( id_exists ) +	{ +		std::cout << "No room for any more panels" << std::endl; +	} +	else +	{ +		// now we have the ID we can use it to make the +		// pick texture (id is baked into texture pixels) +		makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels ); + +		// save this in the list of panels +		mMediaPanels.push_back( panel ); + +		// select the panel that was just created +		selectPanel( panel ); + +		// load and start the URL +		panel->mMediaSource->loadURI( url ); +		panel->mMediaSource->start(); + +		std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl; +	} +	 +	return panel; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::updateMediaPanel( mediaPanel* panel ) +{ +//	checkGLError("LLFBConnectTest::updateMediaPanel"); + +	if ( ! panel ) +		return; + +	if(!panel->mMediaSource || !panel->mMediaSource->textureValid()) +	{ +		panel->mReadyToRender = false; +		return; +	} + +	// take a reference copy of the plugin values since they +	// might change during this lifetime of this function +	int plugin_media_width = panel->mMediaSource->getWidth(); +	int plugin_media_height = panel->mMediaSource->getHeight(); +	int plugin_texture_width = panel->mMediaSource->getBitsWidth(); +	int plugin_texture_height = panel->mMediaSource->getBitsHeight(); + +	// If the texture isn't created or the media or texture dimensions changed AND +	// the sizes are valid then we need to delete the old media texture (if necessary) +	// then make a new one. +	if ((panel->mMediaTextureHandle == 0 || +		 panel->mMediaWidth != plugin_media_width || +		 panel->mMediaHeight != plugin_media_height || +		 panel->mTextureWidth != plugin_texture_width || +		 panel->mTextureHeight != plugin_texture_height) && +		( plugin_media_width > 0 && plugin_media_height > 0 && +		  plugin_texture_width > 0 && plugin_texture_height > 0 ) ) +	{ +		std::cout << "Valid media size (" <<  plugin_media_width << " x " << plugin_media_height +				<< ") and texture size (" <<  plugin_texture_width << " x " << plugin_texture_height +				<< ") for panel with ID=" << panel->mId << " - making texture" << std::endl; + +		// delete old GL texture +		if ( isTexture( panel->mMediaTextureHandle ) ) +		{ +			std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl; +			glDeleteTextures( 1, &panel->mMediaTextureHandle ); +			panel->mMediaTextureHandle = 0; +		} + +		std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl; + +		// make a GL texture based on the dimensions the plugin told us +		GLuint new_texture = 0; +		glGenTextures( 1, &new_texture ); + +		checkGLError("glGenTextures"); + +		std::cout << "glGenTextures returned " << new_texture << std::endl; + +		panel->mMediaTextureHandle = new_texture; + +		bindTexture( panel->mMediaTextureHandle ); + +		std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl; +		glTexImage2D( GL_TEXTURE_2D, 0, +			GL_RGB, +				plugin_texture_width, plugin_texture_height, +					0, GL_RGB, GL_UNSIGNED_BYTE, +						0 ); + + +		std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl; +	}; + +	// update our record of the media and texture dimensions +	// NOTE: do this after we we check for sizes changes +	panel->mMediaWidth = plugin_media_width; +	panel->mMediaHeight = plugin_media_height; +	panel->mTextureWidth = plugin_texture_width; +	panel->mTextureHeight = plugin_texture_height; +	if ( plugin_texture_width > 0 ) +	{ +		panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth; +	}; +	if ( plugin_texture_height > 0 ) +	{ +		panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight; +	}; + +	// update the flag which tells us if the media source uses OprnGL coords or not. +	panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL(); + +	// Check to see if we have enough to render this panel. +	// If we do, set a flag that the display functions use so +	// they only render a panel with media if it's ready. +	if ( panel->mMediaWidth < 0 || +		 panel->mMediaHeight < 0 || +		 panel->mTextureWidth < 1 || +		 panel->mTextureHeight < 1 || +		 panel->mMediaTextureHandle == 0 ) +	{ +		panel->mReadyToRender = false; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel* LLFBConnectTest::replaceMediaPanel( mediaPanel* panel, std::string url ) +{ +	// no media panels so we can't change anything - have to add +	if ( mMediaPanels.size() == 0 ) +		return NULL; + +	// sanity check +	if ( ! panel ) +		return NULL; + +	int index; +	for(index = 0; index < (int)mMediaPanels.size(); index++) +	{ +		if(mMediaPanels[index] == panel) +			break; +	} + +	if(index >= (int)mMediaPanels.size()) +	{ +		// panel isn't in mMediaPanels +		return NULL; +	} + +	std::cout << "Replacing media panel with index " << panel->mId << std::endl; + +	int panel_id = panel->mId; + +	if(mSelectedPanel == panel) +		mSelectedPanel = NULL; + +	delete panel; + +	// Get the plugin filename using the URL +	std::string mime_type = mimeTypeFromUrl( url ); +	std::string plugin_name = pluginNameFromMimeType( mime_type ); + +	// create a random size for the new media +	int media_width; +	int media_height; +	getRandomMediaSize( media_width, media_height, mime_type ); + +	// make a new plugin +	LLPluginClassMedia* media_source = new LLPluginClassMedia(this); + +	// tell the plugin what size we asked for +	media_source->setSize( media_width, media_height ); + +	// Use the launcher start and initialize the plugin +#if LL_DARWIN || LL_LINUX +	std::string launcher_name( "SLPlugin" ); +#elif LL_WINDOWS +	std::string launcher_name( "SLPlugin.exe" ); +#endif + +	// for this test app, use the cwd as the user data path (ugh). +#if LL_WINDOWS +	std::string user_data_path = ".\\"; +#else +        char cwd[ FILENAME_MAX ]; +	if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) +	{ +		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; +		return NULL; +	} +	std::string user_data_path = std::string( cwd ) + "/"; +#endif + +	media_source->setUserDataPath(user_data_path); +	media_source->init( launcher_name, user_data_path, plugin_name, false ); +	//media_source->setDisableTimeout(mDisableTimeout); + +	// make a new panel and save parameters +	panel = new mediaPanel; +	panel->mMediaSource = media_source; +	panel->mStartUrl = url; +	panel->mMimeType = mime_type; +	panel->mMediaWidth = media_width; +	panel->mMediaHeight = media_height; +	panel->mTextureWidth = 0; +	panel->mTextureHeight = 0; +	panel->mTextureScaleX = 0; +	panel->mTextureScaleY = 0; +	panel->mMediaTextureHandle = 0; +	panel->mPickTextureHandle = 0; +	panel->mAppTextureCoordsOpenGL = false;	// really need an 'undefined' state here too +	panel->mReadyToRender = false; + +	panel->mId = panel_id; + +	// Replace the entry in the panels array +	mMediaPanels[index] = panel; + +	// now we have the ID we can use it to make the +	// pick texture (id is baked into texture pixels) +	makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels ); + +	// select the panel that was just created +	selectPanel( panel ); + +	// load and start the URL +	panel->mMediaSource->loadURI( url ); +	panel->mMediaSource->start(); +	 +	return panel; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::getRandomMediaSize( int& width, int& height, std::string mime_type ) +{ +	// Make a new media source with a random size which we'll either +	// directly or the media plugin will tell us what it wants later. +	// Use a random size so we can test support for weird media sizes. +	// (Almost everything else will get filled in later once the +	// plugin responds) +	// NB. Do we need to enforce that width is on 4 pixel boundary? +	width = ( ( rand() % 170 ) + 30 ) * 4; +	height = ( ( rand() % 170 ) + 30 ) * 4; + +	// adjust this random size if it's a browser so we get +	// a more useful size for testing.. +	if ( mime_type == "text/html" || mime_type == "example/example"  ) +	{ +		width = ( ( rand() % 100 ) + 100 ) * 4; +		height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000; +	}; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::remMediaPanel( mediaPanel* panel ) +{ +	// always leave one panel +	if ( mMediaPanels.size() == 1 ) +		return; + +	// sanity check - don't think this can happen but see above for a case where it might... +	if ( ! panel ) +		return; + +	std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl; + +	if(mSelectedPanel == panel) +		mSelectedPanel = NULL; + +	delete panel; + +	// remove from storage list +	for( int i = 0; i < (int)mMediaPanels.size(); ++i ) +	{ +		if ( mMediaPanels[ i ] == panel ) +		{ +			mMediaPanels.erase( mMediaPanels.begin() + i ); +			break; +		}; +	}; + +	// select the first panel +	selectPanel( mMediaPanels[ 0 ] ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::updateStatusBar() +{ +	if ( ! mSelectedPanel ) +		return; + +	// cache results - this is a very slow function +	static int cached_id = -1; +	static int cached_media_width = -1; +	static int cached_media_height = -1; +	static int cached_texture_width = -1; +	static int cached_texture_height = -1; +	static bool cached_supports_browser_media = true; +	static bool cached_supports_time_media = false; +	static int cached_movie_time = -1; +	static GLfloat cached_distance = -1.0f; + +	static std::string cached_plugin_version = ""; +	if ( +		 cached_id == mSelectedPanel->mId && +		 cached_media_width == mSelectedPanel->mMediaWidth && +		 cached_media_height  == mSelectedPanel->mMediaHeight && +		 cached_texture_width == mSelectedPanel->mTextureWidth && +		 cached_texture_height == mSelectedPanel->mTextureHeight && +		 cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() && +		 cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() && +		 cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() && +		 cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime() && +		 cached_distance == mDistanceCameraToSelectedGeometry +	   ) +	{ +		// nothing changed so don't spend time here +		return; +	}; + +	std::ostringstream stream( "" ); + +	stream.str( "" ); +	stream.clear(); + +	stream << "Id: "; +	stream << std::setw( 2 ) << std::setfill( '0' ); +	stream << mSelectedPanel->mId; +	stream << " | "; +	stream << "Media: "; +	stream << std::setw( 3 ) << std::setfill( '0' ); +	stream << mSelectedPanel->mMediaWidth; +	stream << " x "; +	stream << std::setw( 3 ) << std::setfill( '0' ); +	stream << mSelectedPanel->mMediaHeight; +	stream << " | "; +	stream << "Texture: "; +	stream << std::setw( 4 ) << std::setfill( '0' ); +	stream << mSelectedPanel->mTextureWidth; +	stream << " x "; +	stream << std::setw( 4 ) << std::setfill( '0' ); +	stream << mSelectedPanel->mTextureHeight; + +	stream << " | "; +	stream << "Distance: "; +	stream << std::setw( 6 ); +	stream << std::setprecision( 3 ); +	stream << std::setprecision( 3 ); +	stream << mDistanceCameraToSelectedGeometry; +	stream << " | "; + +	if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() ) +		stream << "BROWSER"; +	else +	if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) +		stream << "TIME   "; +	stream << " | "; +	stream << mSelectedPanel->mMediaSource->getPluginVersion(); +	stream << " | "; +	if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) +	{ +		stream << std::setw( 3 ) << std::setfill( '0' ); +		stream << (int)mSelectedPanel->mMediaSource->getCurrentTime(); +		stream << " / "; +		stream << std::setw( 3 ) << std::setfill( '0' ); +		stream << (int)mSelectedPanel->mMediaSource->getDuration(); +		stream << " @ "; +		stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate(); +		stream << " | "; +	}; + +	glutSetWindow( mBottomGLUIWindow->get_glut_window_id() ); +	mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) ); +	glutSetWindow( mAppWindow ); + +	// caching +	cached_id = mSelectedPanel->mId; +	cached_media_width = mSelectedPanel->mMediaWidth; +	cached_media_height = mSelectedPanel->mMediaHeight; +	cached_texture_width = mSelectedPanel->mTextureWidth; +	cached_texture_height = mSelectedPanel->mTextureHeight; +	cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser(); +	cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime(); +	cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion(); +	cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::dumpPanelInfo() +{ +	std::cout << std::endl << "===== Media Panels =====" << std::endl; +	for( int i = 0; i < (int)mMediaPanels.size(); ++i ) +	{ +		std::cout << std::setw( 2 ) << std::setfill( '0' ); +		std::cout << i + 1 << "> "; +		std::cout << "Id: "; +		std::cout << std::setw( 2 ) << std::setfill( '0' ); +		std::cout << mMediaPanels[ i ]->mId; +		std::cout << " | "; +		std::cout << "Media: "; +		std::cout << std::setw( 3 ) << std::setfill( '0' ); +		std::cout << mMediaPanels[ i ]->mMediaWidth; +		std::cout << " x "; +		std::cout << std::setw( 3 ) << std::setfill( '0' ); +		std::cout << mMediaPanels[ i ]->mMediaHeight; +		std::cout << " | "; +		std::cout << "Texture: "; +		std::cout << std::setw( 4 ) << std::setfill( '0' ); +		std::cout << mMediaPanels[ i ]->mTextureWidth; +		std::cout << " x "; +		std::cout << std::setw( 4 ) << std::setfill( '0' ); +		std::cout << mMediaPanels[ i ]->mTextureHeight; +		std::cout << " | "; +		if ( mMediaPanels[ i ] == mSelectedPanel ) +			std::cout << "(selected)"; + +		std::cout << std::endl; +	}; +	std::cout << "========================" << std::endl; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFBConnectTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ +	// Uncomment this to make things much, much quieter. +//	return; + +	switch(event) +	{ +		case MEDIA_EVENT_CONTENT_UPDATED: +			// too spammy -- don't log these +//			std::cerr <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << std::endl; +		break; + +		case MEDIA_EVENT_TIME_DURATION_UPDATED: +			// too spammy -- don't log these +//			std::cerr <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl; +		break; + +		case MEDIA_EVENT_SIZE_CHANGED: +			std::cerr <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << std::endl; +		break; + +		case MEDIA_EVENT_CURSOR_CHANGED: +			std::cerr <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl; +		break; + +		case MEDIA_EVENT_NAVIGATE_BEGIN: +			std::cerr <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl; +		break; + +		case MEDIA_EVENT_NAVIGATE_COMPLETE: +			std::cerr <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl; +		break; + +		case MEDIA_EVENT_PROGRESS_UPDATED: +			std::cerr <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl; +		break; + +		case MEDIA_EVENT_STATUS_TEXT_CHANGED: +			std::cerr <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl; +		break; + +		case MEDIA_EVENT_NAME_CHANGED: +			std::cerr <<  "Media event:  MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl; +			glutSetWindowTitle( self->getMediaName().c_str() ); +		break; + +		case MEDIA_EVENT_LOCATION_CHANGED: +		{ +			std::cerr <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl; +			mediaPanel* panel = findMediaPanel(self); +			if(panel != NULL) +			{ +				panel->mStartUrl = self->getLocation(); +				if(panel == mSelectedPanel) +				{ +					mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) ); +				} +			} +		} +		break; + +		case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: +			std::cerr <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE, uri is: " << self->getClickURL() << std::endl; +		break; +			 +		case MEDIA_EVENT_CLICK_LINK_HREF: +		{ +			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << ", target is " << self->getClickTarget() << std::endl; +			// retrieve the event parameters +			std::string url = self->getClickURL(); +			std::string target = self->getClickTarget(); +			 +			if(target == "_external") +			{ +				// this should open in an external browser, but since this is a test app we don't care. +			} +			else if(target == "_blank") +			{ +				// Create a new panel with the specified URL. +				addMediaPanel(url); +			} +			else // other named target +			{ +				mediaPanel *target_panel = findMediaPanel(target); +				if(target_panel) +				{ +					target_panel = replaceMediaPanel(target_panel, url); +				} +				else +				{ +					target_panel = addMediaPanel(url); +				} + +				if(target_panel) +				{ +					target_panel->mTarget = target; +				} +			} +		} +		break; + +		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: +			std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl; +		break; + +		case MEDIA_EVENT_PLUGIN_FAILED: +			std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << std::endl; +		break; + +		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: +			std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl; +		break; + +		case MEDIA_EVENT_CLOSE_REQUEST: +			std::cerr <<  "Media event:  MEDIA_EVENT_CLOSE_REQUEST" << std::endl; +		break; +		 +		case MEDIA_EVENT_PICK_FILE_REQUEST: +			std::cerr <<  "Media event:  MEDIA_EVENT_PICK_FILE_REQUEST" << std::endl; +			// TODO: display an actual file picker +			self->sendPickFileResponse("cake"); +		break; + +		case MEDIA_EVENT_GEOMETRY_CHANGE: +			std::cerr <<  "Media event:  MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID()  +				<< ", x = " << self->getGeometryX()  +				<< ", y = " << self->getGeometryY()  +				<< ", width = " << self->getGeometryWidth()  +				<< ", height = " << self->getGeometryHeight()  +				<< std::endl; +		break; + +		case MEDIA_EVENT_AUTH_REQUEST: +		{ +			//std::cerr <<  "Media event:  MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl; + +			// TODO: display an auth dialog +			self->sendAuthResponse(false, "", ""); +		} +		break; + +		case MEDIA_EVENT_LINK_HOVERED: +		{ +			std::cerr <<  "Media event:  MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << std::endl; +		} +		break; + +		default: +		{ +			std::cerr <<  "Media event:  <unknown>, code is: " << int(event) << std::endl; +		} +		break; +	} +} + +//////////////////////////////////////////////////////////////////////////////// +// +static void gluiCallbackWrapper( int control_id ) +{ +	if ( gApplication ) +		gApplication->gluiCallback( control_id ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutReshape( int width, int height ) +{ +	if ( gApplication ) +		gApplication->reshape( width, height ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutDisplay() +{ +	if ( gApplication ) +		gApplication->display(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutIdle(int update_ms) +{ +	GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms); + +	if ( gApplication ) +		gApplication->idle(); + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutKeyboard( unsigned char key, int x, int y ) +{ +	if ( gApplication ) +		gApplication->keyboard( key ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMousePassive( int x, int y ) +{ +	if ( gApplication ) +		gApplication->mousePassive( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseMove( int x , int y ) +{ +	if ( gApplication ) +		gApplication->mouseMove( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseButton( int button, int state, int x, int y ) +{ +	if ( gApplication ) +		gApplication->mouseButton( button, state, x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +int main( int argc, char* argv[] ) +{ +#if LL_DARWIN +	// Set the current working directory to <application bundle>/Contents/Resources/ +	CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); +	if(resources_url != NULL) +	{ +		CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle); +		CFRelease(resources_url); +		if(resources_string != NULL) +		{ +			char buffer[PATH_MAX] = ""; +			if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8)) +			{ +				chdir(buffer); +			} +			CFRelease(resources_string); +		} +	} +#endif + +	glutInit( &argc, argv ); +	glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB ); + +	const int app_window_x = 80; +	const int app_window_y = 0; +	const int app_window_width = 960; +	const int app_window_height = 960; + +	glutInitWindowPosition( app_window_x, app_window_y ); +	glutInitWindowSize( app_window_width, app_window_height ); + +	int app_window_handle = glutCreateWindow( "LLFBConnectTest" ); + +	glutDisplayFunc( glutDisplay ); + +	GLUI_Master.set_glutReshapeFunc( glutReshape ); +	GLUI_Master.set_glutKeyboardFunc( glutKeyboard ); +	GLUI_Master.set_glutMouseFunc( glutMouseButton ); + +	glutPassiveMotionFunc( glutMousePassive ); +	glutMotionFunc( glutMouseMove ); + +	glutSetWindow( app_window_handle ); + +	gApplication = new LLFBConnectTest( app_window_handle, app_window_width, app_window_height ); + +	// update at approximately 60hz +	int update_ms = 1000 / 60; + +	GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms); + +	glutMainLoop(); + +	delete gApplication; +} diff --git a/indra/test_apps/llfbconnecttest/llfbconnecttest.h b/indra/test_apps/llfbconnecttest/llfbconnecttest.h new file mode 100644 index 0000000000..6f442a55b3 --- /dev/null +++ b/indra/test_apps/llfbconnecttest/llfbconnecttest.h @@ -0,0 +1,207 @@ +/** + * @file LLFBConnectTest.cpp + * @brief Facebook Connect Test App + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_FB_CONNECT_H +#define LL_FB_CONNECT_H + +#include <vector> +#include <string> +#include "llpluginclassmedia.h" +#include "llgl.h" + +// Forward declarations +class GLUI_Rotation; +class GLUI_Translation; +class GLUI_Listbox; +class GLUI_EditText; +class GLUI_StaticText; +class GLUI; +class GLUI_Button; + +//////////////////////////////////////////////////////////////////////////////// +// +struct mediaPanel +{ +	public: +		mediaPanel(); +		~mediaPanel(); +		int mId; +		std::string mStartUrl; +		std::string mMimeType; +		std::string mTarget; +		LLPluginClassMedia *mMediaSource; +		int mMediaWidth; +		int mMediaHeight; +		int mTextureWidth; +		int mTextureHeight; +		double mTextureScaleX; +		double mTextureScaleY; +		GLuint mMediaTextureHandle; +		GLuint mPickTextureHandle; +		unsigned char* mPickTexturePixels; +		bool mAppTextureCoordsOpenGL; +		bool mReadyToRender; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +class LLFBConnectTest : public LLPluginClassMediaOwner +{ +	public: +		LLFBConnectTest( int app_window, int window_width, int window_height ); +		~LLFBConnectTest(); + +		void reshape( int width, int height ); +		void display(); +		void idle(); +		void gluiCallback( int control_id ); +		void keyboard( int key ); +		void mousePassive( int x, int y ); +		void mouseButton( int button, int state, int x, int y ); +		void mouseMove( int x, int y ); + +		void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1); +		bool checkGLError(const char *name = "OpenGL"); +		void drawGeometry( int panel, bool selected ); +		void startPanelHighlight( float red, float green, float blue, float line_width ); +		void endPanelHighlight(); +		enum { DrawTypePickTexture, DrawTypeMediaTexture }; +		void draw( int draw_type ); +		void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id ); + +		mediaPanel* addMediaPanel( std::string url ); +		void updateMediaPanel( mediaPanel* panel ); +		void remMediaPanel( mediaPanel* panel ); +		mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url ); +		void getRandomMediaSize( int& width, int& height, std::string mime_type ); +		void navigateToNewURI( std::string uri ); +        void initUrlHistory( std::string uri ); +		void selectPanelById( int id ); +		void selectPanel( mediaPanel* panel ); +		mediaPanel* findMediaPanel( LLPluginClassMedia* panel ); +		mediaPanel* findMediaPanel( const std::string &target_name ); +		void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels ); +		void makeChrome(); +		void resetView(); + +		void dumpPanelInfo(); +		void updateStatusBar(); + +		GLfloat distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z ); +		 + +	// Inherited from LLPluginClassMediaOwner +	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent); + +	private: +		const int mVersionMajor; +		const int mVersionMinor; +		const int mVersionPatch; +		const int mMaxPanels; +		int mAppWindow; +		int mWindowWidth; +		int mWindowHeight; +		int mCurMouseX; +		int mCurMouseY; +		unsigned char mPixelReadColor[ 3 ]; +		bool mFuzzyMedia; +		const std::string mHomeWebUrl; + +		std::vector< mediaPanel* > mMediaPanels; +		mediaPanel* mSelectedPanel; +		std::string mimeTypeFromUrl( std::string& url ); +		std::string pluginNameFromMimeType( std::string& mime_type ); + +		GLUI_Rotation* mViewRotationCtrl; +		GLUI_Translation* mViewScaleCtrl; +		GLUI_Translation* mViewTranslationCtrl; +		float mViewportAspect; +		float mViewPos[ 3 ]; +		float mViewRotation[ 16 ]; + +		float mDistanceCameraToSelectedGeometry; + +		int mIdControlAddPanel; +		int mIdControlRemPanel; + +		std::vector< std::pair< std::string, std::string > > mBookmarks; +		GLUI_Listbox* mBookmarkList; +		int mIdBookmarks; +		int mIdUrlEdit; +		GLUI_EditText* mUrlEdit; +        //int mIdUrlInitHistoryEdit; +		//GLUI_EditText* mUrlInitHistoryEdit; +		int mSelBookmark; +		//int mIdRandomPanelCount; +		//int mRandomPanelCount; +		//int mIdRandomBookmarks; +		//int mRandomBookmarks; +		//int mIdDisableTimeout; +		//int mDisableTimeout; +		//int mIdUsePluginReadThread; +		//int mUsePluginReadThread; +		//int mIdLargePanelSpacing; +		//int mLargePanelSpacing; +		//int mIdControlCrashPlugin; +		//int mIdControlHangPlugin; +		int mIdControlExitApp; + +		//GLUI* mGluiMediaTimeControlWindow; +		//int mIdMediaTimeControlPlay; +		//int mIdMediaTimeControlLoop; +		//int mIdMediaTimeControlPause; +		//int mIdMediaTimeControlStop; +		//int mIdMediaTimeControlSeek; +		//int mIdMediaTimeControlVolume; +		//int mMediaTimeControlVolume; +		//int mIdMediaTimeControlSeekSeconds; +		//int mMediaTimeControlSeekSeconds; +		//int mIdMediaTimeControlRewind; +		//int mIdMediaTimeControlFastForward; + +		GLUI* mGluiMediaBrowserControlWindow; +		int mIdMediaBrowserControlBack; +		GLUI_Button* mMediaBrowserControlBackButton; +		int mIdMediaBrowserControlStop; +		int mIdMediaBrowserControlForward; +		GLUI_Button* mMediaBrowserControlForwardButton; +		bool mGluiMediaTimeControlWindowFlag; +		bool mGluiMediaBrowserControlWindowFlag; +		bool mMediaBrowserControlBackButtonFlag; +		bool mMediaBrowserControlForwardButtonFlag; +		int mIdMediaBrowserControlHome; +		int mIdMediaBrowserControlReload; +		int mIdMediaBrowserControlClearCache; +		int mIdMediaBrowserControlClearCookies; +		int mIdMediaBrowserControlEnableCookies; +		int mMediaBrowserControlEnableCookies; + +		GLUI* mBottomGLUIWindow; +		GLUI_StaticText* mStatusText; +}; + +#endif	// LL_FB_CONNECT_H + diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index d6e06e5316..dc8ff2f644 100755 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -79,7 +79,6 @@ void LLUpdateChecker::checkVersion(std::string const & urlBase,  //----------------------------------------------------------------------------- -const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";  const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1"; @@ -150,40 +149,11 @@ void LLUpdateChecker::Implementation::completed(U32 status,  			server_error += content["error_text"].asString();  		} -		if (status == 404) -		{ -			if (mProtocol == sProtocolVersion) -			{ -				mProtocol = sLegacyProtocolVersion; -				std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); - -				LL_WARNS("UpdaterService") -					<< "update response using " << sProtocolVersion -					<< " was HTTP 404 (" << server_error -					<< "); retry with legacy protocol " << mProtocol -					<< "\n at " << retryUrl -					<< LL_ENDL; -	 -				mHttpClient.get(retryUrl, this); -			} -			else -			{ -				LL_WARNS("UpdaterService") -					<< "update response using " << sLegacyProtocolVersion -					<< " was 404 (" << server_error -					<< "); request failed" -					<< LL_ENDL; -				mClient.error(reason); -			} -		} -		else -		{ -			LL_WARNS("UpdaterService") << "response error " << status -									   << " " << reason -									   << " (" << server_error << ")" -									   << LL_ENDL; -			mClient.error(reason); -		} +		LL_WARNS("UpdaterService") << "response error " << status +								   << " " << reason +								   << " (" << server_error << ")" +								   << LL_ENDL; +		mClient.error(reason);  	}  	else  	{ @@ -213,11 +183,8 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBas  	path.append(channel);  	path.append(version);  	path.append(platform); -	if (mProtocol != sLegacyProtocolVersion) -	{ -		path.append(platform_version); -		path.append(willing_to_test ? "testok" : "testno"); -		path.append((char*)uniqueid); -	} +	path.append(platform_version); +	path.append(willing_to_test ? "testok" : "testno"); +	path.append((char*)uniqueid);  	return LLURI::buildHTTP(urlBase, path).asString();  } diff --git a/indra/viewer_components/updater/scripts/darwin/update_install.py b/indra/viewer_components/updater/scripts/darwin/update_install.py index 2fc6fcdb29..10d507c9ef 100755 --- a/indra/viewer_components/updater/scripts/darwin/update_install.py +++ b/indra/viewer_components/updater/scripts/darwin/update_install.py @@ -17,6 +17,7 @@ $/LicenseInfo$  import os  import sys  import cgitb +from contextlib import contextmanager  import errno  import glob  import plistlib @@ -32,6 +33,11 @@ import Tkinter, tkMessageBox  TITLE = "Second Life Viewer Updater"  # Magic bundle identifier used by all Second Life viewer bundles  BUNDLE_IDENTIFIER = "com.secondlife.indra.viewer" +# Magic OS directory name that causes Cocoa viewer to crash on OS X 10.7.5 +# (see MAINT-3331) +STATE_DIR = os.path.join( +    os.environ["HOME"], "Library", "Saved Application State", +    BUNDLE_IDENTIFIER + ".savedState")  # Global handle to the MessageFrame so we can update message  FRAME = None @@ -137,6 +143,23 @@ def write_marker(markerfile, markertext):          log("%s exception: %s" % (err.__class__.__name__, err))  # **************************************************************************** +#   Utility +# **************************************************************************** +@contextmanager +def allow_errno(errn): +    """ +    Execute body of 'with' statement, accepting OSError with specific errno +    'errn'. Propagate any other exception, or an OSError with any other errno. +    """ +    try: +        # run the body of the 'with' statement +        yield +    except OSError, err: +        # unless errno == passed errn, re-raise the exception +        if err.errno != errn: +            raise + +# ****************************************************************************  #   Main script logic  # ****************************************************************************  def main(dmgfile, markerfile, markertext): @@ -158,12 +181,9 @@ def main(dmgfile, markerfile, markertext):          # Move the old updater.log file out of the way          logname = os.path.join(logsdir, "updater.log") -        try: +        # Nonexistence is okay. Anything else, not so much. +        with allow_errno(errno.ENOENT):              os.rename(logname, logname + ".old") -        except OSError, err: -            # Nonexistence is okay. Anything else, not so much. -            if err.errno != errno.ENOENT: -                raise          # Open new updater.log.          global LOGF @@ -345,6 +365,13 @@ def main(dmgfile, markerfile, markertext):              log("touch " + appdir)              os.utime(appdir, None)      # set to current time +            # MAINT-3331: remove STATE_DIR. Empirically, this resolves a +            # persistent, mysterious crash after updating our viewer on an OS +            # X 10.7.5 system. +            log("rm -rf '%s'" % STATE_DIR) +            with allow_errno(errno.ENOENT): +                shutil.rmtree(STATE_DIR) +              command = ["open", appdir]              log(' '.join(command))              subprocess.check_call(command, stdout=LOGF, stderr=subprocess.STDOUT)  | 
