diff options
42 files changed, 872 insertions, 138 deletions
| @@ -143,3 +143,4 @@ a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release  19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start  09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1  09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1 +e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start diff --git a/doc/contributions.txt b/doc/contributions.txt index bad78dcd5f..a619d11737 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -20,6 +20,7 @@ Aimee Trescothick  	SNOW-570  	SNOW-572  	SNOW-575 +	STORM-1315  	VWR-3321  	VWR-3336  	VWR-3903 @@ -103,6 +104,7 @@ Ales Beaumont  Alexandrea Fride      STORM-255  	STORM-960 +	STORM-1459  Alissa Sabre  	VWR-81  	VWR-83 @@ -449,6 +451,7 @@ Jonathan Yap  	STORM-899  	STORM-1273  	STORM-1462 +	STORM-1459  Kage Pixel  	VWR-11  Ken March @@ -690,6 +693,7 @@ Robin Cornelius  	STORM-1019  	STORM-1095  	STORM-1128 +	STORM-1459  	VWR-2488  	VWR-9557  	VWR-10579 @@ -831,6 +835,7 @@ Thickbrick Sleaford  	VWR-24420  	STORM-956  	STORM-1147 +	STORM-1325  Thraxis Epsilon  	SVC-371  	VWR-383 diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 3dcaca4f16..0018b8e844 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@  const S32 LL_VERSION_MAJOR = 2;  const S32 LL_VERSION_MINOR = 8; -const S32 LL_VERSION_PATCH = 0; +const S32 LL_VERSION_PATCH = 1;  const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 9dadad7dd3..cd100cdf9f 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -12,6 +12,8 @@ include_directories(  set(llmath_SOURCE_FILES      llbbox.cpp      llbboxlocal.cpp +    llcalc.cpp +    llcalcparser.cpp      llcamera.cpp      llcoordframe.cpp      llline.cpp @@ -46,6 +48,8 @@ set(llmath_HEADER_FILES      coordframe.h      llbbox.h      llbboxlocal.h +    llcalc.h +    llcalcparser.h      llcamera.h      llcoord.h      llcoordframe.h diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp new file mode 100644 index 0000000000..597d0815fb --- /dev/null +++ b/indra/llmath/llcalc.cpp @@ -0,0 +1,145 @@ +/* + *  LLCalc.cpp + *  SecondLife + * + *  Created by Aimee Walton on 28/09/2008. + *  Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalc.h" + +#include "llcalcparser.h" +#include "llmath.h" + + +// Variable names for use in the build floater +const char* LLCalc::X_POS = "PX"; +const char* LLCalc::Y_POS = "PY"; +const char* LLCalc::Z_POS = "PZ"; +const char* LLCalc::X_SCALE = "SX"; +const char* LLCalc::Y_SCALE = "SY"; +const char* LLCalc::Z_SCALE = "SZ"; +const char* LLCalc::X_ROT = "RX"; +const char* LLCalc::Y_ROT = "RY"; +const char* LLCalc::Z_ROT = "RZ"; +const char* LLCalc::HOLLOW = "HLW"; +const char* LLCalc::CUT_BEGIN = "CB"; +const char* LLCalc::CUT_END = "CE"; +const char* LLCalc::PATH_BEGIN = "PB"; +const char* LLCalc::PATH_END = "PE"; +const char* LLCalc::TWIST_BEGIN = "TB"; +const char* LLCalc::TWIST_END = "TE"; +const char* LLCalc::X_SHEAR = "SHX"; +const char* LLCalc::Y_SHEAR = "SHY"; +const char* LLCalc::X_TAPER = "TPX"; +const char* LLCalc::Y_TAPER = "TPY"; +const char* LLCalc::RADIUS_OFFSET = "ROF"; +const char* LLCalc::REVOLUTIONS = "REV"; +const char* LLCalc::SKEW = "SKW"; +const char* LLCalc::X_HOLE = "HLX"; +const char* LLCalc::Y_HOLE = "HLY"; +const char* LLCalc::TEX_U_SCALE = "TSU"; +const char* LLCalc::TEX_V_SCALE = "TSV"; +const char* LLCalc::TEX_U_OFFSET = "TOU"; +const char* LLCalc::TEX_V_OFFSET = "TOV"; +const char* LLCalc::TEX_ROTATION = "TROT"; +const char* LLCalc::TEX_TRANSPARENCY = "TRNS"; +const char* LLCalc::TEX_GLOW = "GLOW"; + + +LLCalc* LLCalc::sInstance = NULL; + +LLCalc::LLCalc() : mLastErrorPos(0) +{ +	// Init table of constants +	mConstants["PI"] = F_PI; +	mConstants["TWO_PI"] = F_TWO_PI; +	mConstants["PI_BY_TWO"] = F_PI_BY_TWO; +	mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; +	mConstants["SQRT2"] = F_SQRT2; +	mConstants["SQRT3"] = F_SQRT3; +	mConstants["DEG_TO_RAD"] = DEG_TO_RAD; +	mConstants["RAD_TO_DEG"] = RAD_TO_DEG; +	mConstants["GRAVITY"] = GRAVITY; +} + +LLCalc::~LLCalc() +{ +} + +//static +void LLCalc::cleanUp() +{ +	delete sInstance; +	sInstance = NULL; +} + +//static +LLCalc* LLCalc::getInstance() +{ +    if (!sInstance)	sInstance = new LLCalc(); +	return sInstance; +} + +void LLCalc::setVar(const std::string& name, const F32& value) +{ +	mVariables[name] = value; +} + +void LLCalc::clearVar(const std::string& name) +{ +	mVariables.erase(name); +} + +void LLCalc::clearAllVariables() +{ +	mVariables.clear(); +} + +/* +void LLCalc::updateVariables(LLSD& vars) +{ +	LLSD::map_iterator cIt = vars.beginMap(); +	for(; cIt != vars.endMap(); cIt++) +	{ +		setVar(cIt->first, (F32)(LLSD::Real)cIt->second); +	} +} +*/ + +bool LLCalc::evalString(const std::string& expression, F32& result) +{ +	std::string expr_upper = expression; +	LLStringUtil::toUpper(expr_upper); +	 +	LLCalcParser calc(result, &mConstants, &mVariables); + +	mLastErrorPos = 0; +	std::string::iterator start = expr_upper.begin(); + 	parse_info<std::string::iterator> info; +	 +	try +	{ +		info = parse(start, expr_upper.end(), calc, space_p); +		lldebugs << "Math expression: " << expression << " = " << result << llendl; +	} +	catch(parser_error<std::string, std::string::iterator> &e) +	{ +		mLastErrorPos = e.where - expr_upper.begin(); +		 +		llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl; +		return false; +	} +	 +	if (!info.full) +	{ +		mLastErrorPos = info.stop - expr_upper.begin(); +		llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl; +		return false; +	} +	 +	return true; +} diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h new file mode 100644 index 0000000000..cc31950cb6 --- /dev/null +++ b/indra/llmath/llcalc.h @@ -0,0 +1,83 @@ +/* + *  LLCalc.h + *  SecondLife + * + *  Created by Aimee Walton on 28/09/2008. + *  Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALC_H +#define LL_CALC_H + +#include <map> +#include <string> + +class LLCalc +{ +public: +	LLCalc(); +	~LLCalc(); + +	// Variable name constants +	static const char* X_POS; +	static const char* Y_POS; +	static const char* Z_POS; +	static const char* X_SCALE; +	static const char* Y_SCALE; +	static const char* Z_SCALE; +	static const char* X_ROT; +	static const char* Y_ROT; +	static const char* Z_ROT; +	static const char* HOLLOW; +	static const char* CUT_BEGIN; +	static const char* CUT_END; +	static const char* PATH_BEGIN; +	static const char* PATH_END; +	static const char* TWIST_BEGIN; +	static const char* TWIST_END; +	static const char* X_SHEAR; +	static const char* Y_SHEAR; +	static const char* X_TAPER; +	static const char* Y_TAPER; +	static const char* RADIUS_OFFSET; +	static const char* REVOLUTIONS; +	static const char* SKEW; +	static const char* X_HOLE; +	static const char* Y_HOLE; +	static const char* TEX_U_SCALE; +	static const char* TEX_V_SCALE; +	static const char* TEX_U_OFFSET; +	static const char* TEX_V_OFFSET; +	static const char* TEX_ROTATION; +	static const char* TEX_TRANSPARENCY; +	static const char* TEX_GLOW; + +	void	setVar(const std::string& name, const F32& value); +	void	clearVar(const std::string& name); +	void	clearAllVariables(); +//	void	updateVariables(LLSD& vars); + +	bool	evalString(const std::string& expression, F32& result); +	std::string::size_type	getLastErrorPos()	{ return mLastErrorPos; } +	 +	static LLCalc* getInstance(); +	static void cleanUp(); + +	typedef	std::map<std::string, F32> calc_map_t; +	 +private: +	std::string::size_type	mLastErrorPos; +	 +	calc_map_t	mConstants; +	calc_map_t	mVariables; +	 +	// *TODO: Add support for storing user defined variables, and stored functions. +	//	Will need UI work, and a means to save them between sessions. +//	calc_map_t mUserVariables; +	 +	// "There shall be only one" +	static LLCalc*	sInstance; +}; + +#endif // LL_CALC_H diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp new file mode 100644 index 0000000000..fd55376fa9 --- /dev/null +++ b/indra/llmath/llcalcparser.cpp @@ -0,0 +1,46 @@ +/* + *  LLCalcParser.cpp + *  SecondLife + * + *  Created by Aimee Walton on 28/09/2008. + *  Copyright 2008 Aimee Walton. + * + */ + +#include "linden_common.h" + +#include "llcalcparser.h" +using namespace boost::spirit::classic; + +F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const +{ +	LLCalc::calc_map_t::iterator iter; + +	std::string name(start, end); +	 +	if (mConstants) +	{ +		iter = mConstants->find(name); +		if (iter != mConstants->end()) +		{ +			return (*iter).second; +		} +	} +	else +	{ +		// This should never happen! +		throw_(end, std::string("Missing constants table")); +	} +	 +	if (mVariables) +	{ +		iter = mVariables->find(name); +		if (iter != mVariables->end()) +		{ +			return (*iter).second; +		} +	} +	 +	throw_(end, std::string("Unknown symbol " + name)); +	return 0.f; +} diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h new file mode 100644 index 0000000000..600e173661 --- /dev/null +++ b/indra/llmath/llcalcparser.h @@ -0,0 +1,174 @@ +/* + *  LLCalcParser.h + *  SecondLife + * + *  Created by Aimee Walton on 28/09/2008. + *  Copyright 2008 Aimee Walton. + * + */ + +#ifndef LL_CALCPARSER_H +#define LL_CALCPARSER_H + +#include <boost/spirit/include/classic_attribute.hpp> +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_error_handling.hpp> +#include <boost/spirit/include/classic_position_iterator.hpp> +#include <boost/spirit/include/phoenix1_binders.hpp> +#include <boost/spirit/include/classic_symbols.hpp> +using namespace boost::spirit::classic; + +#include "llcalc.h" +#include "llmath.h" + +struct LLCalcParser : grammar<LLCalcParser> +{ +	LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : +		mResult(result), mConstants(constants), mVariables(vars) {}; +	 +	struct value_closure : closure<value_closure, F32> +	{ +		member1 value; +	}; +	 +	template <typename ScannerT> +	struct definition +	{ +		// Rule declarations +		rule<ScannerT> statement, identifier; +		rule<ScannerT, value_closure::context_t> expression, term, +			power,  +			unary_expr,  +			factor,  +			unary_func,  +			binary_func, +			group; + +		// start() should return the starting symbol +		rule<ScannerT> const& start() const { return statement; } +		 +		definition(LLCalcParser const& self) +		{ +			using namespace phoenix; +			 +			assertion<std::string> assert_domain("Domain error"); +//			assertion<std::string> assert_symbol("Unknown symbol"); +			assertion<std::string> assert_syntax("Syntax error"); +			 +			identifier = +				lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] +			; +			 +			group = +				'(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) +			; + +			unary_func = +				((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) | +				 (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) | +				 (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) | +				 (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) | +				 (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) | +				 (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) | +				 (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | +				 (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | +				 (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | +				 (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) | +				 (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) | +				 (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)]) +				) >> assert_syntax(ch_p(')')) +			; +			 +			binary_func = +				((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> +				  expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | +				 (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >>  +				  expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | +				 (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >>  +				  expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) +				) >> assert_syntax(ch_p(')')) +			; +			 +			// *TODO: Localisation of the decimal point? +			// Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate +			// for the current locale. However to do that here could clash with using +			// the comma as a separator when passing arguments to functions. +			factor = +				(ureal_p[factor.value = arg1] | +				 group[factor.value = arg1] | +				 unary_func[factor.value = arg1] | +				 binary_func[factor.value = arg1] | +				 // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, +				 // would be "neater" to handle symbol lookup from here with an assertive parser. +//				 constants_p[factor.value = arg1]| +				 identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)] +				) >> +				// Detect and throw math errors. +				assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value))) +			; + +			unary_expr = +				!ch_p('+') >> factor[unary_expr.value = arg1] | +				'-' >> factor[unary_expr.value = -arg1] +			; +			 +			power = +				unary_expr[power.value = arg1] >> +				*('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)])) +			; +			 +			term = +				power[term.value = arg1] >> +				*(('*' >> assert_syntax(power[term.value *= arg1])) | +				  ('/' >> assert_syntax(power[term.value /= arg1])) | +				  ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)])) +				) +			; +			 +			expression = +				assert_syntax(term[expression.value = arg1]) >> +				*(('+' >> assert_syntax(term[expression.value += arg1])) | +				  ('-' >> assert_syntax(term[expression.value -= arg1])) +				) +			; + +			statement = +				!ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) +			; +		} +	}; +	 +private: +	// Member functions for semantic actions +	F32	lookup(const std::string::iterator&, const std::string::iterator&) const; +	F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } +	F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } +	 +	bool checkNaN(const F32& a) const { return !llisnan(a); } +	 +	//FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz +	F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } +	F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } +	F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } +	F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); } +	F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); } +	F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); } +	F32 _sqrt(const F32& a) const { return sqrt(a); } +	F32 _log(const F32& a) const { return log(a); } +	F32 _exp(const F32& a) const { return exp(a); } +	F32 _fabs(const F32& a) const { return fabs(a); } +	F32 _floor(const F32& a) const { return llfloor(a); } +	F32 _ceil(const F32& a) const { return llceil(a); } + +	F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + + + +	LLCalc::calc_map_t* mConstants; +	LLCalc::calc_map_t* mVariables; +//	LLCalc::calc_map_t* mUserVariables; +	 +	F32&		mResult; +}; + +#endif // LL_CALCPARSER_H diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2893e746e9..2893e746e9 100644..100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 9886d49ccc..22edd9dad8 100644 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -124,14 +124,19 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):              # Suppress error output as well              pass +class Server(HTTPServer): +    # This pernicious flag is on by default in HTTPServer. But proper +    # operation of freeport() absolutely depends on it being off. +    allow_reuse_address = False +  if __name__ == "__main__": -    # Instantiate an HTTPServer(TestHTTPRequestHandler) on the first free port +    # Instantiate a Server(TestHTTPRequestHandler) on the first free port      # in the specified port range. Doing this inline is better than in a      # daemon thread: if it blows up here, we'll get a traceback. If it blew up      # in some other thread, the traceback would get eaten and we'd run the      # subject test program anyway.      httpd, port = freeport(xrange(8000, 8020), -                           lambda port: HTTPServer(('127.0.0.1', port), TestHTTPRequestHandler)) +                           lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler))      # Pass the selected port number to the subject test program via the      # environment. We don't want to impose requirements on the test program's      # command-line parsing -- and anyway, for C++ integration tests, that's diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index f329ec2a0e..f2c841532a 100644 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -27,6 +27,8 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA  $/LicenseInfo$  """ +from __future__ import with_statement +  import os  import sys  import re @@ -79,9 +81,14 @@ def freeport(portlist, expr):      Example: +    class Server(HTTPServer): +        # If you use BaseHTTPServer.HTTPServer, turning off this flag is +        # essential for proper operation of freeport()! +        allow_reuse_address = False +    # ...      server, port = freeport(xrange(8000, 8010), -                            lambda port: HTTPServer(("localhost", port), -                                                    MyRequestHandler)) +                            lambda port: Server(("localhost", port), +                                                MyRequestHandler))      # pass 'port' to client code      # call server.serve_forever()      """ @@ -164,3 +171,92 @@ def run(*args, **kwds):      rc = os.spawnv(os.P_WAIT, args[0], args)      debug("%s returned %s", args[0], rc)      return rc + +# **************************************************************************** +#   test code -- manual at this point, see SWAT-564 +# **************************************************************************** +def test_freeport(): +    # ------------------------------- Helpers -------------------------------- +    from contextlib import contextmanager +    # helper Context Manager for expecting an exception +    # with exc(SomeError): +    #     raise SomeError() +    # raises AssertionError otherwise. +    @contextmanager +    def exc(exception_class, *args): +        try: +            yield +        except exception_class, err: +            for i, expected_arg in enumerate(args): +                assert expected_arg == err.args[i], \ +                       "Raised %s, but args[%s] is %r instead of %r" % \ +                       (err.__class__.__name__, i, err.args[i], expected_arg) +            print "Caught expected exception %s(%s)" % \ +                  (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)) +        else: +            assert False, "Failed to raise " + exception_class.__class__.__name__ + +    # helper to raise specified exception +    def raiser(exception): +        raise exception + +    # the usual +    def assert_equals(a, b): +        assert a == b, "%r != %r" % (a, b) + +    # ------------------------ Sanity check the above ------------------------ +    class SomeError(Exception): pass +    # Without extra args, accept any err.args value +    with exc(SomeError): +        raiser(SomeError("abc")) +    # With extra args, accept only the specified value +    with exc(SomeError, "abc"): +        raiser(SomeError("abc")) +    with exc(AssertionError): +        with exc(SomeError, "abc"): +            raiser(SomeError("def")) +    with exc(AssertionError): +        with exc(socket.error, errno.EADDRINUSE): +            raiser(socket.error(errno.ECONNREFUSED, 'Connection refused')) + +    # ----------- freeport() without engaging socket functionality ----------- +    # If portlist is empty, freeport() raises StopIteration. +    with exc(StopIteration): +        freeport([], None) + +    assert_equals(freeport([17], str), ("17", 17)) + +    # This is the magic exception that should prompt us to retry +    inuse = socket.error(errno.EADDRINUSE, 'Address already in use') +    # Get the iterator to our ports list so we can check later if we've used all +    ports = iter(xrange(5)) +    with exc(socket.error, errno.EADDRINUSE): +        freeport(ports, lambda port: raiser(inuse)) +    # did we entirely exhaust 'ports'? +    with exc(StopIteration): +        ports.next() + +    ports = iter(xrange(2)) +    # Any exception but EADDRINUSE should quit immediately +    with exc(SomeError): +        freeport(ports, lambda port: raiser(SomeError())) +    assert_equals(ports.next(), 1) + +    # ----------- freeport() with platform-dependent socket stuff ------------ +    # This is what we should've had unit tests to begin with (see CHOP-661). +    def newbind(port): +        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +        sock.bind(('127.0.0.1', port)) +        return sock + +    bound0, port0 = freeport(xrange(7777, 7780), newbind) +    assert_equals(port0, 7777) +    bound1, port1 = freeport(xrange(7777, 7780), newbind) +    assert_equals(port1, 7778) +    bound2, port2 = freeport(xrange(7777, 7780), newbind) +    assert_equals(port2, 7779) +    with exc(socket.error, errno.EADDRINUSE): +        bound3, port3 = freeport(xrange(7777, 7780), newbind) + +if __name__ == "__main__": +    test_freeport() diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 123997e5e9..06fbc0f234 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -37,6 +37,7 @@  #include "llgl.h"  #include "lltimer.h" +#include "llcalc.h"  //#include "llclipboard.h"  #include "llcontrol.h"  #include "llbutton.h" @@ -133,6 +134,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)  	mIgnoreTab( p.ignore_tab ),  	mDrawAsterixes( p.is_password ),  	mSelectAllonFocusReceived( p.select_on_focus ), +	mSelectAllonCommit( TRUE ),  	mPassDelete(FALSE),  	mReadOnly(FALSE),  	mBgImage( p.background_image ), @@ -230,7 +232,10 @@ void LLLineEditor::onCommit()  	setControlValue(getValue());  	LLUICtrl::onCommit(); -	selectAll(); + +	// Selection on commit needs to be turned off when evaluating maths +	// expressions, to allow indication of the error position +	if (mSelectAllonCommit) selectAll();  }  // Returns TRUE if user changed value at all @@ -2072,6 +2077,32 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)  	return success;  } +BOOL LLLineEditor::evaluateFloat() +{ +	bool success; +	F32 result = 0.f; +	std::string expr = getText(); +	LLStringUtil::toUpper(expr); + +	success = LLCalc::getInstance()->evalString(expr, result); + +	if (!success) +	{ +		// Move the cursor to near the error on failure +		setCursor(LLCalc::getInstance()->getLastErrorPos()); +		// *TODO: Translated error message indicating the type of error? Select error text? +	} +	else +	{ +		// Replace the expression with the result +		std::string result_str = llformat("%f",result); +		setText(result_str); +		selectAll(); +	} + +	return success; +} +  void LLLineEditor::onMouseCaptureLost()  {  	endSelection(); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 4b77708590..583bde360a 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -221,6 +221,7 @@ public:  	void			deleteSelection();  	void			setSelectAllonFocusReceived(BOOL b); +	void			setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; }  	typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t;  	void			setKeystrokeCallback(callback_t callback, void* user_data); @@ -241,6 +242,7 @@ public:  	static BOOL		postvalidateFloat(const std::string &str);  	bool			prevalidateInput(const LLWString& wstr); +	BOOL			evaluateFloat();  	// line history support:  	void			setEnableLineHistory( BOOL enabled ) { mHaveHistory = enabled; } // switches line history on or off  @@ -340,6 +342,7 @@ protected:  	BOOL		mDrawAsterixes;  	BOOL		mSelectAllonFocusReceived; +	BOOL		mSelectAllonCommit;  	BOOL		mPassDelete;  	BOOL		mReadOnly; diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 15a7438ec9..934879cdfd 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -44,7 +44,7 @@  #include "llresmgr.h"  #include "lluictrlfactory.h" -const U32 MAX_STRING_LENGTH = 32; +const U32 MAX_STRING_LENGTH = 255;  static LLDefaultChildRegistry::Register<LLSpinCtrl> r2("spinner"); @@ -124,14 +124,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	params.max_length.bytes(MAX_STRING_LENGTH);  	params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2))); -	if( mPrecision>0 )//should accept float numbers -	{ -		params.prevalidate_callback(&LLTextValidate::validateFloat); -	} -	else //should accept int numbers -	{ -		params.prevalidate_callback(&LLTextValidate::validateInt); -	} +	//*NOTE: allow entering of any chars for LLCalc, proper input will be evaluated on commit  	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);  	mEditor = LLUICtrlFactory::create<LLLineEditor> (params); @@ -140,6 +133,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	// than when it doesn't.  Instead, if you always have to double click to select all the text,   	// it's easier to understand  	//mEditor->setSelectAllonFocusReceived(TRUE); +	mEditor->setSelectAllonCommit(FALSE);  	addChild(mEditor);  	updateEditor(); @@ -304,9 +298,10 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )  {  	BOOL success = FALSE; -	std::string text = mEditor->getText(); -	if( LLLineEditor::postvalidateFloat( text ) ) +	if( mEditor->evaluateFloat() )  	{ +		std::string text = mEditor->getText(); +  		LLLocale locale(LLLocale::USER_LOCALE);  		F32 val = (F32) atof(text.c_str()); @@ -327,7 +322,11 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )  	}  	updateEditor(); -	if( !success ) +	if( success ) +	{ +		updateEditor(); +	} +	else  	{  		reportInvalidData();		  	} diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1d9519d675..80ac385e3b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -56,6 +56,7 @@  #include "llallocator.h"  #include "llares.h"   #include "llcurl.h" +#include "llcalc.h"  #include "lltexturestats.h"  #include "lltexturestats.h"  #include "llviewerwindow.h" @@ -1543,7 +1544,9 @@ bool LLAppViewer::cleanup()  	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.  	LLWorldMap::getInstance()->reset(); // release any images -	 + +	LLCalc::cleanUp(); +  	llinfos << "Global stuff deleted" << llendflush;  	if (gAudiop) diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index a05cbc64fb..966f5b941e 100755 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -458,7 +458,7 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)  	std::string result = content["state"];  	LLUUID new_id = content["new_asset"]; -	llinfos << "result: " << result << "new_id:" << new_id << llendl; +	llinfos << "result: " << result << " new_id: " << new_id << llendl;  	if (result == "complete"  		&& mBakedUploadData != NULL)  	{	// Invoke  diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 70871b62e2..381b919c4a 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -112,6 +112,7 @@ private:  struct LLBakedUploadData;  class LLSendTexLayerResponder : public LLAssetUploadResponder  { +	LOG_CLASS(LLSendTexLayerResponder);  public:  	LLSendTexLayerResponder(const LLSD& post_data,  							const LLUUID& vfile_id, diff --git a/indra/newview/llfloaterdeleteenvpreset.cpp b/indra/newview/llfloaterdeleteenvpreset.cpp index 4fefd2242a..d08aa81cfe 100644 --- a/indra/newview/llfloaterdeleteenvpreset.cpp +++ b/indra/newview/llfloaterdeleteenvpreset.cpp @@ -258,7 +258,7 @@ void LLFloaterDeleteEnvPreset::populateDayCyclesList()  void LLFloaterDeleteEnvPreset::postPopulate()  {  	// Handle empty list and empty selection. -	bool has_selection = mPresetCombo->getItemCount() > 1 && mPresetCombo->getSelectedValue().isDefined(); +	bool has_selection = mPresetCombo->getItemCount() > 0 && mPresetCombo->getSelectedValue().isDefined();  	if (!has_selection)  	{ diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 07c0878877..bedc7ef704 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -317,11 +317,8 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)  // static  void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)  { -	LL_DEBUGS("Windlight") << "Processing region info" << LL_ENDL; -  	LLPanel* panel;  	LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); -	llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl;  	if(!floater)  	{  		return; @@ -330,6 +327,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)  	// We need to re-request environment setting here,  	// otherwise after we apply (send) updated region settings we won't get them back,  	// so our environment won't be updated. +	// This is also the way to know about externally changed region environment.  	LLEnvManagerNew::instance().requestRegionSettings();  	LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); @@ -3249,29 +3247,30 @@ void LLPanelEnvironmentInfo::setDirty(bool dirty)  	getChildView("cancel_btn")->setEnabled(dirty);  } -void LLPanelEnvironmentInfo::sendRegionSunUpdate(F32 sun_angle) +void LLPanelEnvironmentInfo::sendRegionSunUpdate()  {  	LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); -	bool region_use_fixed_sky = sun_angle >= 0.f; -	// Set sun hour. +	// If the region is being switched to fixed sky, +	// change the region's sun hour according to the (fixed) sun position. +	// This is needed for llGetSunDirection() LSL function to work properly (STORM-1330). +	const LLSD& sky_map = mNewRegionSettings.getSkyMap(); +	bool region_use_fixed_sky = sky_map.size() == 1;  	if (region_use_fixed_sky)  	{  		LLWLParamSet param_set; -		LLSD params; -		std::string unused; -		if (!getSelectedSkyParams(params, unused)) -		{ -			return; -		} -		param_set.setAll(params); +		llassert(sky_map.isMap()); +		param_set.setAll(sky_map.beginMap()->second); +		F32 sun_angle = param_set.getSunAngle(); +		LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;  		// convert value range from 0..2pi to 6..30  		region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f;  	}  	region_info.setUseFixedSun(region_use_fixed_sky);  	region_info.mUseEstateSun = !region_use_fixed_sky; +	LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;  	region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());  } @@ -3555,7 +3554,6 @@ void LLPanelEnvironmentInfo::onBtnApply()  	LLSD day_cycle;  	LLSD sky_map;  	LLSD water_params; -	F32 sun_angle = -1.f; // invalid value meaning no fixed sky  	if (use_defaults)  	{ @@ -3588,9 +3586,6 @@ void LLPanelEnvironmentInfo::onBtnApply()  			param_set.setAll(params);  			refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here  			sky_map = LLWLParamManager::createSkyMap(refs); - -			// Remember the sun angle to set fixed region sun hour below. -			sun_angle = param_set.getSunAngle();  		}  		else // use day cycle  		{ @@ -3611,16 +3606,6 @@ void LLPanelEnvironmentInfo::onBtnApply()  				LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL;  				day_cycle[0][0] = 0.0f;  			} - -			// If the day cycle contains exactly one preset (i.e it's effectively a fixed sky), -			// remember the preset's sun angle to set fixed region sun hour below. -			if (sky_map.size() == 1) -			{ -				LLWLParamSet param_set; -				llassert(sky_map.isMap()); -				param_set.setAll(sky_map.beginMap()->second); -				sun_angle = param_set.getSunAngle(); -			}  		}  		// Get water params. @@ -3640,8 +3625,9 @@ void LLPanelEnvironmentInfo::onBtnApply()  		return;  	} -	// Set the region sun phase/flags according to the chosen new preferences. -	sendRegionSunUpdate(sun_angle); +	// When the settings get applied, we'll also send the region sun position update. +	// To determine the sun angle we're going to need the new settings. +	mNewRegionSettings = new_region_settings;  	// Start spinning the progress indicator.  	setApplyProgress(true); @@ -3672,10 +3658,18 @@ void LLPanelEnvironmentInfo::onRegionSettingschange()  void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok)  { -	LL_DEBUGS("Windlight") << "Applying region settings finished, stopping indicator" << LL_ENDL;  	// If applying new settings has failed, stop the indicator right away.  	// Otherwise it will be stopped when we receive the updated settings from server. -	if (!ok) +	if (ok) +	{ +		// Set the region sun phase/flags according to the chosen new preferences. +		// +		// If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481). +		// That is caused by the simulator re-sending the region info, which in turn makes us +		// re-request and display old region environment settings while the new ones haven't been applied yet. +		sendRegionSunUpdate(); +	} +	else  	{  		setApplyProgress(false); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 4809937324..e7917c382c 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -34,6 +34,8 @@  #include "llhost.h"  #include "llpanel.h" +#include "llenvmanager.h" // for LLEnvironmentSettings +  class LLAvatarName;  class LLDispatcher;  class LLLineEditor; @@ -431,7 +433,7 @@ private:  	void setApplyProgress(bool started);  	void setDirty(bool dirty); -	void sendRegionSunUpdate(F32 sun_angle); +	void sendRegionSunUpdate();  	void populateWaterPresetsList();  	void populateSkyPresetsList(); @@ -454,6 +456,9 @@ private:  	void onRegionSettingschange();  	void onRegionSettingsApplied(bool ok); +	/// New environment settings that are being applied to the region. +	LLEnvironmentSettings	mNewRegionSettings; +  	bool			mEnableEditing;  	LLRadioGroup*	mRegionSettingsRadioGroup; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 93a6a2a078..78e2716be2 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -49,6 +49,7 @@  #include "llthread.h"  #include "llvfile.h"  #include "llviewercontrol.h" +#include "llviewerinventory.h"  #include "llviewermenufile.h"  #include "llviewerobjectlist.h"  #include "llviewerregion.h" @@ -1301,6 +1302,7 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  	LLSD res;  	result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); +	result["texture_folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);  	result["asset_type"] = "mesh";  	result["inventory_type"] = "object";  	result["description"] = "(No Description)"; @@ -2220,6 +2222,38 @@ void LLMeshRepository::notifyLoadedMeshes()  			LLAssetType::EType asset_type = LLAssetType::lookup(data.mPostData["asset_type"].asString());  			LLInventoryType::EType inventory_type = LLInventoryType::lookup(data.mPostData["inventory_type"].asString()); +			// Handle addition of texture, if any. +			if ( data.mResponse.has("new_texture_folder_id") ) +			{ +				const LLUUID& folder_id = data.mResponse["new_texture_folder_id"].asUUID(); + +				if ( folder_id.notNull() ) +				{ +					LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); + +					std::string name; +					// Check if the server built a different name for the texture folder +					if ( data.mResponse.has("new_texture_folder_name") ) +					{ +						name = data.mResponse["new_texture_folder_name"].asString(); +					} +					else +					{ +						name = data.mPostData["name"].asString(); +					} + +					// Add the category to the internal representation +					LLPointer<LLViewerInventoryCategory> cat =  +						new LLViewerInventoryCategory(folder_id, parent_id,  +							LLFolderType::FT_NONE, name, gAgent.getID()); +					cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); + +					LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); +					gInventory.accountForUpdate(update); +					gInventory.updateCategory(cat); +				} +			} +  			on_new_single_inventory_upload_complete(  				asset_type,  				inventory_type, @@ -2229,6 +2263,7 @@ void LLMeshRepository::notifyLoadedMeshes()  				data.mPostData["description"],  				data.mResponse,  				data.mResponse["upload_price"]); +			//}  			mInventoryQ.pop();  		} diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 07c7f35989..a4f6921f98 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -30,6 +30,7 @@  #include "llpanelface.h"  // library includes +#include "llcalc.h"  #include "llerror.h"  #include "llfocusmgr.h"  #include "llrect.h" @@ -926,6 +927,16 @@ void LLPanelFace::getState()  				getChildView("button apply")->setEnabled(enabled);  			}  		} + +		// Set variable values for numeric expressions +		LLCalc* calcp = LLCalc::getInstance(); +		calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal()); +		calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal()); +		calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal()); +		calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal()); +		calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal()); +		calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal()); +		calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());  	}  	else  	{ @@ -961,6 +972,16 @@ void LLPanelFace::getState()  		//getChildView("has media")->setEnabled(FALSE);  		//getChildView("media info set")->setEnabled(FALSE); + +		// Set variable values for numeric expressions +		LLCalc* calcp = LLCalc::getInstance(); +		calcp->clearVar(LLCalc::TEX_U_SCALE); +		calcp->clearVar(LLCalc::TEX_V_SCALE); +		calcp->clearVar(LLCalc::TEX_U_OFFSET); +		calcp->clearVar(LLCalc::TEX_V_OFFSET); +		calcp->clearVar(LLCalc::TEX_ROTATION); +		calcp->clearVar(LLCalc::TEX_TRANSPARENCY); +		calcp->clearVar(LLCalc::TEX_GLOW);		  	}  } diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 52917ff20b..c222bbb191 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -41,6 +41,7 @@  // project includes  #include "llagent.h"  #include "llbutton.h" +#include "llcalc.h"  #include "llcheckboxctrl.h"  #include "llcolorswatch.h"  #include "llcombobox.h" @@ -318,6 +319,8 @@ void LLPanelObject::getState( )  		}  	} +	LLCalc* calcp = LLCalc::getInstance(); +  	LLVOVolume *volobjp = NULL;  	if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))  	{ @@ -334,6 +337,7 @@ void LLPanelObject::getState( )  		// Disable all text input fields  		clearCtrls(); +		calcp->clearAllVariables();  		return;  	} @@ -360,12 +364,18 @@ void LLPanelObject::getState( )  		mCtrlPosX->set( vec.mV[VX] );  		mCtrlPosY->set( vec.mV[VY] );  		mCtrlPosZ->set( vec.mV[VZ] ); +		calcp->setVar(LLCalc::X_POS, vec.mV[VX]); +		calcp->setVar(LLCalc::Y_POS, vec.mV[VY]); +		calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]);  	}  	else  	{  		mCtrlPosX->clear();  		mCtrlPosY->clear();  		mCtrlPosZ->clear(); +		calcp->clearVar(LLCalc::X_POS); +		calcp->clearVar(LLCalc::Y_POS); +		calcp->clearVar(LLCalc::Z_POS);  	} @@ -380,12 +390,18 @@ void LLPanelObject::getState( )  		mCtrlScaleX->set( vec.mV[VX] );  		mCtrlScaleY->set( vec.mV[VY] );  		mCtrlScaleZ->set( vec.mV[VZ] ); +		calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]); +		calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]); +		calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]);  	}  	else  	{  		mCtrlScaleX->clear();  		mCtrlScaleY->clear();  		mCtrlScaleZ->clear(); +		calcp->setVar(LLCalc::X_SCALE, 0.f); +		calcp->setVar(LLCalc::Y_SCALE, 0.f); +		calcp->setVar(LLCalc::Z_SCALE, 0.f);  	}  	mLabelSize->setEnabled( enable_scale ); @@ -405,12 +421,18 @@ void LLPanelObject::getState( )  		mCtrlRotX->set( mCurEulerDegrees.mV[VX] );  		mCtrlRotY->set( mCurEulerDegrees.mV[VY] );  		mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] ); +		calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]); +		calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]); +		calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]);  	}  	else  	{  		mCtrlRotX->clear();  		mCtrlRotY->clear();  		mCtrlRotZ->clear(); +		calcp->clearVar(LLCalc::X_ROT); +		calcp->clearVar(LLCalc::Y_ROT); +		calcp->clearVar(LLCalc::Z_ROT);  	}  	mLabelRotation->setEnabled( enable_rotate ); @@ -625,9 +647,9 @@ void LLPanelObject::getState( )  		F32 end_t	= volume_params.getEndT();  		// Hollowness -		F32 hollow = volume_params.getHollow(); -		mSpinHollow->set( 100.f * hollow ); - +		F32 hollow = 100.f * volume_params.getHollow(); +		mSpinHollow->set( hollow ); +		calcp->setVar(LLCalc::HOLLOW, hollow);  		// All hollow objects allow a shape to be selected.  		if (hollow > 0.f)  		{ @@ -679,6 +701,10 @@ void LLPanelObject::getState( )  		mSpinCutEnd		->set( cut_end );  		mCtrlPathBegin	->set( adv_cut_begin );  		mCtrlPathEnd	->set( adv_cut_end ); +		calcp->setVar(LLCalc::CUT_BEGIN, cut_begin); +		calcp->setVar(LLCalc::CUT_END, cut_end); +		calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin); +		calcp->setVar(LLCalc::PATH_END, adv_cut_end);  		// Twist  		F32 twist		= volume_params.getTwist(); @@ -697,18 +723,24 @@ void LLPanelObject::getState( )  		mSpinTwist		->set( twist );  		mSpinTwistBegin	->set( twist_begin ); +		calcp->setVar(LLCalc::TWIST_END, twist); +		calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin);  		// Shear  		F32 shear_x = volume_params.getShearX();  		F32 shear_y = volume_params.getShearY();  		mSpinShearX->set( shear_x );  		mSpinShearY->set( shear_y ); +		calcp->setVar(LLCalc::X_SHEAR, shear_x); +		calcp->setVar(LLCalc::Y_SHEAR, shear_y);  		// Taper  		F32 taper_x	= volume_params.getTaperX();  		F32 taper_y = volume_params.getTaperY();  		mSpinTaperX->set( taper_x );  		mSpinTaperY->set( taper_y ); +		calcp->setVar(LLCalc::X_TAPER, taper_x); +		calcp->setVar(LLCalc::Y_TAPER, taper_y);  		// Radius offset.  		F32 radius_offset = volume_params.getRadiusOffset(); @@ -738,10 +770,12 @@ void LLPanelObject::getState( )  			}  		}  		mSpinRadiusOffset->set( radius_offset); +		calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset);  		// Revolutions  		F32 revolutions = volume_params.getRevolutions();  		mSpinRevolutions->set( revolutions ); +		calcp->setVar(LLCalc::REVOLUTIONS, revolutions);  		// Skew  		F32 skew	= volume_params.getSkew(); @@ -766,6 +800,7 @@ void LLPanelObject::getState( )  			}  		}  		mSpinSkew->set( skew ); +		calcp->setVar(LLCalc::SKEW, skew);  	}  	// Compute control visibility, label names, and twist range. @@ -869,6 +904,8 @@ void LLPanelObject::getState( )  	case MI_RING:  		mSpinScaleX->set( scale_x );  		mSpinScaleY->set( scale_y ); +		calcp->setVar(LLCalc::X_HOLE, scale_x); +		calcp->setVar(LLCalc::Y_HOLE, scale_y);  		mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);  		mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);  		mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE); @@ -883,6 +920,14 @@ void LLPanelObject::getState( )  			mSpinScaleX->setMaxValue(1.f);  			mSpinScaleY->setMinValue(-1.f);  			mSpinScaleY->setMaxValue(1.f); + +			// Torus' Hole Size is Box/Cyl/Prism's Taper +			calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x); +			calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y); + +			// Box/Cyl/Prism have no hole size +			calcp->setVar(LLCalc::X_HOLE, 0.f); +			calcp->setVar(LLCalc::Y_HOLE, 0.f);  		}  		break;  	} diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 0645fd8a54..f19b54c1d4 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -38,6 +38,8 @@  #include "llsidetray.h"  #include "llviewermenu.h"  #include "llwearableitemslist.h" +#include "llsdserialize.h" +#include "llclipboard.h"  // Context menu and Gear menu helper.  static void edit_outfit() @@ -58,6 +60,7 @@ public:  		registrar.add("Gear.Edit", boost::bind(&edit_outfit));  		registrar.add("Gear.TakeOff", boost::bind(&LLWearingGearMenu::onTakeOff, this)); +		registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing));  		enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2)); @@ -280,4 +283,25 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const  	mCOFItemsList->getSelectedUUIDs(selected_uuids);  } +void LLPanelWearing::copyToClipboard() +{ +	std::string text; +	std::vector<LLSD> data; +	mCOFItemsList->getValues(data); + +	for(std::vector<LLSD>::const_iterator iter = data.begin(); iter != data.end();) +	{ +		LLSD uuid = (*iter); +		LLViewerInventoryItem* item = gInventory.getItem(uuid); + +		iter++; +		if (item != NULL) +		{ +			// Append a newline to all but the last line +			text += iter != data.end() ? item->getName() + "\n" : item->getName(); +		} +	} + +	gClipboard.copyFromString(utf8str_to_wstring(text)); +}  // EOF diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index 157b2c4c5f..9a212b3cca 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -60,6 +60,8 @@ public:  	/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const; +	/*virtual*/ void copyToClipboard(); +  	boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb);  	bool hasItemSelected(); diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp index 6238f183c1..698c4f9bb9 100644 --- a/indra/newview/llregioninfomodel.cpp +++ b/indra/newview/llregioninfomodel.cpp @@ -157,6 +157,7 @@ void LLRegionInfoModel::update(LLMessageSystem* msg)  	// actually the "last set" sun hour, not the current sun hour. JC  	msg->getF32(_PREHASH_RegionInfo, _PREHASH_SunHour, mSunHour); +	LL_DEBUGS("Windlight Sync") << "Got region sun hour: " << mSunHour << LL_ENDL;  	// the only reasonable way to decide if we actually have any data is to  	// check to see if any of these fields have nonzero sizes diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 500c2a7b86..bd41aa64f0 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -51,6 +51,9 @@  using namespace LLVOAvatarDefines; +static const S32 BAKE_UPLOAD_ATTEMPTS = 7; +static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt +  class LLTexLayerInfo  {  	friend class LLTexLayer; @@ -93,11 +96,13 @@ private:  //-----------------------------------------------------------------------------  LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,  									 LLTexLayerSet* layerset, -									 const LLUUID& id) :  +									 const LLUUID& id, +									 bool highest_res) :  	mAvatar(avatar),  	mTexLayerSet(layerset),  	mID(id), -	mStartTime(LLFrameTimer::getTotalTime())		// Record starting time +	mStartTime(LLFrameTimer::getTotalTime()),		// Record starting time +	mIsHighestRes(highest_res)  {   } @@ -116,6 +121,7 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,  	mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates  	mNeedsUpload(FALSE),  	mNumLowresUploads(0), +	mUploadFailCount(0),  	mNeedsUpdate(TRUE),  	mNumLowresUpdates(0),  	mTexLayerSet(owner) @@ -204,6 +210,7 @@ void LLTexLayerSetBuffer::cancelUpload()  	mNeedsUpload = FALSE;  	mUploadPending = FALSE;  	mNeedsUploadTimer.pause(); +	mUploadRetryTimer.reset();  }  void LLTexLayerSetBuffer::pushProjection() const @@ -356,25 +363,38 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const  	if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.  	if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. -	// If we requested an upload and have the final LOD ready, then upload. -	if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; - -	// Upload if we've hit a timeout.  Upload is a pretty expensive process so we need to make sure -	// we aren't doing uploads too frequently. -	const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); -	if (texture_timeout != 0) +	BOOL ready = FALSE; +	if (mTexLayerSet->isLocalTextureDataFinal()) +	{ +		// If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) +		if (mUploadFailCount == 0) +		{ +			ready = TRUE; +		} +		else +		{ +			ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1)); +		} +	} +	else  	{ -		// The timeout period increases exponentially between every lowres upload in order to prevent -		// spamming the server with frequent uploads. -		const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); +		// Upload if we've hit a timeout.  Upload is a pretty expensive process so we need to make sure +		// we aren't doing uploads too frequently. +		const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); +		if (texture_timeout != 0) +		{ +			// The timeout period increases exponentially between every lowres upload in order to prevent +			// spamming the server with frequent uploads. +			const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); -		// If we hit our timeout and have textures available at even lower resolution, then upload. -		const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; -		const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); -		if (has_lower_lod && is_upload_textures_timeout) return TRUE;  +			// If we hit our timeout and have textures available at even lower resolution, then upload. +			const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; +			const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); +			ready = has_lower_lod && is_upload_textures_timeout; +		}  	} -	return FALSE; +	return ready;  }  BOOL LLTexLayerSetBuffer::isReadyToUpdate() const @@ -482,17 +502,20 @@ void LLTexLayerSetBuffer::doUpload()  			if (valid)  			{ +				const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal();  				// Baked_upload_data is owned by the responder and deleted after the request completes.  				LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,   																			 this->mTexLayerSet,  -																			 asset_id); +																			 asset_id, +																			 highest_lod);  				// upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.  				mUploadID = asset_id;  				// Upload the image  				const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");  				if(!url.empty() -					&& !LLPipeline::sForceOldBakedUpload) // toggle debug setting UploadBakedTexOld to change between the new caps method and old method +					&& !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method +					&& (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.  				{  					LLSD body = LLSD::emptyMap();  					// The responder will call LLTexLayerSetBuffer::onTextureUploadComplete() @@ -511,7 +534,6 @@ void LLTexLayerSetBuffer::doUpload()  					llinfos << "Baked texture upload via Asset Store." <<  llendl;  				} -				const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();	  				if (highest_lod)  				{  					// Sending the final LOD for the baked texture.  All done, pause  @@ -603,14 +625,15 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,  {  	LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; -	if ((result == 0) && -		isAgentAvatarValid() && +	if (isAgentAvatarValid() &&  		!gAgentAvatarp->isDead() &&  		(baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.  		(baked_upload_data->mTexLayerSet->hasComposite()))  	{  		LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); -			 +		S32 failures = layerset_buffer->mUploadFailCount; +		layerset_buffer->mUploadFailCount = 0; +  		if (layerset_buffer->mUploadID.isNull())  		{  			// The upload got canceled, we should be in the @@ -626,20 +649,28 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,  		{  			// This is the upload we're currently waiting for.  			layerset_buffer->mUploadID.setNull(); +			const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName()); +			const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";  			if (result >= 0)  			{ -				layerset_buffer->mUploadPending = FALSE; +				layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later  				LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet);  				// Update baked texture info with the new UUID  				U64 now = LLFrameTimer::getTotalTime();		// Record starting time -				llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; +				llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;  				gAgentAvatarp->setNewBakedTexture(baked_te, uuid);  			}  			else  			{	 -				// Avatar appearance is changing, ignore the upload results -				llinfos << "Baked upload failed. Reason: " << result << llendl; -				// *FIX: retry upload after n seconds, asset server could be busy +				++failures; +				S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes +				llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl; +				if (failures < max_attempts) +				{ +					layerset_buffer->mUploadFailCount = failures; +					layerset_buffer->mUploadRetryTimer.start(); +					layerset_buffer->requestUpload(); +				}  			}  		}  		else diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 2d710d2dce..85dadb213c 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -312,6 +312,8 @@ private:  	BOOL					mUploadPending; 				// Whether we have received back the new baked textures  	LLUUID					mUploadID; 						// The current upload process (null if none).  	LLFrameTimer    		mNeedsUploadTimer; 				// Tracks time since upload was requested and performed. +	S32						mUploadFailCount;				// Number of consecutive upload failures +	LLFrameTimer    		mUploadRetryTimer; 				// Tracks time since last upload failure.  	//--------------------------------------------------------------------  	// Updates @@ -363,12 +365,14 @@ struct LLBakedUploadData  {  	LLBakedUploadData(const LLVOAvatarSelf* avatar,   					  LLTexLayerSet* layerset,  -					  const LLUUID& id); +					  const LLUUID& id, +					  bool highest_res);  	~LLBakedUploadData() {}  	const LLUUID				mID;  	const LLVOAvatarSelf*		mAvatar; // note: backlink only; don't LLPointer   	LLTexLayerSet*				mTexLayerSet;     	const U64					mStartTime;	// for measuring baked texture upload time +   	const bool					mIsHighestRes; // whether this is a "final" bake, or intermediate low res  };  #endif  // LL_LLTEXLAYER_H diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 44b3a85f25..e934c38c22 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4346,8 +4346,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)  	LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec); -	LL_DEBUGS("Windlight Sync") << "time_synch() - " << sun_direction << ", " << sun_ang_velocity -		<< ", " << phase << LL_ENDL; +	LL_DEBUGS("Windlight Sync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL;  	gSky.setSunPhase(phase);  	gSky.setSunTargetDirection(sun_direction, sun_ang_velocity); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 9c6c62053b..5b7492b66f 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -661,6 +661,7 @@ void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)  {  	// send it to 'observers'  	// *TODO: switch the floaters to using LLRegionInfoModel +	llinfos << "Processing region info" << llendl;  	LLRegionInfoModel::instance().update(msg);  	LLFloaterGodTools::processRegionInfo(msg);  	LLFloaterRegionInfo::processRegionInfo(msg); diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml index 68b861fe92..b5d8ac44bc 100644 --- a/indra/newview/skins/default/xui/da/strings.xml +++ b/indra/newview/skins/default/xui/da/strings.xml @@ -1209,9 +1209,6 @@ Prøv venligst om lidt igen.  	<string name="InvFolder My Inventory">  		Min beholdning  	</string> -	<string name="InvFolder My Favorites"> -		Mine favoritter -	</string>  	<string name="InvFolder Library">  		Bibliotek  	</string> @@ -1270,10 +1267,10 @@ Prøv venligst om lidt igen.  		Bevægelser  	</string>  	<string name="InvFolder Favorite"> -		Favoritter +		Mine favoritter  	</string>  	<string name="InvFolder favorite"> -		Favoritter +		Mine favoritter  	</string>  	<string name="InvFolder Current Outfit">  		Nuværende sæt diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index d77b4a1e44..ed38267466 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1238,9 +1238,6 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.  	<string name="InvFolder My Inventory">  		Mein Inventar  	</string> -	<string name="InvFolder My Favorites"> -		Meine Favoriten -	</string>  	<string name="InvFolder Library">  		Bibliothek  	</string> @@ -1299,10 +1296,10 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.  		Gesten  	</string>  	<string name="InvFolder Favorite"> -		Favoriten +		Meine Favoriten  	</string>  	<string name="InvFolder favorite"> -		Favoriten +		Meine Favoriten  	</string>  	<string name="InvFolder Current Outfit">  		Aktuelles Outfit diff --git a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml index 0ac2c14253..0e858ccf10 100644 --- a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml @@ -20,4 +20,11 @@           function="Gear.OnEnable"           parameter="take_off" />      </menu_item_call> +    <menu_item_call +     label="Copy outfit list to clipboard" +     layout="topleft" +     name="copy"> +        <on_click +         function="Gear.Copy" /> +    </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2e2ef6ee19..022c97f341 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2069,7 +2069,6 @@ Returns a string with the requested data about the region  	<!-- inventory folder -->  	<string name="InvFolder My Inventory">My Inventory</string> -	<string name="InvFolder My Favorites">My Favorites</string>  	<string name="InvFolder Library">Library</string>  	<string name="InvFolder Textures">Textures</string>  	<string name="InvFolder Sounds">Sounds</string> @@ -2089,10 +2088,10 @@ Returns a string with the requested data about the region  	<string name="InvFolder Uncompressed Sounds">Uncompressed Sounds</string>  	<string name="InvFolder Animations">Animations</string>  	<string name="InvFolder Gestures">Gestures</string> -	<string name="InvFolder Favorite">Favorites</string> +	<string name="InvFolder Favorite">My Favorites</string>    <!-- historically default name of the Favorites folder can start from either "f" or "F" letter.    We should localize both of them with the same value --> -	<string name="InvFolder favorite">Favorites</string> +	<string name="InvFolder favorite">My Favorites</string>  	<string name="InvFolder Current Outfit">Current Outfit</string>  	<string name="InvFolder Initial Outfits">Initial Outfits</string>  	<string name="InvFolder My Outfits">My Outfits</string> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index b759eed738..72d7493a02 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -1211,9 +1211,6 @@ Intenta iniciar sesión de nuevo en unos instantes.  	<string name="InvFolder My Inventory">  		Mi Inventario  	</string> -	<string name="InvFolder My Favorites"> -		Mis Favoritos -	</string>  	<string name="InvFolder Library">  		Biblioteca  	</string> @@ -1272,10 +1269,10 @@ Intenta iniciar sesión de nuevo en unos instantes.  		Gestos  	</string>  	<string name="InvFolder Favorite"> -		Favoritos +		Mis Favoritos  	</string>  	<string name="InvFolder favorite"> -		Favoritos +		Mis Favoritos  	</string>  	<string name="InvFolder Current Outfit">  		Vestuario actual diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 3ec85551da..077e545851 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1238,9 +1238,6 @@ Veuillez réessayer de vous connecter dans une minute.  	<string name="InvFolder My Inventory">  		Mon inventaire  	</string> -	<string name="InvFolder My Favorites"> -		Mes Favoris -	</string>  	<string name="InvFolder Library">  		Bibliothèque  	</string> @@ -1299,10 +1296,10 @@ Veuillez réessayer de vous connecter dans une minute.  		Gestes  	</string>  	<string name="InvFolder Favorite"> -		Favoris +		Mes Favoris  	</string>  	<string name="InvFolder favorite"> -		Favoris +		Mes Favoris  	</string>  	<string name="InvFolder Current Outfit">  		Tenue actuelle diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index cbe8ef24c4..6af515d82d 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -1217,9 +1217,6 @@ Prova ad accedere nuovamente tra un minuto.  	<string name="InvFolder My Inventory">  		Il mio inventario  	</string> -	<string name="InvFolder My Favorites"> -		I miei preferiti -	</string>  	<string name="InvFolder Library">  		Libreria  	</string> @@ -1278,10 +1275,10 @@ Prova ad accedere nuovamente tra un minuto.  		Gesture  	</string>  	<string name="InvFolder Favorite"> -		Preferiti +		I miei preferiti  	</string>  	<string name="InvFolder favorite"> -		Preferiti +		I miei preferiti  	</string>  	<string name="InvFolder Current Outfit">  		Abbigliamento attuale diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index ff22221aab..fa6d25d238 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -1238,9 +1238,6 @@ support@secondlife.com にお問い合わせください。  	<string name="InvFolder My Inventory">  		持ち物  	</string> -	<string name="InvFolder My Favorites"> -		お気に入り -	</string>  	<string name="InvFolder Library">  		ライブラリ  	</string> diff --git a/indra/newview/skins/default/xui/nl/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml index a53c0769dc..e9db237e82 100644 --- a/indra/newview/skins/default/xui/nl/strings.xml +++ b/indra/newview/skins/default/xui/nl/strings.xml @@ -849,9 +849,6 @@  	<string name="InvFolder My Inventory">  		Mijn Inventaris  	</string> -	<string name="InvFolder My Favorites"> -		Mijn Favorieten -	</string>  	<string name="InvFolder Library">  		Bibliotheek  	</string> @@ -910,10 +907,10 @@  		Gebaren  	</string>  	<string name="InvFolder Favorite"> -		Favoriten +		Mijn Favorieten  	</string>  	<string name="InvFolder favorite"> -		Favoriten +		Mijn Favorieten  	</string>  	<string name="InvFolder Current Outfit">  		Huidige Uitrusting diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index 6eceed46d3..e93da48dc0 100644 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -1072,9 +1072,6 @@  	<string name="InvFolder My Inventory">  		Moja Szafa  	</string> -	<string name="InvFolder My Favorites"> -		Moje ulubione -	</string>  	<string name="InvFolder Library">  		Biblioteka  	</string> @@ -1133,10 +1130,10 @@  		Gesturki  	</string>  	<string name="InvFolder Favorite"> -		Ulubione +		Moje ulubione  	</string>  	<string name="InvFolder favorite"> -		Ulubione +		Moje ulubione  	</string>  	<string name="InvFolder Current Outfit">  		Obecny strój diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index c5268966c1..ed93217d59 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -1172,9 +1172,6 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar  	<string name="InvFolder My Inventory">  		Meu inventário  	</string> -	<string name="InvFolder My Favorites"> -		Meus favoritos -	</string>  	<string name="InvFolder Library">  		Biblioteca  	</string> @@ -1233,10 +1230,10 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar  		Gestos  	</string>  	<string name="InvFolder Favorite"> -		Favoritos +		Meus favoritos  	</string>  	<string name="InvFolder favorite"> -		Favoritos +		Meus favoritos  	</string>  	<string name="InvFolder Current Outfit">  		Look atual diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index 986ab82523..28b8cce5b2 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -1099,9 +1099,6 @@  	<string name="InvFolder My Inventory">  		我的收納區  	</string> -	<string name="InvFolder My Favorites"> -		My Favorites -	</string>  	<string name="InvFolder Library">  		Library  	</string> @@ -1160,10 +1157,10 @@  		姿勢  	</string>  	<string name="InvFolder Favorite"> -		Favorites +		My Favorites  	</string>  	<string name="InvFolder favorite"> -		Favorites +		My Favorites  	</string>  	<string name="InvFolder Current Outfit">  		目前裝扮 | 
