diff options
582 files changed, 23072 insertions, 9432 deletions
@@ -504,3 +504,9 @@ afd8d4756e8eda3c8f760625d1c17a2ad40ad6c8 3.7.27-release d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release 67edc442c80b8d2fadd2a6c4a7184b469906cdbf 3.7.30-release 797ed69e6134ef48bb922577ab2540fb2d964668 3.8.0-release +3f61ed662347dc7c6941b8266e72746a66d90e2a 3.8.1-release +3a62616f3dd8bd512fcdfd29ef033b2505b11213 3.8.2-release +60572f718879f786f6bc8b5c9373ebebf4693078 3.8.3-release +27e3cf444c4cc645884960a61325a9ee0e9a2d0f 3.8.4-release +e821ef17c6edea4a59997719d8ba416d8c16e143 3.8.5-release +5a5bd148943bfb46cf2ff2ccf376c42dee93d19b 3.8.6-release diff --git a/doc/contributions.txt b/doc/contributions.txt index 211d4fcf08..7493e96c39 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -185,6 +185,7 @@ Ansariel Hiller BUG-3764 STORM-1984 STORM-1979 + MAINT-5533 Aralara Rajal Arare Chantilly CHUIBUG-191 diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 7a320ffc59..1a3b6c5117 100755 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -191,7 +191,7 @@ if (DARWIN) add_definitions(-DLL_DARWIN=1) set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") - set(DARWIN_extra_cstar_flags "-g") + set(DARWIN_extra_cstar_flags "-g -Wno-unused-local-typedef -Wno-deprecated-declarations") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}") # NOTE: it's critical that the optimization flag is put in front. diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 76d92d7a48..2fb47c58a7 100755 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -130,10 +130,10 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(DARWIN 1) - # now we only support Xcode 6.0 using 10.9 (Mavericks), minimum OS 10.7 (Lion) - set(XCODE_VERSION 6.0) + # now we only support Xcode 7.0 using 10.11 (El Capitan), minimum OS 10.7 (Lion) + set(XCODE_VERSION 7.0) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) - set(CMAKE_OSX_SYSROOT macosx10.9) + set(CMAKE_OSX_SYSROOT macosx10.11) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0") set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL 3) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 1459b9ada2..5863310162 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -37,6 +37,7 @@ set(llcommon_SOURCE_FILES llbase32.cpp llbase64.cpp llbitpack.cpp + llcallbacklist.cpp llcommon.cpp llcommonutils.cpp llcoros.cpp @@ -129,6 +130,7 @@ set(llcommon_HEADER_FILES llbase64.h llbitpack.h llboost.h + llcallbacklist.h llcommon.h llcommonutils.h llcoros.h diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 5a95a58d93..3a4b5dad18 100755 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -107,6 +107,9 @@ public: AT_LINK_FOLDER = 25, // Inventory folder link + AT_MARKETPLACE_FOLDER = 26, + // Marketplace folder. Same as an AT_CATEGORY but different display methods. + AT_WIDGET = 40, // UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...) diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp new file mode 100644 index 0000000000..541ff75ee4 --- /dev/null +++ b/indra/llcommon/llcallbacklist.cpp @@ -0,0 +1,230 @@ +/** + * @file llcallbacklist.cpp + * @brief A simple list of callback functions to call. + * + * $LicenseInfo:firstyear=2001&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 "llcallbacklist.h" +#include "lleventtimer.h" +#include "llerrorlegacy.h" + +// Globals +// +LLCallbackList gIdleCallbacks; + +// +// Member functions +// + +LLCallbackList::LLCallbackList() +{ + // nothing +} + +LLCallbackList::~LLCallbackList() +{ +} + + +void LLCallbackList::addFunction( callback_t func, void *data) +{ + if (!func) + { + return; + } + + // only add one callback per func/data pair + // + if (containsFunction(func)) + { + return; + } + + callback_pair_t t(func, data); + mCallbackList.push_back(t); +} + +bool LLCallbackList::containsFunction( callback_t func, void *data) +{ + callback_pair_t t(func, data); + callback_list_t::iterator iter = find(func,data); + if (iter != mCallbackList.end()) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +bool LLCallbackList::deleteFunction( callback_t func, void *data) +{ + callback_list_t::iterator iter = find(func,data); + if (iter != mCallbackList.end()) + { + mCallbackList.erase(iter); + return TRUE; + } + else + { + return FALSE; + } +} + +inline +LLCallbackList::callback_list_t::iterator +LLCallbackList::find(callback_t func, void *data) +{ + callback_pair_t t(func, data); + return std::find(mCallbackList.begin(), mCallbackList.end(), t); +} + +void LLCallbackList::deleteAllFunctions() +{ + mCallbackList.clear(); +} + + +void LLCallbackList::callFunctions() +{ + for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) + { + callback_list_t::iterator curiter = iter++; + curiter->first(curiter->second); + } +} + +// Shim class to allow arbitrary boost::bind +// expressions to be run as one-time idle callbacks. +class OnIdleCallbackOneTime +{ +public: + OnIdleCallbackOneTime(nullary_func_t callable): + mCallable(callable) + { + } + static void onIdle(void *data) + { + gIdleCallbacks.deleteFunction(onIdle, data); + OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data); + self->call(); + delete self; + } + void call() + { + mCallable(); + } +private: + nullary_func_t mCallable; +}; + +void doOnIdleOneTime(nullary_func_t callable) +{ + OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor); +} + +// Shim class to allow generic boost functions to be run as +// recurring idle callbacks. Callable should return true when done, +// false to continue getting called. +class OnIdleCallbackRepeating +{ +public: + OnIdleCallbackRepeating(bool_func_t callable): + mCallable(callable) + { + } + // Will keep getting called until the callable returns true. + static void onIdle(void *data) + { + OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data); + bool done = self->call(); + if (done) + { + gIdleCallbacks.deleteFunction(onIdle, data); + delete self; + } + } + bool call() + { + return mCallable(); + } +private: + bool_func_t mCallable; +}; + +void doOnIdleRepeating(bool_func_t callable) +{ + OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable); + gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor); +} + +class NullaryFuncEventTimer: public LLEventTimer +{ +public: + NullaryFuncEventTimer(nullary_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } + +private: + BOOL tick() + { + mCallable(); + return TRUE; + } + + nullary_func_t mCallable; +}; + +// Call a given callable once after specified interval. +void doAfterInterval(nullary_func_t callable, F32 seconds) +{ + new NullaryFuncEventTimer(callable, seconds); +} + +class BoolFuncEventTimer: public LLEventTimer +{ +public: + BoolFuncEventTimer(bool_func_t callable, F32 seconds): + LLEventTimer(seconds), + mCallable(callable) + { + } +private: + BOOL tick() + { + return mCallable(); + } + + bool_func_t mCallable; +}; + +// Call a given callable every specified number of seconds, until it returns true. +void doPeriodically(bool_func_t callable, F32 seconds) +{ + new BoolFuncEventTimer(callable, seconds); +} diff --git a/indra/newview/llcallbacklist.h b/indra/llcommon/llcallbacklist.h index 0516c9cdb4..89716cd74c 100755..100644 --- a/indra/newview/llcallbacklist.h +++ b/indra/llcommon/llcallbacklist.h @@ -28,27 +28,34 @@ #define LL_LLCALLBACKLIST_H #include "llstl.h" +#include <boost/function.hpp> +#include <list> class LLCallbackList { public: typedef void (*callback_t)(void*); + + typedef std::pair< callback_t,void* > callback_pair_t; + // NOTE: It is confirmed that we DEPEND on the order provided by using a list :( + // + typedef std::list< callback_pair_t > callback_list_t; LLCallbackList(); ~LLCallbackList(); - void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data) - BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair - BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found - void callFunctions(); // calls all functions + void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data) + bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair + bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found + void callFunctions(); // calls all functions void deleteAllFunctions(); static void test(); protected: - // Use a list so that the callbacks are ordered in case that matters - typedef std::pair<callback_t,void*> callback_pair_t; - typedef std::list<callback_pair_t > callback_list_t; + + inline callback_list_t::iterator find(callback_t func, void *data); + callback_list_t mCallbackList; }; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 2100989316..5ed348e13c 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -119,6 +119,7 @@ namespace { LL_INFOS() << "Error setting log file to " << filename << LL_ENDL; } mWantsTime = true; + mWantsTags = true; } ~RecordToFile() @@ -558,7 +559,7 @@ namespace LLError mFunctionString += std::string(mFunction) + ":"; for (size_t i = 0; i < mTagCount; i++) { - mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " "); + mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : ","); } } @@ -931,14 +932,19 @@ namespace } if (show_level && r->wantsLevel()) - { - message_stream << site.mLevelString << " "; - } + { + message_stream << site.mLevelString; + } if (show_tags && r->wantsTags()) { - message_stream << site.mTagString << " "; + message_stream << site.mTagString; } + if ((show_level && r->wantsLevel())|| + (show_tags && r->wantsTags())) + { + message_stream << " "; + } if (show_function && r->wantsFunctionName()) { diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index ae11988df8..3a8eabac09 100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -2176,8 +2176,7 @@ void* ll_aligned_malloc_fallback( size_t size, int align ) SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); - unsigned int for_alloc = sysinfo.dwPageSize; - while(for_alloc < size) for_alloc += sysinfo.dwPageSize; + unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize; void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); if(NULL == p) { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index c4c9cc0566..0fb257aab1 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llunits.h" +#include "stdtypes.h" #if !LL_WINDOWS #include <stdint.h> #endif @@ -59,7 +60,7 @@ class LLMutex ; LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); #ifdef SHOW_ASSERT -#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(uintptr_t(ptr),((U32)alignment)) #else #define ll_assert_aligned(ptr,alignment) #endif @@ -69,13 +70,13 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) { return reinterpret_cast<T*>( - (reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF); + (uintptr_t(address) + 0xF) & ~0xF); } template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) { return reinterpret_cast<T*>( - (reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F); + (uintptr_t(address) + 0x3F) & ~0x3F); } #if LL_LINUX || LL_DARWIN @@ -97,7 +98,7 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library - // change preprocessro code to: #if 1 && defined(LL_WINDOWS) + // change preprocessor code to: #if 1 && defined(LL_WINDOWS) #if 0 && defined(LL_WINDOWS) void* ll_aligned_malloc_fallback( size_t size, int align ); diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h index 3659a319a2..ea535cee86 100644 --- a/indra/llcommon/llmutex.h +++ b/indra/llcommon/llmutex.h @@ -33,6 +33,10 @@ #define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) +#if MUTEX_DEBUG +#include <map> +#endif + struct apr_thread_mutex_t; struct apr_pool_t; struct apr_thread_cond_t; diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 715df36f39..e0aa30cc1a 100755 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -738,8 +738,11 @@ LLProcess::LLProcess(const LLSDOrParams& params): { mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i))); } - LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name() - << "('" << desc << "')" << LL_ENDL; + // Removed temporaily for Xcode 7 build tests: error was: + // "error: expression with side effects will be evaluated despite + // being used as an operand to 'typeid' [-Werror,-Wpotentially-evaluated-expression]"" + //LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name() + // << "('" << desc << "')" << LL_ENDL; } } diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 02f10fa2ba..0435cb8a08 100755 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -27,6 +27,7 @@ #ifndef LL_LLSTL_H #define LL_LLSTL_H +#include "stdtypes.h" #include <functional> #include <algorithm> #include <map> @@ -272,6 +273,7 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value) } }; +// Useful for replacing the removeObj() functionality of LLDynamicArray // Example: // for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); ) // { @@ -530,7 +532,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs) return strcmp(lhs->name(), rhs->name()) < 0; #else // not Linux, or gcc 4.4+ // Just use before(), as we normally would - return lhs->before(*rhs); + return lhs->before(*rhs) ? true : false; #endif } diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index d98bc297e5..82d0dc8b4b 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -238,12 +238,12 @@ void LLUriParser::glueSecond(std::string& uri) const { uri += '?'; uri += mQuery; + } - if (mFragment.size()) - { - uri += '#'; - uri += mFragment; - } + if (mFragment.size()) + { + uri += '#'; + uri += mFragment; } } diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 16df27bb8e..08462c7834 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -40,6 +40,545 @@ #include "llimagedxt.h" #include "llmemory.h" +#include <boost/preprocessor.hpp> + +//.................................................................................. +//.................................................................................. +// Helper macrose's for generate cycle unwrap templates +//.................................................................................. +#define _UNROL_GEN_TPL_arg_0(arg) +#define _UNROL_GEN_TPL_arg_1(arg) arg + +#define _UNROL_GEN_TPL_comma_0 +#define _UNROL_GEN_TPL_comma_1 BOOST_PP_COMMA() +//.................................................................................. +#define _UNROL_GEN_TPL_ARGS_macro(z,n,seq) \ + BOOST_PP_CAT(_UNROL_GEN_TPL_arg_, BOOST_PP_MOD(n, 2))(BOOST_PP_SEQ_ELEM(n, seq)) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) + +#define _UNROL_GEN_TPL_ARGS(seq) \ + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_ARGS_macro, seq) +//.................................................................................. + +#define _UNROL_GEN_TPL_TYPE_ARGS_macro(z,n,seq) \ + BOOST_PP_SEQ_ELEM(n, seq) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) + +#define _UNROL_GEN_TPL_TYPE_ARGS(seq) \ + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_TYPE_ARGS_macro, seq) +//.................................................................................. +#define _UNROLL_GEN_TPL_foreach_ee(z, n, seq) \ + executor<n>(_UNROL_GEN_TPL_ARGS(seq)); + +#define _UNROLL_GEN_TPL(name, args_seq, operation, spec) \ + template<> struct name<spec> { \ + private: \ + template<S32 _idx> inline void executor(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ + BOOST_PP_SEQ_ENUM(operation) ; \ + } \ + public: \ + inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ + BOOST_PP_REPEAT(spec, _UNROLL_GEN_TPL_foreach_ee, args_seq) \ + } \ +}; +//.................................................................................. +#define _UNROLL_GEN_TPL_foreach_seq_macro(r, data, elem) \ + _UNROLL_GEN_TPL(BOOST_PP_SEQ_ELEM(0, data), BOOST_PP_SEQ_ELEM(1, data), BOOST_PP_SEQ_ELEM(2, data), elem) + +#define UNROLL_GEN_TPL(name, args_seq, operation, spec_seq) \ + /*general specialization - should not be implemented!*/ \ + template<U8> struct name { inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { /*static_assert(!"Should not be instantiated.");*/ } }; \ + BOOST_PP_SEQ_FOR_EACH(_UNROLL_GEN_TPL_foreach_seq_macro, (name)(args_seq)(operation), spec_seq) +//.................................................................................. +//.................................................................................. + + +//.................................................................................. +// Generated unrolling loop templates with specializations +//.................................................................................. +//example: for(c = 0; c < ch; ++c) comp[c] = cx[0] = 0; +UNROLL_GEN_TPL(uroll_zeroze_cx_comp, (S32 *)(cx)(S32 *)(comp), (cx[_idx] = comp[_idx] = 0), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] >>= 4; +UNROLL_GEN_TPL(uroll_comp_rshftasgn_constval, (S32 *)(comp)(const S32)(cval), (comp[_idx] >>= cval), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] = (cx[c] >> 5) * yap; +UNROLL_GEN_TPL(uroll_comp_asgn_cx_rshft_cval_all_mul_val, (S32 *)(comp)(S32 *)(cx)(const S32)(cval)(S32)(val), (comp[_idx] = (cx[_idx] >> cval) * val), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * Cy; +UNROLL_GEN_TPL(uroll_comp_plusasgn_cx_rshft_cval_all_mul_val, (S32 *)(comp)(S32 *)(cx)(const S32)(cval)(S32)(val), (comp[_idx] += (cx[_idx] >> cval) * val), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] += pix[c] * info.xapoints[x]; +UNROLL_GEN_TPL(uroll_inp_plusasgn_pix_mul_val, (S32 *)(comp)(const U8 *)(pix)(S32)(val), (comp[_idx] += pix[_idx] * val), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) cx[c] = pix[c] * info.xapoints[x]; +UNROLL_GEN_TPL(uroll_inp_asgn_pix_mul_val, (S32 *)(comp)(const U8 *)(pix)(S32)(val), (comp[_idx] = pix[_idx] * val), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] = ((cx[c] * info.yapoints[y]) + (comp[c] * (256 - info.yapoints[y]))) >> 16; +UNROLL_GEN_TPL(uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r, (S32 *)(comp)(S32 *)(cx)(S32)(apoint), (comp[_idx] = ((cx[_idx] * apoint) + (comp[_idx] * (256 - apoint))) >> 16), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] = (comp[c] + pix[c] * info.yapoints[y]) >> 8; +UNROLL_GEN_TPL(uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r, (S32 *)(comp)(const U8 *)(pix)(S32)(apoint), (comp[_idx] = (comp[_idx] + pix[_idx] * apoint) >> 8), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) comp[c] = ((comp[c]*(256 - info.xapoints[x])) + ((cx[c] * info.xapoints[x]))) >> 12; +UNROLL_GEN_TPL(uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r, (S32 *)(comp)(S32)(apoint)(S32 *)(cx), (comp[_idx] = ((comp[_idx] * (256-apoint)) + (cx[_idx] * apoint)) >> 12), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) *dptr++ = comp[c]&0xff; +UNROLL_GEN_TPL(uroll_uref_dptr_inc_asgn_comp_and_ff, (U8 *&)(dptr)(S32 *)(comp), (*dptr++ = comp[_idx]&0xff), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) *dptr++ = (sptr[info.xpoints[x]*ch + c])&0xff; +UNROLL_GEN_TPL(uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff, (U8 *&)(dptr)(const U8 *)(sptr)(S32)(apoint), (*dptr++ = sptr[apoint + _idx]&0xff), (1)(3)(4)); +//example: for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; +UNROLL_GEN_TPL(uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff, (U8 *&)(dptr)(S32 *)(comp)(const S32)(cval), (*dptr++ = (comp[_idx]>>cval)&0xff), (1)(3)(4)); +//.................................................................................. + + +template<U8 ch> +struct scale_info +{ +public: + std::vector<S32> xpoints; + std::vector<const U8*> ystrides; + std::vector<S32> xapoints, yapoints; + S32 xup_yup; + +public: + //unrolling loop types declaration + typedef uroll_zeroze_cx_comp<ch> uroll_zeroze_cx_comp_t; + typedef uroll_comp_rshftasgn_constval<ch> uroll_comp_rshftasgn_constval_t; + typedef uroll_comp_asgn_cx_rshft_cval_all_mul_val<ch> uroll_comp_asgn_cx_rshft_cval_all_mul_val_t; + typedef uroll_comp_plusasgn_cx_rshft_cval_all_mul_val<ch> uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t; + typedef uroll_inp_plusasgn_pix_mul_val<ch> uroll_inp_plusasgn_pix_mul_val_t; + typedef uroll_inp_asgn_pix_mul_val<ch> uroll_inp_asgn_pix_mul_val_t; + typedef uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r<ch> uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t; + typedef uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r<ch> uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t; + typedef uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r<ch> uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t; + typedef uroll_uref_dptr_inc_asgn_comp_and_ff<ch> uroll_uref_dptr_inc_asgn_comp_and_ff_t; + typedef uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff<ch> uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t; + typedef uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff<ch> uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t; + +public: + scale_info(const U8 *src, U32 srcW, U32 srcH, U32 dstW, U32 dstH, U32 srcStride) + : xup_yup((dstW >= srcW) + ((dstH >= srcH) << 1)) + { + calc_x_points(srcW, dstW); + calc_y_strides(src, srcStride, srcH, dstH); + calc_aa_points(srcW, dstW, xup_yup&1, xapoints); + calc_aa_points(srcH, dstH, xup_yup&2, yapoints); + } + +private: + //........................................................................................... + void calc_x_points(U32 srcW, U32 dstW) + { + xpoints.resize(dstW+1); + + S32 val = dstW >= srcW ? 0x8000 * srcW / dstW - 0x8000 : 0; + S32 inc = (srcW << 16) / dstW; + + for(U32 i = 0, j = 0; i < dstW; ++i, ++j, val += inc) + { + xpoints[j] = llmax(0, val >> 16); + } + } + //........................................................................................... + void calc_y_strides(const U8 *src, U32 srcStride, U32 srcH, U32 dstH) + { + ystrides.resize(dstH+1); + + S32 val = dstH >= srcH ? 0x8000 * srcH / dstH - 0x8000 : 0; + S32 inc = (srcH << 16) / dstH; + + for(U32 i = 0, j = 0; i < dstH; ++i, ++j, val += inc) + { + ystrides[j] = src + llmax(0, val >> 16) * srcStride; + } + } + //........................................................................................... + void calc_aa_points(U32 srcSz, U32 dstSz, bool scale_up, std::vector<S32> &vp) + { + vp.resize(dstSz); + + if(scale_up) + { + S32 val = 0x8000 * srcSz / dstSz - 0x8000; + S32 inc = (srcSz << 16) / dstSz; + U32 pos; + + for(U32 i = 0, j = 0; i < dstSz; ++i, ++j, val += inc) + { + pos = val >> 16; + + if (pos >= (srcSz - 1)) + vp[j] = 0; + else + vp[j] = (val >> 8) - ((val >> 8) & 0xffffff00); + } + } + else + { + S32 inc = (srcSz << 16) / dstSz; + S32 Cp = ((dstSz << 14) / srcSz) + 1; + S32 ap; + + for(U32 i = 0, j = 0, val = 0; i < dstSz; ++i, ++j, val += inc) + { + ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; + vp[j] = ap | (Cp << 16); + } + } + } +}; + + +template<U8 ch> +inline void bilinear_scale( + const U8 *src, U32 srcW, U32 srcH, U32 srcStride + , U8 *dst, U32 dstW, U32 dstH, U32 dstStride + ) +{ + typedef scale_info<ch> scale_info_t; + + scale_info_t info(src, srcW, srcH, dstW, dstH, srcStride); + + const U8 *sptr; + U8 *dptr; + U32 x, y; + const U8 *pix; + + S32 cx[ch], comp[ch]; + + + if(3 == info.xup_yup) + { //scale x/y - up + for(y = 0; y < dstH; ++y) + { + dptr = dst + (y * dstStride); + sptr = info.ystrides[y]; + + if(0 < info.yapoints[y]) + { + for(x = 0; x < dstW; ++x) + { + //for(c = 0; c < ch; ++c) cx[c] = comp[c] = 0; + typename scale_info_t::uroll_zeroze_cx_comp_t()(cx, comp); + + if(0 < info.xapoints[x]) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.xapoints[x]); + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); + + pix += ch; + + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * info.xapoints[x]; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, info.xapoints[x]); + + pix += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * info.xapoints[x]; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, info.xapoints[x]); + + pix -= ch; + + //for(c = 0; c < ch; ++c) { + // cx[c] += pix[c] * (256 - info.xapoints[x]); + // comp[c] = ((cx[c] * info.yapoints[y]) + (comp[c] * (256 - info.yapoints[y]))) >> 16; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, 256 - info.xapoints[x]); + typename scale_info_t::uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t()(comp, cx, info.yapoints[y]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + else + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.yapoints[y]); + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256-info.yapoints[y]); + + pix += srcStride; + + //for(c = 0; c < ch; ++c) { + // comp[c] = (comp[c] + pix[c] * info.yapoints[y]) >> 8; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.yapoints[y]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + } + } + else + { + for(x = 0; x < dstW; ++x) + { + if(0 < info.xapoints[x]) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) { + // comp[c] = pix[c] * (256 - info.xapoints[x]); + // comp[c] = (comp[c] + pix[c] * info.xapoints[x]) >> 8; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); + typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.xapoints[x]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + else + { + //for(c = 0; c < ch; ++c) *dptr++ = (sptr[info.xpoints[x]*ch + c])&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t()(dptr, sptr, info.xpoints[x]*ch); + } + } + } + } + } + else if(info.xup_yup == 1) + { //scaling down vertically + S32 Cy, j; + S32 yap; + + for(y = 0; y < dstH; y++) + { + Cy = info.yapoints[y] >> 16; + yap = info.yapoints[y] & 0xffff; + + dptr = dst + (y * dstStride); + + for(x = 0; x < dstW; x++) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * yap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, yap); + + pix += srcStride; + + for(j = (1 << 14) - yap; j > Cy; j -= Cy, pix += srcStride) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cy; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cy); + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); + } + + if(info.xapoints[x] > 0) + { + pix = info.ystrides[y] + info.xpoints[x]*ch + ch; + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * yap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, yap); + + pix += srcStride; + for(j = (1 << 14) - yap; j > Cy; j -= Cy) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cy; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cy); + pix += srcStride; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); + } + + //for(c = 0; c < ch; ++c) comp[c] = ((comp[c]*(256 - info.xapoints[x])) + ((cx[c] * info.xapoints[x]))) >> 12; + typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.xapoints[x], cx); + } + else + { + //for(c = 0; c < ch; ++c) comp[c] >>= 4; + typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); + } + } + } + else if(info.xup_yup == 2) + { // scaling down horizontally + S32 Cx, j; + S32 xap; + + for(y = 0; y < dstH; y++) + { + dptr = dst + (y * dstStride); + + for(x = 0; x < dstW; x++) + { + Cx = info.xapoints[x] >> 16; + xap = info.xapoints[x] & 0xffff; + + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, xap); + + pix+=ch; + for(j = (1 << 14) - xap; j > Cx; j -= Cx) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cx); + pix+=ch; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); + } + + if(info.yapoints[y] > 0) + { + pix = info.ystrides[y] + info.xpoints[x]*ch + srcStride; + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(j = (1 << 14) - xap; j > Cx; j -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); + } + + //for(c = 0; c < ch; ++c) comp[c] = ((comp[c] * (256 - info.yapoints[y])) + ((cx[c] * info.yapoints[y]))) >> 12; + typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.yapoints[y], cx); + } + else + { + //for(c = 0; c < ch; ++c) comp[c] >>= 4; + typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); + } + } + } + else + { //scale x/y - down + S32 Cx, Cy, i, j; + S32 xap, yap; + + for(y = 0; y < dstH; y++) + { + Cy = info.yapoints[y] >> 16; + yap = info.yapoints[y] & 0xffff; + + dptr = dst + (y * dstStride); + for(x = 0; x < dstW; x++) + { + Cx = info.xapoints[x] >> 16; + xap = info.xapoints[x] & 0xffff; + + sptr = info.ystrides[y] + info.xpoints[x] * ch; + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] = (cx[c] >> 5) * yap; + typename scale_info_t::uroll_comp_asgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, yap); + + for(j = (1 << 14) - yap; j > Cy; j -= Cy) + { + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * Cy; + typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, Cy); + } + + if(j > 0) + { + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * j; + typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, j); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>23)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 23); + } + } + } //else +} + +//wrapper +static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 srcStride, U8 *dst, U32 dstW, U32 dstH, U32 dstCh, U32 dstStride) +{ + llassert(srcCh == dstCh); + + switch(srcCh) + { + case 1: + bilinear_scale<1>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + case 3: + bilinear_scale<3>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + case 4: + bilinear_scale<4>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + default: + llassert(!"Implement if need"); + break; + } + +} + //--------------------------------------------------------------------------- // LLImage //--------------------------------------------------------------------------- @@ -559,6 +1098,7 @@ void LLImageRaw::composite( LLImageRaw* src ) } } + // Src and dst can be any size. Src has 4 components. Dst has 3 components. void LLImageRaw::compositeScaled4onto3(LLImageRaw* src) { @@ -589,21 +1129,6 @@ void LLImageRaw::compositeScaled4onto3(LLImageRaw* src) // Src and dst are same size. Src has 4 components. Dst has 3 components. void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src ) { - /* - //test fastFractionalMult() - { - U8 i = 255; - U8 j = 255; - do - { - do - { - llassert( fastFractionalMult(i, j) == (U8)(255*(i/255.f)*(j/255.f) + 0.5f) ); - } while( j-- ); - } while( i-- ); - } - */ - LLImageRaw* dst = this; // Just for clarity. llassert( (3 == src->getComponents()) || (4 == src->getComponents()) ); @@ -639,6 +1164,7 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src ) } } + void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill) { LLImageRaw* dst = this; // Just for clarity. @@ -846,6 +1372,12 @@ void LLImageRaw::copyScaled( LLImageRaw* src ) return; } + bilinear_scale( + src->getData(), src->getWidth(), src->getHeight(), src->getComponents(), src->getWidth()*src->getComponents() + , dst->getData(), dst->getWidth(), dst->getHeight(), dst->getComponents(), dst->getWidth()*dst->getComponents() + ); + + /* S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents(); llassert_always(temp_data_size > 0); std::vector<U8> temp_buffer(temp_data_size); @@ -861,6 +1393,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src ) { copyLineScaled( &temp_buffer[0] + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 ); } + */ } @@ -880,6 +1413,7 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) if (scale_image_data) { + /* S32 temp_data_size = old_width * new_height * getComponents(); llassert_always(temp_data_size > 0); std::vector<U8> temp_buffer(temp_data_size); @@ -899,6 +1433,19 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) { copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 ); } + */ + + S32 new_data_size = new_width * new_height * getComponents(); + llassert_always(new_data_size > 0); + + U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size); + if(NULL == new_data) + { + return FALSE; + } + + bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents()); + setDataAndSize(new_data, new_width, new_height, getComponents()); } else { diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index 8573fe0d91..a2ce2fee86 100755 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -443,6 +443,10 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src ) mBitfieldMask[2] = 0x000000FF; } + if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } S32 src_row_span = getWidth() * 4; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 @@ -476,6 +480,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src ) S32 src_row_span = getWidth() * 1; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 + if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } + for( S32 row = 0; row < getHeight(); row++ ) { for( S32 col = 0; col < getWidth(); col++ ) @@ -501,6 +510,11 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src ) S32 src_row_span = getWidth() * 3; S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4 + if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } + for( S32 row = 0; row < getHeight(); row++ ) { for( S32 col = 0; col < getWidth(); col++ ) diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index 4eb8dc7440..d0ae105ba7 100755 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -437,7 +437,13 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu // Origin is the bottom left U8* dst = raw_image->getData(); U8* src = getData() + mDataOffset; + S32 pixels = getWidth() * getHeight(); + + if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset) + { //here we have situation when data size in src less than actually needed + return FALSE; + } if (getComponents() == 4) { diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 23bf6da1f9..86aca77de8 100755 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -96,6 +96,10 @@ LLFolderDictionary::LLFolderDictionary() addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE)); addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE)); + + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE)); + addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE)); + addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE)); addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE)); }; diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h index a0c847914f..515bb05a3f 100755..100644 --- a/indra/llinventory/llfoldertype.h +++ b/indra/llinventory/llfoldertype.h @@ -87,6 +87,10 @@ public: FT_BASIC_ROOT = 52, + FT_MARKETPLACE_LISTINGS = 53, + FT_MARKETPLACE_STOCK = 54, + FT_MARKETPLACE_VERSION = 55, // Note: We actually *never* create folders with that type. This is used for icon override only. + FT_COUNT, FT_NONE = -1 diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c2198b91a7..8608e45a91 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2536,6 +2536,8 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) U32 cur_influence = 0; LLVector4 wght(0,0,0,0); + U32 joints[4] = {0,0,0,0}; + LLVector4 joints_with_weights(0,0,0,0); while (joint != END_INFLUENCES && idx < weights.size()) { @@ -2543,7 +2545,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) influence |= ((U16) weights[idx++] << 8); F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); - wght.mV[cur_influence++] = (F32) joint + w; + wght.mV[cur_influence] = w; + joints[cur_influence] = joint; + cur_influence++; if (cur_influence >= 4) { @@ -2554,8 +2558,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) joint = weights[idx++]; } } - - face.mWeights[cur_vertex].loadua(wght.mV); + F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; + if (wsum <= 0.f) + { + wght = LLVector4(0.99999f,0.f,0.f,0.f); + } + for (U32 k=0; k<4; k++) + { + joints_with_weights[k] = (F32) joints[k] + wght[k]; + } + face.mWeights[cur_vertex].loadua(joints_with_weights.mV); cur_vertex++; } @@ -5584,7 +5596,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) { resizeVertices(num_vertices+1); - if (!partial_build) + //if (!partial_build) { resizeIndices(num_indices+3); } @@ -5592,7 +5604,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) else { resizeVertices(num_vertices); - if (!partial_build) + //if (!partial_build) { resizeIndices(num_indices); } @@ -5714,10 +5726,10 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) LL_CHECK_MEMORY - if (partial_build) - { - return TRUE; - } + //if (partial_build) + //{ + // return TRUE; + //} if (mTypeMask & HOLLOW_MASK) { @@ -6072,7 +6084,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con if (new_verts > mNumAllocatedVertices) { - //double buffer size on expansion + // double buffer size on expansion new_verts *= 2; S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; @@ -6088,18 +6100,21 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con mNormals = mPositions+new_verts; mTexCoords = (LLVector2*) (mNormals+new_verts); - //positions - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize); - - //normals - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize); + if (old_buf != NULL) + { + // copy old positions into new buffer + LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); - //tex coords - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size); + // normals + LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize); - //just clear tangents - ll_aligned_free_16(mTangents); - mTangents = NULL; + // tex coords + LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size); + } + + // just clear tangents + ll_aligned_free_16(mTangents); + mTangents = NULL; ll_aligned_free<64>(old_buf); mNumAllocatedVertices = new_verts; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c8476f6897..1da2d0c6b1 100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -190,8 +190,12 @@ const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; +// for value checks, assign new value after adding new types +const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +const U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR; const S32 LL_SCULPT_MESH_MAX_FACES = 8; @@ -968,6 +972,7 @@ protected: ~LLVolume(); // use unref public: + typedef std::vector<LLVolumeFace> face_list_t; struct FaceParams { @@ -1041,6 +1046,10 @@ public: // conversion if *(LLVolume*) to LLVolume& const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + face_list_t& getVolumeFaces() { return mVolumeFaces; } + U32 mFaceMask; // bit array of which faces exist in this volume LLVector3 mLODScaleBias; // vector for biasing LOD based on scale @@ -1080,7 +1089,6 @@ public: BOOL mGenerateSingleFace; - typedef std::vector<LLVolumeFace> face_list_t; face_list_t mVolumeFaces; public: diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 6a1b4143cf..d89c482804 100755 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -274,6 +274,19 @@ const LLMatrix4& LLMatrix4::invert(void) return *this; } +// Convenience func for simplifying comparison-heavy code by +// intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f +// +void LLMatrix4::condition(void) +{ + U32 i; + U32 j; + for (i = 0; i < 3;i++) + for (j = 0; j < 3;j++) + mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON) + && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j]; +} + LLVector4 LLMatrix4::getFwdRow4() const { return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]); diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index a7dce10397..a77c5bc76d 100755 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -180,6 +180,11 @@ public: const LLMatrix4& setTranslation(const LLVector4 &translation); const LLMatrix4& setTranslation(const LLVector3 &translation); + // Convenience func for simplifying comparison-heavy code by + // intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0 + // + void condition(void); + /////////////////////////// // // Get properties of a matrix diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 8ba2535531..61663e1982 100755 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -633,6 +633,10 @@ void LLAssetStorage::downloadCompleteCallback( vfile.remove(); } } + + // we will be deleting elements of mPendingDownloads which req might be part of, save id and type for reference + LLUUID callback_id = req->getUUID(); + LLAssetType::EType callback_type = req->getType(); // find and callback ALL pending requests for this UUID // SJB: We process the callbacks in reverse order, I do not know if this is important, @@ -660,7 +664,7 @@ void LLAssetStorage::downloadCompleteCallback( { add(sFailedDownloadCount, 1); } - tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status); + tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result, ext_status); } delete tmp; } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index f8db3dded2..60f17e6870 100755 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -572,6 +572,17 @@ void LLHTTPClient::patch( request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers); } +void LLHTTPClient::putRaw( + const std::string& url, + const U8* data, + S32 size, + ResponderPtr responder, + const LLSD& headers, + const F32 timeout) +{ + request(url, HTTP_PUT, new RawInjector(data, size), responder, timeout, headers); +} + void LLHTTPClient::post( const std::string& url, const LLSD& body, diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index b18258fd7b..fd48b4a743 100755 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -79,6 +79,14 @@ public: ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); + static void putRaw( + const std::string& url, + const U8* data, + S32 size, + ResponderPtr responder, + const LLSD& headers = LLSD(), + const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); + static void patch( const std::string& url, diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 52626b0302..4bfd0de81e 100755 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -146,6 +146,8 @@ void LLPluginClassMedia::reset() mClickTarget.clear(); mClickUUID.clear(); mStatusCode = 0; + + mClickEnforceTarget = false; // media_time class mCurrentTime = 0.0f; @@ -1358,6 +1360,12 @@ void LLPluginClassMedia::addCertificateFilePath(const std::string& path) sendMessage(message); } +void LLPluginClassMedia::setOverrideClickTarget(const std::string &target) +{ + mClickEnforceTarget = true; + mOverrideClickTarget = target; +} + void LLPluginClassMedia::crashPlugin() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 5fe8254331..96d577f43c 100755 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -249,6 +249,13 @@ public: // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // mClickTarget is received from message and governs how link will be opened + // use this to enforce your own way of opening links inside plugins + void setOverrideClickTarget(const std::string &target); + void resetOverrideClickTarget() { mClickEnforceTarget = false; }; + bool isOverrideClickTarget() const { return mClickEnforceTarget; } + std::string getOverrideClickTarget() const { return mOverrideClickTarget; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE std::string getDebugMessageText() const { return mDebugMessageText; }; std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; @@ -404,6 +411,8 @@ protected: std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + bool mClickEnforceTarget; + std::string mOverrideClickTarget; std::string mDebugMessageText; std::string mDebugMessageLevel; S32 mGeometryX; diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index d1475cf734..75ce624a58 100755 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -8,6 +8,7 @@ include(LLMath) include(LLMessage) include(LLXML) include(LLPhysicsExtensions) +include(LLCharacter) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -16,6 +17,7 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada ${LIBS_PREBUILT_DIR}/include/collada/1.4 + ${LLCHARACTER_INCLUDE_DIRS} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -24,11 +26,13 @@ include_directories(SYSTEM ) set(llprimitive_SOURCE_FILES + lldaeloader.cpp llmaterialid.cpp llmaterial.cpp llmaterialtable.cpp llmediaentry.cpp llmodel.cpp + llmodelloader.cpp llprimitive.cpp llprimtexturelist.cpp lltextureanim.cpp @@ -40,16 +44,17 @@ set(llprimitive_SOURCE_FILES set(llprimitive_HEADER_FILES CMakeLists.txt - + lldaeloader.h legacy_object_types.h - lllslconstants.h llmaterial.h llmaterialid.h llmaterialtable.h llmediaentry.h llmodel.h + llmodelloader.h llprimitive.h llprimtexturelist.h + lllslconstants.h lltextureanim.h lltextureentry.h lltreeparams.h @@ -72,6 +77,7 @@ target_link_libraries(llprimitive ${LLMESSAGE_LIBRARIES} ${LLXML_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} + ${LLCHARACTER_LIBRARIES} ) diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp new file mode 100644 index 0000000000..c1b74b1fd7 --- /dev/null +++ b/indra/llprimitive/lldaeloader.cpp @@ -0,0 +1,2436 @@ +/** + * @file lldaeloader.cpp + * @brief LLDAELoader class implementation + * + * $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$ + */ + +#if LL_MSVC +#pragma warning (disable : 4263) +#pragma warning (disable : 4264) +#endif +#include "dae.h" +#include "dom/domAsset.h" +#include "dom/domBind_material.h" +#include "dom/domCOLLADA.h" +#include "dom/domConstants.h" +#include "dom/domController.h" +#include "dom/domEffect.h" +#include "dom/domGeometry.h" +#include "dom/domInstance_geometry.h" +#include "dom/domInstance_material.h" +#include "dom/domInstance_node.h" +#include "dom/domInstance_effect.h" +#include "dom/domMaterial.h" +#include "dom/domMatrix.h" +#include "dom/domNode.h" +#include "dom/domProfile_COMMON.h" +#include "dom/domRotate.h" +#include "dom/domScale.h" +#include "dom/domTranslate.h" +#include "dom/domVisual_scene.h" +#if LL_MSVC +#pragma warning (default : 4263) +#pragma warning (default : 4264) +#endif + +#include <boost/lexical_cast.hpp> + +#include "lldaeloader.h" +#include "llsdserialize.h" +#include "lljoint.h" + +#include "glh/glh_linear.h" +#include "llmatrix4a.h" + +std::string colladaVersion[VERSIONTYPE_COUNT+1] = +{ + "1.4.0", + "1.4.1", + "Unsupported" +}; + +static const std::string lod_suffix[LLModel::NUM_LODS] = +{ + "_LOD0", + "_LOD1", + "_LOD2", + "", + "_PHYS", +}; + +const U32 LIMIT_MATERIALS_OUTPUT = 12; + +bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, + domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +{ + idx_stride = 0; + + for (U32 j = 0; j < inputs.getCount(); ++j) + { + idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) + { //found vertex array + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if ( !vertices ) + { + return false; + } + + domInputLocal_Array& v_inp = vertices->getInput_array(); + + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + pos_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + pos_source = (domSource*) elem.cast(); + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) + { + norm_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + } + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + { + //found normal array for this triangle list + norm_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) + { //found texCoords + tc_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + tc_source = (domSource*) elem.cast(); + } + } + + idx_stride += 1; + + return true; +} + +LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri) +{ + LLVolumeFace face; + std::vector<LLVolumeFace::VertexData> verts; + std::vector<U16> indices; + + const domInputLocalOffset_Array& inputs = tri->getInput_array(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) + { + return LLModel::BAD_ELEMENT; + } + + if (!pos_source || !pos_source->getFloat_array()) + { + LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + domPRef p = tri->getP(); + domListOfUInts& idx = p->getValue(); + + domListOfFloats dummy ; + domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; + + if (pos_source) + { + if(v.getCount() == 0) + { + return LLModel::BAD_ELEMENT; + } + + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < idx.getCount(); i += idx_stride) + { + LLVolumeFace::VertexData cv; + if (pos_source) + { + cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], + v[idx[i+pos_offset]*3+1], + v[idx[i+pos_offset]*3+2])); + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], + tc[idx[i+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], + n[idx[i+norm_offset]*3+1], + n[idx[i+norm_offset]*3+2])); + } + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + + if (point_iter != point_map.end()) + { + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + // We have a matching loc + // + if ((point_iter->second)[j] == cv) + { + U16 shared_index = (point_iter->second)[j].mIndex; + + // Don't share verts within the same tri, degenerate + // + if ((indices.size() % 3) && (indices[indices.size()-1] != shared_index)) + { + found = true; + indices.push_back(shared_index); + } + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + indices.push_back(index); + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + } + } + + if (indices.size()%3 == 0 && verts.size() >= 65532) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + point_map.clear(); + } + } + + if (!verts.empty()) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly) +{ + domPRef p = poly->getP(); + domListOfUInts& idx = p->getValue(); + + if (idx.getCount() == 0) + { + return LLModel::NO_ERRORS ; + } + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + domListOfUInts& vcount = poly->getVcount()->getValue(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) + { + return LLModel::BAD_ELEMENT; + } + + LLVolumeFace face; + + std::vector<U16> indices; + std::vector<LLVolumeFace::VertexData> verts; + + domListOfFloats v; + domListOfFloats tc; + domListOfFloats n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + U32 cur_idx = 0; + for (U32 i = 0; i < vcount.getCount(); ++i) + { //for each polygon + U32 first_index = 0; + U32 last_index = 0; + for (U32 j = 0; j < vcount[i]; ++j) + { //for each vertex + + LLVolumeFace::VertexData cv; + + if (pos_source) + { + cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], + v[idx[cur_idx+pos_offset]*3+1], + v[idx[cur_idx+pos_offset]*3+2]); + if (!cv.getPosition().isFinite3()) + { + LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], + tc[idx[cur_idx+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], + n[idx[cur_idx+norm_offset]*3+1], + n[idx[cur_idx+norm_offset]*3+2]); + + if (!cv.getNormal().isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + cur_idx += idx_stride; + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + LLVector3 pos3(cv.getPosition().getF32ptr()); + point_iter = point_map.find(pos3); + + if (point_iter != point_map.end()) + { + for (U32 k = 0; k < point_iter->second.size(); ++k) + { + if ((point_iter->second)[k] == cv) + { + found = TRUE; + U32 index = (point_iter->second)[k].mIndex; + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // if these are the same, we have a very, very skinny triangle (coincident verts on one or more edges) + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // detect very skinny degenerate triangles with collapsed edges + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos3].push_back(d); + } + } + + if (indices.size()%3 == 0 && indices.size() >= 65532) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + verts.clear(); + indices.clear(); + point_map.clear(); + } + } + } + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly) +{ + LLVolumeFace face; + std::vector<U16> indices; + std::vector<LLVolumeFace::VertexData> verts; + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + S32 v_offset = -1; + S32 n_offset = -1; + S32 t_offset = -1; + + domListOfFloats* v = NULL; + domListOfFloats* n = NULL; + domListOfFloats* t = NULL; + + U32 stride = 0; + for (U32 i = 0; i < inputs.getCount(); ++i) + { + stride = llmax((U32) inputs[i]->getOffset()+1, stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) + { //found vertex array + v_offset = inputs[i]->getOffset(); + + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if (!vertices) + { + return LLModel::BAD_ELEMENT; + } + domInputLocal_Array& v_inp = vertices->getInput_array(); + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + v = &(src->getFloat_array()->getValue()); + } + } + } + else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) + { + n_offset = inputs[i]->getOffset(); + //found normal array for this triangle list + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + n = &(src->getFloat_array()->getValue()); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) + { //found texCoords + t_offset = inputs[i]->getOffset(); + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + t = &(src->getFloat_array()->getValue()); + } + } + + domP_Array& ps = poly->getP_array(); + + //make a triangle list in <verts> + for (U32 i = 0; i < ps.getCount(); ++i) + { //for each polygon + domListOfUInts& idx = ps[i]->getValue(); + for (U32 j = 0; j < idx.getCount()/stride; ++j) + { //for each vertex + if (j > 2) + { + U32 size = verts.size(); + LLVolumeFace::VertexData v0 = verts[size-3]; + LLVolumeFace::VertexData v1 = verts[size-1]; + + verts.push_back(v0); + verts.push_back(v1); + } + + LLVolumeFace::VertexData vert; + + + if (v) + { + U32 v_idx = idx[j*stride+v_offset]*3; + v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); + vert.getPosition().set(v->get(v_idx), + v->get(v_idx+1), + v->get(v_idx+2)); + } + + //bounds check n and t lookups because some FBX to DAE converters + //use negative indices and empty arrays to indicate data does not exist + //for a particular channel + if (n && n->getCount() > 0) + { + U32 n_idx = idx[j*stride+n_offset]*3; + n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); + vert.getNormal().set(n->get(n_idx), + n->get(n_idx+1), + n->get(n_idx+2)); + } + else + { + vert.getNormal().clear(); + } + + + if (t && t->getCount() > 0) + { + U32 t_idx = idx[j*stride+t_offset]*2; + t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); + vert.mTexCoord.setVec(t->get(t_idx), + t->get(t_idx+1)); + } + else + { + vert.mTexCoord.clear(); + } + + + verts.push_back(vert); + } + } + + if (verts.empty()) + { + return LLModel::NO_ERRORS; + } + + face.mExtents[0] = verts[0].getPosition(); + face.mExtents[1] = verts[0].getPosition(); + + //create a map of unique vertices to indices + std::map<LLVolumeFace::VertexData, U32> vert_idx; + + U32 cur_idx = 0; + for (U32 i = 0; i < verts.size(); ++i) + { + std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]); + if (iter == vert_idx.end()) + { + vert_idx[verts[i]] = cur_idx++; + } + } + + //build vertex array from map + std::vector<LLVolumeFace::VertexData> new_verts; + new_verts.resize(vert_idx.size()); + + for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) + { + new_verts[iter->second] = iter->first; + update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); + } + + //build index array from map + indices.resize(verts.size()); + + for (U32 i = 0; i < verts.size(); ++i) + { + indices[i] = vert_idx[verts[i]]; + llassert(!i || (indices[i-1] != indices[i])); + } + + // DEBUG just build an expanded triangle list + /*for (U32 i = 0; i < verts.size(); ++i) + { + indices.push_back((U16) i); + update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); + }*/ + + if (!new_verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(new_verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!n) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!t) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +//----------------------------------------------------------------------------- +// LLDAELoader +//----------------------------------------------------------------------------- +LLDAELoader::LLDAELoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes, + U32 modelLimit) +: LLModelLoader( + filename, + lod, + load_cb, + joint_lookup_func, + texture_load_func, + state_cb, + opaque_userdata, + jointMap, + jointsFromNodes), +mGeneratedModelLimit(modelLimit) +{ +} + +LLDAELoader::~LLDAELoader() +{ +} + +struct ModelSort +{ + bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs) + { + if (lhs->mSubmodelID < rhs->mSubmodelID) + { + return true; + } + return LLStringUtil::compareInsensitive(lhs->mLabel, rhs->mLabel) < 0; + } +}; + +bool LLDAELoader::OpenFile(const std::string& filename) +{ + //no suitable slm exists, load from the .dae file + DAE dae; + domCOLLADA* dom = dae.open(filename); + + if (!dom) + { + LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL; + setLoadState( ERROR_PARSING ); + return false; + } + //Dom version + daeString domVersion = dae.getDomVersion(); + std::string sldom(domVersion); + LL_INFOS()<<"Collada Importer Version: "<<sldom<<LL_ENDL; + //Dae version + domVersionType docVersion = dom->getVersion(); + //0=1.4 + //1=1.4.1 + //2=Currently unsupported, however may work + if (docVersion > 1 ) + { + docVersion = VERSIONTYPE_COUNT; + } + LL_INFOS()<<"Dae version "<<colladaVersion[docVersion]<<LL_ENDL; + + + daeDatabase* db = dae.getDatabase(); + + daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); + + daeDocument* doc = dae.getDoc(mFilename); + if (!doc) + { + LL_WARNS() << "can't find internal doc" << LL_ENDL; + return false; + } + + daeElement* root = doc->getDomRoot(); + if (!root) + { + LL_WARNS() << "document has no root" << LL_ENDL; + return false; + } + + //Verify some basic properties of the dae + //1. Basic validity check on controller + U32 controllerCount = (int) db->getElementCount( NULL, "controller" ); + bool result = false; + for ( int i=0; i<controllerCount; ++i ) + { + domController* pController = NULL; + db->getElement( (daeElement**) &pController, i , NULL, "controller" ); + result = verifyController( pController ); + if (!result) + { + LL_INFOS() << "Could not verify controller" << LL_ENDL; + setLoadState( ERROR_PARSING ); + return true; + } + } + + + //get unit scale + mTransform.setIdentity(); + + domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); + + if (unit) + { + F32 meter = unit->getMeter(); + mTransform.mMatrix[0][0] = meter; + mTransform.mMatrix[1][1] = meter; + mTransform.mMatrix[2][2] = meter; + } + + //get up axis rotation + LLMatrix4 rotation; + + domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP + domAsset::domUp_axis* up_axis = + daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + + if (up_axis) + { + up = up_axis->getValue(); + } + + if (up == UPAXISTYPE_X_UP) + { + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + } + else if (up == UPAXISTYPE_Y_UP) + { + rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); + } + + rotation *= mTransform; + mTransform = rotation; + + mTransform.condition(); + + U32 submodel_limit = count > 0 ? mGeneratedModelLimit/count : 0; + for (daeInt idx = 0; idx < count; ++idx) + { //build map of domEntities to LLModel + domMesh* mesh = NULL; + db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); + + if (mesh) + { + + std::vector<LLModel*> models; + + loadModelsFromDomMesh(mesh, models, submodel_limit); + + std::vector<LLModel*>::iterator i; + i = models.begin(); + while (i != models.end()) + { + LLModel* mdl = *i; + if(mdl->getStatus() != LLModel::NO_ERRORS) + { + setLoadState(ERROR_MODEL + mdl->getStatus()) ; + return false; //abort + } + + if (mdl && validate_model(mdl)) + { + mModelList.push_back(mdl); + mModelsMap[mesh].push_back(mdl); + } + i++; + } + } + } + + std::sort(mModelList.begin(), mModelList.end(), ModelSort()); + + model_list::iterator model_iter = mModelList.begin(); + while (model_iter != mModelList.end()) + { + LLModel* mdl = *model_iter; + U32 material_count = mdl->mMaterialList.size(); + LL_INFOS() << "Importing " << mdl->mLabel << " model with " << material_count << " material references" << LL_ENDL; + std::vector<std::string>::iterator mat_iter = mdl->mMaterialList.begin(); + std::vector<std::string>::iterator end_iter = material_count > LIMIT_MATERIALS_OUTPUT + ? mat_iter + LIMIT_MATERIALS_OUTPUT + : mdl->mMaterialList.end(); + while (mat_iter != end_iter) + { + LL_INFOS() << mdl->mLabel << " references " << (*mat_iter) << LL_ENDL; + mat_iter++; + } + model_iter++; + } + + count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); + for (daeInt idx = 0; idx < count; ++idx) + { //add skinned meshes as instances + domSkin* skin = NULL; + db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); + + if (skin) + { + domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()); + + if (geom) + { + domMesh* mesh = geom->getMesh(); + if (mesh) + { + std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); + while (i != mModelsMap[mesh].end()) + { + LLPointer<LLModel> mdl = *i; + LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin); + i++; + } + } + } + } + } + + LL_INFOS()<< "Collada skins processed: " << count <<LL_ENDL; + + daeElement* scene = root->getDescendant("visual_scene"); + + if (!scene) + { + LL_WARNS() << "document has no visual_scene" << LL_ENDL; + setLoadState( ERROR_PARSING ); + return true; + } + + setLoadState( DONE ); + + bool badElement = false; + + processElement( scene, badElement, &dae ); + + if ( badElement ) + { + LL_INFOS()<<"Scene could not be parsed"<<LL_ENDL; + setLoadState( ERROR_PARSING ); + } + + return true; +} + +void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, domMesh* mesh, domSkin* skin) +{ + llassert(model && dae && mesh && skin); + + if (model) + { + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 normalized_transformation; + normalized_transformation.setTranslation(mesh_translation_vector); + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= normalized_transformation; + normalized_transformation = mesh_scale; + + glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix); + inv_mat = inv_mat.inverse(); + LLMatrix4 inverse_normalized_transformation(inv_mat.m); + + domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); + + if (bind_mat) + { //get bind shape matrix + domFloat4x4& dom_value = bind_mat->getValue(); + + LLMeshSkinInfo& skin_info = model->mSkinInfo; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + LLMatrix4 trans = normalized_transformation; + trans *= skin_info.mBindShapeMatrix; + skin_info.mBindShapeMatrix = trans; + } + + + //Some collada setup for accessing the skeleton + daeElement* pElement = 0; + dae->getDatabase()->getElement( &pElement, 0, 0, "skeleton" ); + + //Try to get at the skeletal instance controller + domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement ); + bool missingSkeletonOrScene = false; + + //If no skeleton, do a breadth-first search to get at specific joints + bool rootNode = false; + + //Need to test for a skeleton that does not have a root node + //This occurs when your instance controller does not have an associated scene + if ( pSkeleton ) + { + daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); + if ( pSkeletonRootNode ) + { + rootNode = true; + } + + } + if ( !pSkeleton || !rootNode ) + { + daeElement* pScene = root->getDescendant("visual_scene"); + if ( !pScene ) + { + LL_WARNS()<<"No visual scene - unable to parse bone offsets "<<LL_ENDL; + missingSkeletonOrScene = true; + } + else + { + //Get the children at this level + daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); + S32 childCount = children.getCount(); + + //Process any children that are joints + //Not all children are joints, some code be ambient lights, cameras, geometry etc.. + for (S32 i = 0; i < childCount; ++i) + { + domNode* pNode = daeSafeCast<domNode>(children[i]); + if ( isNodeAJoint( pNode ) ) + { + processJointNode( pNode, mJointList ); + } + } + } + } + else + //Has Skeleton + { + //Get the root node of the skeleton + daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); + if ( pSkeletonRootNode ) + { + //Once we have the root node - start acccessing it's joint components + const int jointCnt = mJointMap.size(); + JointMap :: const_iterator jointIt = mJointMap.begin(); + + //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. + for ( int i=0; i<jointCnt; ++i, ++jointIt ) + { + //Build a joint for the resolver to work with + char str[64]={0}; + sprintf(str,"./%s",(*jointIt).first.c_str() ); + //LL_WARNS()<<"Joint "<< str <<LL_ENDL; + + //Setup the resolver + daeSIDResolver resolver( pSkeletonRootNode, str ); + + //Look for the joint + domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() ); + if ( pJoint ) + { + //Pull out the translate id and store it in the jointTranslations map + daeSIDResolver jointResolverA( pJoint, "./translate" ); + domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); + daeSIDResolver jointResolverB( pJoint, "./location" ); + domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); + + LLMatrix4 workingTransform; + + //Translation via SID + if ( pTranslateA ) + { + extractTranslation( pTranslateA, workingTransform ); + } + else + if ( pTranslateB ) + { + extractTranslation( pTranslateB, workingTransform ); + } + else + { + //Translation via child from element + daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); + if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) + { + LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; + missingSkeletonOrScene = true; + } + else + if ( pTranslateElement ) + { + extractTranslationViaElement( pTranslateElement, workingTransform ); + } + else + { + extractTranslationViaSID( pJoint, workingTransform ); + } + + } + + //Store the joint transform w/respect to it's name. + mJointList[(*jointIt).second.c_str()] = workingTransform; + } + } + + //If anything failed in regards to extracting the skeleton, joints or translation id, + //mention it + if ( missingSkeletonOrScene ) + { + LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; + } + }//got skeleton? + } + + + domSkin::domJoints* joints = skin->getJoints(); + + domInputLocal_Array& joint_input = joints->getInput_array(); + + for (size_t i = 0; i < joint_input.getCount(); ++i) + { + domInputLocal* input = joint_input.get(i); + xsNMTOKEN semantic = input->getSemantic(); + + if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) + { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames + daeElement* elem = input->getSource().getElement(); + + domSource* source = daeSafeCast<domSource>(elem); + if (source) + { + + + domName_array* names_source = source->getName_array(); + + if (names_source) + { + domListOfNames &names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j)); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; + } + } + else + { + domIDREF_array* names_source = source->getIDREF_array(); + if (names_source) + { + xsIDREFS& names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j).getID()); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; + } + } + } + } + } + else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) + { //found inv_bind_matrix array, fill model->mInvBindMatrix + domSource* source = daeSafeCast<domSource>(input->getSource().getElement()); + if (source) + { + domFloat_array* t = source->getFloat_array(); + if (t) + { + domListOfFloats& transform = t->getValue(); + S32 count = transform.getCount()/16; + + for (S32 k = 0; k < count; ++k) + { + LLMatrix4 mat; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + mat.mMatrix[i][j] = transform[k*16 + i + j*4]; + } + } + + model->mSkinInfo.mInvBindMatrix.push_back(mat); + } + } + } + } + } + + //Now that we've parsed the joint array, let's determine if we have a full rig + //(which means we have all the joint sthat are required for an avatar versus + //a skinned asset attached to a node in a file that contains an entire skeleton, + //but does not use the skeleton). + buildJointToNodeMappingFromScene( root ); + critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames ); + + if ( !missingSkeletonOrScene ) + { + //Set the joint translations on the avatar - if it's a full mapping + //The joints are reset in the dtor + if ( getRigWithSceneParity() ) + { + JointMap :: const_iterator masterJointIt = mJointMap.begin(); + JointMap :: const_iterator masterJointItEnd = mJointMap.end(); + for (;masterJointIt!=masterJointItEnd;++masterJointIt ) + { + std::string lookingForJoint = (*masterJointIt).first.c_str(); + + if ( mJointList.find( lookingForJoint ) != mJointList.end() ) + { + //LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL; + LLMatrix4 jointTransform = mJointList[lookingForJoint]; + LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData); + if ( pJoint ) + { + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); + } + else + { + //Most likely an error in the asset. + LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; + } + } + } + } + } //missingSkeletonOrScene + + //We need to construct the alternate bind matrix (which contains the new joint positions) + //in the same order as they were stored in the joint buffer. The joints associated + //with the skeleton are not stored in the same order as they are in the exported joint buffer. + //This remaps the skeletal joints to be in the same order as the joints stored in the model. + std::vector<std::string> :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); + const int jointCnt = model->mSkinInfo.mJointNames.size(); + for ( int i=0; i<jointCnt; ++i, ++jointIt ) + { + std::string lookingForJoint = (*jointIt).c_str(); + //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key + //and store it in the alternate bind matrix + if ( mJointList.find( lookingForJoint ) != mJointList.end() ) + { + LLMatrix4 jointTransform = mJointList[lookingForJoint]; + LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; + newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); + model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); + } + else + { + LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL; + } + } + + //grab raw position array + + domVertices* verts = mesh->getVertices(); + if (verts) + { + domInputLocal_Array& inputs = verts->getInput_array(); + for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) + { + domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); + if (pos_source) + { + domFloat_array* pos_array = pos_source->getFloat_array(); + if (pos_array) + { + domListOfFloats& pos = pos_array->getValue(); + + for (size_t j = 0; j < pos.getCount(); j += 3) + { + if (pos.getCount() <= j+2) + { + LL_ERRS() << "Invalid position array size." << LL_ENDL; + } + + LLVector3 v(pos[j], pos[j+1], pos[j+2]); + + //transform from COLLADA space to volume space + v = v * inverse_normalized_transformation; + + model->mPosition.push_back(v); + } + } + } + } + } + } + + //grab skin weights array + domSkin::domVertex_weights* weights = skin->getVertex_weights(); + if (weights) + { + domInputLocalOffset_Array& inputs = weights->getInput_array(); + domFloat_array* vertex_weights = NULL; + for (size_t i = 0; i < inputs.getCount(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) + { + domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); + if (weight_source) + { + vertex_weights = weight_source->getFloat_array(); + } + } + } + + if (vertex_weights) + { + domListOfFloats& w = vertex_weights->getValue(); + domListOfUInts& vcount = weights->getVcount()->getValue(); + domListOfInts& v = weights->getV()->getValue(); + + U32 c_idx = 0; + for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) + { //for each vertex + daeUInt count = vcount[vc_idx]; + + //create list of weights that influence this vertex + LLModel::weight_list weight_list; + + for (daeUInt i = 0; i < count; ++i) + { //for each weight + daeInt joint_idx = v[c_idx++]; + daeInt weight_idx = v[c_idx++]; + + if (joint_idx == -1) + { + //ignore bindings to bind_shape_matrix + continue; + } + + F32 weight_value = w[weight_idx]; + + weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); + } + + //sort by joint weight + std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); + + std::vector<LLModel::JointWeight> wght; + + F32 total = 0.f; + + for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) + { //take up to 4 most significant weights + if (weight_list[i].mWeight > 0.f) + { + wght.push_back( weight_list[i] ); + total += weight_list[i].mWeight; + } + } + + F32 scale = 1.f/total; + if (scale != 1.f) + { //normalize weights + for (U32 i = 0; i < wght.size(); ++i) + { + wght[i].mWeight *= scale; + } + } + + model->mSkinWeights[model->mPosition[vc_idx]] = wght; + } + } + + } + + //add instance to scene for this model + + LLMatrix4 transformation; + transformation.initScale(mesh_scale_vector); + transformation.setTranslation(mesh_translation_vector); + transformation *= mTransform; + + std::map<std::string, LLImportMaterial> materials; + for (U32 i = 0; i < model->mMaterialList.size(); ++i) + { + materials[model->mMaterialList[i]] = LLImportMaterial(); + } + mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + } +} + +//----------------------------------------------------------------------------- +// buildJointToNodeMappingFromScene() +//----------------------------------------------------------------------------- +void LLDAELoader::buildJointToNodeMappingFromScene( daeElement* pRoot ) +{ + daeElement* pScene = pRoot->getDescendant("visual_scene"); + if ( pScene ) + { + daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); + S32 childCount = children.getCount(); + for (S32 i = 0; i < childCount; ++i) + { + domNode* pNode = daeSafeCast<domNode>(children[i]); + processJointToNodeMapping( pNode ); + } + } +} +//----------------------------------------------------------------------------- +// processJointToNodeMapping() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointToNodeMapping( domNode* pNode ) +{ + if ( isNodeAJoint( pNode ) ) + { + //1.Store the parent + std::string nodeName = pNode->getName(); + if ( !nodeName.empty() ) + { + mJointsFromNode.push_front( pNode->getName() ); + } + //2. Handle the kiddo's + processChildJoints( pNode ); + } + else + { + //Determine if the're any children wrt to this failed node. + //This occurs when an armature is exported and ends up being what essentially amounts to + //as the root for the visual_scene + if ( pNode ) + { + processChildJoints( pNode ); + } + else + { + LL_INFOS()<<"Node is NULL"<<LL_ENDL; + } + + } +} +//----------------------------------------------------------------------------- +// processChildJoint() +//----------------------------------------------------------------------------- +void LLDAELoader::processChildJoints( domNode* pParentNode ) +{ + daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren(); + S32 childOfChildCount = childOfChild.getCount(); + for (S32 i = 0; i < childOfChildCount; ++i) + { + domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); + if ( pChildNode ) + { + processJointToNodeMapping( pChildNode ); + } + } +} + +//----------------------------------------------------------------------------- +// isNodeAJoint() +//----------------------------------------------------------------------------- +bool LLDAELoader::isNodeAJoint( domNode* pNode ) +{ + if ( !pNode ) + { + LL_INFOS()<<"Created node is NULL"<<LL_ENDL; + return false; + } + + return LLModelLoader::isNodeAJoint(pNode->getName()); +} +//----------------------------------------------------------------------------- +// verifyCount +//----------------------------------------------------------------------------- +bool LLDAELoader::verifyCount( int expected, int result ) +{ + if ( expected != result ) + { + LL_INFOS()<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<LL_ENDL; + return false; + } + return true; +} +//----------------------------------------------------------------------------- +// verifyController +//----------------------------------------------------------------------------- +bool LLDAELoader::verifyController( domController* pController ) +{ + + bool result = true; + + domSkin* pSkin = pController->getSkin(); + + if ( pSkin ) + { + xsAnyURI & uri = pSkin->getSource(); + domElement* pElement = uri.getElement(); + + if ( !pElement ) + { + LL_INFOS()<<"Can't resolve skin source"<<LL_ENDL; + return false; + } + + daeString type_str = pElement->getTypeName(); + if ( stricmp(type_str, "geometry") == 0 ) + { + //Skin is reference directly by geometry and get the vertex count from skin + domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); + U32 vertexWeightsCount = pVertexWeights->getCount(); + domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); + domMesh* pMesh = pGeometry->getMesh(); + + if ( pMesh ) + { + //Get vertex count from geometry + domVertices* pVertices = pMesh->getVertices(); + if ( !pVertices ) + { + LL_INFOS()<<"No vertices!"<<LL_ENDL; + return false; + } + + if ( pVertices ) + { + xsAnyURI src = pVertices->getInput_array()[0]->getSource(); + domSource* pSource = (domSource*) (domElement*) src.getElement(); + U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); + result = verifyCount( verticesCount, vertexWeightsCount ); + if ( !result ) + { + return result; + } + } + } + + U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); + result = verifyCount( vcountCount, vertexWeightsCount ); + if ( !result ) + { + return result; + } + + domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); + U32 sum = 0; + for (size_t i=0; i<vcountCount; i++) + { + sum += pVertexWeights->getVcount()->getValue()[i]; + } + result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() ); + } + } + + return result; +} + +//----------------------------------------------------------------------------- +// extractTranslation() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ) +{ + domFloat3 jointTrans = pTranslate->getValue(); + LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] ); + transform.setTranslation( singleJointTranslation ); +} +//----------------------------------------------------------------------------- +// extractTranslationViaElement() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ) +{ + if ( pTranslateElement ) + { + domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement ); + domFloat3 translateChild = pTranslateChild->getValue(); + LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] ); + transform.setTranslation( singleJointTranslation ); + } +} +//----------------------------------------------------------------------------- +// extractTranslationViaSID() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ) +{ + if ( pElement ) + { + daeSIDResolver resolver( pElement, "./transform" ); + domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() ); + //We are only extracting out the translational component atm + LLMatrix4 workingTransform; + if ( pMatrix ) + { + domFloat4x4 domArray = pMatrix->getValue(); + for ( int i = 0; i < 4; i++ ) + { + for( int j = 0; j < 4; j++ ) + { + workingTransform.mMatrix[i][j] = domArray[i + j*4]; + } + } + LLVector3 trans = workingTransform.getTranslation(); + transform.setTranslation( trans ); + } + } + else + { + LL_WARNS()<<"Element is nonexistent - empty/unsupported node."<<LL_ENDL; + } +} +//----------------------------------------------------------------------------- +// processJointNode() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms ) +{ + if (pNode->getName() == NULL) + { + LL_WARNS() << "nameless node, can't process" << LL_ENDL; + return; + } + + //LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL; + + //1. handle the incoming node - extract out translation via SID or element + + LLMatrix4 workingTransform; + + //Pull out the translate id and store it in the jointTranslations map + daeSIDResolver jointResolverA( pNode, "./translate" ); + domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); + daeSIDResolver jointResolverB( pNode, "./location" ); + domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); + + //Translation via SID was successful + if ( pTranslateA ) + { + extractTranslation( pTranslateA, workingTransform ); + } + else + if ( pTranslateB ) + { + extractTranslation( pTranslateB, workingTransform ); + } + else + { + //Translation via child from element + daeElement* pTranslateElement = getChildFromElement( pNode, "translate" ); + if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() ) + { + //LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; + daeSIDResolver jointResolver( pNode, "./matrix" ); + domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() ); + if ( pMatrix ) + { + //LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL; + domFloat4x4 domArray = pMatrix->getValue(); + for ( int i = 0; i < 4; i++ ) + { + for( int j = 0; j < 4; j++ ) + { + workingTransform.mMatrix[i][j] = domArray[i + j*4]; + } + } + } + else + { + LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL; + } + } + else + { + extractTranslationViaElement( pTranslateElement, workingTransform ); + } + } + + //Store the working transform relative to the nodes name. + jointTransforms[ pNode->getName() ] = workingTransform; + + //2. handle the nodes children + + //Gather and handle the incoming nodes children + daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren(); + S32 childOfChildCount = childOfChild.getCount(); + + for (S32 i = 0; i < childOfChildCount; ++i) + { + domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); + if ( pChildNode ) + { + processJointNode( pChildNode, jointTransforms ); + } + } +} +//----------------------------------------------------------------------------- +// getChildFromElement() +//----------------------------------------------------------------------------- +daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string const & name ) +{ + daeElement* pChildOfElement = pElement->getChild( name.c_str() ); + if ( pChildOfElement ) + { + return pChildOfElement; + } + LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; + return NULL; +} + +void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae ) +{ + LLMatrix4 saved_transform; + bool pushed_mat = false; + + domNode* node = daeSafeCast<domNode>(element); + if (node) + { + pushed_mat = true; + saved_transform = mTransform; + } + + domTranslate* translate = daeSafeCast<domTranslate>(element); + if (translate) + { + domFloat3 dom_value = translate->getValue(); + + LLMatrix4 translation; + translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + translation *= mTransform; + mTransform = translation; + mTransform.condition(); + } + + domRotate* rotate = daeSafeCast<domRotate>(element); + if (rotate) + { + domFloat4 dom_value = rotate->getValue(); + + LLMatrix4 rotation; + rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); + + rotation *= mTransform; + mTransform = rotation; + mTransform.condition(); + } + + domScale* scale = daeSafeCast<domScale>(element); + if (scale) + { + domFloat3 dom_value = scale->getValue(); + + + LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); + scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes + LLMatrix4 scaling; + scaling.initScale(scale_vector); + + scaling *= mTransform; + mTransform = scaling; + mTransform.condition(); + } + + domMatrix* matrix = daeSafeCast<domMatrix>(element); + if (matrix) + { + domFloat4x4 dom_value = matrix->getValue(); + + LLMatrix4 matrix_transform; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + matrix_transform *= mTransform; + mTransform = matrix_transform; + mTransform.condition(); + } + + domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element); + if (instance_geo) + { + domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()); + if (geo) + { + domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))); + if (mesh) + { + + std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); + while (i != mModelsMap[mesh].end()) + { + LLModel* model = *i; + + LLMatrix4 transformation = mTransform; + + if (mTransform.determinant() < 0) + { //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + LLModelLoader::material_map materials = getMaterials(model, instance_geo, dae); + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + mesh_translation *= transformation; + transformation = mesh_translation; + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= transformation; + transformation = mesh_scale; + + if (transformation.determinant() < 0) + { //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + std::string label; + + if (model->mLabel.empty()) + { + label = getLodlessLabel(instance_geo); + + llassert(!label.empty()); + + if (model->mSubmodelID) + { + label += (char)((int)'a' + model->mSubmodelID); + } + + model->mLabel = label + lod_suffix[mLod]; + } + else + { + // Don't change model's name if possible, it will play havoc with scenes that already use said model. + size_t ext_pos = getSuffixPosition(model->mLabel); + if (ext_pos != -1) + { + label = model->mLabel.substr(0, ext_pos); + } + else + { + label = model->mLabel; + } + } + + mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + i++; + } + } + } + else + { + LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL; + badElement = true; + } + + } + + domInstance_node* instance_node = daeSafeCast<domInstance_node>(element); + if (instance_node) + { + daeElement* instance = instance_node->getUrl().getElement(); + if (instance) + { + processElement(instance,badElement, dae); + } + } + + //process children + daeTArray< daeSmartRef<daeElement> > children = element->getChildren(); + int childCount = children.getCount(); + for (S32 i = 0; i < childCount; i++) + { + processElement(children[i],badElement, dae); + } + + if (pushed_mat) + { //this element was a node, restore transform before processiing siblings + mTransform = saved_transform; + } +} + +std::map<std::string, LLImportMaterial> LLDAELoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae) +{ + std::map<std::string, LLImportMaterial> materials; + for (int i = 0; i < model->mMaterialList.size(); i++) + { + LLImportMaterial import_material; + + domInstance_material* instance_mat = NULL; + + domBind_material::domTechnique_common* technique = + daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); + + if (technique) + { + daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>(); + for (int j = 0; j < inst_materials.getCount(); j++) + { + std::string symbol(inst_materials[j]->getSymbol()); + + if (symbol == model->mMaterialList[i]) // found the binding + { + instance_mat = inst_materials[j]; + break; + } + } + } + + if (instance_mat) + { + domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement()); + if (material) + { + domInstance_effect* instance_effect = + daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); + if (instance_effect) + { + domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement()); + if (effect) + { + domProfile_COMMON* profile = + daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); + if (profile) + { + import_material = profileToMaterial(profile, dae); + } + } + } + } + } + + import_material.mBinding = model->mMaterialList[i]; + materials[model->mMaterialList[i]] = import_material; + } + + return materials; +} + +LLImportMaterial LLDAELoader::profileToMaterial(domProfile_COMMON* material, DAE* dae) +{ + LLImportMaterial mat; + mat.mFullbright = FALSE; + + daeElement* diffuse = material->getDescendant("diffuse"); + if (diffuse) + { + domCommon_color_or_texture_type_complexType::domTexture* texture = + daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture")); + if (texture) + { + domCommon_newparam_type_Array newparams = material->getNewparam_array(); + if (newparams.getCount()) + { + + for (S32 i = 0; i < newparams.getCount(); i++) + { + domFx_surface_common* surface = newparams[i]->getSurface(); + if (surface) + { + domFx_surface_init_common* init = surface->getFx_surface_init_common(); + if (init) + { + domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); + + if (init_from.getCount() > i) + { + domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement()); + if (image) + { + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (init) + { + mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + } + } + } + else if (texture->getTexture()) + { + domImage* image = NULL; + dae->getDatabase()->getElement((daeElement**) &image, 0, texture->getTexture(), COLLADA_TYPE_IMAGE); + if (image) + { + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (init) + { + std::string image_path_value = cdom::uriToNativePath(init->getValue().str()); + +#if LL_WINDOWS + // Work-around DOM tendency to resort to UNC names which are only confusing for downstream... + // + std::string::iterator i = image_path_value.begin(); + while (*i == '\\') + i++; + mat.mDiffuseMapFilename.assign(i, image_path_value.end()); +#else + mat.mDiffuseMapFilename = image_path_value; +#endif + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + mat.mDiffuseColor = value; + } + } + + daeElement* emission = material->getDescendant("emission"); + if (emission) + { + LLColor4 emission_color = getDaeColor(emission); + if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) + { + mat.mFullbright = TRUE; + } + } + + return mat; +} + +// try to get a decent label for this element +std::string LLDAELoader::getElementLabel(daeElement *element) +{ + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + std::string index_string; + if (parent) + { + // retrieve index to distinguish items inside same parent + size_t ind = 0; + parent->getChildren().find(element, ind); + index_string = "_" + boost::lexical_cast<std::string>(ind); + + // if parent has a name or ID, use it + std::string name = parent->getAttribute("name"); + if (!name.length()) + { + name = std::string(parent->getID()); + } + + if (name.length()) + { + // make sure that index won't mix up with pre-named lod extensions + size_t ext_pos = getSuffixPosition(name); + + if (ext_pos == -1) + { + return name + index_string; + } + else + { + return name.insert(ext_pos, index_string); + } + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name) + index_string; + } + + // if all else fails, use "object" + return std::string("object") + index_string; +} + +// static +size_t LLDAELoader::getSuffixPosition(std::string label) +{ + if ((label.find("_LOD") != -1) || (label.find("_PHYS") != -1)) + { + return label.rfind('_'); + } + return -1; +} + +// static +std::string LLDAELoader::getLodlessLabel(daeElement *element) +{ + std::string label = getElementLabel(element); + size_t ext_pos = getSuffixPosition(label); + if (ext_pos != -1) + { + return label.substr(0, ext_pos); + } + return label; +} + +LLColor4 LLDAELoader::getDaeColor(daeElement* element) +{ + LLColor4 value; + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + } + + return value; +} + +bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh) +{ + LLModel::EModelStatus status = LLModel::NO_ERRORS; + domTriangles_Array& tris = mesh->getTriangles_array(); + + for (U32 i = 0; i < tris.getCount(); ++i) + { + domTrianglesRef& tri = tris.get(i); + + status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri); + pModel->mStatus = status; + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + domPolylist_Array& polys = mesh->getPolylist_array(); + for (U32 i = 0; i < polys.getCount(); ++i) + { + domPolylistRef& poly = polys.get(i); + status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + domPolygons_Array& polygons = mesh->getPolygons_array(); + + for (U32 i = 0; i < polygons.getCount(); ++i) + { + domPolygonsRef& poly = polygons.get(i); + status = load_face_from_dom_polygons(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + return (status == LLModel::NO_ERRORS); +} + +//static +LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* ret = new LLModel(volume_params, 0.f); + createVolumeFacesFromDomMesh(ret, mesh); + if (ret->mLabel.empty()) + { + ret->mLabel = getElementLabel(mesh); + } + return ret; +} + +//static diff version supports creating multiple models when material counts spill +// over the 8 face server-side limit +// +bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit) +{ + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + models_out.clear(); + + LLModel* ret = new LLModel(volume_params, 0.f); + + std::string model_name = getLodlessLabel(mesh); + ret->mLabel = model_name + lod_suffix[mLod]; + + llassert(!ret->mLabel.empty()); + + // Like a monkey, ready to be shot into space + // + ret->ClearFacesAndMaterials(); + + // Get the whole set of volume faces + // + addVolumeFacesFromDomMesh(ret, mesh); + + U32 volume_faces = ret->getNumVolumeFaces(); + + // Side-steps all manner of issues when splitting models + // and matching lower LOD materials to base models + // + ret->sortVolumeFacesByMaterialName(); + + bool normalized = false; + + int submodelID = 0; + + // remove all faces that definitely won't fit into one model and submodel limit + U32 face_limit = (submodel_limit + 1) * LL_SCULPT_MESH_MAX_FACES; + if (face_limit < volume_faces) + { + ret->setNumVolumeFaces(face_limit); + } + + LLVolume::face_list_t remainder; + do + { + // Insure we do this once with the whole gang and not per-model + // + if (!normalized && !mNoNormalize) + { + normalized = true; + ret->normalizeVolumeFaces(); + } + + ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder); + + if (!mNoOptimize) + { + ret->optimizeVolumeFaces(); + } + + volume_faces = remainder.size(); + + models_out.push_back(ret); + + // If we have left-over volume faces, create another model + // to absorb them... + // + if (volume_faces) + { + LLModel* next = new LLModel(volume_params, 0.f); + next->mSubmodelID = ++submodelID; + next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod]; + next->getVolumeFaces() = remainder; + next->mNormalizedScale = ret->mNormalizedScale; + next->mNormalizedTranslation = ret->mNormalizedTranslation; + if ( ret->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES) + { + next->mMaterialList.assign(ret->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, ret->mMaterialList.end()); + } + ret = next; + } + + remainder.clear(); + + } while (volume_faces); + + return true; +} + +bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh) +{ + if (mesh) + { + pModel->ClearFacesAndMaterials(); + + addVolumeFacesFromDomMesh(pModel, mesh); + + if (pModel->getNumVolumeFaces() > 0) + { + pModel->normalizeVolumeFaces(); + pModel->optimizeVolumeFaces(); + + if (pModel->getNumVolumeFaces() > 0) + { + return true; + } + } + } + else + { + LL_WARNS() << "no mesh found" << LL_ENDL; + } + + return false; +} diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h new file mode 100644 index 0000000000..7d91a6063b --- /dev/null +++ b/indra/llprimitive/lldaeloader.h @@ -0,0 +1,107 @@ +/** + * @file lldaeloader.h + * @brief LLDAELoader class definition + * + * $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_LLDAELOADER_H +#define LL_LLDAELOADER_H + +#include "llmodelloader.h" + +class DAE; +class daeElement; +class domProfile_COMMON; +class domInstance_geometry; +class domNode; +class domTranslate; +class domController; +class domSkin; +class domMesh; + +class LLDAELoader : public LLModelLoader +{ +public: + typedef std::map<std::string, LLImportMaterial> material_map; + typedef std::map<daeElement*, std::vector<LLPointer<LLModel> > > dae_model_map; + dae_model_map mModelsMap; + + LLDAELoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes, + U32 modelLimit); + virtual ~LLDAELoader() ; + + virtual bool OpenFile(const std::string& filename); + +protected: + + void processElement(daeElement* element, bool& badElement, DAE* dae); + void processDomModel(LLModel* model, DAE* dae, daeElement* pRoot, domMesh* mesh, domSkin* skin); + + material_map getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae); + LLImportMaterial profileToMaterial(domProfile_COMMON* material, DAE* dae); + LLColor4 getDaeColor(daeElement* element); + + daeElement* getChildFromElement( daeElement* pElement, std::string const & name ); + + bool isNodeAJoint( domNode* pNode ); + void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms ); + void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ); + void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ); + void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ); + void buildJointToNodeMappingFromScene( daeElement* pRoot ); + void processJointToNodeMapping( domNode* pNode ); + void processChildJoints( domNode* pParentNode ); + + bool verifyCount( int expected, int result ); + + //Verify that a controller matches vertex counts + bool verifyController( domController* pController ); + + static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh); + static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh); + + static LLModel* loadModelFromDomMesh(domMesh* mesh); + + // Loads a mesh breaking it into one or more models as necessary + // to get around volume face limitations while retaining >8 materials + // + bool loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit); + + static std::string getElementLabel(daeElement *element); + static size_t getSuffixPosition(std::string label); + static std::string getLodlessLabel(daeElement *element); + +private: + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels + +}; +#endif // LL_LLDAELLOADER_H diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 1571427d51..e494c55250 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -31,18 +31,6 @@ #include "llconvexdecomposition.h" #include "llsdserialize.h" #include "llvector4a.h" -#if LL_MSVC -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#include "dae.h" -#include "dae/daeErrorHandler.h" -#include "dom/domConstants.h" -#include "dom/domMesh.h" -#if LL_MSVC -#pragma warning (default : 4263) -#pragma warning (default : 4264) -#endif #ifdef LL_USESYSTEMLIBS # include <zlib.h> @@ -50,8 +38,6 @@ # include "zlib/zlib.h" #endif - - std::string model_names[] = { "lowest_lod", @@ -65,7 +51,7 @@ const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string); LLModel::LLModel(LLVolumeParams& params, F32 detail) : LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0) - , mPelvisOffset( 0.0f ), mStatus(NO_ERRORS) + , mPelvisOffset( 0.0f ), mStatus(NO_ERRORS), mSubmodelID(0) { mDecompID = -1; mLocalID = -1; @@ -79,923 +65,112 @@ LLModel::~LLModel() } } - -bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, - domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +//static +std::string LLModel::getStatusString(U32 status) { - idx_stride = 0; + const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"}; - for (U32 j = 0; j < inputs.getCount(); ++j) + if(status < INVALID_STATUS) { - idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) - { //found vertex array - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if ( !vertices ) - { - return false; - } - - domInputLocal_Array& v_inp = vertices->getInput_array(); - - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - pos_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - pos_source = (domSource*) elem.cast(); - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) - { - norm_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); - } - } - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + if(status_strings[status] == std::string()) { - //found normal array for this triangle list - norm_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); + //LL_ERRS() << "No valid status string for this status: " << (U32)status << LL_ENDL(); } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) - { //found texCoords - tc_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - tc_source = (domSource*) elem.cast(); - } - } - - idx_stride += 1; - - return true; -} - -LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri) -{ - LLVolumeFace face; - std::vector<LLVolumeFace::VertexData> verts; - std::vector<U16> indices; - - const domInputLocalOffset_Array& inputs = tri->getInput_array(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) - { - LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; + return status_strings[status] ; } - if (!pos_source) - { - LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - domPRef p = tri->getP(); - domListOfUInts& idx = p->getValue(); - - domListOfFloats dummy ; - domListOfFloats& v = (pos_source && pos_source->getFloat_array()) ? pos_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& tc = (tc_source && tc_source->getFloat_array()) ? tc_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& n = (norm_source && norm_source->getFloat_array()) ? norm_source->getFloat_array()->getValue() : dummy ; + //LL_ERRS() << "Invalid model status: " << (U32)status << LL_ENDL(); - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = (pos_source && pos_source->getFloat_array()) ? v.getCount() : 0; - U32 tc_count = (tc_source && tc_source->getFloat_array()) ? tc.getCount() : 0; - U32 norm_count = (norm_source && norm_source->getFloat_array()) ? n.getCount(): 0; + return std::string() ; +} - if (vertex_count == 0) - { - LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); +void LLModel::offsetMesh( const LLVector3& pivotPoint ) +{ + LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); - for (U32 i = 0; i < index_count; i += idx_stride) - { - LLVolumeFace::VertexData cv; - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((i + pos_offset) > index_count) - || ((idx[i+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], - v[idx[i+pos_offset]*3+1], - v[idx[i+pos_offset]*3+2])); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - - if (((i + tc_offset) > index_count) - || ((idx[i+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], - tc[idx[i+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((i + norm_offset) > index_count) - || ((idx[i+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], - n[idx[i+norm_offset]*3+1], - n[idx[i+norm_offset]*3+2])); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); - - if (point_iter != point_map.end()) - { - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - if ((point_iter->second)[j] == cv) - { - found = TRUE; - indices.push_back((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - indices.push_back(index); - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); - } - } - - if (indices.size()%3 == 0 && verts.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - point_map.clear(); - } - } - - if (!verts.empty()) + for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) { - std::string material; - - if (tri->getMaterial()) - { - material = std::string(tri->getMaterial()); - } + std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; + LLVolumeFace& face = *currentFaceIt; + LLVector4a *pos = (LLVector4a*) face.mPositions; - materials.push_back(material); - face_list.push_back(face); - - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) + for (U32 i=0; i<face.mNumVertices; ++i ) { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; + pos[i].add( pivot ); } } - - return LLModel::NO_ERRORS ; } -LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly) +void LLModel::optimizeVolumeFaces() { - domPRef p = poly->getP(); - domListOfUInts& idx = p->getValue(); - - if (idx.getCount() == 0) - { - return LLModel::NO_ERRORS ; - } - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - - domListOfUInts& vcount = poly->getVcount()->getValue(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) - { - LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - LLVolumeFace face; - - std::vector<U16> indices; - std::vector<LLVolumeFace::VertexData> verts; - - domListOfFloats v; - domListOfFloats tc; - domListOfFloats n; - - if (pos_source) - { - v = pos_source->getFloat_array()->getValue(); - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); - } - - if (tc_source) - { - tc = tc_source->getFloat_array()->getValue(); - } - - if (norm_source) - { - n = norm_source->getFloat_array()->getValue(); - } - - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; - - U32 cur_idx = 0; - for (U32 i = 0; i < vcount.getCount(); ++i) - { //for each polygon - U32 first_index = 0; - U32 last_index = 0; - for (U32 j = 0; j < vcount[i]; ++j) - { //for each vertex - - LLVolumeFace::VertexData cv; - - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((cur_idx + pos_offset) > index_count) - || ((idx[cur_idx+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], - v[idx[cur_idx+pos_offset]*3+1], - v[idx[cur_idx+pos_offset]*3+2]); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading positions from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - if (((cur_idx + tc_offset) > index_count) - || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], - tc[idx[cur_idx+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((cur_idx + norm_offset) > index_count) - || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], - n[idx[cur_idx+norm_offset]*3+1], - n[idx[cur_idx+norm_offset]*3+2]); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - cur_idx += idx_stride; - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - LLVector3 pos3(cv.getPosition().getF32ptr()); - point_iter = point_map.find(pos3); - - if (point_iter != point_map.end()) - { - for (U32 k = 0; k < point_iter->second.size(); ++k) - { - if ((point_iter->second)[k] == cv) - { - found = TRUE; - U32 index = (point_iter->second)[k].mIndex; - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[pos3].push_back(d); - } - } - - if (indices.size()%3 == 0 && indices.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - verts.clear(); - indices.clear(); - point_map.clear(); - } - } - } - - if (!verts.empty()) + for (U32 i = 0; i < getNumVolumeFaces(); ++i) { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } + mVolumeFaces[i].optimize(); } - - return LLModel::NO_ERRORS ; } -LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly) +struct MaterialBinding { - LLVolumeFace face; - std::vector<U16> indices; - std::vector<LLVolumeFace::VertexData> verts; - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - S32 v_offset = -1; - S32 n_offset = -1; - S32 t_offset = -1; - - domListOfFloats* v = NULL; - domListOfFloats* n = NULL; - domListOfFloats* t = NULL; - - U32 stride = 0; - for (U32 i = 0; i < inputs.getCount(); ++i) - { - stride = llmax((U32) inputs[i]->getOffset()+1, stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) - { //found vertex array - v_offset = inputs[i]->getOffset(); - - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if (!vertices) - { - LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - domInputLocal_Array& v_inp = vertices->getInput_array(); - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - v = &(src->getFloat_array()->getValue()); - } - } - } - else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) - { - n_offset = inputs[i]->getOffset(); - //found normal array for this triangle list - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - n = &(src->getFloat_array()->getValue()); - } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) - { //found texCoords - t_offset = inputs[i]->getOffset(); - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - t = &(src->getFloat_array()->getValue()); - } - } - - domP_Array& ps = poly->getP_array(); - - //make a triangle list in <verts> - for (U32 i = 0; i < ps.getCount(); ++i) - { //for each polygon - domListOfUInts& idx = ps[i]->getValue(); - for (U32 j = 0; j < idx.getCount()/stride; ++j) - { //for each vertex - if (j > 2) - { - U32 size = verts.size(); - LLVolumeFace::VertexData v0 = verts[size-3]; - LLVolumeFace::VertexData v1 = verts[size-1]; - - verts.push_back(v0); - verts.push_back(v1); - } - - LLVolumeFace::VertexData vert; - - - if (v) - { - U32 v_idx = idx[j*stride+v_offset]*3; - v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); - vert.getPosition().set(v->get(v_idx), - v->get(v_idx+1), - v->get(v_idx+2)); - - if (!vert.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - //bounds check n and t lookups because some FBX to DAE converters - //use negative indices and empty arrays to indicate data does not exist - //for a particular channel - if (n && n->getCount() > 0) - { - U32 n_idx = idx[j*stride+n_offset]*3; - n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); - vert.getNormal().set(n->get(n_idx), - n->get(n_idx+1), - n->get(n_idx+2)); - - if (!vert.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.getNormal().clear(); - } - - - if (t && t->getCount() > 0) - { - U32 t_idx = idx[j*stride+t_offset]*2; - t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); - vert.mTexCoord.setVec(t->get(t_idx), - t->get(t_idx+1)); - - if (!vert.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.mTexCoord.clear(); - } - - - verts.push_back(vert); - } - } - - if (verts.empty()) - { - return LLModel::NO_ERRORS; - } - - face.mExtents[0] = verts[0].getPosition(); - face.mExtents[1] = verts[0].getPosition(); - - //create a map of unique vertices to indices - std::map<LLVolumeFace::VertexData, U32> vert_idx; - - U32 cur_idx = 0; - for (U32 i = 0; i < verts.size(); ++i) - { - std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]); - if (iter == vert_idx.end()) - { - vert_idx[verts[i]] = cur_idx++; - } - } - - //build vertex array from map - std::vector<LLVolumeFace::VertexData> new_verts; - new_verts.resize(vert_idx.size()); - - for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) - { - new_verts[iter->second] = iter->first; - update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); - } - - //build index array from map - indices.resize(verts.size()); - - for (U32 i = 0; i < verts.size(); ++i) - { - indices[i] = vert_idx[verts[i]]; - } - - // DEBUG just build an expanded triangle list - /*for (U32 i = 0; i < verts.size(); ++i) - { - indices.push_back((U16) i); - update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); - }*/ - - if (!new_verts.empty()) - { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(new_verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!n) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!t) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} + int index; + std::string matName; +}; -//static -std::string LLModel::getStatusString(U32 status) +struct MaterialSort { - const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"}; - - if(status < INVALID_STATUS) + bool operator()(const MaterialBinding& lhs, const MaterialBinding& rhs) { - if(status_strings[status] == std::string()) - { - LL_ERRS() << "No valid status string for this status: " << (U32)status << LL_ENDL ; - } - return status_strings[status] ; + return LLStringUtil::compareInsensitive(lhs.matName, rhs.matName) < 0; } +}; - LL_ERRS() << "Invalid model status: " << (U32)status << LL_ENDL ; - - return std::string() ; -} - -void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) +void LLModel::sortVolumeFacesByMaterialName() { - domTriangles_Array& tris = mesh->getTriangles_array(); - - for (U32 i = 0; i < tris.getCount(); ++i) - { - domTrianglesRef& tri = tris.get(i); + std::vector<MaterialBinding> bindings; + bindings.resize(mVolumeFaces.size()); - mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); - - if(mStatus != NO_ERRORS) + for (int i = 0; i < bindings.size(); i++) + { + bindings[i].index = i; + if(i < mMaterialList.size()) { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort + bindings[i].matName = mMaterialList[i]; } } + std::sort(bindings.begin(), bindings.end(), MaterialSort()); + std::vector< LLVolumeFace > new_faces; - domPolylist_Array& polys = mesh->getPolylist_array(); - for (U32 i = 0; i < polys.getCount(); ++i) + // remap the faces to be in the same order the mats now are... + // + new_faces.resize(bindings.size()); + for (int i = 0; i < bindings.size(); i++) { - domPolylistRef& poly = polys.get(i); - mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); - - if(mStatus != NO_ERRORS) + new_faces[i] = mVolumeFaces[bindings[i].index]; + if(i < mMaterialList.size()) { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort + mMaterialList[i] = bindings[i].matName; } } - - domPolygons_Array& polygons = mesh->getPolygons_array(); - - for (U32 i = 0; i < polygons.getCount(); ++i) - { - domPolygonsRef& poly = polygons.get(i); - mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } - } - + mVolumeFaces = new_faces; } -BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) +void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remainder) { - if (mesh) - { - mVolumeFaces.clear(); - mMaterialList.clear(); + llassert(new_count <= LL_SCULPT_MESH_MAX_FACES); - addVolumeFacesFromDomMesh(mesh); - - if (getNumVolumeFaces() > 0) - { - normalizeVolumeFaces(); - optimizeVolumeFaces(); - - if (getNumVolumeFaces() > 0) - { - return TRUE; - } - } - } - else - { - LL_WARNS() << "no mesh found" << LL_ENDL; - } - - return FALSE; -} - -void LLModel::offsetMesh( const LLVector3& pivotPoint ) -{ - LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); - - for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) + if (new_count && (getNumVolumeFaces() > new_count)) { - std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; - LLVolumeFace& face = *currentFaceIt; - LLVector4a *pos = (LLVector4a*) face.mPositions; - - for (U32 i=0; i<face.mNumVertices; ++i ) + // Copy out remaining volume faces for alternative handling, if provided + // + if (remainder) { - pos[i].add( pivot ); - } - } -} + (*remainder).assign(mVolumeFaces.begin() + new_count, mVolumeFaces.end()); + } -void LLModel::optimizeVolumeFaces() -{ - for (U32 i = 0; i < getNumVolumeFaces(); ++i) - { - mVolumeFaces[i].optimize(); + // Trim down to the final set of volume faces (now stuffed to the gills!) + // + mVolumeFaces.resize(new_count); } } @@ -1009,11 +184,6 @@ void LLModel::optimizeVolumeFaces() // within the unit cube. void LLModel::normalizeVolumeFaces() { - - // ensure we don't have too many faces - if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES) - mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES); - if (!mVolumeFaces.empty()) { LLVector4a min, max; @@ -1480,68 +650,10 @@ void LLModel::generateNormals(F32 angle_cutoff) } } -//static -std::string LLModel::getElementLabel(daeElement *element) -{ // try to get a decent label for this element - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -//static -LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) -{ - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - LLModel* ret = new LLModel(volume_params, 0.f); - ret->createVolumeFacesFromDomMesh(mesh); - ret->mLabel = getElementLabel(mesh); - return ret; -} std::string LLModel::getName() const { - if (!mRequestedLabel.empty()) - return mRequestedLabel; - else - return mLabel; + return mRequestedLabel.empty() ? mLabel : mRequestedLabel; } //static @@ -1556,7 +668,8 @@ LLSD LLModel::writeModel( BOOL upload_skin, BOOL upload_joints, BOOL nowrite, - BOOL as_slm) + BOOL as_slm, + int submodel_id) { LLSD mdl; @@ -1585,6 +698,14 @@ LLSD LLModel::writeModel( model[LLModel::LOD_PHYSICS] = NULL; } } + else if (submodel_id) + { + const LLModel::Decomposition fake_decomp; + mdl["secondary"] = true; + mdl["submodel_id"] = submodel_id; + mdl["physics_convex"] = fake_decomp.asLLSD(); + model[LLModel::LOD_PHYSICS] = NULL; + } if (as_slm) { //save material list names @@ -1596,7 +717,7 @@ LLSD LLModel::writeModel( for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) { - if (model[idx] && model[idx]->getNumVolumeFaces() > 0) + if (model[idx] && (model[idx]->getNumVolumeFaces() > 0) && model[idx]->getVolumeFace(0).mPositions != NULL) { LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr()); LLVector3 max_pos = min_pos; @@ -1829,6 +950,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO } } + if (mdl.has("submodel_id")) + { //write out submodel id + header["submodel_id"] = (LLSD::Integer)mdl["submodel_id"]; + } + std::string out[MODEL_NAMES_LENGTH]; for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) @@ -2012,7 +1138,9 @@ bool LLModel::loadModel(std::istream& is) } } - static const std::string nm[] = + mSubmodelID = header.has("submodel_id") ? header["submodel_id"].asInteger() : false; + + static const std::string lod_name[] = { "lowest_lod", "low_lod", @@ -2025,8 +1153,8 @@ bool LLModel::loadModel(std::istream& is) S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS); - if (header[nm[lod]]["offset"].asInteger() == -1 || - header[nm[lod]]["size"].asInteger() == 0 ) + if (header[lod_name[lod]]["offset"].asInteger() == -1 || + header[lod_name[lod]]["size"].asInteger() == 0 ) { //cannot load requested LOD LL_WARNS() << "LoD data is invalid!" << LL_ENDL; return false; @@ -2035,23 +1163,23 @@ bool LLModel::loadModel(std::istream& is) bool has_skin = header["skin"]["offset"].asInteger() >=0 && header["skin"]["size"].asInteger() > 0; - if (lod == LLModel::LOD_HIGH) + if ((lod == LLModel::LOD_HIGH) && !mSubmodelID) { //try to load skin info and decomp info std::ios::pos_type cur_pos = is.tellg(); loadSkinInfo(header, is); is.seekg(cur_pos); } - if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) + if ((lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) && !mSubmodelID) { std::ios::pos_type cur_pos = is.tellg(); loadDecomposition(header, is); is.seekg(cur_pos); } - is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + is.seekg(header[lod_name[lod]]["offset"].asInteger(), std::ios_base::cur); - if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger())) + if (unpackVolumeFaces(is, header[lod_name[lod]]["size"].asInteger())) { if (has_skin) { @@ -2117,8 +1245,10 @@ bool LLModel::isMaterialListSubset( LLModel* ref ) break; } } + if (!foundRef) { + LL_INFOS() << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << LL_ENDL; return false; } } @@ -2169,41 +1299,42 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn for (U32 i = 0; i < mMaterialList.size(); i++) { index_map[ref->mMaterialList[i]] = i; - if (!reorder) - { //if any material name does not match reference, we need to reorder - reorder = ref->mMaterialList[i] != mMaterialList[i]; - } + //if any material name does not match reference, we need to reorder + reorder |= ref->mMaterialList[i] != mMaterialList[i]; base_mat.insert(ref->mMaterialList[i]); cur_mat.insert(mMaterialList[i]); } - if (reorder && - base_mat == cur_mat) //don't reorder if material name sets don't match + if (reorder && (base_mat == cur_mat)) //don't reorder if material name sets don't match { std::vector<LLVolumeFace> new_face_list; - new_face_list.resize(mVolumeFaces.size()); + new_face_list.resize(mMaterialList.size()); std::vector<std::string> new_material_list; - new_material_list.resize(mVolumeFaces.size()); + new_material_list.resize(mMaterialList.size()); //rebuild face list so materials have the same order //as the reference model for (U32 i = 0; i < mMaterialList.size(); ++i) { U32 ref_idx = index_map[mMaterialList[i]]; - new_face_list[ref_idx] = mVolumeFaces[i]; + if (i < mVolumeFaces.size()) + { + new_face_list[ref_idx] = mVolumeFaces[i]; + } new_material_list[ref_idx] = mMaterialList[i]; } llassert(new_material_list == ref->mMaterialList); mVolumeFaces = new_face_list; - } - //override material list with reference model ordering - mMaterialList = ref->mMaterialList; + //override material list with reference model ordering + mMaterialList = ref->mMaterialList; + } + return true; } @@ -2234,7 +1365,7 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is) S32 offset = header["physics_convex"]["offset"].asInteger(); S32 size = header["physics_convex"]["size"].asInteger(); - if (offset >= 0 && size > 0) + if (offset >= 0 && size > 0 && !mSubmodelID) { is.seekg(offset, std::ios_base::cur); @@ -2642,3 +1773,227 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs) } } +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance) +{ + // small area check + { + LLVector4a edge1; edge1.setSub( a, b ); + LLVector4a edge2; edge2.setSub( a, c ); + ////////////////////////////////////////////////////////////////////////// + /// Linden Modified + ////////////////////////////////////////////////////////////////////////// + + // If no one edge is more than 10x longer than any other edge, we weaken + // the tolerance by a factor of 1e-4f. + + LLVector4a edge3; edge3.setSub( c, b ); + const F32 len1sq = edge1.dot3(edge1).getF32(); + const F32 len2sq = edge2.dot3(edge2).getF32(); + const F32 len3sq = edge3.dot3(edge3).getF32(); + bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); + bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); + bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); + if ( abOK && acOK && cbOK ) + { + tolerance *= 1e-4f; + } + + ////////////////////////////////////////////////////////////////////////// + /// End Modified + ////////////////////////////////////////////////////////////////////////// + + LLVector4a cross; cross.setCross3( edge1, edge2 ); + + LLVector4a edge1b; edge1b.setSub( b, a ); + LLVector4a edge2b; edge2b.setSub( b, c ); + LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); + + if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) + { + return true; + } + } + + // point triangle distance check + { + LLVector4a Q; Q.setSub(a, b); + LLVector4a R; R.setSub(c, b); + + const F32 QQ = dot3fpu(Q, Q); + const F32 RR = dot3fpu(R, R); + const F32 QR = dot3fpu(R, Q); + + volatile F32 QQRR = QQ * RR; + volatile F32 QRQR = QR * QR; + F32 Det = (QQRR - QRQR); + + if( Det == 0.0f ) + { + return true; + } + } + + return false; +} + +bool validate_face(const LLVolumeFace& face) +{ + for (U32 i = 0; i < face.mNumIndices; ++i) + { + if (face.mIndices[i] >= face.mNumVertices) + { + LL_WARNS() << "Face has invalid index." << LL_ENDL; + return false; + } + } + + if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) + { + LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; + return false; + } + + /*const LLVector4a scale(0.5f); + + for (U32 i = 0; i < face.mNumIndices; i+=3) + { + U16 idx1 = face.mIndices[i]; + U16 idx2 = face.mIndices[i+1]; + U16 idx3 = face.mIndices[i+2]; + + LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); + LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); + LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); + + if (ll_is_degenerate(v1,v2,v3)) + { + llwarns << "Degenerate face found!" << LL_ENDL; + return false; + } + }*/ + + return true; +} + +bool validate_model(const LLModel* mdl) +{ + if (mdl->getNumVolumeFaces() == 0) + { + LL_WARNS() << "Model has no faces!" << LL_ENDL; + return false; + } + + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + if (mdl->getVolumeFace(i).mNumVertices == 0) + { + LL_WARNS() << "Face has no vertices." << LL_ENDL; + return false; + } + + if (mdl->getVolumeFace(i).mNumIndices == 0) + { + LL_WARNS() << "Face has no indices." << LL_ENDL; + return false; + } + + if (!validate_face(mdl->getVolumeFace(i))) + { + return false; + } + } + + return true; +} + +LLModelInstance::LLModelInstance(LLSD& data) + : LLModelInstanceBase() +{ + mLocalMeshID = data["mesh_id"].asInteger(); + mLabel = data["label"].asString(); + mTransform.setValue(data["transform"]); + + for (U32 i = 0; i < data["material"].size(); ++i) + { + LLImportMaterial mat(data["material"][i]); + mMaterial[mat.mBinding] = mat; + } +} + + +LLSD LLModelInstance::asLLSD() +{ + LLSD ret; + + ret["mesh_id"] = mModel->mLocalID; + ret["label"] = mLabel; + ret["transform"] = mTransform.getValue(); + + U32 i = 0; + for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) + { + ret["material"][i++] = iter->second.asLLSD(); + } + + return ret; +} + + +LLImportMaterial::~LLImportMaterial() +{ +} + +LLImportMaterial::LLImportMaterial(LLSD& data) +{ + mDiffuseMapFilename = data["diffuse"]["filename"].asString(); + mDiffuseMapLabel = data["diffuse"]["label"].asString(); + mDiffuseColor.setValue(data["diffuse"]["color"]); + mFullbright = data["fullbright"].asBoolean(); + mBinding = data["binding"].asString(); +} + + +LLSD LLImportMaterial::asLLSD() +{ + LLSD ret; + + ret["diffuse"]["filename"] = mDiffuseMapFilename; + ret["diffuse"]["label"] = mDiffuseMapLabel; + ret["diffuse"]["color"] = mDiffuseColor.getValue(); + ret["fullbright"] = mFullbright; + ret["binding"] = mBinding; + + return ret; +} + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + + if (mDiffuseMapID != rhs.mDiffuseMapID) + { + return mDiffuseMapID < rhs.mDiffuseMapID; + } + + if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) + { + return mDiffuseMapFilename < rhs.mDiffuseMapFilename; + } + + if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) + { + return mDiffuseMapLabel < rhs.mDiffuseMapLabel; + } + + if (mDiffuseColor != rhs.mDiffuseColor) + { + return mDiffuseColor < rhs.mDiffuseColor; + } + + if (mBinding != rhs.mBinding) + { + return mBinding < rhs.mBinding; + } + + return mFullbright < rhs.mFullbright; +} + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index aaafc55258..ae602c09df 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -31,6 +31,7 @@ #include "llvolume.h" #include "v4math.h" #include "m4math.h" +#include <queue> class daeElement; class domMesh; @@ -138,15 +139,16 @@ public: BOOL upload_skin, BOOL upload_joints, BOOL nowrite = FALSE, - BOOL as_slm = FALSE); + BOOL as_slm = FALSE, + int submodel_id = 0); static LLSD writeModelToStream( std::ostream& ostr, LLSD& mdl, BOOL nowrite = FALSE, BOOL as_slm = FALSE); + + void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); } - static LLModel* loadModelFromDomMesh(domMesh* mesh); - static std::string getElementLabel(daeElement* element); std::string getName() const; std::string getMetric() const {return mMetric;} EModelStatus getStatus() const {return mStatus;} @@ -169,20 +171,25 @@ public: void addFace(const LLVolumeFace& face); + void sortVolumeFacesByMaterialName(); void normalizeVolumeFaces(); + void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); void optimizeVolumeFaces(); void offsetMesh( const LLVector3& pivotPoint ); void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); LLVector3 getTransformedCenter(const LLMatrix4& mat); - + //reorder face list based on mMaterialList in this and reference so //order matches that of reference (material ordering touchup) bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt ); bool isMaterialListSubset( LLModel* ref ); bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt ); - - std::vector<std::string> mMaterialList; + typedef std::vector<std::string> material_list; + + material_list mMaterialList; + + material_list& getMaterialList() { return mMaterialList; } //data used for skin weights class JointWeight @@ -275,9 +282,115 @@ public: Decomposition mPhysics; EModelStatus mStatus ; + + int mSubmodelID; +}; + +typedef std::vector<LLPointer<LLModel> > model_list; +typedef std::queue<LLPointer<LLModel> > model_queue; + +class LLModelMaterialBase +{ +public: + std::string mDiffuseMapFilename; + std::string mDiffuseMapLabel; + std::string mBinding; + LLColor4 mDiffuseColor; + bool mFullbright; + + LLModelMaterialBase() + : mFullbright(false) + { + mDiffuseColor.set(1,1,1,1); + } +}; + +class LLImportMaterial : public LLModelMaterialBase +{ +public: + friend class LLMeshUploadThread; + friend class LLModelPreview; + + bool operator<(const LLImportMaterial ¶ms) const; + + LLImportMaterial() : LLModelMaterialBase() + { + mDiffuseColor.set(1,1,1,1); + } + + LLImportMaterial(LLSD& data); + virtual ~LLImportMaterial(); + + LLSD asLLSD(); + + const LLUUID& getDiffuseMap() const { return mDiffuseMapID; } + void setDiffuseMap(const LLUUID& texId) { mDiffuseMapID = texId; } + protected: - void addVolumeFacesFromDomMesh(domMesh* mesh); - virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); + + LLUUID mDiffuseMapID; + void* mOpaqueData; // allow refs to viewer/platform-specific structs for each material + // currently only stores an LLPointer< LLViewerFetchedTexture > > to + // maintain refs to textures associated with each material for free + // ref counting. }; +typedef std::map<std::string, LLImportMaterial> material_map; + +class LLModelInstanceBase +{ +public: + LLPointer<LLModel> mModel; + LLPointer<LLModel> mLOD[5]; + LLUUID mMeshID; + + LLMatrix4 mTransform; + material_map mMaterial; + + LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials) + : mModel(model), mTransform(transform), mMaterial(materials) + { + } + + LLModelInstanceBase() + : mModel(NULL) + { + } +}; + +typedef std::vector<LLModelInstanceBase> model_instance_list; + +class LLModelInstance : public LLModelInstanceBase +{ +public: + std::string mLabel; + LLUUID mMeshID; + S32 mLocalMeshID; + + LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials) + : LLModelInstanceBase(model, transform, materials), mLabel(label) + { + mLocalMeshID = -1; + } + + LLModelInstance(LLSD& data); + + LLSD asLLSD(); +}; + +#define LL_DEGENERACY_TOLERANCE 1e-7f + +inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) +{ + volatile F32 p0 = a[0] * b[0]; + volatile F32 p1 = a[1] * b[1]; + volatile F32 p2 = a[2] * b[2]; + return p0 + p1 + p2; +} + +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE); + +bool validate_face(const LLVolumeFace& face); +bool validate_model(const LLModel* mdl); + #endif //LL_LLMODEL_H diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp new file mode 100644 index 0000000000..81d92d151b --- /dev/null +++ b/indra/llprimitive/llmodelloader.cpp @@ -0,0 +1,640 @@ +/** + * @file llmodelloader.cpp + * @brief LLModelLoader class implementation + * + * $LicenseInfo:firstyear=2004&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 "llmodelloader.h" +#include "llsdserialize.h" +#include "lljoint.h" +#include "llcallbacklist.h" + +#include "glh/glh_linear.h" +#include "llmatrix4a.h" +#include <boost/bind.hpp> + +std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList; + +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) +{ + LLVector4a box[] = + { + LLVector4a(-1, 1,-1), + LLVector4a(-1, 1, 1), + LLVector4a(-1,-1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1, 1,-1), + LLVector4a( 1, 1, 1), + LLVector4a( 1,-1,-1), + LLVector4a( 1,-1, 1), + }; + + for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) + { + const LLVolumeFace& face = model->getVolumeFace(j); + + LLVector4a center; + center.setAdd(face.mExtents[0], face.mExtents[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(face.mExtents[1],face.mExtents[0]); + size.mul(0.5f); + + for (U32 i = 0; i < 8; i++) + { + LLVector4a t; + t.setMul(size, box[i]); + t.add(center); + + LLVector4a v; + + mat.affineTransform(t, v); + + if (first_transform) + { + first_transform = FALSE; + min = max = v; + } + else + { + update_min_max(min, max, v); + } + } + } +} + +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) +{ + LLVector4a mina, maxa; + LLMatrix4a mata; + + mata.loadu(mat); + mina.load3(min.mV); + maxa.load3(max.mV); + + stretch_extents(model, mata, mina, maxa, first_transform); + + min.set(mina.getF32ptr()); + max.set(maxa.getF32ptr()); +} + +//----------------------------------------------------------------------------- +// LLModelLoader +//----------------------------------------------------------------------------- +LLModelLoader::LLModelLoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes ) +: mJointList( jointMap ) +, mJointsFromNode( jointsFromNodes ) +, LLThread("Model Loader") +, mFilename(filename) +, mLod(lod) +, mFirstTransform(TRUE) +, mNumOfFetchingTextures(0) +, mLoadCallback(load_cb) +, mJointLookupFunc(joint_lookup_func) +, mTextureLoadFunc(texture_load_func) +, mStateCallback(state_cb) +, mOpaqueData(opaque_userdata) +, mNoNormalize(false) +, mNoOptimize(false) +, mCacheOnlyHitIfRigged(false) +{ + mJointMap["mPelvis"] = "mPelvis"; + mJointMap["mTorso"] = "mTorso"; + mJointMap["mChest"] = "mChest"; + mJointMap["mNeck"] = "mNeck"; + mJointMap["mHead"] = "mHead"; + mJointMap["mSkull"] = "mSkull"; + mJointMap["mEyeRight"] = "mEyeRight"; + mJointMap["mEyeLeft"] = "mEyeLeft"; + mJointMap["mCollarLeft"] = "mCollarLeft"; + mJointMap["mShoulderLeft"] = "mShoulderLeft"; + mJointMap["mElbowLeft"] = "mElbowLeft"; + mJointMap["mWristLeft"] = "mWristLeft"; + mJointMap["mCollarRight"] = "mCollarRight"; + mJointMap["mShoulderRight"] = "mShoulderRight"; + mJointMap["mElbowRight"] = "mElbowRight"; + mJointMap["mWristRight"] = "mWristRight"; + mJointMap["mHipRight"] = "mHipRight"; + mJointMap["mKneeRight"] = "mKneeRight"; + mJointMap["mAnkleRight"] = "mAnkleRight"; + mJointMap["mFootRight"] = "mFootRight"; + mJointMap["mToeRight"] = "mToeRight"; + mJointMap["mHipLeft"] = "mHipLeft"; + mJointMap["mKneeLeft"] = "mKneeLeft"; + mJointMap["mAnkleLeft"] = "mAnkleLeft"; + mJointMap["mFootLeft"] = "mFootLeft"; + mJointMap["mToeLeft"] = "mToeLeft"; + + mJointMap["avatar_mPelvis"] = "mPelvis"; + mJointMap["avatar_mTorso"] = "mTorso"; + mJointMap["avatar_mChest"] = "mChest"; + mJointMap["avatar_mNeck"] = "mNeck"; + mJointMap["avatar_mHead"] = "mHead"; + mJointMap["avatar_mSkull"] = "mSkull"; + mJointMap["avatar_mEyeRight"] = "mEyeRight"; + mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; + mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; + mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; + mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; + mJointMap["avatar_mWristLeft"] = "mWristLeft"; + mJointMap["avatar_mCollarRight"] = "mCollarRight"; + mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; + mJointMap["avatar_mElbowRight"] = "mElbowRight"; + mJointMap["avatar_mWristRight"] = "mWristRight"; + mJointMap["avatar_mHipRight"] = "mHipRight"; + mJointMap["avatar_mKneeRight"] = "mKneeRight"; + mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; + mJointMap["avatar_mFootRight"] = "mFootRight"; + mJointMap["avatar_mToeRight"] = "mToeRight"; + mJointMap["avatar_mHipLeft"] = "mHipLeft"; + mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; + mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; + mJointMap["avatar_mFootLeft"] = "mFootLeft"; + mJointMap["avatar_mToeLeft"] = "mToeLeft"; + + + mJointMap["hip"] = "mPelvis"; + mJointMap["abdomen"] = "mTorso"; + mJointMap["chest"] = "mChest"; + mJointMap["neck"] = "mNeck"; + mJointMap["head"] = "mHead"; + mJointMap["figureHair"] = "mSkull"; + mJointMap["lCollar"] = "mCollarLeft"; + mJointMap["lShldr"] = "mShoulderLeft"; + mJointMap["lForeArm"] = "mElbowLeft"; + mJointMap["lHand"] = "mWristLeft"; + mJointMap["rCollar"] = "mCollarRight"; + mJointMap["rShldr"] = "mShoulderRight"; + mJointMap["rForeArm"] = "mElbowRight"; + mJointMap["rHand"] = "mWristRight"; + mJointMap["rThigh"] = "mHipRight"; + mJointMap["rShin"] = "mKneeRight"; + mJointMap["rFoot"] = "mFootRight"; + mJointMap["lThigh"] = "mHipLeft"; + mJointMap["lShin"] = "mKneeLeft"; + mJointMap["lFoot"] = "mFootLeft"; + + //move into joint mapper class + //1. joints for joint offset verification + mMasterJointList.push_front("mPelvis"); + mMasterJointList.push_front("mTorso"); + mMasterJointList.push_front("mChest"); + mMasterJointList.push_front("mNeck"); + mMasterJointList.push_front("mHead"); + mMasterJointList.push_front("mCollarLeft"); + mMasterJointList.push_front("mShoulderLeft"); + mMasterJointList.push_front("mElbowLeft"); + mMasterJointList.push_front("mWristLeft"); + mMasterJointList.push_front("mCollarRight"); + mMasterJointList.push_front("mShoulderRight"); + mMasterJointList.push_front("mElbowRight"); + mMasterJointList.push_front("mWristRight"); + mMasterJointList.push_front("mHipRight"); + mMasterJointList.push_front("mKneeRight"); + mMasterJointList.push_front("mFootRight"); + mMasterJointList.push_front("mHipLeft"); + mMasterJointList.push_front("mKneeLeft"); + mMasterJointList.push_front("mFootLeft"); + + //2. legacy joint list - used to verify rigs that will not be using joint offsets + mMasterLegacyJointList.push_front("mPelvis"); + mMasterLegacyJointList.push_front("mTorso"); + mMasterLegacyJointList.push_front("mChest"); + mMasterLegacyJointList.push_front("mNeck"); + mMasterLegacyJointList.push_front("mHead"); + mMasterLegacyJointList.push_front("mHipRight"); + mMasterLegacyJointList.push_front("mKneeRight"); + mMasterLegacyJointList.push_front("mFootRight"); + mMasterLegacyJointList.push_front("mHipLeft"); + mMasterLegacyJointList.push_front("mKneeLeft"); + mMasterLegacyJointList.push_front("mFootLeft"); + + assert_main_thread(); + sActiveLoaderList.push_back(this) ; +} + +LLModelLoader::~LLModelLoader() +{ + assert_main_thread(); + sActiveLoaderList.remove(this); +} + +void LLModelLoader::run() +{ + doLoadModel(); + doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); +} + +bool LLModelLoader::doLoadModel() +{ + //first, look for a .slm file of the same name that was modified later + //than the .dae + + if (mTrySLM) + { + std::string filename = mFilename; + + std::string::size_type i = filename.rfind("."); + if (i != std::string::npos) + { + filename.replace(i, filename.size()-1, ".slm"); + llstat slm_status; + if (LLFile::stat(filename, &slm_status) == 0) + { //slm file exists + llstat dae_status; + if (LLFile::stat(mFilename, &dae_status) != 0 || + dae_status.st_mtime < slm_status.st_mtime) + { + if (loadFromSLM(filename)) + { //slm successfully loaded, if this fails, fall through and + //try loading from dae + + mLod = -1; //successfully loading from an slm implicitly sets all + //LoDs + return true; + } + } + } + } + } + + return OpenFile(mFilename); +} + +void LLModelLoader::setLoadState(U32 state) +{ + mStateCallback(state, mOpaqueData); +} + +bool LLModelLoader::loadFromSLM(const std::string& filename) +{ + //only need to populate mScene with data from slm + llstat stat; + + if (LLFile::stat(filename, &stat)) + { //file does not exist + return false; + } + + S32 file_size = (S32) stat.st_size; + + llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary); + LLSD data; + LLSDSerialize::fromBinary(data, ifstream, file_size); + ifstream.close(); + + //build model list for each LoD + model_list model[LLModel::NUM_LODS]; + + if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) + { //unsupported version + return false; + } + + LLSD& mesh = data["mesh"]; + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + for (U32 i = 0; i < mesh.size(); ++i) + { + std::stringstream str(mesh[i].asString()); + LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod); + if (loaded_model->loadModel(str)) + { + loaded_model->mLocalID = i; + model[lod].push_back(loaded_model); + + if (lod == LLModel::LOD_HIGH) + { + if (!loaded_model->mSkinInfo.mJointNames.empty()) + { + //check to see if rig is valid + critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames ); + } + else if (mCacheOnlyHitIfRigged) + { + return false; + } + } + } + } + } + + if (model[LLModel::LOD_HIGH].empty()) + { //failed to load high lod + return false; + } + + //load instance list + model_instance_list instance_list; + + LLSD& instance = data["instance"]; + + for (U32 i = 0; i < instance.size(); ++i) + { + //deserialize instance list + instance_list.push_back(LLModelInstance(instance[i])); + + //match up model instance pointers + S32 idx = instance_list[i].mLocalMeshID; + std::string instance_label = instance_list[i].mLabel; + + for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + if (!model[lod].empty()) + { + if (idx >= model[lod].size()) + { + if (model[lod].size()) + { + instance_list[i].mLOD[lod] = model[lod][0]; + } + else + { + instance_list[i].mLOD[lod] = NULL; + } + continue; + } + + if (model[lod][idx] + && model[lod][idx]->mLabel.empty() + && !instance_label.empty()) + { + // restore model names + std::string name = instance_label; + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + model[lod][idx]->mLabel = name; + } + + instance_list[i].mLOD[lod] = model[lod][idx]; + } + } + + if (!instance_list[i].mModel) + instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; + } + + // Set name for UI to use + std::string name = data["name"]; + if (!name.empty()) + { + model[LLModel::LOD_HIGH][0]->mRequestedLabel = name; + } + + + //convert instance_list to mScene + mFirstTransform = TRUE; + for (U32 i = 0; i < instance_list.size(); ++i) + { + LLModelInstance& cur_instance = instance_list[i]; + mScene[cur_instance.mTransform].push_back(cur_instance); + stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); + } + + setLoadState( DONE ); + + return true; +} + +//static +bool LLModelLoader::isAlive(LLModelLoader* loader) +{ + if(!loader) + { + return false ; + } + + std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ; + for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; + + return *iter == loader ; +} + +void LLModelLoader::loadModelCallback() +{ + mLoadCallback(mScene,mModelList,mLod, mOpaqueData); + + while (!isStopped()) + { //wait until this thread is stopped before deleting self + apr_sleep(100); + } + + //double check if "this" is valid before deleting it, in case it is aborted during running. + if(!isAlive(this)) + { + return ; + } + + delete this; +} + +//----------------------------------------------------------------------------- +// critiqueRigForUploadApplicability() +//----------------------------------------------------------------------------- +void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ) +{ + critiqueJointToNodeMappingFromScene(); + + //Determines the following use cases for a rig: + //1. It is suitable for upload with skin weights & joint positions, or + //2. It is suitable for upload as standard av with just skin weights + + bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); + bool isRigLegacyOK = isRigLegacy( jointListFromAsset ); + + //It's OK that both could end up being true, both default to false + if ( isJointPositionUploadOK ) + { + setRigValidForJointPositionUpload( true ); + } + + if ( isRigLegacyOK) + { + setLegacyRigValid( true ); + } + +} +//----------------------------------------------------------------------------- +// critiqueJointToNodeMappingFromScene() +//----------------------------------------------------------------------------- +void LLModelLoader::critiqueJointToNodeMappingFromScene( void ) +{ + //Do the actual nodes back the joint listing from the dae? + //if yes then this is a fully rigged asset, otherwise it's just a partial rig + + JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin(); + JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end(); + bool result = true; + + if ( !mJointsFromNode.empty() ) + { + for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt ) + { + std::string name = *jointsFromNodeIt; + if ( mJointTransformMap.find( name ) != mJointTransformMap.end() ) + { + continue; + } + else + { + LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL; + result = false; + } + } + } + else + { + result = false; + } + + //Determines the following use cases for a rig: + //1. Full av rig w/1-1 mapping from the scene and joint array + //2. Partial rig but w/o parity between the scene and joint array + if ( result ) + { + setRigWithSceneParity( true ); + } +} +//----------------------------------------------------------------------------- +// isRigLegacy() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAsset ) +{ + //No joints in asset + if ( jointListFromAsset.size() == 0 ) + { + return false; + } + + bool result = false; + + JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); + JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); + + std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin(); + std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); + + for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) + { + result = false; + modelJointIt = jointListFromAsset.begin(); + + for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) + { + if ( *masterJointIt == *modelJointIt ) + { + result = true; + break; + } + } + if ( !result ) + { + LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; + break; + } + } + return result; +} +//----------------------------------------------------------------------------- +// isRigSuitableForJointPositionUpload() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ) +{ + bool result = false; + + JointSet :: const_iterator masterJointIt = mMasterJointList.begin(); + JointSet :: const_iterator masterJointEndIt = mMasterJointList.end(); + + std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin(); + std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); + + for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) + { + result = false; + modelJointIt = jointListFromAsset.begin(); + + for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) + { + if ( *masterJointIt == *modelJointIt ) + { + result = true; + break; + } + } + if ( !result ) + { + LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; + break; + } + } + return result; +} + + +//called in the main thread +void LLModelLoader::loadTextures() +{ + BOOL is_paused = isPaused() ; + pause() ; //pause the loader + + for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) + { + for(U32 i = 0 ; i < iter->second.size(); i++) + { + for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin(); + j != iter->second[i].mMaterial.end(); ++j) + { + LLImportMaterial& material = j->second; + + if(!material.mDiffuseMapFilename.empty()) + { + mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData); + } + } + } + } + + if(!is_paused) + { + unpause() ; + } +} diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h new file mode 100644 index 0000000000..bb4d06dca3 --- /dev/null +++ b/indra/llprimitive/llmodelloader.h @@ -0,0 +1,212 @@ +/** + * @file llmodelloader.h + * @brief LLModelLoader class definition + * + * $LicenseInfo:firstyear=2004&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_LLMODELLOADER_H +#define LL_LLMODELLOADER_H + +#include "llmodel.h" +#include "llthread.h" +#include <boost/function.hpp> +#include <list> + +class LLJoint; + +typedef std::map<std::string, LLMatrix4> JointTransformMap; +typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt; +typedef std::map<std::string, std::string> JointMap; +typedef std::deque<std::string> JointSet; + +const S32 SLM_SUPPORTED_VERSION = 3; +const S32 NUM_LOD = 4; + +class LLModelLoader : public LLThread +{ +public: + + typedef std::map<std::string, LLImportMaterial> material_map; + typedef std::vector<LLPointer<LLModel > > model_list; + typedef std::vector<LLModelInstance> model_instance_list; + typedef std::map<LLMatrix4, model_instance_list > scene; + + // Callback with loaded model data and loaded LoD + // + typedef boost::function<void (scene&,model_list&,S32,void*) > load_callback_t; + + // Function to provide joint lookup by name + // (within preview avi skeleton, for example) + // + typedef boost::function<LLJoint* (const std::string&,void*) > joint_lookup_func_t; + + // Func to load and associate material with all it's textures, + // returned value is the number of textures loaded + // intentionally non-const so func can modify material to + // store platform-specific data + // + typedef boost::function<U32 (LLImportMaterial&,void*) > texture_load_func_t; + + // Callback to inform client of state changes + // during loading process (errors will be reported + // as state changes here as well) + // + typedef boost::function<void (U32,void*) > state_callback_t; + + typedef enum + { + STARTING = 0, + READING_FILE, + CREATING_FACES, + GENERATING_VERTEX_BUFFERS, + GENERATING_LOD, + DONE, + ERROR_PARSING, //basically loading failed + ERROR_MATERIALS, + ERROR_PASSWORD_REQUIRED, + ERROR_NEED_MORE_MEMORY, + ERROR_INVALID_FILE, + ERROR_LOADER_SETUP, + ERROR_INVALID_PARAMETERS, + ERROR_OUT_OF_RANGE, + ERROR_FILE_VERSION_INVALID, + ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code + } eLoadState; + + U32 mState; + std::string mFilename; + + S32 mLod; + + LLMatrix4 mTransform; + BOOL mFirstTransform; + LLVector3 mExtents[2]; + + bool mTrySLM; + bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info) + + model_list mModelList; + scene mScene; + + typedef std::queue<LLPointer<LLModel> > model_queue; + + //queue of models that need a physics rep + model_queue mPhysicsQ; + + //map of avatar joints as named in COLLADA assets to internal joint names + JointMap mJointMap; + JointTransformMap& mJointList; + JointSet& mJointsFromNode; + + LLModelLoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes); + virtual ~LLModelLoader() ; + + virtual void setNoNormalize() { mNoNormalize = true; } + virtual void setNoOptimize() { mNoOptimize = true; } + + virtual void run(); + + // Will try SLM or derived class OpenFile as appropriate + // + virtual bool doLoadModel(); + + // Derived classes need to provide their parsing of files here + // + virtual bool OpenFile(const std::string& filename) = 0; + + bool loadFromSLM(const std::string& filename); + + void loadModelCallback(); + void loadTextures() ; //called in the main thread. + void setLoadState(U32 state); + + + + S32 mNumOfFetchingTextures ; //updated in the main thread + bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. + + bool verifyCount( int expected, int result ); + + //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) + void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ); + void critiqueJointToNodeMappingFromScene( void ); + + //Determines if a rig is a legacy from the joint list + bool isRigLegacy( const std::vector<std::string> &jointListFromAsset ); + + //Determines if a rig is suitable for upload + bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ); + + void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } + const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } + + const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } + void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } + + const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } + + //----------------------------------------------------------------------------- + // isNodeAJoint() + //----------------------------------------------------------------------------- + bool isNodeAJoint(const char* name) + { + return mJointMap.find(name) != mJointMap.end(); + } + +protected: + + LLModelLoader::load_callback_t mLoadCallback; + LLModelLoader::joint_lookup_func_t mJointLookupFunc; + LLModelLoader::texture_load_func_t mTextureLoadFunc; + LLModelLoader::state_callback_t mStateCallback; + void* mOpaqueData; + + bool mRigParityWithScene; + bool mRigValidJointUpload; + bool mLegacyRigValid; + + bool mNoNormalize; + bool mNoOptimize; + + JointSet mMasterJointList; + JointSet mMasterLegacyJointList; + JointTransformMap mJointTransformMap; + + static std::list<LLModelLoader*> sActiveLoaderList; + static bool isAlive(LLModelLoader* loader) ; +}; +class LLMatrix4a; +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform); +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform); + +#endif // LL_LLMODELLOADER_H diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 29747cb09c..9eff74f1e8 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -317,9 +317,9 @@ S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID return mTextureList.setMaterialID(index, pMaterialID); } -S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) +S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer) { - return mTextureList.setMaterialParams(index, pMaterialParams); + return mTextureList.setMaterialParams(index, pMaterialParams, isInitFromServer); } LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index) @@ -1869,9 +1869,12 @@ BOOL LLSculptParams::pack(LLDataPacker &dp) const BOOL LLSculptParams::unpack(LLDataPacker &dp) { - dp.unpackUUID(mSculptTexture, "texture"); - dp.unpackU8(mSculptType, "type"); - + U8 type; + LLUUID id; + dp.unpackUUID(id, "texture"); + dp.unpackU8(type, "type"); + + setSculptTexture(id, type); return TRUE; } @@ -1896,8 +1899,7 @@ bool LLSculptParams::operator==(const LLNetworkData& data) const void LLSculptParams::copy(const LLNetworkData& data) { const LLSculptParams *param = (LLSculptParams*)&data; - mSculptTexture = param->mSculptTexture; - mSculptType = param->mSculptType; + setSculptTexture(param->mSculptTexture, param->mSculptType); } @@ -1915,20 +1917,38 @@ LLSD LLSculptParams::asLLSD() const bool LLSculptParams::fromLLSD(LLSD& sd) { const char *w; - w = "texture"; + U8 type; + w = "type"; if (sd.has(w)) { - setSculptTexture( sd[w] ); - } else goto fail; - w = "type"; + type = sd[w].asInteger(); + } + else return false; + + w = "texture"; if (sd.has(w)) { - setSculptType( (U8)sd[w].asInteger() ); - } else goto fail; - + setSculptTexture(sd[w], type); + } + else return false; + return true; - fail: - return false; +} + +void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) +{ + U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; + U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; + if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) + { + mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptType = LL_SCULPT_TYPE_SPHERE; + } + else + { + mSculptTexture = texture_id; + mSculptType = sculpt_type; + } } //============================================================================ diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 1bf83e36b4..54870fbb10 100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -259,9 +259,8 @@ public: operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); - void setSculptTexture(const LLUUID& id) { mSculptTexture = id; } + void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); LLUUID getSculptTexture() const { return mSculptTexture; } - void setSculptType(U8 type) { mSculptType = type; } U8 getSculptType() const { return mSculptType; } }; @@ -385,7 +384,7 @@ public: virtual S32 setTEMediaFlags(const U8 te, const U8 flags); virtual S32 setTEGlow(const U8 te, const F32 glow); virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); - virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); + virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer); virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed virtual void setTESelected(const U8 te, bool sel); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index f4f08248b8..6aae2f97c6 100755 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -368,11 +368,18 @@ S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMateri return TEM_CHANGE_NONE; } -S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) +S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer) { if (index < mEntryList.size()) { - return mEntryList[index]->setMaterialParams(pMaterialParams); + if (!isInitFromServer && mEntryList[index]->isMatParamsInitFromServer()) + { + return TEM_CHANGE_NONE; + } + else + { + return mEntryList[index]->setMaterialParams(pMaterialParams); + } } return TEM_CHANGE_NONE; } diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 49c636e40f..63e6372405 100755 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -105,7 +105,7 @@ public: S32 setMediaFlags(const U8 index, const U8 media_flags); S32 setGlow(const U8 index, const F32 glow); S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); - S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); + S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer); LLMaterialPtr getMaterialParams(const U8 index); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 284dfc15f4..6020031099 100755 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -63,6 +63,7 @@ LLTextureEntry::LLTextureEntry() : mMediaEntry(NULL) , mSelected(false) , mMaterialUpdatePending(false) + , mInitMatParamsFromServer(false) { init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } @@ -71,6 +72,7 @@ LLTextureEntry::LLTextureEntry(const LLUUID& tex_id) : mMediaEntry(NULL) , mSelected(false) , mMaterialUpdatePending(false) + , mInitMatParamsFromServer(false) { init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } @@ -79,6 +81,7 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) : mMediaEntry(NULL) , mSelected(false) , mMaterialUpdatePending(false) + , mInitMatParamsFromServer(false) { mID = rhs.mID; mScaleS = rhs.mScaleS; @@ -562,6 +565,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) mMaterialUpdatePending = true; } mMaterial = pMaterialParams; + this->mInitMatParamsFromServer = TRUE; return TEM_CHANGE_TEXTURE; } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 19edcaa27d..81e2e8a5a2 100755 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -89,6 +89,10 @@ public: bool operator==(const LLTextureEntry &rhs) const; bool operator!=(const LLTextureEntry &rhs) const; + + // Added to allow use with std::map + // + bool operator <(const LLTextureEntry &rhs) const; LLSD asLLSD() const; void asLLSD(LLSD& sd) const; @@ -156,6 +160,8 @@ public: const LLMaterialID& getMaterialID() const { return mMaterialID; }; const LLMaterialPtr getMaterialParams() const { return mMaterial; }; + bool isMatParamsInitFromServer() const { return mInitMatParamsFromServer; }; + // *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL. // CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData() // to NOT return NULL. @@ -213,6 +219,8 @@ protected: bool mMaterialUpdatePending; LLMaterialID mMaterialID; LLMaterialPtr mMaterial; + bool mInitMatParamsFromServer; // Flag to identification when material paramas initialized from + // Note the media data is not sent via the same message structure as the rest of the TE LLMediaEntry* mMediaEntry; // The media data for the face diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 3ceed95248..f9f7d07c89 100755 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -722,10 +722,77 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms) GLint activeCount; glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); + //........................................................................................................................................ + //........................................................................................ + + /* + EXPLANATION: + This is part of code is temporary because as the final result the mapUniform() should be rewrited. + But it's a huge a volume of work which is need to be a more carefully performed for avoid possible + regression's (i.e. it should be formalized a separate ticket in JIRA). + + RESON: + The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear + first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) + it influence to which is texture matrix will be updated during rendering. + + But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want + , even if the "diffuseMap" will be appear and use first in shader code. + + As example where this situation appear see: "Deferred Material Shader 28/29/30/31" + And tickets: MAINT-4165, MAINT-4839 + */ + + + S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap"); + S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap"); + + std::set<S32> skip_index; + + if(diffuseMap != -1 && bumpMap != -1) + { + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; + + //diffuse map + for (S32 i = 0; i < activeCount; i++) + { + name[0] = 0; + + glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name); + + if(std::string(name) == "diffuseMap") { + diffuseMap = i; + } + + if(std::string(name) == "bumpMap") { + bumpMap = i; + } + } + + if(bumpMap < diffuseMap) + { + mapUniform(diffuseMap, uniforms); + mapUniform(bumpMap, uniforms); + + skip_index.insert(diffuseMap); + skip_index.insert(bumpMap); + } + } + + //........................................................................................ + for (S32 i = 0; i < activeCount; i++) { + //........................................................................................ + if(skip_index.end() != skip_index.find(i)) continue; + //........................................................................................ + mapUniform(i, uniforms); } + //........................................................................................................................................ unbind(); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1ca6e99ecf..69420dd0bb 100755 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -104,10 +104,10 @@ LLTexUnit::LLTexUnit(S32 index) mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), - mHasMipMaps(false) + mHasMipMaps(false), + mIndex(index) { llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS); - mIndex = index; } //static @@ -227,33 +227,34 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) stop_glerror(); if (mIndex >= 0) { - gGL.flush(); + gGL.flush(); + + LLImageGL* gl_tex = NULL ; - LLImageGL* gl_tex = NULL ; if (texture != NULL && (gl_tex = texture->getGLTexture())) - { - if (gl_tex->getTexName()) //if texture exists - { - //in audit, replace the selected texture by the default one. - if ((mCurrTexture != gl_tex->getTexName()) || forceBind) - { - activate(); - enable(gl_tex->getTarget()); - mCurrTexture = gl_tex->getTexName(); - glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); - if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) - { - texture->setActive() ; - texture->updateBindStatsForTester() ; - } - mHasMipMaps = gl_tex->mHasMipMaps; - if (gl_tex->mTexOptionsDirty) { - gl_tex->mTexOptionsDirty = false; - setTextureAddressMode(gl_tex->mAddressMode); - setTextureFilteringOption(gl_tex->mFilterOption); - } - } + if (gl_tex->getTexName()) //if texture exists + { + //in audit, replace the selected texture by the default one. + if ((mCurrTexture != gl_tex->getTexName()) || forceBind) + { + activate(); + enable(gl_tex->getTarget()); + mCurrTexture = gl_tex->getTexName(); + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) + { + texture->setActive() ; + texture->updateBindStatsForTester() ; + } + mHasMipMaps = gl_tex->mHasMipMaps; + if (gl_tex->mTexOptionsDirty) + { + gl_tex->mTexOptionsDirty = false; + setTextureAddressMode(gl_tex->mAddressMode); + setTextureFilteringOption(gl_tex->mFilterOption); + } + } } else { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 42b02a8159..a67fb8da52 100755 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -198,7 +198,7 @@ public: void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } protected: - S32 mIndex; + const S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; eTextureBlendType mCurrBlendType; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index b32aea5ffa..559895da1a 100755 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -443,6 +443,7 @@ void LLComboBox::onFocusLost() { mTextEntry->selectAll(); } + mButton->setForcePressedState(false); LLUICtrl::onFocusLost(); } diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 74ef8dd0c3..3e159365e5 100755 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -131,6 +131,25 @@ LLCommand * LLCommandManager::getCommand(const LLCommandId& commandId) return command_match; } +LLCommand * LLCommandManager::getCommand(const std::string& name) +{ + LLCommand * command_match = NULL; + + CommandVector::const_iterator it = mCommands.begin(); + + while (it != mCommands.end()) + { + if ((*it)->name() == name) + { + command_match = *it; + break; + } + it++; + } + + return command_match; +} + void LLCommandManager::addCommand(LLCommand * command) { LLCommandId command_id = command->id(); diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index ff5a8a3257..f2f2145953 100755 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -190,6 +190,7 @@ public: U32 commandCount() const; LLCommand * getCommand(U32 commandIndex); LLCommand * getCommand(const LLCommandId& commandId); + LLCommand * getCommand(const std::string& name); static bool load(); diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 3396213f1c..c937d190c6 100755 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -153,7 +153,7 @@ void LLDockableFloater::setVisible(BOOL visible) mDockControl.get()->repositionDockable(); } - if (visible) + if (visible && !isMinimized()) { LLFloater::setFrontmost(getAutoFocus()); } diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 4c05d001a0..3282c5f726 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -730,7 +730,7 @@ void LLFolderView::removeSelectedItems() // structures. std::vector<LLFolderViewItem*> items; S32 count = mSelectedItems.size(); - if(count == 0) return; + if(count <= 0) return; LLFolderViewItem* item = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) @@ -947,7 +947,6 @@ void LLFolderView::cut() if (listener) { listener->cutToClipboard(); - listener->removeItem(); } } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 747b472ac2..3def0386e1 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -104,7 +104,8 @@ LLFolderViewItem::Params::Params() item_height("item_height"), item_top_pad("item_top_pad"), creation_date(), - allow_open("allow_open", true), + allow_wear("allow_wear", true), + allow_drop("allow_drop", true), font_color("font_color"), font_highlight_color("font_highlight_color"), left_pad("left_pad", 0), @@ -128,6 +129,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mSelectPending(FALSE), mLabelStyle( LLFontGL::NORMAL ), mHasVisibleChildren(FALSE), + mIsFolderComplete(true), mLocalIndentation(p.folder_indentation), mIndentation(0), mItemHeight(p.item_height), @@ -137,7 +139,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mRoot(p.root), mViewModelItem(p.listener), mIsMouseOverTitle(false), - mAllowOpen(p.allow_open), + mAllowWear(p.allow_wear), + mAllowDrop(p.allow_drop), mFontColor(p.font_color), mFontHighlightColor(p.font_highlight_color), mLeftPad(p.left_pad), @@ -471,7 +474,7 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) void LLFolderViewItem::openItem( void ) { - if (mAllowOpen) + if (mAllowWear || !getViewModelItem()->isItemWearable()) { getViewModelItem()->openItem(); } @@ -672,7 +675,7 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L // const S32 TOP_PAD = default_params.item_top_pad; - if (hasVisibleChildren()) + if (hasVisibleChildren() || !isFolderComplete()) { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( @@ -932,6 +935,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): mLastArrangeGeneration( -1 ), mLastCalculatedWidth(0) { + // folder might have children that are not loaded yet. Mark it as incomplete until chance to check it. + mIsFolderComplete = false; } void LLFolderViewFolder::updateLabelRotation() @@ -1014,6 +1019,12 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) mHasVisibleChildren = found; } + if (!mIsFolderComplete) + { + mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); + } + + // calculate height as a single item (without any children), and reshapes rectangle to match LLFolderViewItem::arrange( width, height ); @@ -1337,7 +1348,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo { return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1356,7 +1367,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1378,7 +1389,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1397,7 +1408,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo return; } - if (selecting) + if (selecting && (*it)->getVisible()) { items.push_back(*it); } @@ -1461,31 +1472,37 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) LLFolderView* root = getRoot(); - for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); + BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected + + // array always go from 'will be selected' to ' will be unselected', iterate + // in opposite direction to simplify identification of 'point of origin' in + // case it is in the list we are working with + for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend(); it != end_it; ++it) { LLFolderViewItem* item = *it; - if (item->isSelected()) + BOOL selected = item->isSelected(); + if (!selection_reverse && selected) { - root->removeFromSelectionList(item); + // it is our 'point of origin' where we shift/expand from + // don't deselect it + selection_reverse = TRUE; } else { - item->selectItem(); + root->changeSelection(item, !selected); } - root->addToSelectionList(item); } - if (new_selection->isSelected()) - { - root->removeFromSelectionList(new_selection); - } - else + if (selection_reverse) { - new_selection->selectItem(); + // at some point we reversed selection, first element should be deselected + root->changeSelection(last_selected_item_from_cur, FALSE); } - root->addToSelectionList(new_selection); + + // element we expand to should always be selected + root->changeSelection(new_selection, TRUE); } @@ -1494,12 +1511,14 @@ void LLFolderViewFolder::destroyView() while (!mItems.empty()) { LLFolderViewItem *itemp = mItems.back(); + mItems.pop_back(); itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems } while (!mFolders.empty()) { LLFolderViewFolder *folderp = mFolders.back(); + mFolders.pop_back(); folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders } @@ -1673,7 +1692,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r mIsOpen = openitem; if(!was_open && openitem) { - getViewModelItem()->openItem(); + getViewModelItem()->openItem(); + // openItem() will request content, it won't be incomplete + mIsFolderComplete = true; } else if(was_open && !openitem) { @@ -1797,9 +1818,16 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { + if (!mAllowDrop) + { + *accept = ACCEPT_NO; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); + return TRUE; + } + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) + + if (accepted) { mDragAndDropTarget = TRUE; *accept = ACCEPT_YES_MULTI; diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 5ad5731cad..0322c8836d 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -59,7 +59,8 @@ public: item_top_pad; Optional<time_t> creation_date; - Optional<bool> allow_open; + Optional<bool> allow_wear; + Optional<bool> allow_drop; Optional<LLUIColor> font_color; Optional<LLUIColor> font_highlight_color; @@ -114,10 +115,12 @@ protected: F32 mControlLabelRotation; LLFolderView* mRoot; bool mHasVisibleChildren, + mIsFolderComplete, // indicates that some children were not loaded/added yet mIsCurSelection, mDragAndDropTarget, mIsMouseOverTitle, - mAllowOpen, + mAllowWear, + mAllowDrop, mSelectPending; LLUIColor mFontColor; @@ -210,6 +213,9 @@ public: BOOL hasVisibleChildren() { return mHasVisibleChildren; } + // true if object can't have children + BOOL isFolderComplete() { return mIsFolderComplete; } + // Call through to the viewed object and return true if it can be // removed. Returns true if it's removed. //virtual BOOL removeRecursively(BOOL single_item); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index f6550eae42..a395af537a 100755 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -122,6 +122,7 @@ public: virtual void filter() = 0; virtual bool contentsReady() = 0; + virtual bool isFolderComplete(class LLFolderViewFolder*) = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; virtual LLFolderViewFilter& getFilter() = 0; virtual const LLFolderViewFilter& getFilter() const = 0; @@ -156,6 +157,8 @@ public: virtual void openItem( void ) = 0; virtual void closeItem( void ) = 0; virtual void selectItem(void) = 0; + + virtual BOOL isItemWearable() const { return FALSE; } virtual BOOL isItemRenameable() const = 0; virtual BOOL renameItem(const std::string& new_name) = 0; @@ -169,7 +172,7 @@ public: virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; + virtual BOOL cutToClipboard() = 0; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; @@ -442,6 +445,7 @@ public: // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, // this method needs to be overloaded and return the relevant fetch status. virtual bool contentsReady() { return true; } + virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; } struct ViewModelCompare { diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7cdbcb0621..848367f8a8 100755 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -225,7 +225,6 @@ BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask) BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask) { - setHover(TRUE); getWindow()->setCursor(UI_CURSOR_ARROW); return TRUE; } @@ -236,6 +235,18 @@ BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLUICtrl::handleRightMouseDown(x,y,mask); } +void LLMenuItemGL::onMouseEnter(S32 x, S32 y, MASK mask) +{ + setHover(TRUE); + LLUICtrl::onMouseEnter(x,y,mask); +} + +void LLMenuItemGL::onMouseLeave(S32 x, S32 y, MASK mask) +{ + setHover(FALSE); + LLUICtrl::onMouseLeave(x,y,mask); +} + //virtual BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask) { @@ -533,9 +544,6 @@ void LLMenuItemGL::draw( void ) gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1); } } - - // clear got hover every frame - setHover(FALSE); } BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& text ) @@ -1043,7 +1051,7 @@ void LLMenuItemBranchGL::onCommit( void ) // keyboard navigation automatically propagates highlight to sub-menu // to facilitate fast menu control via jump keys - if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem()) + if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem()) { getBranch()->highlightNextItem(NULL); } @@ -1456,7 +1464,16 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask ) { // switch to mouse control mode LLMenuGL::setKeyboardMode(FALSE); - onCommit(); + + if (getVisible() && isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + else + { + onCommit(); + } + make_ui_sound("UISndClick"); return TRUE; } @@ -1588,10 +1605,6 @@ void LLMenuItemBranchDownGL::draw( void ) gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS); } } - - // reset every frame so that we only show highlight - // when we get hover events on that frame - setHover(FALSE); } @@ -3381,6 +3394,11 @@ BOOL LLMenuBarGL::handleMouseDown(S32 x, S32 y, MASK mask) return LLMenuGL::handleMouseDown(x, y, mask); } +BOOL LLMenuBarGL::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + return LLMenuGL::handleMouseDown(x, y, mask); +} + void LLMenuBarGL::draw() { LLMenuItemGL* itemp = getHighlightedItem(); @@ -3625,8 +3643,24 @@ BOOL LLMenuHolderGL::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; if (!handled) { - // clicked off of menu, hide them all - hideMenus(); + LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu(); + LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL; + if (parent_menu && parent_menu->getVisible()) + { + // don't hide menu if parent was hit + LLRect parent_rect; + parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this); + if (!parent_rect.pointInRect(x, y)) + { + // clicked off of menu and parent, hide them all + hideMenus(); + } + } + else + { + // no visible parent, clicked off of menu, hide them all + hideMenus(); + } } return handled; } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index ae9b169691..628dedb906 100755 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -158,6 +158,10 @@ public: virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + virtual void draw( void ); BOOL getHover() const { return mGotHover; } @@ -753,6 +757,7 @@ public: /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ BOOL handleJumpKey(KEY key); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); /*virtual*/ void draw(); /*virtual*/ BOOL jumpKeysActive(); diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index ea96fc573d..1fdd05a11c 100755 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llsearcheditor.h" +#include "llkeyboard.h" LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) : LLUICtrl(p), @@ -166,4 +167,16 @@ void LLSearchEditor::handleKeystroke() { mKeystrokeCallback(this, getValue()); } + + KEY key = gKeyboard->currentKey(); + if (key == KEY_LEFT || + key == KEY_RIGHT) + { + return; + } + + if (mTextChangedCallback) + { + mTextChangedCallback(this, getValue()); + } } diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index c2d7916938..3b12868225 100755 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -82,12 +82,14 @@ public: virtual void setFocus( BOOL b ); void setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; } + void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; } protected: void onClearButtonClick(const LLSD& data); virtual void handleKeystroke(); commit_callback_t mKeystrokeCallback; + commit_callback_t mTextChangedCallback; LLLineEditor* mSearchEditor; LLButton* mSearchButton; LLButton* mClearButton; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 4b08798892..701a06a085 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1775,6 +1775,11 @@ void LLTabContainer::onNextBtn( const LLSD& data ) scrollNext(); } mScrolled = FALSE; + + if(mCurrentTabIdx < mTabList.size()-1) + { + selectNextTab(); + } } void LLTabContainer::onNextBtnHeld( const LLSD& data ) @@ -1783,6 +1788,11 @@ void LLTabContainer::onNextBtnHeld( const LLSD& data ) { mScrollTimer.reset(); scrollNext(); + + if(mCurrentTabIdx < mTabList.size()-1) + { + selectNextTab(); + } mScrolled = TRUE; } } @@ -1794,6 +1804,11 @@ void LLTabContainer::onPrevBtn( const LLSD& data ) scrollPrev(); } mScrolled = FALSE; + + if(mCurrentTabIdx > 0) + { + selectPrevTab(); + } } void LLTabContainer::onJumpFirstBtn( const LLSD& data ) @@ -1812,6 +1827,11 @@ void LLTabContainer::onPrevBtnHeld( const LLSD& data ) { mScrollTimer.reset(); scrollPrev(); + + if(mCurrentTabIdx > 0) + { + selectPrevTab(); + } mScrolled = TRUE; } } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 602a703450..bf660849c4 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -37,6 +37,7 @@ #include "lltextparser.h" #include "lltextutil.h" #include "lltooltip.h" +#include "lltrans.h" #include "lluictrl.h" #include "llurlaction.h" #include "llurlregistry.h" @@ -2060,27 +2061,33 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para // add icon before url if need LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); + if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() ) + { + setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon")); + } // output the styled Url appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly()); + bool tooltip_required = !match.getTooltip().empty(); + + // set the tooltip for the Url label + if (tooltip_required) + { + setLastSegmentToolTip(match.getTooltip()); + } - // show query part of url with gray color only for LLUrlEntryHTTP and LLUrlEntryHTTPNoProtocol url entries + // show query part of url with gray color only for LLUrlEntryHTTP url entries std::string label = match.getQuery(); if (label.size()) { link_params.color = LLColor4::grey; link_params.readonly_color = LLColor4::grey; appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); - } - - // set the tooltip for the Url label - if (! match.getTooltip().empty()) - { - segment_set_t::iterator it = getSegIterContaining(getLength()-1); - if (it != mSegments.end()) + + // set the tooltip for the query part of url + if (tooltip_required) { - LLTextSegmentPtr segment = *it; - segment->setToolTip(match.getTooltip()); + setLastSegmentToolTip(match.getTooltip()); } } @@ -2107,6 +2114,16 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } } +void LLTextBase::setLastSegmentToolTip(const std::string &tooltip) +{ + segment_set_t::iterator it = getSegIterContaining(getLength()-1); + if (it != mSegments.end()) + { + LLTextSegmentPtr segment = *it; + segment->setToolTip(tooltip); + } +} + static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text"); void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) @@ -3557,6 +3574,22 @@ S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin return 0; } +BOOL LLImageTextSegment::handleToolTip(S32 x, S32 y, MASK mask) +{ + if (!mTooltip.empty()) + { + LLToolTipMgr::instance().show(mTooltip); + return TRUE; + } + + return FALSE; +} + +void LLImageTextSegment::setToolTip(const std::string& tooltip) +{ + mTooltip = tooltip; +} + F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { if ( (start >= 0) && (end <= mEnd - mStart)) diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index dfc10923f3..87809aa8fb 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -241,9 +241,15 @@ public: S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); + /*virtual*/ void setToolTip(const std::string& tooltip); + private: class LLTextBase& mEditor; LLStyleConstSP mStyle; + +protected: + std::string mTooltip; }; typedef LLPointer<LLTextSegment> LLTextSegmentPtr; @@ -392,6 +398,8 @@ public: const std::string& getLabel() { return mLabel.getString(); } const LLWString& getWlabel() { return mLabel.getWString();} + void setLastSegmentToolTip(const std::string &tooltip); + /** * If label is set, draws text label (which is LLLabelTextSegment) * that is visible when no user text provided diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 6db0d88998..7f6cc22e90 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -203,10 +203,10 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const { LLUriParser up(unescapeUrl(url)); - std::string query; + std::string label; up.extractParts(); - up.glueSecond(query); - + up.glueFirst(label); + std::string query = url.substr(label.size()); return query; } @@ -229,7 +229,7 @@ static std::string getStringAfterToken(const std::string str, const std::string LLUrlEntryHTTP::LLUrlEntryHTTP() : LLUrlEntryBase() { - mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", + mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?\\.[a-z](:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); @@ -287,46 +287,6 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const return getUrlFromWikiLink(string); } -// -// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com -// -LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol() - : LLUrlEntryBase() -{ - mPattern = boost::regex("(" - "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR - "|" // or - "(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net - ")", - boost::regex::perl|boost::regex::icase); - mMenuName = "menu_url_http.xml"; - mTooltip = LLTrans::getString("TooltipHttpUrl"); -} - -std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb) -{ - return urlToLabelWithGreyQuery(url); -} - -std::string LLUrlEntryHTTPNoProtocol::getQuery(const std::string &url) const -{ - return urlToGreyQuery(url); -} - -std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const -{ - if (string.find("://") == std::string::npos) - { - return "http://" + escapeUrl(string); - } - return escapeUrl(string); -} - -std::string LLUrlEntryHTTPNoProtocol::getTooltip(const std::string &url) const -{ - return unescapeUrl(url); -} - LLUrlEntryInvalidSLURL::LLUrlEntryInvalidSLURL() : LLUrlEntryBase() { @@ -489,7 +449,7 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const // LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL() { - mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*", + mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*", boost::regex::perl|boost::regex::icase); mIcon = "Hand"; @@ -527,7 +487,7 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const // LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() { - mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)", + mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)", boost::regex::perl|boost::regex::icase); mIcon = "Hand"; @@ -1401,9 +1361,43 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url) return mIcon; } +// +// LLUrlEntryEmail Describes a generic mailto: Urls +// +LLUrlEntryEmail::LLUrlEntryEmail() + : LLUrlEntryBase() +{ + mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}", + boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_email.xml"; + mTooltip = LLTrans::getString("TooltipEmail"); +} + +std::string LLUrlEntryEmail::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + int pos = url.find("mailto:"); + + if (pos == std::string::npos) + { + return escapeUrl(url); + } + + std::string ret = escapeUrl(url.substr(pos + 7, url.length() - pos + 8)); + return ret; +} + +std::string LLUrlEntryEmail::getUrl(const std::string &string) const +{ + if (string.find("mailto:") == std::string::npos) + { + return "mailto:" + escapeUrl(string); + } + return escapeUrl(string); +} + LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile() { - mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*", + mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/profile", boost::regex::perl|boost::regex::icase); mIcon = "Generic_Experience"; mMenuName = "menu_url_experience.xml"; diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index dd1f257a3d..413c20a657 100755 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -157,19 +157,6 @@ public: /*virtual*/ std::string getUrl(const std::string &string) const; }; -/// -/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com -/// -class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase -{ -public: - LLUrlEntryHTTPNoProtocol(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getQuery(const std::string &url) const; - /*virtual*/ std::string getUrl(const std::string &string) const; - /*virtual*/ std::string getTooltip(const std::string &url) const; -}; - class LLUrlEntryInvalidSLURL : public LLUrlEntryBase { public: @@ -506,5 +493,16 @@ public: /*virtual*/ std::string getIcon(const std::string &url); }; +/// +/// LLUrlEntryEmail Describes a generic mailto: Urls +/// +class LLUrlEntryEmail : public LLUrlEntryBase +{ +public: + LLUrlEntryEmail(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getUrl(const std::string &string) const; +}; + #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 2085505947..69eefa736c 100755 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -76,9 +76,7 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntrySL()); mUrlEntrySLLabel = new LLUrlEntrySLLabel(); registerUrl(mUrlEntrySLLabel); - // most common pattern is a URL without any protocol, - // e.g., "secondlife.com" - registerUrl(new LLUrlEntryHTTPNoProtocol()); + registerUrl(new LLUrlEntryEmail()); } LLUrlRegistry::~LLUrlRegistry() @@ -155,11 +153,9 @@ static bool stringHasUrl(const std::string &text) return (text.find("://") != std::string::npos || text.find("www.") != std::string::npos || text.find(".com") != std::string::npos || - text.find(".net") != std::string::npos || - text.find(".edu") != std::string::npos || - text.find(".org") != std::string::npos || text.find("<nolink>") != std::string::npos || - text.find("<icon") != std::string::npos); + text.find("<icon") != std::string::npos || + text.find("@") != std::string::npos); } bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted) @@ -218,9 +214,40 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL // did we find a match? if so, return its details in the match object if (match_entry) { + + // Skip if link is an email with an empty username (starting with @). See MAINT-5371. + if (match_start > 0 && text.substr(match_start - 1, 1) == "@") + return false; + // fill in the LLUrlMatch object and return it std::string url = text.substr(match_start, match_end - match_start + 1); + LLUrlEntryBase *stripped_entry = NULL; + if(LLStringUtil::containsNonprintable(url)) + { + LLStringUtil::stripNonprintable(url); + + std::vector<LLUrlEntryBase *>::iterator iter; + for (iter = mUrlEntry.begin(); iter != mUrlEntry.end(); ++iter) + { + LLUrlEntryBase *url_entry = *iter; + U32 start = 0, end = 0; + if (matchRegex(url.c_str(), url_entry->getPattern(), start, end)) + { + if (mLLUrlEntryInvalidSLURL == *iter) + { + if(url_entry && url_entry->isSLURLvalid(url)) + { + continue; + } + } + stripped_entry = url_entry; + break; + } + } + } + + if (match_entry == mUrlEntryTrusted) { LLUriParser up(url); @@ -228,10 +255,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL url = up.normalizedUri(); } + std::string url_label = stripped_entry? stripped_entry->getLabel(url, cb) : match_entry->getLabel(url, cb); + std::string url_query = stripped_entry? stripped_entry->getQuery(url) : match_entry->getQuery(url); match.setValues(match_start, match_end, match_entry->getUrl(url), - match_entry->getLabel(url, cb), - match_entry->getQuery(url), + url_label, + url_query, match_entry->getTooltip(url), match_entry->getIcon(url), match_entry->getStyle(), diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 15f2354552..96e94c0f80 100755 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -653,79 +653,6 @@ namespace tut void object::test<11>() { // - // test LLUrlEntryHTTPNoProtocol - general URLs without a protocol - // - LLUrlEntryHTTPNoProtocol url; - - testRegex("naked .com URL", url, - "see google.com", - "http://google.com"); - - testRegex("naked .org URL", url, - "see en.wikipedia.org for details", - "http://en.wikipedia.org"); - - testRegex("naked .net URL", url, - "example.net", - "http://example.net"); - - testRegex("naked .edu URL (2 instances)", url, - "MIT web site is at web.mit.edu and also www.mit.edu", - "http://web.mit.edu"); - - testRegex("don't match e-mail addresses", url, - "test@lindenlab.com", - ""); - - testRegex(".com URL with path", url, - "see secondlife.com/status for grid status", - "http://secondlife.com/status"); - - testRegex(".com URL with port", url, - "secondlife.com:80", - "http://secondlife.com:80"); - - testRegex(".com URL with port and path", url, - "see secondlife.com:80/status", - "http://secondlife.com:80/status"); - - testRegex("www.*.com URL with port and path", url, - "see www.secondlife.com:80/status", - "http://www.secondlife.com:80/status"); - - testRegex("invalid .com URL [1]", url, - "..com", - ""); - - testRegex("invalid .com URL [2]", url, - "you.come", - ""); - - testRegex("invalid .com URL [3]", url, - "recommended", - ""); - - testRegex("invalid .edu URL", url, - "hi there scheduled maitenance has begun", - ""); - - testRegex("invalid .net URL", url, - "foo.netty", - ""); - - testRegex("XML tags around URL [1]", url, - "<foo>secondlife.com</foo>", - "http://secondlife.com"); - - testRegex("XML tags around URL [2]", url, - "<foo>secondlife.com/status?bar=1</foo>", - "http://secondlife.com/status?bar=1"); - } - - template<> template<> - void object::test<12>() - { - // // test LLUrlEntryNoLink - turn off hyperlinking // LLUrlEntryNoLink url; @@ -752,7 +679,7 @@ namespace tut } template<> template<> - void object::test<13>() + void object::test<12>() { // // test LLUrlEntryRegion - secondlife:///app/region/<location> URLs @@ -860,4 +787,101 @@ namespace tut "secondlife:///app/region/Product%20Engine", "Product Engine"); } + + template<> template<> + void object::test<13>() + { + // + // test LLUrlEntryemail - general emails + // + LLUrlEntryEmail url; + + // Regex tests. + testRegex("match e-mail addresses", url, + "test@lindenlab.com", + "mailto:test@lindenlab.com"); + + testRegex("match e-mail addresses with mailto: prefix", url, + "mailto:test@lindenlab.com", + "mailto:test@lindenlab.com"); + + testRegex("match e-mail addresses with different domains", url, + "test@foo.org.us", + "mailto:test@foo.org.us"); + + testRegex("match e-mail addresses with different domains", url, + "test@foo.bar", + "mailto:test@foo.bar"); + + testRegex("don't match incorrect e-mail addresses", url, + "test @foo.com", + ""); + + testRegex("don't match incorrect e-mail addresses", url, + "test@ foo.com", + ""); + } + + template<> template<> + void object::test<14>() + { + // + // test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com/* and http://*lindenlab.com/* urls + // + LLUrlEntrySecondlifeURL url; + + testRegex("match urls with protocol", url, + "this url should match http://lindenlab.com/products/second-life", + "http://lindenlab.com/products/second-life"); + + testRegex("match urls with protocol", url, + "search something https://marketplace.secondlife.com/products/search on marketplace and test the https", + "https://marketplace.secondlife.com/products/search"); + + testRegex("match urls with port", url, + "let's specify some port http://secondlife.com:888/status", + "http://secondlife.com:888/status"); + + testRegex("don't match urls w/o protocol", url, + "looks like an url something www.marketplace.secondlife.com/products but no https prefix", + ""); + + testRegex("but with a protocol www is fine", url, + "so let's add a protocol http://www.marketplace.secondlife.com:8888/products", + "http://www.marketplace.secondlife.com:8888/products"); + + testRegex("don't match urls w/o protocol", url, + "and even no www something secondlife.com/status", + ""); + } + + template<> template<> + void object::test<15>() + { + // + // test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com and http://*lindenlab.com urls + // + + LLUrlEntrySimpleSecondlifeURL url; + + testRegex("match urls with a protocol", url, + "this url should match http://lindenlab.com", + "http://lindenlab.com"); + + testRegex("match urls with a protocol", url, + "search something https://marketplace.secondlife.com on marketplace and test the https", + "https://marketplace.secondlife.com"); + + testRegex("don't match urls w/o protocol", url, + "looks like an url something www.marketplace.secondlife.com but no https prefix", + ""); + + testRegex("but with a protocol www is fine", url, + "so let's add a protocol http://www.marketplace.secondlife.com", + "http://www.marketplace.secondlife.com"); + + testRegex("don't match urls w/o protocol", url, + "and even no www something lindenlab.com", + ""); + } } diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 1c9160a42d..deb8cb90d8 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -239,7 +239,11 @@ attributedStringInfo getSegments(NSAttributedString *str) { [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval]; } else { - [glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval]; + // supress this error after move to Xcode 7: + // error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull] + // Tried using ObjC 'nonnull' keyword as per SO article but didn't build + GLint swapInterval=0; + [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; } mOldResize = false; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 5720660034..1b24250618 100755 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -49,8 +49,8 @@ LLSplashScreen *gSplashScreenp = NULL; BOOL gDebugClicks = FALSE; BOOL gDebugWindowProc = FALSE; -const S32 gURLProtocolWhitelistCount = 4; -const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:" }; +const S32 gURLProtocolWhitelistCount = 5; +const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" }; // CP: added a handler list - this is what's used to open the protocol and is based on registry entry // only meaningful difference currently is that file: protocols are opened using http: diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index f02052ca6a..e6e8f27f53 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -53,6 +53,7 @@ bool runMainLoop(); void initMainLoop(); void cleanupViewer(); void handleUrl(const char* url); +void dispatchUrl(std::string url); /* Defined in llwindowmacosx-objc.mm: */ int createNSApp(int argc, const char **argv); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index cd2be87fad..7e0eb9cf31 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2292,6 +2292,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ sHandleLeftMouseUp = true; break; } + sHandleDoubleClick = true; //if (gDebugClicks) //{ diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 67c00576be..001cdf2de4 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -140,7 +140,6 @@ set(viewer_SOURCE_FILES llbreadcrumbview.cpp llbrowsernotification.cpp llbuycurrencyhtml.cpp - llcallbacklist.cpp llcallingcard.cpp llcapabilitylistener.cpp llcaphttpsender.cpp @@ -267,6 +266,7 @@ set(viewer_SOURCE_FILES llfloaterlagmeter.cpp llfloaterland.cpp llfloaterlandholdings.cpp + llfloatermarketplacelistings.cpp llfloatermap.cpp llfloatermediasettings.cpp llfloatermemleak.cpp @@ -274,6 +274,7 @@ set(viewer_SOURCE_FILES llfloatermodeluploadbase.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp + llfloaternotificationstabbed.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp llfloateroutbox.cpp @@ -408,6 +409,8 @@ set(viewer_SOURCE_FILES llnotificationgrouphandler.cpp llnotificationhandlerutil.cpp llnotificationhinthandler.cpp + llnotificationlistitem.cpp + llnotificationlistview.cpp llnotificationmanager.cpp llnotificationofferhandler.cpp llnotificationscripthandler.cpp @@ -755,7 +758,6 @@ set(viewer_HEADER_FILES llbox.h llbreadcrumbview.h llbuycurrencyhtml.h - llcallbacklist.h llcallingcard.h llcapabilitylistener.h llcapabilityprovider.h @@ -887,12 +889,14 @@ set(viewer_HEADER_FILES llfloaterland.h llfloaterlandholdings.h llfloatermap.h + llfloatermarketplacelistings.h llfloatermediasettings.h llfloatermemleak.h llfloatermodelpreview.h llfloatermodeluploadbase.h llfloaternamedesc.h llfloaternotificationsconsole.h + llfloaternotificationstabbed.h llfloaterobjectweights.h llfloateropenobject.h llfloateroutbox.h @@ -1020,6 +1024,8 @@ set(viewer_HEADER_FILES llnavigationbar.h llnetmap.h llnotificationhandler.h + llnotificationlistitem.h + llnotificationlistview.h llnotificationmanager.h llnotificationstorage.h lloutfitslist.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index f280719674..4351a7e3a3 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.8.1 +3.8.7 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 7b329e2092..2cd6638042 100755 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -118,6 +118,18 @@ tooltip_ref="Command_Marketplace_Tooltip" execute_function="Avatar.OpenMarketplace" /> + <command name="marketplacelistings" + available_in_toybox="true" + icon="Command_MktListings_Icon" + label_ref="Command_MarketplaceListings_Label" + tooltip_ref="Command_MarketplaceListings_Tooltip" + execute_function="Marketplace.Toggle" + execute_parameters="marketplace" + is_enabled_function="Marketplace.Enabled" + is_enabled_parameters="marketplace" + is_running_function="Floater.IsOpen" + is_running_parameters="marketplace_listings" + /> <command name="minimap" available_in_toybox="true" icon="Command_MiniMap_Icon" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9d9bc43bd7..5f378c64e8 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,39 @@ <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> <map> + <key>ImporterDebug</key> + <map> + <key>Comment</key> + <string>Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ImporterLegacyMatching</key> + <map> + <key>Comment</key> + <string>Enable index based model matching.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ImporterModelLimit</key> + <map> + <key>Comment</key> + <string>Limits amount of importer generated models for dae files</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>768</integer> + </map> <key>IMShowTime</key> <map> <key>Comment</key> @@ -3459,6 +3492,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>MinObjectsForUnlinkConfirm</key> + <map> + <key>Comment</key> + <string>Minimum amount of objects in linkset for showing confirmation dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>6</integer> + </map> <key>EffectScriptChatParticles</key> <map> <key>Comment</key> @@ -4680,17 +4724,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>InventoryDisplayOutbox</key> - <map> - <key>Comment</key> - <string>Override merchant inventory outbox display</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>InventoryInboxToggleState</key> <map> <key>Comment</key> @@ -4713,6 +4746,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryOutboxDisplayBoth</key> + <map> + <key>Comment</key> + <string>Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>InventoryOutboxLogging</key> <map> <key>Comment</key> @@ -4744,7 +4788,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>21</integer> + <integer>20</integer> </map> <key>InventoryOutboxMaxFolderDepth</key> <map> @@ -4768,6 +4812,17 @@ <key>Value</key> <integer>200</integer> </map> + <key>InventoryOutboxMaxStockItemCount</key> + <map> + <key>Comment</key> + <string>Maximum number of items allowed in a stock folder.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>200</integer> + </map> <key>InventorySortOrder</key> <map> <key>Comment</key> @@ -4779,6 +4834,17 @@ <key>Value</key> <integer>7</integer> </map> + <key>MarketplaceListingsSortOrder</key> + <map> + <key>Comment</key> + <string>Specifies sort for marketplace listings</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>2</integer> + </map> <key>InvertMouse</key> <map> <key>Comment</key> @@ -5628,6 +5694,17 @@ <key>Value</key> <string /> </map> + <key>MarketplaceListingsLogging</key> + <map> + <key>Comment</key> + <string>Enable debug output associated with the Marketplace Listings (SLM) API.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MarketplaceURL</key> <map> <key>Comment</key> @@ -14131,6 +14208,17 @@ <key>Value</key> <integer>-1</integer> </map> + <key>MaxFPS</key> + <map> + <key>Comment</key> + <string>OBSOLETE UNUSED setting.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>-1.0</real> + </map> <key>ForcePeriodicRenderingTime</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 6cd38d8ef5..3060307b21 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -37,8 +37,7 @@ mat4 getObjectSkinnedTransform() index = min(index, vec4(51.0)); index = max(index, vec4( 0.0)); - float scale = 1.0/(w.x+w.y+w.z+w.w); - w *= scale; + w *= 1.0/(w.x+w.y+w.z+w.w); int i1 = int(index.x); int i2 = int(index.y); diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 595c11fae2..58fb01d200 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -29,6 +29,7 @@ out vec4 frag_data[3]; #define frag_data gl_FragData #endif +uniform float minimum_alpha; uniform sampler2D diffuseMap; uniform sampler2D bumpMap; @@ -47,16 +48,23 @@ vec2 encode_normal(vec3 n) void main() { - vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; - vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; + vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); + + if(col.a < minimum_alpha) + { + discard; + } + col *= vertex_color; + + vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; - vec3 tnorm = vec3(dot(norm,vary_mat0), + vec3 tnorm = vec3(dot(norm,vary_mat0), dot(norm,vary_mat1), dot(norm,vary_mat2)); - frag_data[0] = vec4(col, 0.0); - frag_data[1] = vertex_color.aaaa; // spec - //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested - vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(tnorm); + frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0); } diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml index d61aee9a14..36e4eb91fd 100755 --- a/indra/newview/app_settings/toolbars.xml +++ b/indra/newview/app_settings/toolbars.xml @@ -23,4 +23,7 @@ <command name="snapshot"/> <command name="facebook"/> </left_toolbar> + <right_toolbar + button_display_mode="icons_only"> + </right_toolbar> </toolbars> diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 8c8b4971cf..b8677fd9e4 100755 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -165,7 +165,9 @@ lbl_configure_default_lang: StrCpy $LANGUAGE $0
# For silent installs, no language prompt, use default
- IfSilent lbl_return
+ IfSilent 0 +3
+ StrCpy $SKIP_AUTORUN "true"
+ Goto lbl_return
StrCmp $SKIP_DIALOGS "true" lbl_return
lbl_build_menu:
@@ -298,6 +300,11 @@ CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \ CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
'"$INSTDIR\uninst.exe"' ''
+# Create *.bat file to specify lang params on first run from installer - see MAINT-5259
+FileOpen $9 "$INSTDIR\autorun.bat" w
+FileWrite $9 'start "$INSTDIR\$INSTEXE" "$INSTDIR\$INSTEXE" $SHORTCUT_LANG_PARAM$\r$\n'
+FileClose $9
+
# Write registry
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}"
@@ -682,7 +689,7 @@ Call CheckWindowsServPack # Warn if not on the latest SP before asking to launc Push $R0 # Option value, unused
StrCmp $SKIP_AUTORUN "true" +2;
# Assumes SetOutPath $INSTDIR
- Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTEXE"'
+ Exec '"$WINDIR\explorer.exe" "$INSTDIR\autorun.bat"'
Pop $R0
FunctionEnd
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 359171c5bd..297bd9a05b 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2843,7 +2843,7 @@ BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */ // This implementation should mirror LLAgentInfo::hasPowerInGroup BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const { - if (isGodlike()) + if (isGodlikeWithoutAdminMenuFakery()) return true; // GP_NO_POWERS can also mean no power is enough to grant an ability. @@ -3873,6 +3873,12 @@ void LLAgent::handleTeleportFinished() LLNotificationsUtil::add("PreferredMaturityChanged", args); mIsMaturityRatingChangingDuringTeleport = false; } + + // Init SLM Marketplace connection so we know which UI should be used for the user as a merchant + // Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all. + // Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport. + // *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp) + check_merchant_status(); } void LLAgent::handleTeleportFailed() diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 7f0330ee99..aed27924fe 100755 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -147,6 +147,7 @@ LLAgentCamera::LLAgentCamera() : mCameraUpVector(LLVector3::z_axis), // default is straight up mFocusOnAvatar(TRUE), + mAllowChangeToFollow(FALSE), mFocusGlobal(), mFocusTargetGlobal(), mFocusObject(NULL), @@ -1152,8 +1153,10 @@ void LLAgentCamera::updateCamera() mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); } - if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) + if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getActiveFollowCamParams()) { + mAllowChangeToFollow = FALSE; + mFocusOnAvatar = TRUE; changeCameraToFollow(); } @@ -2610,6 +2613,7 @@ void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) { // keep camera focus point consistent, even though it is now unlocked setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); + mAllowChangeToFollow = FALSE; } mFocusOnAvatar = focus_on_avatar; diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 4d0f9a80de..ab793ff316 100755 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -206,13 +206,15 @@ public: void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); void clearFocusObject(); void setFocusObject(LLViewerObject* object); + void setAllowChangeToFollow(BOOL focus) { mAllowChangeToFollow = focus; } void setObjectTracking(BOOL track) { mTrackFocusObject = track; } const LLVector3d &getFocusGlobal() const { return mFocusGlobal; } const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; } private: LLVector3d mCameraFocusOffset; // Offset from focus point in build mode LLVector3d mCameraFocusOffsetTarget; // Target towards which we are lerping the camera's focus offset - BOOL mFocusOnAvatar; + BOOL mFocusOnAvatar; + BOOL mAllowChangeToFollow; LLVector3d mFocusGlobal; LLVector3d mFocusTargetGlobal; LLPointer<LLViewerObject> mFocusObject; diff --git a/indra/newview/llagentdata.cpp b/indra/newview/llagentdata.cpp index 5f6a082d75..d2c644a06f 100755 --- a/indra/newview/llagentdata.cpp +++ b/indra/newview/llagentdata.cpp @@ -31,3 +31,4 @@ LLUUID gAgentID; LLUUID gAgentSessionID; +std::string gAgentUsername; diff --git a/indra/newview/llagentdata.h b/indra/newview/llagentdata.h index 83d6a53d5e..efdd97f6c4 100755 --- a/indra/newview/llagentdata.h +++ b/indra/newview/llagentdata.h @@ -30,5 +30,6 @@ extern LLUUID gAgentID; extern LLUUID gAgentSessionID; +extern std::string gAgentUsername; #endif diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 5589ab4aa7..cce1eb5895 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llagentwearables.h" +#include "llattachmentsmgr.h" #include "llaccordionctrltab.h" #include "llagent.h" #include "llagentcamera.h" @@ -985,6 +986,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it S32 matched = 0, mismatched = 0; const S32 arr_size = LLWearableType::WT_COUNT; S32 type_counts[arr_size]; + BOOL update_inventory = FALSE; std::fill(type_counts,type_counts+arr_size,0); for (S32 i = 0; i < count; i++) { @@ -1012,10 +1014,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it continue; } - // Don't care about this case - ordering of wearables with the same asset id has no effect. - // Causes the two-alphas error case in MAINT-4158. + // Update only inventory in this case - ordering of wearables with the same asset id has no effect. + // Updating wearables in this case causes the two-alphas error in MAINT-4158. // We should actually disallow wearing two wearables with the same asset id. -#if 0 if (curr_wearable->getName() != new_item->getName() || curr_wearable->getItemID() != new_item->getUUID()) { @@ -1023,10 +1024,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it << curr_wearable->getName() << " vs " << new_item->getName() << " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID() << LL_ENDL; - mismatched++; + update_inventory = TRUE; continue; } -#endif // If we got here, everything matches. matched++; } @@ -1040,14 +1040,15 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it mismatched++; } } - if (mismatched == 0) + if (mismatched == 0 && !update_inventory) { LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL; mCOFChangeInProgress = false; return; } - - + + // updating inventory + // TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later // note: shirt is the first non-body part wearable item. Update if wearable order changes. // This loop should remove all clothing, but not any body parts @@ -1068,7 +1069,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it if (new_wearable) { const LLWearableType::EType type = new_wearable->getType(); - + + LLUUID old_wearable_id = new_wearable->getItemID(); new_wearable->setName(new_item->getName()); new_wearable->setItemID(new_item->getUUID()); @@ -1076,11 +1078,18 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { // exactly one wearable per body part setWearable(type,0,new_wearable); + if (old_wearable_id.notNull()) + { + // we changed id before setting wearable, update old item manually + // to complete the swap. + gInventory.addChangedMask(LLInventoryObserver::LABEL, old_wearable_id); + } } else { pushWearable(type,new_wearable); } + const BOOL removed = FALSE; wearableUpdated(new_wearable, removed); } @@ -1088,6 +1097,15 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it gInventory.notifyObservers(); + if (mismatched == 0) + { + LL_DEBUGS("Avatar") << "inventory updated, wearable assets not changed, bailing out" << LL_ENDL; + mCOFChangeInProgress = false; + return; + } + + // updating agent avatar + if (isAgentAvatarValid()) { gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); @@ -1353,6 +1371,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo if (objects_to_remove.empty()) return; + LL_DEBUGS("Avatar") << "ATT [ObjectDetach] removing " << objects_to_remove.size() << " objects" << LL_ENDL; gMessageSystem->newMessage("ObjectDetach"); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -1366,6 +1385,10 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo //gAgentAvatarp->resetJointPositionsOnDetach(objectp); gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); + const LLUUID& item_id = objectp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT removing object, item is " << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + LLAttachmentsMgr::instance().onDetachRequested(item_id); } gMessageSystem->sendReliable(gAgent.getRegionHost()); } @@ -1374,51 +1397,18 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra { // Build a compound message to send all the objects that need to be rezzed. S32 obj_count = obj_item_array.size(); - - // Limit number of packets to send - const S32 MAX_PACKETS_TO_SEND = 10; - const S32 OBJECTS_PER_PACKET = 4; - const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET; - if( obj_count > MAX_OBJECTS_TO_SEND ) + if (obj_count > 0) { - obj_count = MAX_OBJECTS_TO_SEND; + LL_DEBUGS("Avatar") << "ATT attaching multiple, total obj_count " << obj_count << LL_ENDL; } - - // Create an id to keep the parts of the compound message together - LLUUID compound_msg_id; - compound_msg_id.generate(); - LLMessageSystem* msg = gMessageSystem; - for(S32 i = 0; i < obj_count; ++i) - { - if( 0 == (i % OBJECTS_PER_PACKET) ) - { - // Start a new message chunk - msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_HeaderData); - msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); - msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); - msg->addBOOLFast(_PREHASH_FirstDetachAll, false ); - } - - const LLInventoryItem* item = obj_item_array.at(i).get(); - msg->nextBlockFast(_PREHASH_ObjectData ); - msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD); // Wear at the previous or default attachment point - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - msg->addStringFast(_PREHASH_Name, item->getName()); - msg->addStringFast(_PREHASH_Description, item->getDescription()); - - if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) - { - // End of message chunk - msg->sendReliable( gAgent.getRegion()->getHost() ); - } - } + for(LLInventoryModel::item_array_t::const_iterator it = obj_item_array.begin(); + it != obj_item_array.end(); + ++it) + { + const LLInventoryItem* item = *it; + LLAttachmentsMgr::instance().addAttachmentRequest(item->getLinkedUUID(), 0, TRUE); + } } // Returns false if the given wearable is already topmost/bottommost diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 9d887a61f1..714b456ae7 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -315,7 +315,8 @@ SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& conten CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, - LLPointer<LLInventoryCallback> callback): + LLPointer<LLInventoryCallback> callback, + bool copy_subfolders): AISCommand(callback) { std::string cap; @@ -328,6 +329,10 @@ CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id, LLUUID tid; tid.generate(); std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString(); + if (!copy_subfolders) + { + url += ",depth=0"; + } LL_INFOS() << url << LL_ENDL; LLCurl::ResponderPtr responder = this; LLSD headers; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 5a2ec94af9..bb483fb133 100755 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -124,7 +124,7 @@ private: class CopyLibraryCategoryCommand: public AISCommand { public: - CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback); + CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback, bool copy_subfolders = true); protected: /* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b3317e937e..142a3250c8 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -525,6 +525,15 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD { } +LLRequestServerAppearanceUpdateOnDestroy::~LLRequestServerAppearanceUpdateOnDestroy() +{ + LL_DEBUGS("Avatar") << "ATT requesting server appearance update" << LL_ENDL; + if (!LLApp::isExiting()) + { + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } +} + void edit_wearable_and_customize_avatar(LLUUID item_id) { // Start editing the item if previously requested. @@ -828,6 +837,12 @@ void LLWearableHoldingPattern::onAllComplete() // pre-attachment states. gAgentAvatarp->clearAttachmentPosOverrides(); + if (objects_to_remove.size() || items_to_add.size()) + { + LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size() + << " and add " << items_to_add.size() << " items" << LL_ENDL; + } + // Take off the attachments that will no longer be in the outfit. LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); @@ -1356,28 +1371,46 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, const LLUUID& item_id_to_wear = *it; - if (item_id_to_wear.isNull()) continue; + if (item_id_to_wear.isNull()) + { + LL_DEBUGS("Avatar") << "null id " << item_id_to_wear << LL_ENDL; + continue; + } LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); - if (!item_to_wear) continue; + if (!item_to_wear) + { + LL_DEBUGS("Avatar") << "inventory item not found for id " << item_id_to_wear << LL_ENDL; + continue; + } if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) { + LL_DEBUGS("Avatar") << "inventory item in library, will copy and wear " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace)); - copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb); + copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), + item_to_wear->getUUID(), LLUUID::null, std::string(), cb); continue; } else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID())) { - continue; // not in library and not in agent's inventory + // not in library and not in agent's inventory + LL_DEBUGS("Avatar") << "inventory item not in user inventory or library, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; + continue; } else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) { LLNotificationsUtil::add("CannotWearTrash"); + LL_DEBUGS("Avatar") << "inventory item is in trash, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; continue; } else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911 { + LL_DEBUGS("Avatar") << "inventory item is already in COF, skipping " + << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; continue; } @@ -1753,9 +1786,15 @@ bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) { return false; } - + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); - return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); + gInventory.collectDescendentsIf(outfit_cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_worn); + return items.size() > 0; } // static @@ -1830,6 +1869,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) { ++n_clothes; } + else if (item->getType() == LLAssetType::AT_BODYPART) + { + return isAgentAvatarValid(); + } else { LL_WARNS() << "Unexpected wearable type" << LL_ENDL; @@ -2432,7 +2475,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append); LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper( std::string("wear_inventory_category_callback"), copy_cb); - LLPointer<AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb); + LLPointer<AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb, false); ais_ran=cmd_ptr->run_command(); } @@ -2711,28 +2754,23 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) { - LLInventoryModel::item_array_t result; - const LLViewerInventoryItem *vitem = - dynamic_cast<const LLViewerInventoryItem*>(gInventory.getItem(item_id)); - if (vitem) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(LLAppearanceMgr::getCOF(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - for (S32 i=0; i<item_array.size(); i++) - { - const LLViewerInventoryItem* inv_item = item_array.at(i).get(); - if (inv_item->getLinkedUUID() == vitem->getLinkedUUID()) - { - result.push_back(item_array.at(i)); - } - } - } + LLUUID linked_id = gInventory.getLinkedItemID(item_id); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.size(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.at(i).get(); + if (inv_item->getLinkedUUID() == linked_id) + { + result.push_back(item_array.at(i)); + } + } return result; } @@ -3309,7 +3347,7 @@ void RequestAgentUpdateAppearanceResponder::onRequestRequested() } // Actually send the request. - LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL; + LL_DEBUGS("Avatar") << "ATT sending bake request for cof_version " << cof_version << LL_ENDL; mRetryPolicy->reset(); sendRequest(); } @@ -3782,6 +3820,11 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) { const LLUUID& id_to_remove = *it; const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove); + LLViewerInventoryItem *item = gInventory.getItem(linked_item_id); + if (item && item->getType() == LLAssetType::AT_OBJECT) + { + LL_DEBUGS("Avatar") << "ATT removing attachment " << item->getName() << " id " << item->getUUID() << LL_ENDL; + } removeCOFItemLinks(linked_item_id, cb); addDoomedTempAttachment(linked_item_id); } @@ -3789,10 +3832,9 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) { - LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); - LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy; - removeCOFItemLinks(linked_item_id, cb); - addDoomedTempAttachment(linked_item_id); + uuid_vec_t ids_to_remove; + ids_to_remove.push_back(id_to_remove); + removeItemsFromAvatar(ids_to_remove); } @@ -3977,37 +4019,32 @@ void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg) void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) { - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - - if (mAttachmentInvLinkEnabled) - { - // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. - // it will trigger gAgentWariables.notifyLoadingFinished() - // But it is not acceptable solution. See EXT-7777 - if (!isLinkedInCOF(item_id)) - { - LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(); - LLAppearanceMgr::addCOFItemLink(item_id, cb); // Add COF link for item. - } - } - else - { - //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; - } + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT registering attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + + LLAttachmentsMgr::instance().onAttachmentArrived(item_id); } void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT unregistering attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - if (mAttachmentInvLinkEnabled) - { - LLAppearanceMgr::removeCOFItemLinks(item_id); - } - else - { - //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; - } + LLAttachmentsMgr::instance().onDetachCompleted(item_id); + if (mAttachmentInvLinkEnabled && isLinkedInCOF(item_id)) + { + LL_DEBUGS("Avatar") << "ATT removing COF link for attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + LLAppearanceMgr::removeCOFItemLinks(item_id); + } + else + { + //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; + } } BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const @@ -4021,14 +4058,6 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const return FALSE; } -// static -bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) -{ - const LLUUID& target_id = gInventory.getLinkedItemID(obj_id); - LLLinkedItemIDMatches find_links(target_id); - return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links); -} - BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const { if (!getIsInCOF(obj_id)) return FALSE; @@ -4147,10 +4176,56 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) } } +void add_wearable_type_counts(const uuid_vec_t& ids, + S32& clothing_count, + S32& bodypart_count, + S32& object_count, + S32& other_count) +{ + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + const LLUUID& item_id_to_wear = *it; + LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); + if (item_to_wear) + { + if (item_to_wear->getType() == LLAssetType::AT_CLOTHING) + { + clothing_count++; + } + else if (item_to_wear->getType() == LLAssetType::AT_BODYPART) + { + bodypart_count++; + } + else if (item_to_wear->getType() == LLAssetType::AT_OBJECT) + { + object_count++; + } + else + { + other_count++; + } + } + else + { + other_count++; + } + } +} + void wear_multiple(const uuid_vec_t& ids, bool replace) { - LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy; - LLAppearanceMgr::instance().wearItemsOnAvatar(ids, false, replace, cb); + S32 clothing_count = 0; + S32 bodypart_count = 0; + S32 object_count = 0; + S32 other_count = 0; + add_wearable_type_counts(ids, clothing_count, bodypart_count, object_count, other_count); + + LLPointer<LLInventoryCallback> cb = NULL; + if (clothing_count > 0 || bodypart_count > 0) + { + cb = new LLUpdateAppearanceOnDestroy; + } + LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb); } // SLapp for easy-wearing of a stock (library) avatar diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index ee9d3b7209..4ed8c1bfb9 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -284,11 +284,6 @@ public: BOOL getIsInCOF(const LLUUID& obj_id) const; // Is this in the COF and can the user delete it from the COF? BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; - - /** - * Checks if COF contains link to specified object. - */ - static bool isLinkInCOF(const LLUUID& obj_id); }; class LLUpdateAppearanceOnDestroy: public LLInventoryCallback @@ -320,6 +315,15 @@ private: LLUUID mItemID; }; +class LLRequestServerAppearanceUpdateOnDestroy: public LLInventoryCallback +{ +public: + LLRequestServerAppearanceUpdateOnDestroy() {} + ~LLRequestServerAppearanceUpdateOnDestroy(); + + /* virtual */ void fire(const LLUUID& item_id) {} +}; + LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name); // Invoke a given callable after category contents are fully fetched. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a2aee2e000..fbf2a04bcc 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2784,10 +2784,12 @@ bool LLAppViewer::initConfiguration() // gWindowTitle = LLTrans::getString("APP_NAME"); #if LL_DEBUG - gWindowTitle += std::string(" [DEBUG] ") + gArgs; -#else - gWindowTitle += std::string(" ") + gArgs; + gWindowTitle += std::string(" [DEBUG]") #endif + if (!gArgs.empty()) + { + gWindowTitle += std::string(" ") + gArgs; + } LLStringUtil::truncate(gWindowTitle, 255); //RN: if we received a URL, hand it off to the existing instance. @@ -3091,8 +3093,8 @@ void LLAppViewer::initUpdater() U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod"); bool willing_to_test; LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL; - static const boost::regex is_test_channel("\\bTest$"); - if (boost::regex_search(channel, is_test_channel)) + + if (LLVersionInfo::TEST_VIEWER == LLVersionInfo::getViewerMaturity()) { LL_INFOS("UpdaterService") << "Test build: overriding willing_to_test by sending testno" << LL_ENDL; willing_to_test = false; @@ -4948,6 +4950,7 @@ void LLAppViewer::idle() gIdleCallbacks.callFunctions(); gInventory.idleNotifyObservers(); + LLAvatarTracker::instance().idleNotifyObservers(); } // Metrics logging (LLViewerAssetStats, etc.) diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 56154a2de3..09227806fd 100755 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -62,9 +62,10 @@ namespace // They are not used immediately by the app. int gArgC; char** gArgV; - LLAppViewerMacOSX* gViewerAppPtr; + LLAppViewerMacOSX* gViewerAppPtr = NULL; void (*gOldTerminateHandler)() = NULL; + std::string gHandleSLURL; } static void exceptionTerminateHandler() @@ -107,7 +108,11 @@ bool initViewer() { LL_WARNS() << "Application init failed." << LL_ENDL; } - + else if (!gHandleSLURL.empty()) + { + dispatchUrl(gHandleSLURL); + gHandleSLURL = ""; + } return ok; } @@ -393,22 +398,31 @@ bool LLAppViewerMacOSX::getMasterSystemAudioMute() void handleUrl(const char* url_utf8) { - if (url_utf8) + if (url_utf8 && gViewerAppPtr) { - std::string url = url_utf8; - // Safari 3.2 silently mangles secondlife:///app/ URLs into - // secondlife:/app/ (only one leading slash). - // Fix them up to meet the URL specification. JC - const std::string prefix = "secondlife:/app/"; - std::string test_prefix = url.substr(0, prefix.length()); - LLStringUtil::toLower(test_prefix); - if (test_prefix == prefix) - { - url.replace(0, prefix.length(), "secondlife:///app/"); - } - - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - LLURLDispatcher::dispatch(url, "", web, trusted_browser); + gHandleSLURL = ""; + dispatchUrl(url_utf8); } + else if (url_utf8) + { + gHandleSLURL = url_utf8; + } +} + +void dispatchUrl(std::string url) +{ + // Safari 3.2 silently mangles secondlife:///app/ URLs into + // secondlife:/app/ (only one leading slash). + // Fix them up to meet the URL specification. JC + const std::string prefix = "secondlife:/app/"; + std::string test_prefix = url.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if (test_prefix == prefix) + { + url.replace(0, prefix.length(), "secondlife:///app/"); + } + + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, "", web, trusted_browser); } diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 256980eb04..2a137cc39b 100755 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -27,15 +27,24 @@ #include "llviewerprecompiledheaders.h" #include "llattachmentsmgr.h" +#include "llvoavatarself.h" #include "llagent.h" +#include "llappearancemgr.h" #include "llinventorymodel.h" #include "lltooldraganddrop.h" // pack_permissions_slam #include "llviewerinventory.h" #include "llviewerregion.h" #include "message.h" +const F32 COF_LINK_BATCH_TIME = 5.0F; +const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F; +const F32 MIN_RETRY_REQUEST_TIME = 5.0F; +const F32 MAX_BAD_COF_TIME = 30.0F; -LLAttachmentsMgr::LLAttachmentsMgr() +LLAttachmentsMgr::LLAttachmentsMgr(): + mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME), + mDetachRequests("detach",MIN_RETRY_REQUEST_TIME), + mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME) { } @@ -43,15 +52,37 @@ LLAttachmentsMgr::~LLAttachmentsMgr() { } -void LLAttachmentsMgr::addAttachment(const LLUUID& item_id, - const U8 attachment_pt, - const BOOL add) +void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id, + const U8 attachment_pt, + const BOOL add) { + LLViewerInventoryItem *item = gInventory.getItem(item_id); + + if (mAttachmentRequests.wasRequestedRecently(item_id)) + { + LL_DEBUGS("Avatar") << "ATT not adding attachment to mPendingAttachments, recent request is already pending: " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + return; + } + + LL_DEBUGS("Avatar") << "ATT adding attachment to mPendingAttachments " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + AttachmentsInfo attachment; attachment.mItemID = item_id; attachment.mAttachmentPt = attachment_pt; attachment.mAdd = add; mPendingAttachments.push_back(attachment); + + mAttachmentRequests.addTime(item_id); +} + +void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id) +{ + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment was requested " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + mAttachmentRequests.addTime(item_id); } // static @@ -68,31 +99,79 @@ void LLAttachmentsMgr::onIdle() return; } - S32 obj_count = mPendingAttachments.size(); + if (LLApp::isExiting()) + { + return; + } + + requestPendingAttachments(); + + linkRecentlyArrivedAttachments(); + + expireOldAttachmentRequests(); + + expireOldDetachRequests(); + + checkInvalidCOFLinks(); + + spamStatusInfo(); +} + +void LLAttachmentsMgr::requestPendingAttachments() +{ + if (mPendingAttachments.size()) + { + requestAttachments(mPendingAttachments); + } +} + +// Send request(s) for a group of attachments. As coded, this can +// request at most 40 attachments and the rest will be +// ignored. Currently the max attachments per avatar is 38, so the 40 +// limit should not be hit in practice. +void LLAttachmentsMgr::requestAttachments(attachments_vec_t& attachment_requests) +{ + // Make sure we got a region before trying anything else + if( !gAgent.getRegion() ) + { + return; + } + + // For unknown reasons, requesting many attachments at once causes + // frequent server-side failures. Here we're limiting the number + // of attachments requested per idle loop. + const S32 max_objects_per_request = 5; + S32 obj_count = llmin((S32)attachment_requests.size(),max_objects_per_request); if (obj_count == 0) { return; } - + // Limit number of packets to send const S32 MAX_PACKETS_TO_SEND = 10; const S32 OBJECTS_PER_PACKET = 4; const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET; if( obj_count > MAX_OBJECTS_TO_SEND ) { + LL_WARNS() << "ATT Too many attachments requested: " << obj_count + << " exceeds limit of " << MAX_OBJECTS_TO_SEND << LL_ENDL; + obj_count = MAX_OBJECTS_TO_SEND; } + LL_DEBUGS("Avatar") << "ATT [RezMultipleAttachmentsFromInv] attaching multiple from attachment_requests," + " total obj_count " << obj_count << LL_ENDL; + LLUUID compound_msg_id; compound_msg_id.generate(); LLMessageSystem* msg = gMessageSystem; - - S32 i = 0; - for (attachments_vec_t::const_iterator iter = mPendingAttachments.begin(); - iter != mPendingAttachments.end(); - ++iter) - { + // by construction above, obj_count <= attachment_requests.size(), so no + // check against attachment_requests.empty() is needed. + llassert(obj_count <= attachment_requests.size()); + + for (S32 i=0; i<obj_count; i++) + { if( 0 == (i % OBJECTS_PER_PACKET) ) { // Start a new message chunk @@ -106,32 +185,337 @@ void LLAttachmentsMgr::onIdle() msg->addBOOLFast(_PREHASH_FirstDetachAll, false ); } - const AttachmentsInfo &attachment = (*iter); + const AttachmentsInfo& attachment = attachment_requests.front(); LLViewerInventoryItem* item = gInventory.getItem(attachment.mItemID); - if (!item) + if (item) + { + LL_DEBUGS("Avatar") << "ATT requesting from attachment_requests " << item->getName() + << " " << item->getLinkedUUID() << LL_ENDL; + S32 attachment_pt = attachment.mAttachmentPt; + if (attachment.mAdd) + attachment_pt |= ATTACHMENT_ADD; + + msg->nextBlockFast(_PREHASH_ObjectData ); + msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); + msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); + msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); + pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); + msg->addStringFast(_PREHASH_Name, item->getName()); + msg->addStringFast(_PREHASH_Description, item->getDescription()); + } + else { - LL_INFOS() << "Attempted to add non-existant item ID:" << attachment.mItemID << LL_ENDL; - continue; + LL_WARNS("Avatar") << "ATT Attempted to add non-existent item ID:" << attachment.mItemID << LL_ENDL; } - S32 attachment_pt = attachment.mAttachmentPt; - if (attachment.mAdd) - attachment_pt |= ATTACHMENT_ADD; - - msg->nextBlockFast(_PREHASH_ObjectData ); - msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - msg->addStringFast(_PREHASH_Name, item->getName()); - msg->addStringFast(_PREHASH_Description, item->getDescription()); if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) { // End of message chunk msg->sendReliable( gAgent.getRegion()->getHost() ); } - i++; + attachment_requests.pop_front(); } +} + +void LLAttachmentsMgr::linkRecentlyArrivedAttachments() +{ + if (mRecentlyArrivedAttachments.size()) + { + // One or more attachments have arrived but have not yet been + // processed for COF links + if (mAttachmentRequests.empty()) + { + // Not waiting for any more. + LL_DEBUGS("Avatar") << "ATT all pending attachments have arrived after " + << mCOFLinkBatchTimer.getElapsedTimeF32() << " seconds" << LL_ENDL; + } + else if (mCOFLinkBatchTimer.getElapsedTimeF32() > COF_LINK_BATCH_TIME) + { + LL_DEBUGS("Avatar") << "ATT " << mAttachmentRequests.size() + << " pending attachments have not arrived, but wait time exceeded" << LL_ENDL; + } + else + { + return; + } + + LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size() + << " recently arrived items" << LL_ENDL; + + uuid_vec_t ids_to_link; + for (std::set<LLUUID>::iterator it = mRecentlyArrivedAttachments.begin(); + it != mRecentlyArrivedAttachments.end(); ++it) + { + if (isAgentAvatarValid() && + gAgentAvatarp->isWearingAttachment(*it) && + !LLAppearanceMgr::instance().isLinkedInCOF(*it)) + { + LLUUID item_id = *it; + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT adding COF link for attachment " + << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; + ids_to_link.push_back(item_id); + } + } + if (ids_to_link.size()) + { + LLPointer<LLInventoryCallback> cb = new LLRequestServerAppearanceUpdateOnDestroy(); + for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin(); + uuid_it != ids_to_link.end(); ++uuid_it) + { + LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb); + } + } + mRecentlyArrivedAttachments.clear(); + } +} + +LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout): + mOpName(op_name), + mTimeout(timeout) +{ +} + +void LLAttachmentsMgr::LLItemRequestTimes::addTime(const LLUUID& inv_item_id) +{ + LLInventoryItem *item = gInventory.getItem(inv_item_id); + LL_DEBUGS("Avatar") << "ATT " << mOpName << " adding request time " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + LLTimer current_time; + (*this)[inv_item_id] = current_time; +} + +void LLAttachmentsMgr::LLItemRequestTimes::removeTime(const LLUUID& inv_item_id) +{ + LLInventoryItem *item = gInventory.getItem(inv_item_id); + S32 remove_count = (*this).erase(inv_item_id); + if (remove_count) + { + LL_DEBUGS("Avatar") << "ATT " << mOpName << " removing request time " + << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + } +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::getTime(const LLUUID& inv_item_id, LLTimer& timer) const +{ + std::map<LLUUID,LLTimer>::const_iterator it = (*this).find(inv_item_id); + if (it != (*this).end()) + { + timer = it->second; + return TRUE; + } + return FALSE; +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::wasRequestedRecently(const LLUUID& inv_item_id) const +{ + LLTimer request_time; + if (getTime(inv_item_id, request_time)) + { + F32 request_time_elapsed = request_time.getElapsedTimeF32(); + return request_time_elapsed < mTimeout; + } + else + { + return FALSE; + } +} + +// If we've been waiting for an attachment a long time, we want to +// forget the request, because if the request is invalid (say the +// object does not exist), the existence of a request that never goes +// away will gum up the COF batch logic, causing it to always wait for +// the timeout. Expiring a request means if the item does show up +// late, the COF link request may not get properly batched up, but +// behavior will be no worse than before we had the batching mechanism +// in place; the COF link will still be created, but extra +// requestServerAppearanceUpdate() calls may occur. +void LLAttachmentsMgr::expireOldAttachmentRequests() +{ + for (std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.begin(); + it != mAttachmentRequests.end(); ) + { + std::map<LLUUID,LLTimer>::iterator curr_it = it; + ++it; + if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) + { + LLInventoryItem *item = gInventory.getItem(curr_it->first); + LL_WARNS("Avatar") << "ATT expiring request for attachment " + << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first + << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; + mAttachmentRequests.erase(curr_it); + } + } +} + +void LLAttachmentsMgr::expireOldDetachRequests() +{ + for (std::map<LLUUID,LLTimer>::iterator it = mDetachRequests.begin(); + it != mDetachRequests.end(); ) + { + std::map<LLUUID,LLTimer>::iterator curr_it = it; + ++it; + if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) + { + LLInventoryItem *item = gInventory.getItem(curr_it->first); + LL_WARNS("Avatar") << "ATT expiring request for detach " + << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first + << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; + mDetachRequests.erase(curr_it); + } + } +} + +// When an attachment arrives, we want to stop waiting for it, and add +// it to the set of recently arrived items. +void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id) +{ + LLTimer timer; + bool expected = mAttachmentRequests.getTime(inv_item_id, timer); + if (!expected) + { + LLInventoryItem *item = gInventory.getItem(inv_item_id); + LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: " + << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; + } + mAttachmentRequests.removeTime(inv_item_id); + if (expected && mAttachmentRequests.empty()) + { + // mAttachmentRequests just emptied out + LL_DEBUGS("Avatar") << "ATT all active attachment requests have completed" << LL_ENDL; + } + if (mRecentlyArrivedAttachments.empty()) + { + // Start the timer for sending off a COF link batch. + mCOFLinkBatchTimer.reset(); + } + mRecentlyArrivedAttachments.insert(inv_item_id); +} + +void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id) +{ + mDetachRequests.addTime(inv_item_id); +} + +void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) +{ + LLTimer timer; + LLInventoryItem *item = gInventory.getItem(inv_item_id); + if (mDetachRequests.getTime(inv_item_id, timer)) + { + LL_DEBUGS("Avatar") << "ATT detach completed after " << timer.getElapsedTimeF32() + << " seconds for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + mDetachRequests.removeTime(inv_item_id); + if (mDetachRequests.empty()) + { + LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL; + } + } + else + { + LL_WARNS() << "ATT unexpected detach for " + << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; + } + + LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking " + << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; + mQuestionableCOFLinks.addTime(inv_item_id); +} + +// Check for attachments that are (a) linked in COF and (b) not +// attached to the avatar. This is a rotten function to have to +// include, because it runs the risk of either repeatedly spamming out +// COF link removals if they're failing for some reason, or getting +// into a tug of war with some other sequence of events that's in the +// process of adding the attachment in question. However, it's needed +// because we have no definitive source of authority for what things +// are actually supposed to be attached. Scripts, run on the server +// side, can remove an attachment without our expecting it. If this +// happens to an attachment that's just been added, then the COF link +// creation may still be in flight, and we will have to delete the +// link after it shows up. +// +// Note that we only flag items for possible link removal if they have +// been previously detached. This means that an attachment failure +// will leave the link in the COF, where it will hopefully resolve +// correctly on relog. +// +// See related: MAINT-5070, MAINT-4409 +// +void LLAttachmentsMgr::checkInvalidCOFLinks() +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.size(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.at(i).get(); + const LLUUID& item_id = inv_item->getLinkedUUID(); + if (inv_item->getType() == LLAssetType::AT_OBJECT) + { + LLTimer timer; + bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); + bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); + if (is_wearing_attachment && is_flagged_questionable) + { + LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now " + << (is_wearing_attachment ? "attached " : "") + <<"removing flag after " + << timer.getElapsedTimeF32() << " item " + << inv_item->getName() << " id " << item_id << LL_ENDL; + mQuestionableCOFLinks.removeTime(item_id); + } + } + } + + for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); + it != mQuestionableCOFLinks.end(); ) + { + LLItemRequestTimes::iterator curr_it = it; + ++it; + const LLUUID& item_id = curr_it->first; + LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); + if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) + { + if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) + { + LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " + << curr_it->second.getElapsedTimeF32() << " seconds for " + << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + LLAppearanceMgr::instance().removeCOFItemLinks(item_id); + } + mQuestionableCOFLinks.erase(curr_it); + continue; + } + } +} + +void LLAttachmentsMgr::spamStatusInfo() +{ +#if 0 + static LLTimer spam_timer; + const F32 spam_frequency = 100.0F; - mPendingAttachments.clear(); + if (spam_timer.getElapsedTimeF32() > spam_frequency) + { + spam_timer.reset(); + + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), + cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; i<item_array.size(); i++) + { + const LLViewerInventoryItem* inv_item = item_array.at(i).get(); + if (inv_item->getType() == LLAssetType::AT_OBJECT) + { + LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << " parent: " << inv_item->getParentUUID() + << LL_ENDL; + } + } + } +#endif } diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index 1d8ab74dfd..d56d6eb27b 100755 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -32,42 +32,101 @@ class LLViewerInventoryItem; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//-------------------------------------------------------------------------------- // LLAttachmentsMgr // -// The sole purpose of this class is to take attachment -// requests, queue them up, and send them all at once. -// This handles situations where the viewer may request -// a bunch of attachments at once in a short period of -// time, where each of the requests would normally be -// sent as a separate message versus being batched into -// one single message. -// -// The intent of this batching is to reduce viewer->server -// traffic. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This class manages batching up of requests at two stages of +// attachment rezzing. +// +// First, attachments requested to rez get saved in +// mPendingAttachments and sent as a single +// RezMultipleAttachmentsFromInv request. This batching is needed +// mainly because of weaknessing the UI element->inventory item +// handling, such that we don't always know when we are requesting +// multiple items. Now they just pile up and get swept into a single +// request during the idle loop. +// +// Second, after attachments arrive, we need to generate COF links for +// them. There are both efficiency and UI correctness reasons why it +// is better to request all the COF links at once and run a single +// callback after they all complete. Given the vagaries of the +// attachment system, there is no guarantee that we will get all the +// attachments we ask for, but we frequently do. So in the common case +// that all the desired attachments arrive fairly quickly, we generate +// a single batched request for COF links. If attachments arrive late +// or not at all, we will still issue COF link requests once a timeout +// value has been exceeded. +// +// To handle attachments that never arrive, we forget about requests +// that exceed a timeout value. +//-------------------------------------------------------------------------------- class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr> { public: - LLAttachmentsMgr(); - virtual ~LLAttachmentsMgr(); - - void addAttachment(const LLUUID& item_id, - const U8 attachment_pt, - const BOOL add); - static void onIdle(void *); -protected: - void onIdle(); -private: + // Stores info for attachments that will be requested during idle. struct AttachmentsInfo { LLUUID mItemID; U8 mAttachmentPt; BOOL mAdd; }; + typedef std::deque<AttachmentsInfo> attachments_vec_t; + + LLAttachmentsMgr(); + virtual ~LLAttachmentsMgr(); + + void addAttachmentRequest(const LLUUID& item_id, + const U8 attachment_pt, + const BOOL add); + void onAttachmentRequested(const LLUUID& item_id); + void requestAttachments(attachments_vec_t& attachment_requests); + static void onIdle(void *); - typedef std::vector<AttachmentsInfo> attachments_vec_t; + void onAttachmentArrived(const LLUUID& inv_item_id); + + void onDetachRequested(const LLUUID& inv_item_id); + void onDetachCompleted(const LLUUID& inv_item_id); + +private: + + class LLItemRequestTimes: public std::map<LLUUID,LLTimer> + { + public: + LLItemRequestTimes(const std::string& op_name, F32 timeout); + void addTime(const LLUUID& inv_item_id); + void removeTime(const LLUUID& inv_item_id); + BOOL wasRequestedRecently(const LLUUID& item_id) const; + BOOL getTime(const LLUUID& inv_item_id, LLTimer& timer) const; + + private: + F32 mTimeout; + std::string mOpName; + }; + + void removeAttachmentRequestTime(const LLUUID& inv_item_id); + void onIdle(); + void requestPendingAttachments(); + void linkRecentlyArrivedAttachments(); + void expireOldAttachmentRequests(); + void expireOldDetachRequests(); + void checkInvalidCOFLinks(); + void spamStatusInfo(); + + // Attachments that we are planning to rez but haven't requested from the server yet. attachments_vec_t mPendingAttachments; + + // Attachments that have been requested from server but have not arrived yet. + LLItemRequestTimes mAttachmentRequests; + + // Attachments that have been requested to detach but have not gone away yet. + LLItemRequestTimes mDetachRequests; + + // Attachments that have arrived but have not been linked in the COF yet. + std::set<LLUUID> mRecentlyArrivedAttachments; + LLTimer mCOFLinkBatchTimer; + + // Attachments that are linked in the COF but may be invalid. + LLItemRequestTimes mQuestionableCOFLinks; }; #endif diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 281e591b48..25a5df9781 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -311,6 +311,7 @@ bool LLAvatarIconCtrl::updateFromCache() else { LLIconCtrl::setValue(mDefaultIconName); + return false; } return true; diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp index 59ecbdd0ea..59ecbdd0ea 100755..100644 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/newview/llcallbacklist.cpp diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index b6c5496c17..f79d1aa609 100755 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -97,7 +97,8 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, LLAvatarTracker::LLAvatarTracker() : mTrackingData(NULL), mTrackedAgentValid(false), - mModifyMask(0x0) + mModifyMask(0x0), + mIsNotifyObservers(FALSE) { } @@ -272,7 +273,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) << "]" << LL_ENDL; } } - notifyObservers(); + // do not notify observers here - list can be large so let it be done on idle. return new_buddy_count; } @@ -473,8 +474,25 @@ void LLAvatarTracker::removeObserver(LLFriendObserver* observer) mObservers.end()); } +void LLAvatarTracker::idleNotifyObservers() +{ + if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0) + { + return; + } + notifyObservers(); +} + void LLAvatarTracker::notifyObservers() { + if (mIsNotifyObservers) + { + // Don't allow multiple calls. + // new masks and ids will be processed later from idle. + return; + } + mIsNotifyObservers = TRUE; + observer_list_t observers(mObservers); observer_list_t::iterator it = observers.begin(); observer_list_t::iterator end = observers.end(); @@ -490,6 +508,7 @@ void LLAvatarTracker::notifyObservers() mModifyMask = LLFriendObserver::NONE; mChangedBuddyIDs.clear(); + mIsNotifyObservers = FALSE; } void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer) @@ -531,7 +550,7 @@ void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id) // store flag for change // and id of object change applies to void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent) -{ +{ mModifyMask |= mask; if (referent.notNull()) { diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 6e5fc01cd8..1f819a42fd 100755 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -143,6 +143,7 @@ public: // observers left behind. void addObserver(LLFriendObserver* observer); void removeObserver(LLFriendObserver* observer); + void idleNotifyObservers(); void notifyObservers(); // Observers interested in updates of a particular avatar. @@ -209,6 +210,8 @@ private: LLAvatarTracker(const LLAvatarTracker&); bool operator==(const LLAvatarTracker&); + BOOL mIsNotifyObservers; + public: // don't you dare create or delete this object LLAvatarTracker(); diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index b0537a83f1..d6240838b6 100755 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -35,6 +35,7 @@ #include "llviewerwindow.h" #include "llrootview.h" #include "llsyswellwindow.h" +#include "llfloaternotificationstabbed.h" #include "llfloaterreg.h" #include <algorithm> @@ -131,7 +132,7 @@ void LLChannelManager::onLoginCompleted() S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound); - mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4)); + mStartUpChannel->setMouseDownCallback(boost::bind(&LLFloaterNotificationsTabbed::onStartUpToastClick, LLFloaterNotificationsTabbed::getInstance(), _2, _3, _4)); mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this)); mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime")); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f0bd63ba46..dc0835eb1c 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -376,6 +376,10 @@ public: || mSourceType == CHAT_SOURCE_SYSTEM) { mFrom = LLTrans::getString("SECOND_LIFE"); + if(!chat.mFromName.empty() && (mFrom != chat.mFromName)) + { + mFrom += " (" + chat.mFromName + ")"; + } user_name->setValue(mFrom); updateMinUserNameWidth(); } @@ -934,7 +938,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // compact mode: show a timestamp and name if (use_plain_text_chat_history) { - square_brackets = chat.mFromName == SYSTEM_FROM; + square_brackets = chat.mSourceType == CHAT_SOURCE_SYSTEM; LLStyle::Params timestamp_style(body_message_params); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 46b7679915..dedb06c945 100755 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -35,6 +35,7 @@ #include "llscriptfloater.h" #include "llsingleton.h" #include "llsyswellwindow.h" +#include "llfloaternotificationstabbed.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); @@ -165,7 +166,7 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) mNotificationChannel.reset(new ChicletNotificationChannel(this)); // ensure that notification well window exists, to synchronously // handle toast add/delete events. - LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); + LLFloaterNotificationsTabbed::getInstance()->setSysWellChiclet(this); } void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) @@ -173,7 +174,7 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) std::string action = user_data.asString(); if("close all" == action) { - LLNotificationWellWindow::getInstance()->closeAll(); + LLFloaterNotificationsTabbed::getInstance()->closeAll(); LLIMWellWindow::getInstance()->closeAll(); } } @@ -224,7 +225,8 @@ bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNo 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())) + //|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID())) + || (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID(), notification->getName())) ) { displayNotification = false; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index d8b04f7004..254e3f61a8 100755 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -31,6 +31,7 @@ #include "lllayoutstack.h" #include "llpaneltopinfobar.h" #include "llsyswellwindow.h" +#include "llfloaternotificationstabbed.h" namespace { @@ -49,7 +50,7 @@ BOOL LLChicletBar::postBuild() mToolbarStack = getChild<LLLayoutStack>("toolbar_stack"); mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); - showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty()); + showWellButton("notification_well", !LLFloaterNotificationsTabbed::getInstance()->isWindowEmpty()); LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 19dba3f917..5ea7efc045 100755 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -30,6 +30,7 @@ #include "llcommandhandler.h" #include "llnotificationsutil.h" #include "llcommanddispatcherlistener.h" +#include "llstartup.h" #include "stringize.h" // system includes @@ -116,7 +117,11 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; if (! slurl_blocked) { - LLNotificationsUtil::add("BlockedSLURL"); + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + // Note: commands can arrive before we initialize everything we need for Notification. + LLNotificationsUtil::add("BlockedSLURL"); + } slurl_blocked = true; } return true; @@ -138,7 +143,10 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL; if (! slurl_throttled) { - LLNotificationsUtil::add("ThrottledSLURL"); + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + LLNotificationsUtil::add("ThrottledSLURL"); + } slurl_throttled = true; } return true; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index b38d472156..62f08144b9 100755 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -153,6 +153,7 @@ public: * file name is conversation.log */ std::string getFileName(); + LLConversation* findConversation(const LLIMModel::LLIMSession* session); private: @@ -184,7 +185,7 @@ private: void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name); void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages); - LLConversation* findConversation(const LLIMModel::LLIMSession* session); + typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 6e32ce60ec..328a638f2f 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -136,7 +136,24 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 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")); + + if (getType() != CONV_SESSION_1_ON_1) + { + items.push_back(std::string("voice_call")); + } + else + { + LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL; + if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel()) + { + items.push_back(std::string("voice_call")); + } + else + { + items.push_back(std::string("disconnect_from_voice")); + } + } + items.push_back(std::string("chat_history")); items.push_back(std::string("separator_chat_history")); items.push_back(std::string("add_friend")); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index deff94ea16..af7b50802c 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -86,7 +86,7 @@ public: virtual void move( LLFolderViewModelItem* parent_listener ) { } virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } - virtual BOOL cutToClipboard() const { return FALSE; } + virtual BOOL cutToClipboard() { return FALSE; } virtual BOOL isClipboardPasteable() const { return FALSE; } virtual void pasteFromClipboard() { } virtual void pasteLinkFromClipboard() { } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index e1d3d1a905..8bbc529244 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1553,7 +1553,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) { if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) - { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues + { + //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues for (S32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* facep = drawable->getFace(i); @@ -1570,13 +1571,15 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* buffer = face->getVertexBuffer(); } else - { //just rebuild this face + { + //just rebuild this face getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); } } if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) - { //perform software vertex skinning for this face + { + //perform software vertex skinning for this face LLStrider<LLVector3> position; LLStrider<LLVector3> normal; @@ -1600,6 +1603,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (!joint) + { + joint = avatar->getJoint("mPelvis"); + } if (joint) { mat[j] = skin->mInvBindMatrix[j]; @@ -1624,12 +1631,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* { F32 w = weight[j][k]; - idx[k] = llclamp((S32) floorf(w), 0, JOINT_COUNT-1); + idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)JOINT_COUNT-1); wght[k] = w - floorf(w); scale += wght[k]; } - + // This is enforced in unpackVolumeFaces() + llassert(scale>0.f); wght *= 1.f/scale; for (U32 k = 0; k < 4; k++) @@ -1729,6 +1737,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) for (U32 i = 0; i < count; ++i) { LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); + if (!joint) + { + joint = avatar->getJoint("mPelvis"); + } if (joint) { mat[i] = skin->mInvBindMatrix[i]; @@ -1797,9 +1809,12 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) if (mat) { - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP)); - gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); + //order is important here LLRender::DIFFUSE_MAP should be last, becouse it change + //(gGL).mCurrTextureUnitIndex gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP)); + gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP), false, true); + LLColor4 col = mat->getSpecularLightColor(); F32 spec = mat->getSpecularLightExponent()/255.f; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 33f7bc305c..7b9fd5c6c6 100755 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -864,6 +864,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass) { LLDrawInfo& params = **i; + gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff); LLDrawPoolBump::bindBumpMap(params, bump_channel); pushBatch(params, mask, TRUE); } diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..7f2363aadc 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -29,6 +29,7 @@ #include "llviewerprecompiledheaders.h" #include "llexperienceassociationresponder.h" #include "llexperiencecache.h" +#include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llagent.h" @@ -47,7 +48,13 @@ void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& ob void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback) { - LLViewerRegion* region = gAgent.getRegion(); + LLViewerObject* object = gObjectList.findObject(request["object-id"]); + if (!object) + { + LL_WARNS() << "Failed to find object with ID " << request["object-id"] << " in fetchAssociatedExperience" << LL_ENDL; + return; + } + LLViewerRegion* region = object->getRegion(); if (region) { std::string lookup_url=region->getCapability("GetMetadata"); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index fc9e85caf8..8f3eaaa207 100755 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -380,9 +380,11 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mShowDragMarker(FALSE), mLandingTab(NULL), mLastTab(NULL), - mTabsHighlightEnabled(TRUE) - , mUpdateDropDownItems(true) -, mRestoreOverflowMenu(false) + mTabsHighlightEnabled(TRUE), + mUpdateDropDownItems(true), + mRestoreOverflowMenu(false), + mGetPrevItems(true), + mItemsChangedTimer() { // Register callback for menus with current registrar (will be parent panel's registrar) LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected", @@ -659,6 +661,15 @@ void LLFavoritesBarCtrl::changed(U32 mask) LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); } updateButtons(); + if (!mItemsChangedTimer.getStarted()) + { + mItemsChangedTimer.start(); + } + else + { + mItemsChangedTimer.reset(); + } + } } @@ -693,6 +704,21 @@ void LLFavoritesBarCtrl::draw() // Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again) mShowDragMarker = FALSE; } + if (mItemsChangedTimer.getStarted()) + { + if (mItemsChangedTimer.getElapsedTimeF32() > 1.f) + { + LLFavoritesOrderStorage::instance().saveFavoritesRecord(); + mItemsChangedTimer.stop(); + } + } + + if(!mItemsChangedTimer.getStarted() && LLFavoritesOrderStorage::instance().mUpdateRequired) + { + LLFavoritesOrderStorage::instance().mUpdateRequired = false; + mItemsChangedTimer.start(); + } + } const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() @@ -723,6 +749,12 @@ void LLFavoritesBarCtrl::updateButtons() return; } + if(mGetPrevItems) + { + LLFavoritesOrderStorage::instance().mPrevFavorites = mItems; + mGetPrevItems = false; + } + const LLButton::Params& button_params = getButtonParams(); if(mItems.empty()) @@ -844,6 +876,7 @@ void LLFavoritesBarCtrl::updateButtons() { mUpdateDropDownItems = false; } + } LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset) @@ -912,9 +945,11 @@ BOOL LLFavoritesBarCtrl::postBuild() BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &items) { + if (mFavoriteFolderId.isNull()) return FALSE; + LLInventoryModel::cat_array_t cats; LLIsType is_type(LLAssetType::AT_LANDMARK); @@ -1411,6 +1446,7 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; const S32 LLFavoritesOrderStorage::NO_INDEX = -1; +bool LLFavoritesOrderStorage::mSaveOnExit = false; void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) { @@ -1447,6 +1483,7 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL; onLandmarkLoaded(asset_id, lm); } + return; } // static @@ -1482,13 +1519,16 @@ void LLFavoritesOrderStorage::destroyClass() LLFile::remove(old_filename); } - if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) - { - LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); - } - else + std::string filename = getSavedOrderFileName(); + file.open(filename.c_str()); + if (file.is_open()) { - LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); + file.close(); + LLFile::remove(filename); + if(mSaveOnExit) + { + LLFavoritesOrderStorage::instance().saveFavoritesRecord(true); + } } } @@ -1503,108 +1543,57 @@ std::string LLFavoritesOrderStorage::getSavedOrderFileName() void LLFavoritesOrderStorage::load() { - // load per-resident sorting information std::string filename = getSavedOrderFileName(); - LLSD settings_llsd; llifstream file; file.open(filename.c_str()); if (file.is_open()) { LLSDSerialize::fromXML(settings_llsd, file); - LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' " - << (settings_llsd.isMap() ? "" : "un") << "successfully" - << LL_ENDL; - file.close(); - } - else - { - LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL; - } - - for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); - iter != settings_llsd.endMap(); ++iter) - { - mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); + LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' " + << (settings_llsd.isMap() ? "" : "un") << "successfully" + << LL_ENDL; + file.close(); + mSaveOnExit = true; + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) + { + mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); + } } -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ - // Do not change the file if we are not logged in yet. - if (!LLLoginInstance::getInstance()->authSuccess()) + else { - LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL; - return; + filename = getStoredFavoritesFilename(); + if (!filename.empty()) + { + llifstream in_file; + in_file.open(filename.c_str()); + LLSD fav_llsd; + LLSD user_llsd; + if (in_file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, in_file); + LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' " + << (fav_llsd.isMap() ? "" : "un") << "successfully" + << LL_ENDL; + in_file.close(); + user_llsd = fav_llsd[gAgentUsername]; + + S32 index = 0; + for (LLSD::array_iterator iter = user_llsd.beginArray(); + iter != user_llsd.endArray(); ++iter) + { + mSortIndexes.insert(std::make_pair(iter->get("id").asUUID(), index)); + index++; + } + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; + } + } } - - std::string filename = getStoredFavoritesFilename(); - if (!filename.empty()) - { - llifstream in_file; - in_file.open(filename.c_str()); - LLSD fav_llsd; - if (in_file.is_open()) - { - LLSDSerialize::fromXML(fav_llsd, in_file); - LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' " - << (fav_llsd.isMap() ? "" : "un") << "successfully" - << LL_ENDL; - in_file.close(); - } - else - { - LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; - } - - const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - - LLSD user_llsd; - for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) - { - LLSD value; - value["name"] = (*it)->getName(); - value["asset_id"] = (*it)->getAssetUUID(); - - slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); - if (slurl_iter != mSLURLs.end()) - { - LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" << slurl_iter->second << ", value=" << value << LL_ENDL; - value["slurl"] = slurl_iter->second; - user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; - } - else - { - LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL; - } - } - - LLAvatarName av_name; - LLAvatarNameCache::get( gAgentID, &av_name ); - // Note : use the "John Doe" and not the "john.doe" version of the name - // as we'll compare it with the stored credentials in the login panel. - fav_llsd[av_name.getUserName()] = user_llsd; - - llofstream file; - file.open(filename.c_str()); - if ( file.is_open() ) - { - LLSDSerialize::toPrettyXML(fav_llsd, file); - LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName() - << "' to '" << filename << "' " - << LL_ENDL; - file.close(); - } - else - { - LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName() - << "' at '" << filename << "' " - << LL_ENDL; - } - } } void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() @@ -1626,8 +1615,30 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() // See saveFavoritesSLURLs() here above for the reason why. if (fav_llsd.has(av_name.getUserName())) { - LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL; - fav_llsd.erase(av_name.getUserName()); + LLSD user_llsd = fav_llsd[av_name.getUserName()]; + + if (user_llsd.beginArray()->has("id")) + { + for (LLSD::array_iterator iter = user_llsd.beginArray();iter != user_llsd.endArray(); ++iter) + { + LLSD value; + value["id"]= iter->get("id").asUUID(); + iter->assign(value); + } + fav_llsd[av_name.getUserName()] = user_llsd; + llofstream file; + file.open(filename.c_str()); + if ( file.is_open() ) + { + LLSDSerialize::toPrettyXML(fav_llsd, file); + file.close(); + } + } + else + { + LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL; + fav_llsd.erase(av_name.getUserName()); + } } llofstream out_file; @@ -1648,20 +1659,20 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar if (landmark) { LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL; - LLVector3d pos_global; - if (!landmark->getGlobalPos(pos_global)) - { - // If global position was unknown on first getGlobalPos() call - // it should be set for the subsequent calls. - landmark->getGlobalPos(pos_global); - } + LLVector3d pos_global; + if (!landmark->getGlobalPos(pos_global)) + { + // If global position was unknown on first getGlobalPos() call + // it should be set for the subsequent calls. + landmark->getGlobalPos(pos_global); + } - if (!pos_global.isExactlyZero()) - { - LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL; - LLLandmarkActions::getSLURLfromPosGlobal(pos_global, + if (!pos_global.isExactlyZero()) + { + LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL; + LLLandmarkActions::getSLURLfromPosGlobal(pos_global, boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); - } + } } } @@ -1671,41 +1682,6 @@ void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::st mSLURLs[asset_id] = slurl; } -void LLFavoritesOrderStorage::save() -{ - if (mIsDirty) - { - // something changed, so save it - std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName(); - if (!filename.empty()) - { - LLSD settings_llsd; - - for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) - { - settings_llsd[iter->first.asString()] = iter->second; - } - - llofstream file; - file.open(filename.c_str()); - if ( file.is_open() ) - { - LLSDSerialize::toPrettyXML(settings_llsd, file); - LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL; - } - else - { - LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL; - } - } - else - { - LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL; - } - } -} - - void LLFavoritesOrderStorage::cleanup() { // nothing to clean @@ -1720,7 +1696,7 @@ void LLFavoritesOrderStorage::cleanup() sort_index_map_t aTempMap; //copy unremoved values from mSortIndexes to aTempMap - std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), + std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), inserter(aTempMap, aTempMap.begin()), is_not_in_fav); @@ -1728,6 +1704,17 @@ void LLFavoritesOrderStorage::cleanup() mSortIndexes.swap(aTempMap); } +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) + { + return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()) + < LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + } +}; + void LLFavoritesOrderStorage::saveOrder() { LLInventoryModel::cat_array_t cats; @@ -1735,13 +1722,14 @@ void LLFavoritesOrderStorage::saveOrder() LLIsType is_type(LLAssetType::AT_LANDMARK); LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); saveItemsOrder(items); } void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) { - int sortField = 0; + int sortField = 0; // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) { @@ -1760,16 +1748,7 @@ void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array gInventory.notifyObservers(); } -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: - bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) - { - return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()) - < LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); - } -}; + // * @param source_item_id - LLUUID of the source item to be moved into new position // * @param target_item_id - LLUUID of the target item before which source item should be placed. @@ -1790,6 +1769,110 @@ void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_it saveItemsOrder(items); } +BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed) +{ + + LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + if (favorite_folder.isNull()) + return FALSE; + + LLInventoryModel::item_array_t items; + LLInventoryModel::cat_array_t cats; + + LLIsType is_type(LLAssetType::AT_LANDMARK); + gInventory.collectDescendentsIf(favorite_folder, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + std::sort(items.begin(), items.end(), LLFavoritesSort()); + + if((items != mPrevFavorites) || pref_changed) + { + std::string filename = getStoredFavoritesFilename(); + if (!filename.empty()) + { + llifstream in_file; + in_file.open(filename.c_str()); + LLSD fav_llsd; + if (in_file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, in_file); + in_file.close(); + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; + } + + LLSD user_llsd; + S32 fav_iter = 0; + for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) + { + LLSD value; + if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) + { + value["name"] = (*it)->getName(); + value["asset_id"] = (*it)->getAssetUUID(); + value["id"] = (*it)->getUUID(); + slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); + if (slurl_iter != mSLURLs.end()) + { + value["slurl"] = slurl_iter->second; + user_llsd[fav_iter] = value; + } + else + { + getSLURL((*it)->getAssetUUID()); + mUpdateRequired = true; + return FALSE; + } + } + else + { + value["id"] = (*it)->getUUID(); + user_llsd[fav_iter] = value; + } + + fav_iter ++; + } + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + // Note : use the "John Doe" and not the "john.doe" version of the name + // as we'll compare it with the stored credentials in the login panel. + fav_llsd[av_name.getUserName()] = user_llsd; + llofstream file; + file.open(filename.c_str()); + if ( file.is_open() ) + { + LLSDSerialize::toPrettyXML(fav_llsd, file); + file.close(); + mSaveOnExit = false; + } + else + { + LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName() + << "' at '" << filename << "' " << LL_ENDL; + } + } + + mPrevFavorites = items; + } + + return TRUE; + +} + +void LLFavoritesOrderStorage::showFavoritesOnLoginChanged(BOOL show) +{ + if (show) + { + saveFavoritesRecord(true); + } + else + { + removeFavoritesRecordOfUser(); + } +} + void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) { if (mTargetLandmarkId.isNull()) return; diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index a370724947..66fc8b2ae7 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -105,8 +105,10 @@ protected: bool mUpdateDropDownItems; bool mRestoreOverflowMenu; - LLUUID mSelectedItemID; + bool mGetPrevItems; + LLUUID mSelectedItemID; + LLFrameTimer mItemsChangedTimer; LLUIImage* mImageDragIndication; private: @@ -204,12 +206,23 @@ public: * @see cleanup() */ static void destroyClass(); + static std::string getStoredFavoritesFilename(); + static std::string getSavedOrderFileName(); + + BOOL saveFavoritesRecord(bool pref_changed = false); + void showFavoritesOnLoginChanged(BOOL show); + + LLInventoryModel::item_array_t mPrevFavorites; + const static S32 NO_INDEX; + static bool mSaveOnExit; + bool mUpdateRequired; + private: friend class LLSingleton<LLFavoritesOrderStorage>; - LLFavoritesOrderStorage() : mIsDirty(false) { load(); } - ~LLFavoritesOrderStorage() { save(); } + LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); } + ~LLFavoritesOrderStorage() {} /** * Removes sort indexes for items which are not in Favorites bar for now. @@ -217,13 +230,8 @@ private: void cleanup(); const static std::string SORTING_DATA_FILE_NAME; - std::string getSavedOrderFileName(); - static std::string getStoredFavoritesFilename(); - - void load(); - void save(); - void saveFavoritesSLURLs(); + void load(); // Remove record of current user's favorites from file on disk. void removeFavoritesRecordOfUser(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index b342d8fdf3..c5d637d1fc 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -34,10 +34,12 @@ // Viewer includes #include "llagent.h" #include "llagentui.h" -#include "llappviewer.h" +#include "llappviewer.h" +#include "llnotificationsutil.h" #include "llslurl.h" #include "llvoiceclient.h" #include "lluictrlfactory.h" +#include "llupdaterservice.h" #include "llviewertexteditor.h" #include "llviewercontrol.h" #include "llviewerstats.h" @@ -99,9 +101,23 @@ public: /// separated so that we can programmatically access the same info. static LLSD getInfo(); void onClickCopyToClipboard(); + void onClickUpdateCheck(); + + // checks state of updater service and starts a check outside of schedule. + // subscribes callback for closest state update + static void setUpdateListener(); private: void setSupportText(const std::string& server_release_notes_url); + + // notifications for user requested checks + static void showCheckUpdateNotification(S32 state); + + // callback method for manual checks + static bool callbackCheckUpdate(LLSD const & event); + + // listener name for update checks + static const std::string sCheckUpdateListenerName; }; @@ -132,6 +148,9 @@ BOOL LLFloaterAbout::postBuild() getChild<LLUICtrl>("copy_btn")->setCommitCallback( boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this)); + getChild<LLUICtrl>("update_btn")->setCommitCallback( + boost::bind(&LLFloaterAbout::onClickUpdateCheck, this)); + static const LLUIColor about_color = LLUIColorTable::instance().getColor("TextFgReadOnlyColor"); if (gAgent.getRegion()) @@ -235,6 +254,11 @@ void LLFloaterAbout::onClickCopyToClipboard() support_widget->deselect(); } +void LLFloaterAbout::onClickUpdateCheck() +{ + setUpdateListener(); +} + void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url) { #if LL_WINDOWS @@ -256,6 +280,68 @@ void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url) } ///---------------------------------------------------------------------------- +/// Floater About Update-check related functions +///---------------------------------------------------------------------------- + +const std::string LLFloaterAbout::sCheckUpdateListenerName = "LLUpdateNotificationListener"; + +void LLFloaterAbout::showCheckUpdateNotification(S32 state) +{ + switch (state) + { + case LLUpdaterService::UP_TO_DATE: + LLNotificationsUtil::add("UpdateViewerUpToDate"); + break; + case LLUpdaterService::DOWNLOADING: + case LLUpdaterService::INSTALLING: + LLNotificationsUtil::add("UpdateDownloadInProgress"); + break; + case LLUpdaterService::TERMINAL: + // download complete, user triggered check after download pop-up appeared + LLNotificationsUtil::add("UpdateDownloadComplete"); + break; + default: + LLNotificationsUtil::add("UpdateCheckError"); + break; + } +} + +bool LLFloaterAbout::callbackCheckUpdate(LLSD const & event) +{ + if (!event.has("payload")) + { + return false; + } + + LLSD payload = event["payload"]; + if (payload.has("type") && payload["type"].asInteger() == LLUpdaterService::STATE_CHANGE) + { + LLEventPumps::instance().obtain("mainlooprepeater").stopListening(sCheckUpdateListenerName); + showCheckUpdateNotification(payload["state"].asInteger()); + } + return false; +} + +void LLFloaterAbout::setUpdateListener() +{ + LLUpdaterService update_service; + S32 service_state = update_service.getState(); + // Note: Do not set state listener before forceCheck() since it set's new state + if (update_service.forceCheck() || service_state == LLUpdaterService::CHECKING_FOR_UPDATE) + { + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainlooprepeater")); + if (mainloop.getListener(sCheckUpdateListenerName) == LLBoundListener()) // dummy listener + { + mainloop.listen(sCheckUpdateListenerName, boost::bind(&callbackCheckUpdate, _1)); + } + } + else + { + showCheckUpdateNotification(service_state); + } +} + +///---------------------------------------------------------------------------- /// LLFloaterAboutUtil ///---------------------------------------------------------------------------- void LLFloaterAboutUtil::registerFloater() @@ -265,6 +351,11 @@ void LLFloaterAboutUtil::registerFloater() } +void LLFloaterAboutUtil::checkUpdatesAndNotify() +{ + LLFloaterAbout::setUpdateListener(); +} + ///---------------------------------------------------------------------------- /// Class LLServerReleaseNotesURLFetcher implementation ///---------------------------------------------------------------------------- @@ -289,15 +380,11 @@ void LLServerReleaseNotesURLFetcher::httpCompleted() LL_DEBUGS("ServerReleaseNotes") << dumpResponse() << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; - LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about"); - if (floater_about) + std::string location = getResponseHeader(HTTP_IN_HEADER_LOCATION); + if (location.empty()) { - std::string location = getResponseHeader(HTTP_IN_HEADER_LOCATION); - if (location.empty()) - { - location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); - } - LLAppViewer::instance()->setServerReleaseNotesURL(location); + location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); } + LLAppViewer::instance()->setServerReleaseNotesURL(location); } diff --git a/indra/newview/llfloaterabout.h b/indra/newview/llfloaterabout.h index 8fc1aa4f29..be34b631cc 100755 --- a/indra/newview/llfloaterabout.h +++ b/indra/newview/llfloaterabout.h @@ -30,6 +30,9 @@ namespace LLFloaterAboutUtil { void registerFloater(); + + // Support for user initialized update/state checks + void checkUpdatesAndNotify(); } #endif // LL_LLFLOATERABOUT_H diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 34904cf7ed..957c91b226 100755 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -32,6 +32,7 @@ #include "llavataractions.h" #include "llfloaterbump.h" +#include "llfloaterreg.h" #include "llfloaterreporter.h" #include "llmutelist.h" #include "llpanelblockedlist.h" @@ -87,11 +88,11 @@ BOOL LLFloaterBump::postBuild() // virtual void LLFloaterBump::onOpen(const LLSD& key) { - mNames.clear(); - mList->deleteAllItems(); - if (gMeanCollisionList.empty()) { + mNames.clear(); + mList->deleteAllItems(); + std::string none_detected = getString("none_detected"); LLSD row; row["columns"][0]["value"] = none_detected; @@ -100,12 +101,20 @@ void LLFloaterBump::onOpen(const LLSD& key) } else { - for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); - iter != gMeanCollisionList.end(); ++iter) - { - LLMeanCollisionData *mcd = *iter; - add(mList, mcd); - } + populateCollisionList(); + } +} + +void LLFloaterBump::populateCollisionList() +{ + mNames.clear(); + mList->deleteAllItems(); + + for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); + iter != gMeanCollisionList.end(); ++iter) + { + LLMeanCollisionData *mcd = *iter; + add(mList, mcd); } } @@ -247,3 +256,8 @@ void LLFloaterBump::inviteToGroup() { LLAvatarActions::inviteToGroup(mItemUUID); } + +LLFloaterBump* LLFloaterBump::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterBump>("bumps"); +} diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index 11b7db9fee..ce52c75255 100755 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -46,6 +46,10 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + static LLFloaterBump* getInstance(); + + void populateCollisionList(); + void startIM(); void startCall(); void reportAbuse(); diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 3a2047cfef..da85d378b2 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -64,9 +64,9 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo 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"; -const S32 MAX_QUALITY = 100; // Max quality value for jpeg images -const S32 MIN_QUALITY = 0; // Min quality value for jpeg images -const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook +const S32 MAX_QUALITY = 100; // Max quality value for jpeg images +const S32 MIN_QUALITY = 0; // Min quality value for jpeg images +const S32 TARGET_DATA_SIZE = 950000; // Size of the image (compressed) we're trying to send to Facebook std::string get_map_url() { diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 035eb307c2..62d7efc8b2 100755 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -82,6 +82,7 @@ void LLFloaterHardwareSettings::refresh() mVideoCardMem = gSavedSettings.getS32("TextureMemory"); mFogRatio = gSavedSettings.getF32("RenderFogRatio"); mProbeHardwareOnStartup = gSavedSettings.getBOOL("ProbeHardwareOnStartup"); + mCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); getChild<LLUICtrl>("fsaa")->setValue((LLSD::Integer) mFSAASamples); refreshEnabledState(); @@ -149,6 +150,7 @@ void LLFloaterHardwareSettings::refreshEnabledState() BOOL LLFloaterHardwareSettings::postBuild() { childSetAction("OK", onBtnOK, this); + childSetAction("Cancel", onBtnCancel, this); // Don't do this on Mac as their braindead GL versioning // sets this when 8x and 16x are indeed available @@ -179,18 +181,17 @@ void LLFloaterHardwareSettings::apply() void LLFloaterHardwareSettings::cancel() { - gSavedSettings.setBOOL("RenderVBOEnable", mUseVBO); - gSavedSettings.setBOOL("RenderAnisotropic", mUseAniso); - gSavedSettings.setU32("RenderFSAASamples", mFSAASamples); - gSavedSettings.setF32("RenderGamma", mGamma); - gSavedSettings.setS32("TextureMemory", mVideoCardMem); - gSavedSettings.setF32("RenderFogRatio", mFogRatio); - gSavedSettings.setBOOL("ProbeHardwareOnStartup", mProbeHardwareOnStartup ); - closeFloater(); } // static +void LLFloaterHardwareSettings::onBtnCancel( void* userdata ) +{ + LLFloaterHardwareSettings *fp =(LLFloaterHardwareSettings *)userdata; + fp->cancel(); +} + +// static void LLFloaterHardwareSettings::onBtnOK( void* userdata ) { LLFloaterHardwareSettings *fp =(LLFloaterHardwareSettings *)userdata; @@ -198,4 +199,14 @@ void LLFloaterHardwareSettings::onBtnOK( void* userdata ) fp->closeFloater(false); } - +void LLFloaterHardwareSettings::onClose(bool app_quitting) +{ + gSavedSettings.setBOOL("RenderVBOEnable", mUseVBO); + gSavedSettings.setBOOL("RenderAnisotropic", mUseAniso); + gSavedSettings.setU32("RenderFSAASamples", mFSAASamples); + gSavedSettings.setF32("RenderGamma", mGamma); + gSavedSettings.setS32("TextureMemory", mVideoCardMem); + gSavedSettings.setF32("RenderFogRatio", mFogRatio); + gSavedSettings.setBOOL("ProbeHardwareOnStartup", mProbeHardwareOnStartup ); + gSavedSettings.setBOOL("RenderCompressTextures", mCompressTextures ); +} diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h index 626771b1d2..11c27c266d 100755 --- a/indra/newview/llfloaterhardwaresettings.h +++ b/indra/newview/llfloaterhardwaresettings.h @@ -40,6 +40,7 @@ public: /*virtual*/ ~LLFloaterHardwareSettings(); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); /// initialize all the callbacks for the menu void initCallbacks(void); @@ -47,6 +48,9 @@ public: /// OK button static void onBtnOK( void* userdata ); + /// Cancel button + static void onBtnCancel( void* userdata ); + //// menu management /// show off our menu @@ -76,6 +80,7 @@ protected: S32 mVideoCardMem; F32 mFogRatio; BOOL mProbeHardwareOnStartup; + BOOL mCompressTextures; private: }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ab57e8c170..f1a6ef78a6 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -261,6 +261,8 @@ BOOL LLFloaterIMContainer::postBuild() mInitialized = true; + mIsFirstOpen = true; + // Add callbacks: // We'll take care of view updates on idle gIdleCallbacks.addFunction(idle, this); @@ -636,14 +638,16 @@ void LLFloaterIMContainer::setVisible(BOOL visible) { // Make sure we have the Nearby Chat present when showing the conversation container nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); - if (nearby_chat == NULL) + if ((nearby_chat == NULL) || mIsFirstOpen) { + mIsFirstOpen = false; // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); selectConversationPair(LLUUID(NULL), false, false); } + flashConversationItemWidget(mSelectedSession,false); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); @@ -1216,7 +1220,22 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, { if (selectedIDS.size() > 0) { - LLAvatarActions::viewChatHistory(selectedIDS.front()); + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) + { + LLFloaterReg::showInstance("preview_conversation", conversationItem->getUUID(), true); + } + else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC) + { + LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(conversationItem->getUUID())); + if(conv) + { + LLFloaterReg::showInstance("preview_conversation", conv->getSessionID(), true); + } + } + else + { + LLAvatarActions::viewChatHistory(selectedIDS.front()); + } } } else @@ -1316,6 +1335,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) { return LLLogChat::isNearbyTranscriptExist(); } + else if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_AD_HOC) + { + const LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(uuids.front())); + if(conv) + { + return LLLogChat::isAdHocTranscriptExist(conv->getHistoryFileName()); + } + return false; + } else { bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP); @@ -1881,22 +1909,28 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid) return false; } - if (!gdatap->mMembers.size()) + if (gdatap->mPendingBanRequest) { return false; } - LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); - if (mi == gdatap->mMembers.end()) + if (gdatap->isRoleMemberDataComplete()) { - return false; - } + if (!gdatap->mMembers.size()) + { + return false; + } - LLGroupMemberData* member_data = (*mi).second; - // Is the member an owner? - if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) - { - return false; + LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); + if (mi != gdatap->mMembers.end()) + { + LLGroupMemberData* member_data = (*mi).second; + // Is the member an owner? + if (member_data && member_data->isInRole(gdatap->mOwnerRole)) + { + return false; + } + } } if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) && @@ -1924,20 +1958,8 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid) LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL; return; } - std::vector<LLUUID> ids; - ids.push_back(participant_uuid); - - LLGroupBanData ban_data; - gdatap->createBanEntry(participant_uuid, ban_data); - LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids); - LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids); - LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid); - LLSD args; - std::string name; - gCacheName->getFullName(participant_uuid, name); - args["AVATAR_NAME"] = name; - args["GROUP_NAME"] = gdatap->mName; - LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); + + gdatap->banMemberById(participant_uuid); } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index f21c0b9947..60cef83d9a 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -193,6 +193,8 @@ private: bool mInitialized; bool mIsFirstLaunch; + bool mIsFirstOpen; + LLUUID mSelectedSession; std::string mGeneralTitle; diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index b7fff6cae3..ee3d633dd0 100755 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -326,7 +326,21 @@ void LLFloaterJoystick::onClickOK(void *joy_panel) } } +void LLFloaterJoystick::onClickCloseBtn(bool app_quitting) +{ + cancel(); + closeFloater(app_quitting); +} + void LLFloaterJoystick::setSNDefaults() { LLViewerJoystick::getInstance()->setSNDefaults(); } + +void LLFloaterJoystick::onClose(bool app_quitting) +{ + if (app_quitting) + { + cancel(); + } +} diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index 9c3752540d..a1b5951389 100755 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -45,6 +45,11 @@ public: virtual void draw(); static void setSNDefaults(); +protected: + + void onClose(bool app_quitting); + void onClickCloseBtn(bool app_quitting); + private: LLFloaterJoystick(const LLSD& data); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index f9c39a02c9..f9fd5069af 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -81,6 +81,8 @@ #include "llgroupactions.h" +const F64 COVENANT_REFRESH_TIME_SEC = 60.0f; + static std::string OWNER_ONLINE = "0"; static std::string OWNER_OFFLINE = "1"; static std::string OWNER_GROUP = "2"; @@ -2437,6 +2439,8 @@ void LLPanelLandAccess::refresh() mListAccess->clearSortOrder(); mListAccess->deleteAllItems(); S32 count = parcel->mAccessList.size(); + getChild<LLUICtrl>("AllowedText")->setTextArg("[COUNT]", llformat("%d",count)); + getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); @@ -2444,33 +2448,33 @@ void LLPanelLandAccess::refresh() cit != parcel->mAccessList.end(); ++cit) { const LLAccessEntry& entry = (*cit).second; - std::string suffix; + std::string prefix; if (entry.mTime != 0) { LLStringUtil::format_map_t args; S32 now = time(NULL); S32 seconds = entry.mTime - now; if (seconds < 0) seconds = 0; - suffix.assign(" ("); + prefix.assign(" ("); if (seconds >= 120) { args["[MINUTES]"] = llformat("%d", (seconds/60)); std::string buf = parent_floater->getString ("Minutes", args); - suffix.append(buf); + prefix.append(buf); } else if (seconds >= 60) { - suffix.append("1 " + parent_floater->getString("Minute")); + prefix.append("1 " + parent_floater->getString("Minute")); } else { args["[SECONDS]"] = llformat("%d", seconds); std::string buf = parent_floater->getString ("Seconds", args); - suffix.append(buf); + prefix.append(buf); } - suffix.append(" " + parent_floater->getString("Remaining") + ")"); + prefix.append(" " + parent_floater->getString("Remaining") + ") "); } - mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix); + mListAccess->addNameItem(entry.mID, ADD_DEFAULT, TRUE, "", prefix); } mListAccess->sortByName(TRUE); } @@ -2482,6 +2486,7 @@ void LLPanelLandAccess::refresh() mListBanned->clearSortOrder(); mListBanned->deleteAllItems(); S32 count = parcel->mBanList.size(); + getChild<LLUICtrl>("BanCheck")->setTextArg("[COUNT]", llformat("%d",count)); getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count)); getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); @@ -2490,33 +2495,33 @@ void LLPanelLandAccess::refresh() cit != parcel->mBanList.end(); ++cit) { const LLAccessEntry& entry = (*cit).second; - std::string suffix; + std::string prefix; if (entry.mTime != 0) { LLStringUtil::format_map_t args; S32 now = time(NULL); S32 seconds = entry.mTime - now; if (seconds < 0) seconds = 0; - suffix.assign(" ("); + prefix.assign(" ("); if (seconds >= 120) { args["[MINUTES]"] = llformat("%d", (seconds/60)); std::string buf = parent_floater->getString ("Minutes", args); - suffix.append(buf); + prefix.append(buf); } else if (seconds >= 60) { - suffix.append("1 " + parent_floater->getString("Minute")); + prefix.append("1 " + parent_floater->getString("Minute")); } else { args["[SECONDS]"] = llformat("%d", seconds); std::string buf = parent_floater->getString ("Seconds", args); - suffix.append(buf); + prefix.append(buf); } - suffix.append(" " + parent_floater->getString("Remaining") + ")"); + prefix.append(" " + parent_floater->getString("Remaining") + ") "); } - mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix); + mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, "", prefix); } mListBanned->sortByName(TRUE); } @@ -2919,14 +2924,23 @@ void LLPanelLandAccess::onClickRemoveBanned(void* data) //--------------------------------------------------------------------------- LLPanelLandCovenant::LLPanelLandCovenant(LLParcelSelectionHandle& parcel) : LLPanel(), - mParcel(parcel) -{ + mParcel(parcel), + mNextUpdateTime(0) +{ } LLPanelLandCovenant::~LLPanelLandCovenant() { } +BOOL LLPanelLandCovenant::postBuild() +{ + mLastRegionID = LLUUID::null; + mNextUpdateTime = 0; + + return TRUE; +} + // virtual void LLPanelLandCovenant::refresh() { @@ -2973,14 +2987,23 @@ void LLPanelLandCovenant::refresh() changeable_clause->setText(getString("can_not_change")); } } - - // send EstateCovenantInfo message - LLMessageSystem *msg = gMessageSystem; - msg->newMessage("EstateCovenantRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); - msg->sendReliable(region->getHost()); + + if (mLastRegionID != region->getRegionID() + || mNextUpdateTime < LLTimer::getElapsedSeconds()) + { + // Request Covenant Info + // Note: LLPanelLandCovenant doesn't change Covenant's content and any + // changes made by Estate floater should be requested by Estate floater + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("EstateCovenantRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->sendReliable(region->getHost()); + + mLastRegionID = region->getRegionID(); + mNextUpdateTime = LLTimer::getElapsedSeconds() + COVENANT_REFRESH_TIME_SEC; + } } // static diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 8e8b61c333..0540ddb880 100755 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -394,6 +394,7 @@ class LLPanelLandCovenant public: LLPanelLandCovenant(LLSafeHandle<LLParcelSelection>& parcelp); virtual ~LLPanelLandCovenant(); + virtual BOOL postBuild(); void refresh(); static void updateCovenantText(const std::string& string); static void updateEstateName(const std::string& name); @@ -402,6 +403,10 @@ public: protected: LLSafeHandle<LLParcelSelection>& mParcel; + +private: + LLUUID mLastRegionID; + F64 mNextUpdateTime; //seconds since client start }; #endif diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp new file mode 100755 index 0000000000..b2d36479cd --- /dev/null +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -0,0 +1,949 @@ +/** + * @file llfloatermarketplacelistings.cpp + * @brief Implementation of the marketplace listings floater and panels + * @author merov@lindenlab.com + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatermarketplacelistings.h" + +#include "llfloaterreg.h" +#include "llfiltereditor.h" +#include "llfolderview.h" +#include "llinventorybridge.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventoryfunctions.h" +#include "llmarketplacefunctions.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" +#include "llsidepaneliteminfo.h" +#include "lltextbox.h" +#include "lltrans.h" + +///---------------------------------------------------------------------------- +/// LLPanelMarketplaceListings +///---------------------------------------------------------------------------- + +static LLPanelInjector<LLPanelMarketplaceListings> t_panel_status("llpanelmarketplacelistings"); + +LLPanelMarketplaceListings::LLPanelMarketplaceListings() +: mRootFolder(NULL) +, mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME) +, mFilterListingFoldersOnly(false) +{ + mCommitCallbackRegistrar.add("Marketplace.ViewSort.Action", boost::bind(&LLPanelMarketplaceListings::onViewSortMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("Marketplace.ViewSort.CheckItem", boost::bind(&LLPanelMarketplaceListings::onViewSortMenuItemCheck, this, _2)); +} + +BOOL LLPanelMarketplaceListings::postBuild() +{ + childSetAction("add_btn", boost::bind(&LLPanelMarketplaceListings::onAddButtonClicked, this)); + childSetAction("audit_btn", boost::bind(&LLPanelMarketplaceListings::onAuditButtonClicked, this)); + + mFilterEditor = getChild<LLFilterEditor>("filter_editor"); + mFilterEditor->setCommitCallback(boost::bind(&LLPanelMarketplaceListings::onFilterEdit, this, _2)); + + mAuditBtn = getChild<LLButton>("audit_btn"); + mAuditBtn->setEnabled(FALSE); + + return LLPanel::postBuild(); +} + +BOOL LLPanelMarketplaceListings::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + // Special case the drop zone + if (handled && (handled_view->getName() == "marketplace_drop_zone")) + { + LLFolderView* root_folder = getRootFolder(); + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + return handled; +} + +void LLPanelMarketplaceListings::buildAllPanels() +{ + // Build the All panel first + LLInventoryPanel* panel_all_items; + panel_all_items = buildInventoryPanel("All Items", "panel_marketplace_listings_inventory.xml"); + panel_all_items->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel_all_items->getFilter().markDefault(); + + // Build the other panels + LLInventoryPanel* panel; + panel = buildInventoryPanel("Active Items", "panel_marketplace_listings_listed.xml"); + panel->getFilter().setFilterMarketplaceActiveFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + panel = buildInventoryPanel("Inactive Items", "panel_marketplace_listings_unlisted.xml"); + panel->getFilter().setFilterMarketplaceInactiveFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + panel = buildInventoryPanel("Unassociated Items", "panel_marketplace_listings_unassociated.xml"); + panel->getFilter().setFilterMarketplaceUnassociatedFolders(); + panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems"); + panel->getFilter().markDefault(); + + // Set the tab panel + LLTabContainer* tabs_panel = getChild<LLTabContainer>("marketplace_filter_tabs"); + tabs_panel->setCommitCallback(boost::bind(&LLPanelMarketplaceListings::onTabChange, this)); + tabs_panel->selectTabPanel(panel_all_items); // All panel selected by default + mRootFolder = panel_all_items->getRootFolder(); // Keep the root of the all panel + + // Set the default sort order + setSortOrder(gSavedSettings.getU32("MarketplaceListingsSortOrder")); +} + +LLInventoryPanel* LLPanelMarketplaceListings::buildInventoryPanel(const std::string& childname, const std::string& filename) +{ + LLTabContainer* tabs_panel = getChild<LLTabContainer>("marketplace_filter_tabs"); + LLInventoryPanel* panel = LLUICtrlFactory::createFromFile<LLInventoryPanel>(filename, tabs_panel, LLInventoryPanel::child_registry_t::instance()); + llassert(panel != NULL); + + // Set sort order and callbacks + panel = getChild<LLInventoryPanel>(childname); + panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + panel->setSelectCallback(boost::bind(&LLPanelMarketplaceListings::onSelectionChange, this, panel, _1, _2)); + + return panel; +} + +void LLPanelMarketplaceListings::setSortOrder(U32 sort_order) +{ + mSortOrder = sort_order; + gSavedSettings.setU32("MarketplaceListingsSortOrder", sort_order); + + // Set each panel with that sort order + LLTabContainer* tabs_panel = getChild<LLTabContainer>("marketplace_filter_tabs"); + LLInventoryPanel* panel = (LLInventoryPanel*)tabs_panel->getPanelByName("All Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Active Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Inactive Items"); + panel->setSortOrder(mSortOrder); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Unassociated Items"); + panel->setSortOrder(mSortOrder); +} + +void LLPanelMarketplaceListings::onFilterEdit(const std::string& search_string) +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + // Save filter string (needed when switching tabs) + mFilterSubString = search_string; + // Set filter string on active panel + panel->setFilterSubString(mFilterSubString); + } +} + +void LLPanelMarketplaceListings::draw() +{ + if (LLMarketplaceData::instance().checkDirtyCount()) + { + update_all_marketplace_count(); + } + + // Get the audit button enabled only after the whole inventory is fetched + if (!mAuditBtn->getEnabled()) + { + mAuditBtn->setEnabled(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()); + } + + LLPanel::draw(); +} + +void LLPanelMarketplaceListings::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action) +{ + panel->onSelectionChange(items, user_action); +} + +bool LLPanelMarketplaceListings::allowDropOnRoot() +{ + LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel(); + return (panel ? panel->getAllowDropOnRoot() : false); +} + +void LLPanelMarketplaceListings::onTabChange() +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + // If the panel doesn't allow drop on root, it doesn't allow the creation of new folder on root either + LLButton* add_btn = getChild<LLButton>("add_btn"); + add_btn->setEnabled(panel->getAllowDropOnRoot()); + + // Set filter string on active panel + panel->setFilterSubString(mFilterSubString); + + // Show/hide the drop zone and resize the inventory tabs panel accordingly + LLPanel* drop_zone = (LLPanel*)getChild<LLPanel>("marketplace_drop_zone"); + bool drop_zone_visible = drop_zone->getVisible(); + if (drop_zone_visible != panel->getAllowDropOnRoot()) + { + LLPanel* tabs = (LLPanel*)getChild<LLPanel>("tab_container_panel"); + S32 delta_height = drop_zone->getRect().getHeight(); + delta_height = (drop_zone_visible ? delta_height : -delta_height); + tabs->reshape(tabs->getRect().getWidth(),tabs->getRect().getHeight() + delta_height); + tabs->translate(0,-delta_height); + } + drop_zone->setVisible(panel->getAllowDropOnRoot()); + } +} + +void LLPanelMarketplaceListings::onAddButtonClicked() +{ + // Find active panel + LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + llassert(marketplacelistings_id.notNull()); + LLFolderType::EType preferred_type = LLFolderType::lookup("category"); + LLUUID category = gInventory.createNewCategory(marketplacelistings_id, preferred_type, LLStringUtil::null); + gInventory.notifyObservers(); + panel->setSelectionByID(category, TRUE); + panel->getRootFolder()->setNeedsAutoRename(TRUE); + } +} + +void LLPanelMarketplaceListings::onAuditButtonClicked() +{ + LLSD data(LLSD::emptyMap()); + LLFloaterReg::showInstance("marketplace_validation", data); +} + +void LLPanelMarketplaceListings::onViewSortMenuItemClicked(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + // Sort options + if ((chosen_item == "sort_by_stock_amount") || (chosen_item == "sort_by_name") || (chosen_item == "sort_by_recent")) + { + // We're making sort options exclusive, default is SO_FOLDERS_BY_NAME + if (chosen_item == "sort_by_stock_amount") + { + setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); + } + else if (chosen_item == "sort_by_name") + { + setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + else if (chosen_item == "sort_by_recent") + { + setSortOrder(LLInventoryFilter::SO_DATE); + } + } + // Filter option + else if (chosen_item == "show_only_listing_folders") + { + mFilterListingFoldersOnly = !mFilterListingFoldersOnly; + // Set each panel with that filter flag + LLTabContainer* tabs_panel = getChild<LLTabContainer>("marketplace_filter_tabs"); + LLInventoryPanel* panel = (LLInventoryPanel*)tabs_panel->getPanelByName("All Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Active Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Inactive Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + panel = (LLInventoryPanel*)tabs_panel->getPanelByName("Unassociated Items"); + panel->getFilter().setFilterMarketplaceListingFolders(mFilterListingFoldersOnly); + } +} + +bool LLPanelMarketplaceListings::onViewSortMenuItemCheck(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + if ((chosen_item == "sort_by_stock_amount") || (chosen_item == "sort_by_name") || (chosen_item == "sort_by_recent")) + { + if (chosen_item == "sort_by_stock_amount") + { + return (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); + } + else if (chosen_item == "sort_by_name") + { + return (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + else if (chosen_item == "sort_by_recent") + { + return (mSortOrder & LLInventoryFilter::SO_DATE); + } + } + else if (chosen_item == "show_only_listing_folders") + { + return mFilterListingFoldersOnly; + } + return false; +} + +///---------------------------------------------------------------------------- +/// LLMarketplaceListingsAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLMarketplaceListingsAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLMarketplaceListingsAddedObserver(LLFloaterMarketplaceListings * marketplace_listings_floater) + : LLInventoryCategoryAddedObserver() + , mMarketplaceListingsFloater(marketplace_listings_floater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS) + { + mMarketplaceListingsFloater->initializeMarketPlace(); + } + } + } + +private: + LLFloaterMarketplaceListings * mMarketplaceListingsFloater; +}; + +///---------------------------------------------------------------------------- +/// LLFloaterMarketplaceListings +///---------------------------------------------------------------------------- + +LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key) +: LLFloater(key) +, mCategoriesObserver(NULL) +, mCategoryAddedObserver(NULL) +, mRootFolderId(LLUUID::null) +, mInventoryStatus(NULL) +, mInventoryInitializationInProgress(NULL) +, mInventoryPlaceholder(NULL) +, mInventoryText(NULL) +, mInventoryTitle(NULL) +, mPanelListings(NULL) +, mPanelListingsSet(false) +{ +} + +LLFloaterMarketplaceListings::~LLFloaterMarketplaceListings() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterMarketplaceListings::postBuild() +{ + mInventoryStatus = getChild<LLTextBox>("marketplace_status"); + mInventoryInitializationInProgress = getChild<LLView>("initialization_progress_indicator"); + mInventoryPlaceholder = getChild<LLView>("marketplace_listings_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("marketplace_listings_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("marketplace_listings_inventory_placeholder_title"); + + mPanelListings = static_cast<LLPanelMarketplaceListings*>(getChild<LLUICtrl>("panel_marketplace_listing")); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterMarketplaceListings::onFocusReceived, this)); + + // Observe category creation to catch marketplace listings creation (moot if already existing) + mCategoryAddedObserver = new LLMarketplaceListingsAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + + // Fetch aggressively so we can interact with listings right onOpen() + fetchContents(); + + return TRUE; +} + +void LLFloaterMarketplaceListings::onClose(bool app_quitting) +{ +} + +void LLFloaterMarketplaceListings::onOpen(const LLSD& key) +{ + // + // Initialize the Market Place or go update the marketplace listings + // + if (LLMarketplaceData::instance().getSLMStatus() <= MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE) + { + initializeMarketPlace(); + } + else + { + updateView(); + } +} + +void LLFloaterMarketplaceListings::onFocusReceived() +{ + updateView(); +} + +void LLFloaterMarketplaceListings::fetchContents() +{ + if (mRootFolderId.notNull() && + (LLMarketplaceData::instance().getSLMDataFetched() != MarketplaceFetchCodes::MARKET_FETCH_LOADING) && + (LLMarketplaceData::instance().getSLMDataFetched() != MarketplaceFetchCodes::MARKET_FETCH_DONE)) + { + LLMarketplaceData::instance().setDataFetchedSignal(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); + LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_LOADING); + LLInventoryModelBackgroundFetch::instance().start(mRootFolderId); + LLMarketplaceData::instance().getSLMListings(); + } +} + +void LLFloaterMarketplaceListings::setRootFolder() +{ + if ((LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) && + (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT)) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } + + // We are a merchant. Get the Marketplace listings folder, create it if needs be. + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true); + if (marketplacelistings_id.isNull()) + { + // We should never get there unless the inventory fails badly + LL_ERRS("SLM") << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << LL_ENDL; + return; + } + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + llassert(!mCategoryAddedObserver); + + if (marketplacelistings_id == mRootFolderId) + { + LL_WARNS("SLM") << "Inventory warning: Marketplace listings folder already set" << LL_ENDL; + return; + } + + mRootFolderId = marketplacelistings_id; +} + +void LLFloaterMarketplaceListings::setPanels() +{ + if (mRootFolderId.isNull()) + { + return; + } + + // Consolidate Marketplace listings + // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, + // things get messy and conventions get broken down eventually + gInventory.consolidateForType(mRootFolderId, LLFolderType::FT_MARKETPLACE_LISTINGS); + + // Now that we do have a non NULL root, we can build the inventory panels + mPanelListings->buildAllPanels(); + + // Create observer for marketplace listings modifications + if (!mCategoriesObserver) + { + mCategoriesObserver = new LLInventoryCategoriesObserver(); + llassert(mCategoriesObserver); + gInventory.addObserver(mCategoriesObserver); + mCategoriesObserver->addCategory(mRootFolderId, boost::bind(&LLFloaterMarketplaceListings::onChanged, this)); + } + + // Get the content of the marketplace listings folder + fetchContents(); + + // Flag that this is done + mPanelListingsSet = true; +} + +void LLFloaterMarketplaceListings::initializeMarketPlace() +{ + LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); +} + +S32 LLFloaterMarketplaceListings::getFolderCount() +{ + if (mPanelListings && mRootFolderId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mRootFolderId, cats, items); + + return (cats->size() + items->size()); + } + else + { + return 0; + } +} + +void LLFloaterMarketplaceListings::setStatusString(const std::string& statusString) +{ + mInventoryStatus->setText(statusString); +} + +void LLFloaterMarketplaceListings::updateView() +{ + U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); + bool is_merchant = (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) || (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT); + U32 data_fetched = LLMarketplaceData::instance().getSLMDataFetched(); + + // Get or create the root folder if we are a merchant and it hasn't been done already + if (mRootFolderId.isNull() && is_merchant) + { + setRootFolder(); + } + + // Update the bottom initializing status and progress dial if we are initializing or if we're a merchant and still loading + if ((mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) || (is_merchant && (data_fetched <= MarketplaceFetchCodes::MARKET_FETCH_LOADING)) ) + { + // Just show the loading indicator in that case and fetch the data (fetch will be skipped if it's already loading) + mInventoryInitializationInProgress->setVisible(true); + mPanelListings->setVisible(FALSE); + fetchContents(); + return; + } + else + { + mInventoryInitializationInProgress->setVisible(false); + } + + // Update the middle portion : tabs or messages + if (getFolderCount() > 0) + { + if (!mPanelListingsSet) + { + // We need to rebuild the tabs cleanly the first time we make them visible + setPanels(); + } + mPanelListings->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + } + else + { + mPanelListings->setVisible(FALSE); + mInventoryPlaceholder->setVisible(TRUE); + + std::string text; + std::string title; + std::string tooltip; + + const LLSD& subs = getMarketplaceStringSubstitutions(); + + // Update the top message or flip to the tabs and folders view + // *TODO : check those messages and create better appropriate ones in strings.xml + if (mRootFolderId.notNull()) + { + // "Marketplace listings is empty!" message strings + text = LLTrans::getString("InventoryMarketplaceListingsNoItems", subs); + title = LLTrans::getString("InventoryMarketplaceListingsNoItemsTitle"); + tooltip = LLTrans::getString("InventoryMarketplaceListingsNoItemsTooltip"); + } + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) + { + // "Initializing!" message strings + text = LLTrans::getString("InventoryOutboxInitializing", subs); + title = LLTrans::getString("InventoryOutboxInitializingTitle"); + tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) + { + // "Not a merchant!" message strings + text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + else + { + // "Errors!" message strings + text = LLTrans::getString("InventoryMarketplaceError", subs); + title = LLTrans::getString("InventoryOutboxErrorTitle"); + tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } + + mInventoryText->setValue(text); + mInventoryTitle->setValue(title); + mInventoryPlaceholder->getParent()->setToolTip(tooltip); + } +} + +bool LLFloaterMarketplaceListings::isAccepted(EAcceptance accept) +{ + return (accept >= ACCEPT_YES_COPY_SINGLE); +} + +BOOL LLFloaterMarketplaceListings::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // If there's no panel to accept drops or no existing marketplace listings folder, we refuse all drop + if (!mPanelListings || mRootFolderId.isNull()) + { + return FALSE; + } + + tooltip_msg = ""; + + // Pass to the children + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // If no one handled it or it was not accepted and we drop on an empty panel, we try to accept it at the floater level + // as if it was dropped on the marketplace listings root folder + if ((!handled || !isAccepted(*accept)) && !mPanelListings->getVisible() && mRootFolderId.notNull()) + { + if (!mPanelListingsSet) + { + setPanels(); + } + LLFolderView* root_folder = mPanelListings->getRootFolder(); + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + +BOOL LLFloaterMarketplaceListings::handleHover(S32 x, S32 y, MASK mask) +{ + return LLFloater::handleHover(x, y, mask); +} + +void LLFloaterMarketplaceListings::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLFloater::onMouseLeave(x, y, mask); +} + +void LLFloaterMarketplaceListings::onChanged() +{ + LLViewerInventoryCategory* category = gInventory.getCategory(mRootFolderId); + if (mRootFolderId.notNull() && category) + { + updateView(); + } + else + { + // Invalidate the marketplace listings data + mRootFolderId.setNull(); + } +} + +//----------------------------------------------------------------------------- +// LLFloaterAssociateListing +//----------------------------------------------------------------------------- + +// Tell if a listing has one only version folder +bool hasUniqueVersionFolder(const LLUUID& folder_id) +{ + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(folder_id, categories, items); + return (categories->size() == 1); +} + +LLFloaterAssociateListing::LLFloaterAssociateListing(const LLSD& key) +: LLFloater(key) +, mUUID() +{ +} + +LLFloaterAssociateListing::~LLFloaterAssociateListing() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +BOOL LLFloaterAssociateListing::postBuild() +{ + getChild<LLButton>("OK")->setCommitCallback(boost::bind(&LLFloaterAssociateListing::apply, this, TRUE)); + getChild<LLButton>("Cancel")->setCommitCallback(boost::bind(&LLFloaterAssociateListing::cancel, this)); + getChild<LLLineEditor>("listing_id")->setPrevalidate(&LLTextValidate::validateNonNegativeS32); + center(); + + return LLFloater::postBuild(); +} + +BOOL LLFloaterAssociateListing::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_RETURN && mask == MASK_NONE) + { + apply(); + return TRUE; + } + else if (key == KEY_ESCAPE && mask == MASK_NONE) + { + cancel(); + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); +} + +// static +LLFloaterAssociateListing* LLFloaterAssociateListing::show(const LLUUID& folder_id) +{ + LLFloaterAssociateListing* floater = LLFloaterReg::showTypedInstance<LLFloaterAssociateListing>("associate_listing"); + + floater->mUUID = folder_id; + + return floater; +} + +// Callback for apply if DAMA required... +void LLFloaterAssociateListing::callback_apply(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + apply(FALSE); + } +} + +void LLFloaterAssociateListing::apply(BOOL user_confirm) +{ + if (mUUID.notNull()) + { + S32 id = (S32)getChild<LLUICtrl>("listing_id")->getValue().asInteger(); + if (id > 0) + { + // Check if the id exists in the merchant SLM DB: note that this record might exist in the LLMarketplaceData + // structure even if unseen in the UI, for instance, if its listing_uuid doesn't exist in the merchant inventory + LLUUID listing_uuid = LLMarketplaceData::instance().getListingFolder(id); + if (listing_uuid.notNull() && user_confirm && LLMarketplaceData::instance().getActivationState(listing_uuid) && !hasUniqueVersionFolder(mUUID)) + { + // Look for user confirmation before unlisting + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLFloaterAssociateListing::callback_apply, this, _1, _2)); + return; + } + // Associate the id with the user chosen folder + LLMarketplaceData::instance().associateListing(mUUID,listing_uuid,id); + } + else + { + LLNotificationsUtil::add("AlertMerchantListingInvalidID"); + } + } + closeFloater(); +} + +void LLFloaterAssociateListing::cancel() +{ + closeFloater(); +} + +//----------------------------------------------------------------------------- +// LLFloaterMarketplaceValidation +//----------------------------------------------------------------------------- + +// Note: The key is the UUID of the folder to validate. +// Validates the whole marketplace listings content if UUID is null. + +LLFloaterMarketplaceValidation::LLFloaterMarketplaceValidation(const LLSD& key) +: LLFloater(key), +mEditor(NULL) +{ +} + +BOOL LLFloaterMarketplaceValidation::postBuild() +{ + childSetAction("OK", onOK, this); + + // This widget displays the validation messages + mEditor = getChild<LLTextEditor>("validation_text"); + mEditor->setEnabled(FALSE); + mEditor->setFocus(TRUE); + mEditor->setValue(LLSD()); + + return TRUE; +} + +LLFloaterMarketplaceValidation::~LLFloaterMarketplaceValidation() +{ +} + +// virtual +void LLFloaterMarketplaceValidation::draw() +{ + // draw children + LLFloater::draw(); +} + +void LLFloaterMarketplaceValidation::onOpen(const LLSD& key) +{ + // Clear the messages + clearMessages(); + + // Get the folder UUID to validate. Use the whole marketplace listing if none provided. + LLUUID cat_id(key.asUUID()); + if (cat_id.isNull()) + { + cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + } + + // Validates the folder + if (cat_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false); + } + + // Handle the listing folder being processed + handleCurrentListing(); + + // Dump result to the editor panel + if (mEditor) + { + mEditor->setValue(LLSD()); + if (mMessages.empty()) + { + // Display a no error message + mEditor->appendText(LLTrans::getString("Marketplace Validation No Error"), false); + } + else + { + // Print out all the messages to the panel + message_list_t::iterator mCurrentLine = mMessages.begin(); + bool new_line = false; + while (mCurrentLine != mMessages.end()) + { + // Errors are printed in bold, other messages in normal font + LLStyle::Params style; + LLFontDescriptor new_desc(mEditor->getFont()->getFontDesc()); + new_desc.setStyle(mCurrentLine->mErrorLevel == LLError::LEVEL_ERROR ? LLFontGL::BOLD : LLFontGL::NORMAL); + LLFontGL* new_font = LLFontGL::getFont(new_desc); + style.font = new_font; + mEditor->appendText(mCurrentLine->mMessage, new_line, style); + new_line = true; + mCurrentLine++; + } + } + } + // We don't need the messages anymore + clearMessages(); +} + +// static +void LLFloaterMarketplaceValidation::onOK( void* userdata ) +{ + // destroys this object + LLFloaterMarketplaceValidation* self = (LLFloaterMarketplaceValidation*) userdata; + self->clearMessages(); + self->closeFloater(); +} + +void LLFloaterMarketplaceValidation::appendMessage(std::string& message, S32 depth, LLError::ELevel log_level) +{ + // Dump previous listing messages if we're starting a new listing + if (depth == 1) + { + handleCurrentListing(); + } + + // Store the message in the current listing message list + Message current_message; + current_message.mErrorLevel = log_level; + current_message.mMessage = message; + mCurrentListingMessages.push_back(current_message); + mCurrentListingErrorLevel = (mCurrentListingErrorLevel < log_level ? log_level : mCurrentListingErrorLevel); +} + +// Move the current listing messages to the general list if needs be and reset the current listing data +void LLFloaterMarketplaceValidation::handleCurrentListing() +{ + // Dump the current folder messages to the general message list if level warrants it + if (mCurrentListingErrorLevel > LLError::LEVEL_INFO) + { + message_list_t::iterator mCurrentLine = mCurrentListingMessages.begin(); + while (mCurrentLine != mCurrentListingMessages.end()) + { + mMessages.push_back(*mCurrentLine); + mCurrentLine++; + } + } + + // Reset the current listing + mCurrentListingMessages.clear(); + mCurrentListingErrorLevel = LLError::LEVEL_INFO; +} + +void LLFloaterMarketplaceValidation::clearMessages() +{ + mMessages.clear(); + mCurrentListingMessages.clear(); + mCurrentListingErrorLevel = LLError::LEVEL_INFO; +} + +//----------------------------------------------------------------------------- +// LLFloaterItemProperties +//----------------------------------------------------------------------------- + +LLFloaterItemProperties::LLFloaterItemProperties(const LLSD& key) +: LLFloater(key) +{ +} + +LLFloaterItemProperties::~LLFloaterItemProperties() +{ +} + +BOOL LLFloaterItemProperties::postBuild() +{ + // On the standalone properties floater, we have no need for a back button... + LLSidepanelItemInfo* panel = getChild<LLSidepanelItemInfo>("item_panel"); + LLButton* back_btn = panel->getChild<LLButton>("back_btn"); + back_btn->setVisible(FALSE); + + return LLFloater::postBuild(); +} + +void LLFloaterItemProperties::onOpen(const LLSD& key) +{ + // Tell the panel which item it needs to visualize + LLSidepanelItemInfo* panel = getChild<LLSidepanelItemInfo>("item_panel"); + panel->setItemID(key["id"].asUUID()); +} + diff --git a/indra/newview/llfloatermarketplacelistings.h b/indra/newview/llfloatermarketplacelistings.h new file mode 100755 index 0000000000..ffc098e28a --- /dev/null +++ b/indra/newview/llfloatermarketplacelistings.h @@ -0,0 +1,226 @@ +/** + * @file llfloatermarketplacelistings.h + * @brief Implementation of the marketplace listings floater and panels + * @author merov@lindenlab.com + * + * $LicenseInfo:firstyear=2001&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 + * ABILITY 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_LLFLOATERMARKETPLACELISTINGS_H +#define LL_LLFLOATERMARKETPLACELISTINGS_H + +#include "llfloater.h" +#include "llinventoryfilter.h" +#include "llinventorypanel.h" +#include "llnotificationptr.h" +#include "llmodaldialog.h" +#include "lltexteditor.h" + +class LLInventoryCategoriesObserver; +class LLInventoryCategoryAddedObserver; +class LLTextBox; +class LLView; +class LLFilterEditor; + +class LLFloaterMarketplaceListings; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLPanelMarketplaceListings +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLPanelMarketplaceListings : public LLPanel +{ +public: + LLPanelMarketplaceListings(); + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + void draw(); + LLFolderView* getRootFolder() { return mRootFolder; } + bool allowDropOnRoot(); + + void buildAllPanels(); + +private: + LLInventoryPanel* buildInventoryPanel(const std::string& childname, const std::string& filename); + + // UI callbacks + void onViewSortMenuItemClicked(const LLSD& userdata); + bool onViewSortMenuItemCheck(const LLSD& userdata); + void onAddButtonClicked(); + void onAuditButtonClicked(); + void onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action); + void onTabChange(); + void onFilterEdit(const std::string& search_string); + + void setSortOrder(U32 sort_order); + + LLFolderView* mRootFolder; + LLButton* mAuditBtn; + LLFilterEditor* mFilterEditor; + std::string mFilterSubString; + bool mFilterListingFoldersOnly; + U32 mSortOrder; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterMarketplaceListings +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFloaterMarketplaceListings : public LLFloater +{ +public: + LLFloaterMarketplaceListings(const LLSD& key); + ~LLFloaterMarketplaceListings(); + + void initializeMarketPlace(); + + // virtuals + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void showNotification(const LLNotificationPtr& notification); + + BOOL handleHover(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + +protected: + void setRootFolder(); + void setPanels(); + void fetchContents(); + + void setStatusString(const std::string& statusString); + + void onClose(bool app_quitting); + void onOpen(const LLSD& key); + void onFocusReceived(); + void onChanged(); + + bool isAccepted(EAcceptance accept); + + void updateView(); + +private: + S32 getFolderCount(); + + LLInventoryCategoriesObserver * mCategoriesObserver; + LLInventoryCategoryAddedObserver * mCategoryAddedObserver; + + LLTextBox * mInventoryStatus; + LLView * mInventoryInitializationInProgress; + LLView * mInventoryPlaceholder; + LLTextBox * mInventoryText; + LLTextBox * mInventoryTitle; + + LLUUID mRootFolderId; + LLPanelMarketplaceListings * mPanelListings; + bool mPanelListingsSet; +}; + +//----------------------------------------------------------------------------- +// LLFloaterAssociateListing +//----------------------------------------------------------------------------- +class LLFloaterAssociateListing : public LLFloater +{ + friend class LLFloaterReg; +public: + virtual BOOL postBuild(); + virtual BOOL handleKeyHere(KEY key, MASK mask); + + static LLFloaterAssociateListing* show(const LLUUID& folder_id); + +private: + LLFloaterAssociateListing(const LLSD& key); + virtual ~LLFloaterAssociateListing(); + + // UI Callbacks + void apply(BOOL user_confirm = TRUE); + void cancel(); + void callback_apply(const LLSD& notification, const LLSD& response); + + LLUUID mUUID; +}; + +//----------------------------------------------------------------------------- +// LLFloaterMarketplaceValidation +//----------------------------------------------------------------------------- +// Note: The key is the UUID of the folder to validate. Validates the whole +// marketplace listings content if UUID is null. +// Note: For the moment, we just display the validation text. Eventually, we should +// get the validation triggered on the server and display the html report. +// *TODO : morph into an html/text window using the pattern in llfloatertos + +class LLFloaterMarketplaceValidation : public LLFloater +{ +public: + LLFloaterMarketplaceValidation(const LLSD& key); + virtual ~LLFloaterMarketplaceValidation(); + + virtual BOOL postBuild(); + virtual void draw(); + virtual void onOpen(const LLSD& key); + + void clearMessages(); + void appendMessage(std::string& message, S32 depth, LLError::ELevel log_level); + static void onOK( void* userdata ); + +private: + struct Message { + LLError::ELevel mErrorLevel; + std::string mMessage; + }; + typedef std::vector<Message> message_list_t; + + void handleCurrentListing(); + + message_list_t mCurrentListingMessages; + LLError::ELevel mCurrentListingErrorLevel; + + message_list_t mMessages; + + LLTextEditor* mEditor; +}; + +//----------------------------------------------------------------------------- +// LLFloaterItemProperties +//----------------------------------------------------------------------------- + +class LLFloaterItemProperties : public LLFloater +{ +public: + LLFloaterItemProperties(const LLSD& key); + virtual ~LLFloaterItemProperties(); + + BOOL postBuild(); + virtual void onOpen(const LLSD& key); + +private: +}; + +#endif // LL_LLFLOATERMARKETPLACELISTINGS_H diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 72c9170b06..41005144a7 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -26,35 +26,8 @@ #include "llviewerprecompiledheaders.h" -#if LL_MSVC -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#include "dae.h" -//#include "dom.h" -#include "dom/domAsset.h" -#include "dom/domBind_material.h" -#include "dom/domCOLLADA.h" -#include "dom/domConstants.h" -#include "dom/domController.h" -#include "dom/domEffect.h" -#include "dom/domGeometry.h" -#include "dom/domInstance_geometry.h" -#include "dom/domInstance_material.h" -#include "dom/domInstance_node.h" -#include "dom/domInstance_effect.h" -#include "dom/domMaterial.h" -#include "dom/domMatrix.h" -#include "dom/domNode.h" -#include "dom/domProfile_COMMON.h" -#include "dom/domRotate.h" -#include "dom/domScale.h" -#include "dom/domTranslate.h" -#include "dom/domVisual_scene.h" -#if LL_MSVC -#pragma warning (default : 4263) -#pragma warning (default : 4264) -#endif +#include "llmodelloader.h" +#include "lldaeloader.h" #include "llfloatermodelpreview.h" @@ -112,14 +85,15 @@ #include "llanimationstates.h" #include "llviewernetwork.h" #include "llviewershadermgr.h" -#include "glod/glod.h" -const S32 SLM_SUPPORTED_VERSION = 3; +#include "glod/glod.h" +#include <boost/algorithm/string.hpp> //static S32 LLFloaterModelPreview::sUploadAmount = 10; LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; -std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList; + +bool LLModelPreview::sIgnoreLoadedCallback = false; // "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01 // But according to the UI spec for upload model floater, this parameter @@ -199,190 +173,46 @@ std::string lod_label_name[NUM_LOD+1] = "I went off the end of the lod_label_name array. Me so smart." }; -std::string colladaVersion[VERSIONTYPE_COUNT+1] = -{ - "1.4.0", - "1.4.1", - "Unsupported" -}; - - -#define LL_DEGENERACY_TOLERANCE 1e-7f - -inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) -{ - volatile F32 p0 = a[0] * b[0]; - volatile F32 p1 = a[1] * b[1]; - volatile F32 p2 = a[2] * b[2]; - return p0 + p1 + p2; -} - -bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE) -{ - // small area check - { - LLVector4a edge1; edge1.setSub( a, b ); - LLVector4a edge2; edge2.setSub( a, c ); - ////////////////////////////////////////////////////////////////////////// - /// Linden Modified - ////////////////////////////////////////////////////////////////////////// - - // If no one edge is more than 10x longer than any other edge, we weaken - // the tolerance by a factor of 1e-4f. - - LLVector4a edge3; edge3.setSub( c, b ); - const F32 len1sq = edge1.dot3(edge1).getF32(); - const F32 len2sq = edge2.dot3(edge2).getF32(); - const F32 len3sq = edge3.dot3(edge3).getF32(); - bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); - bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); - bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); - if ( abOK && acOK && cbOK ) - { - tolerance *= 1e-4f; - } - - ////////////////////////////////////////////////////////////////////////// - /// End Modified - ////////////////////////////////////////////////////////////////////////// - - LLVector4a cross; cross.setCross3( edge1, edge2 ); - - LLVector4a edge1b; edge1b.setSub( b, a ); - LLVector4a edge2b; edge2b.setSub( b, c ); - LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); - - if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) - { - return true; - } - } - - // point triangle distance check - { - LLVector4a Q; Q.setSub(a, b); - LLVector4a R; R.setSub(c, b); - - const F32 QQ = dot3fpu(Q, Q); - const F32 RR = dot3fpu(R, R); - const F32 QR = dot3fpu(R, Q); - - volatile F32 QQRR = QQ * RR; - volatile F32 QRQR = QR * QR; - F32 Det = (QQRR - QRQR); - - if( Det == 0.0f ) - { - return true; - } - } - - return false; -} - -bool validate_face(const LLVolumeFace& face) +BOOL stop_gloderror() { + GLuint error = glodGetError(); - for (U32 v = 0; v < face.mNumVertices; v++) - { - if(face.mPositions && !face.mPositions[v].isFinite3()) - { - LL_WARNS() << "NaN position data in face found!" << LL_ENDL; - return false; - } - - if(face.mNormals && !face.mNormals[v].isFinite3()) - { - LL_WARNS() << "NaN normal data in face found!" << LL_ENDL; - return false; - } - } - - for (U32 i = 0; i < face.mNumIndices; ++i) - { - if (face.mIndices[i] >= face.mNumVertices) - { - LL_WARNS() << "Face has invalid index." << LL_ENDL; - return false; - } - } - - if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) + if (error != GLOD_NO_ERROR) { - LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; - return false; + LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL; + return TRUE; } - - /*const LLVector4a scale(0.5f); - - - for (U32 i = 0; i < face.mNumIndices; i+=3) - { - U16 idx1 = face.mIndices[i]; - U16 idx2 = face.mIndices[i+1]; - U16 idx3 = face.mIndices[i+2]; - - LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); - LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); - LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); - - if (ll_is_degenerate(v1,v2,v3)) - { - LL_WARNS() << "Degenerate face found!" << LL_ENDL; - return false; - } - }*/ - return true; + return FALSE; } -bool validate_model(const LLModel* mdl) +LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material) { - if (mdl->getNumVolumeFaces() == 0) - { - LL_WARNS() << "Model has no faces!" << LL_ENDL; - return false; - } + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + if (texture) { - if (mdl->getVolumeFace(i).mNumVertices == 0) - { - LL_WARNS() << "Face has no vertices." << LL_ENDL; - return false; - } - - if (mdl->getVolumeFace(i).mNumIndices == 0) + if (texture->getDiscardLevel() > -1) { - LL_WARNS() << "Face has no indices." << LL_ENDL; - return false; - } - - if (!validate_face(mdl->getVolumeFace(i))) - { - return false; + gGL.getTexUnit(0)->bind(texture, true); + return texture; } } - return true; + return NULL; } -BOOL stop_gloderror() +std::string stripSuffix(std::string name) { - GLuint error = glodGetError(); - - if (error != GLOD_NO_ERROR) + if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1)) { - LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL; - return TRUE; + return name.substr(0, name.rfind('_')); } - - return FALSE; + return name; } - LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod) - : LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) +: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) { mMP = mp; mLOD = lod; @@ -393,6 +223,29 @@ void LLMeshFilePicker::notify(const std::string& filename) mMP->loadModel(mFile, mLOD); } +void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +{ + LLModelLoader::scene::iterator base_iter = scene.begin(); + bool found = false; + while (!found && (base_iter != scene.end())) + { + matOut = base_iter->first; + + LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); + while (!found && (base_instance_iter != base_iter->second.end())) + { + LLModelInstance& base_instance = *base_instance_iter++; + LLModel* base_model = base_instance.mModel; + + if (base_model && (base_model->mLabel == name_to_match)) + { + baseModelOut = base_model; + return; + } + } + base_iter++; + } +} //----------------------------------------------------------------------------- // LLFloaterModelPreview() @@ -613,6 +466,11 @@ void LLFloaterModelPreview::disableViewOption(const std::string& option) void LLFloaterModelPreview::loadModel(S32 lod) { mModelPreview->mLoading = true; + if (lod == LLModel::LOD_PHYSICS) + { + // loading physics from file + mModelPreview->mPhysicsSearchLOD = lod; + } (new LLMeshFilePicker(mModelPreview, lod))->getFile(); } @@ -791,9 +649,9 @@ void LLFloaterModelPreview::draw() childSetTextArg("status", "[STATUS]", getString("status_material_mismatch")); } else - if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING ) - { - childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING))); + if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_MODEL ) + { + childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_MODEL))); } else if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING ) @@ -945,9 +803,16 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) /*virtual*/ void LLFloaterModelPreview::onOpen(const LLSD& key) { + LLModelPreview::sIgnoreLoadedCallback = false; requestAgentUploadPermissions(); } +/*virtual*/ +void LLFloaterModelPreview::onClose(bool app_quitting) +{ + LLModelPreview::sIgnoreLoadedCallback = true; +} + //static void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data) { @@ -1308,1815 +1173,6 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl } //----------------------------------------------------------------------------- -// LLModelLoader -//----------------------------------------------------------------------------- -LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque<std::string>& jointsFromNodes ) -: mJointList( jointMap ) -, mJointsFromNode( jointsFromNodes ) -, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0) -{ - mJointMap["mPelvis"] = "mPelvis"; - mJointMap["mTorso"] = "mTorso"; - mJointMap["mChest"] = "mChest"; - mJointMap["mNeck"] = "mNeck"; - mJointMap["mHead"] = "mHead"; - mJointMap["mSkull"] = "mSkull"; - mJointMap["mEyeRight"] = "mEyeRight"; - mJointMap["mEyeLeft"] = "mEyeLeft"; - mJointMap["mCollarLeft"] = "mCollarLeft"; - mJointMap["mShoulderLeft"] = "mShoulderLeft"; - mJointMap["mElbowLeft"] = "mElbowLeft"; - mJointMap["mWristLeft"] = "mWristLeft"; - mJointMap["mCollarRight"] = "mCollarRight"; - mJointMap["mShoulderRight"] = "mShoulderRight"; - mJointMap["mElbowRight"] = "mElbowRight"; - mJointMap["mWristRight"] = "mWristRight"; - mJointMap["mHipRight"] = "mHipRight"; - mJointMap["mKneeRight"] = "mKneeRight"; - mJointMap["mAnkleRight"] = "mAnkleRight"; - mJointMap["mFootRight"] = "mFootRight"; - mJointMap["mToeRight"] = "mToeRight"; - mJointMap["mHipLeft"] = "mHipLeft"; - mJointMap["mKneeLeft"] = "mKneeLeft"; - mJointMap["mAnkleLeft"] = "mAnkleLeft"; - mJointMap["mFootLeft"] = "mFootLeft"; - mJointMap["mToeLeft"] = "mToeLeft"; - - mJointMap["avatar_mPelvis"] = "mPelvis"; - mJointMap["avatar_mTorso"] = "mTorso"; - mJointMap["avatar_mChest"] = "mChest"; - mJointMap["avatar_mNeck"] = "mNeck"; - mJointMap["avatar_mHead"] = "mHead"; - mJointMap["avatar_mSkull"] = "mSkull"; - mJointMap["avatar_mEyeRight"] = "mEyeRight"; - mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; - mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; - mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; - mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; - mJointMap["avatar_mWristLeft"] = "mWristLeft"; - mJointMap["avatar_mCollarRight"] = "mCollarRight"; - mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; - mJointMap["avatar_mElbowRight"] = "mElbowRight"; - mJointMap["avatar_mWristRight"] = "mWristRight"; - mJointMap["avatar_mHipRight"] = "mHipRight"; - mJointMap["avatar_mKneeRight"] = "mKneeRight"; - mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; - mJointMap["avatar_mFootRight"] = "mFootRight"; - mJointMap["avatar_mToeRight"] = "mToeRight"; - mJointMap["avatar_mHipLeft"] = "mHipLeft"; - mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; - mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; - mJointMap["avatar_mFootLeft"] = "mFootLeft"; - mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - - mJointMap["hip"] = "mPelvis"; - mJointMap["abdomen"] = "mTorso"; - mJointMap["chest"] = "mChest"; - mJointMap["neck"] = "mNeck"; - mJointMap["head"] = "mHead"; - mJointMap["figureHair"] = "mSkull"; - mJointMap["lCollar"] = "mCollarLeft"; - mJointMap["lShldr"] = "mShoulderLeft"; - mJointMap["lForeArm"] = "mElbowLeft"; - mJointMap["lHand"] = "mWristLeft"; - mJointMap["rCollar"] = "mCollarRight"; - mJointMap["rShldr"] = "mShoulderRight"; - mJointMap["rForeArm"] = "mElbowRight"; - mJointMap["rHand"] = "mWristRight"; - mJointMap["rThigh"] = "mHipRight"; - mJointMap["rShin"] = "mKneeRight"; - mJointMap["rFoot"] = "mFootRight"; - mJointMap["lThigh"] = "mHipLeft"; - mJointMap["lShin"] = "mKneeLeft"; - mJointMap["lFoot"] = "mFootLeft"; - - if (mPreview) - { - //only try to load from slm if viewer is configured to do so and this is the - //initial model load (not an LoD or physics shape) - mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty(); - mPreview->setLoadState(STARTING); - } - else - { - mTrySLM = false; - } - - assert_main_thread(); - sActiveLoaderList.push_back(this) ; -} - -LLModelLoader::~LLModelLoader() -{ - assert_main_thread(); - sActiveLoaderList.remove(this); -} - -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) -{ - LLVector4a box[] = - { - LLVector4a(-1, 1,-1), - LLVector4a(-1, 1, 1), - LLVector4a(-1,-1,-1), - LLVector4a(-1,-1, 1), - LLVector4a( 1, 1,-1), - LLVector4a( 1, 1, 1), - LLVector4a( 1,-1,-1), - LLVector4a( 1,-1, 1), - }; - - for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) - { - const LLVolumeFace& face = model->getVolumeFace(j); - - LLVector4a center; - center.setAdd(face.mExtents[0], face.mExtents[1]); - center.mul(0.5f); - LLVector4a size; - size.setSub(face.mExtents[1],face.mExtents[0]); - size.mul(0.5f); - - for (U32 i = 0; i < 8; i++) - { - LLVector4a t; - t.setMul(size, box[i]); - t.add(center); - - LLVector4a v; - - mat.affineTransform(t, v); - - if (first_transform) - { - first_transform = FALSE; - min = max = v; - } - else - { - update_min_max(min, max, v); - } - } - } -} - -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) -{ - LLVector4a mina, maxa; - LLMatrix4a mata; - - mata.loadu(mat); - mina.load3(min.mV); - maxa.load3(max.mV); - - stretch_extents(model, mata, mina, maxa, first_transform); - - min.set(mina.getF32ptr()); - max.set(maxa.getF32ptr()); -} - -void LLModelLoader::run() -{ - doLoadModel(); - doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); -} - -bool LLModelLoader::doLoadModel() -{ - //first, look for a .slm file of the same name that was modified later - //than the .dae - - if (mTrySLM) - { - std::string filename = mFilename; - - std::string::size_type i = filename.rfind("."); - if (i != std::string::npos) - { - filename.replace(i, filename.size()-1, ".slm"); - llstat slm_status; - if (LLFile::stat(filename, &slm_status) == 0) - { //slm file exists - llstat dae_status; - if (LLFile::stat(mFilename, &dae_status) != 0 || - dae_status.st_mtime < slm_status.st_mtime) - { - if (loadFromSLM(filename)) - { //slm successfully loaded, if this fails, fall through and - //try loading from dae - - mLod = -1; //successfully loading from an slm implicitly sets all - //LoDs - return true; - } - } - } - } - } - - //no suitable slm exists, load from the .dae file - DAE dae; - domCOLLADA* dom = dae.open(mFilename); - - if (!dom) - { - LL_INFOS()<<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL; - setLoadState( ERROR_PARSING ); - return false; - } - //Dom version - daeString domVersion = dae.getDomVersion(); - std::string sldom(domVersion); - LL_INFOS()<<"Collada Importer Version: "<<sldom<<LL_ENDL; - //Dae version - domVersionType docVersion = dom->getVersion(); - //0=1.4 - //1=1.4.1 - //2=Currently unsupported, however may work - if (docVersion > 1 ) - { - docVersion = VERSIONTYPE_COUNT; - } - LL_INFOS()<<"Dae version "<<colladaVersion[docVersion]<<LL_ENDL; - - - daeDatabase* db = dae.getDatabase(); - - daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); - - daeDocument* doc = dae.getDoc(mFilename); - if (!doc) - { - LL_WARNS() << "can't find internal doc" << LL_ENDL; - return false; - } - - daeElement* root = doc->getDomRoot(); - if (!root) - { - LL_WARNS() << "document has no root" << LL_ENDL; - return false; - } - - //Verify some basic properties of the dae - //1. Basic validity check on controller - U32 controllerCount = (int) db->getElementCount( NULL, "controller" ); - bool result = false; - for ( int i=0; i<controllerCount; ++i ) - { - domController* pController = NULL; - db->getElement( (daeElement**) &pController, i , NULL, "controller" ); - result = mPreview->verifyController( pController ); - if (!result) - { - setLoadState( ERROR_PARSING ); - return true; - } - } - - - //get unit scale - mTransform.setIdentity(); - - domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); - - if (unit) - { - F32 meter = unit->getMeter(); - mTransform.mMatrix[0][0] = meter; - mTransform.mMatrix[1][1] = meter; - mTransform.mMatrix[2][2] = meter; - } - - //get up axis rotation - LLMatrix4 rotation; - - domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP - domAsset::domUp_axis* up_axis = - daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); - - if (up_axis) - { - up = up_axis->getValue(); - } - - if (up == UPAXISTYPE_X_UP) - { - rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); - } - else if (up == UPAXISTYPE_Y_UP) - { - rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); - } - - rotation *= mTransform; - mTransform = rotation; - - - for (daeInt idx = 0; idx < count; ++idx) - { //build map of domEntities to LLModel - domMesh* mesh = NULL; - db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); - - if (mesh) - { - LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh); - - if(model->getStatus() != LLModel::NO_ERRORS) - { - setLoadState(ERROR_PARSING + model->getStatus()) ; - return false; //abort - } - - if (model.notNull() && validate_model(model)) - { - mModelList.push_back(model); - mModel[mesh] = model; - } - } - } - - count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); - for (daeInt idx = 0; idx < count; ++idx) - { //add skinned meshes as instances - domSkin* skin = NULL; - db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); - - if (skin) - { - domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()); - - if (geom) - { - domMesh* mesh = geom->getMesh(); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 normalized_transformation; - normalized_transformation.setTranslation(mesh_translation_vector); - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= normalized_transformation; - normalized_transformation = mesh_scale; - - glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix); - inv_mat = inv_mat.inverse(); - LLMatrix4 inverse_normalized_transformation(inv_mat.m); - - domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); - - if (bind_mat) - { //get bind shape matrix - domFloat4x4& dom_value = bind_mat->getValue(); - - LLMeshSkinInfo& skin_info = model->mSkinInfo; - - for (int i = 0; i < 4; i++) - { - for(int j = 0; j < 4; j++) - { - skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - LLMatrix4 trans = normalized_transformation; - trans *= skin_info.mBindShapeMatrix; - skin_info.mBindShapeMatrix = trans; - } - - - //Some collada setup for accessing the skeleton - daeElement* pElement = 0; - dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" ); - - //Try to get at the skeletal instance controller - domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement ); - bool missingSkeletonOrScene = false; - - //If no skeleton, do a breadth-first search to get at specific joints - bool rootNode = false; - - //Need to test for a skeleton that does not have a root node - //This occurs when your instance controller does not have an associated scene - if ( pSkeleton ) - { - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if ( pSkeletonRootNode ) - { - rootNode = true; - } - - } - if ( !pSkeleton || !rootNode ) - { - daeElement* pScene = root->getDescendant("visual_scene"); - if ( !pScene ) - { - LL_WARNS()<<"No visual scene - unable to parse bone offsets "<<LL_ENDL; - missingSkeletonOrScene = true; - } - else - { - //Get the children at this level - daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); - S32 childCount = children.getCount(); - - //Process any children that are joints - //Not all children are joints, some code be ambient lights, cameras, geometry etc.. - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast<domNode>(children[i]); - if ( isNodeAJoint( pNode ) ) - { - processJointNode( pNode, mJointList ); - } - } - } - } - else - //Has Skeleton - { - //Get the root node of the skeleton - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if ( pSkeletonRootNode ) - { - //Once we have the root node - start acccessing it's joint components - const int jointCnt = mJointMap.size(); - std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin(); - - //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. - for ( int i=0; i<jointCnt; ++i, ++jointIt ) - { - //Build a joint for the resolver to work with - char str[64]={0}; - sprintf(str,"./%s",(*jointIt).first.c_str() ); - //LL_WARNS()<<"Joint "<< str <<LL_ENDL; - - //Setup the resolver - daeSIDResolver resolver( pSkeletonRootNode, str ); - - //Look for the joint - domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() ); - if ( pJoint ) - { - //Pull out the translate id and store it in the jointTranslations map - daeSIDResolver jointResolverA( pJoint, "./translate" ); - domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); - daeSIDResolver jointResolverB( pJoint, "./location" ); - domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); - - LLMatrix4 workingTransform; - - //Translation via SID - if ( pTranslateA ) - { - extractTranslation( pTranslateA, workingTransform ); - } - else - if ( pTranslateB ) - { - extractTranslation( pTranslateB, workingTransform ); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); - if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) - { - LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; - missingSkeletonOrScene = true; - } - else - if ( pTranslateElement ) - { - extractTranslationViaElement( pTranslateElement, workingTransform ); - } - else - { - extractTranslationViaSID( pJoint, workingTransform ); - } - - } - - //Store the joint transform w/respect to it's name. - mJointList[(*jointIt).second.c_str()] = workingTransform; - } - } - - //If anything failed in regards to extracting the skeleton, joints or translation id, - //mention it - if ( missingSkeletonOrScene ) - { - LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; - } - }//got skeleton? - } - - - domSkin::domJoints* joints = skin->getJoints(); - - domInputLocal_Array& joint_input = joints->getInput_array(); - - for (size_t i = 0; i < joint_input.getCount(); ++i) - { - domInputLocal* input = joint_input.get(i); - xsNMTOKEN semantic = input->getSemantic(); - - if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) - { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames - daeElement* elem = input->getSource().getElement(); - - domSource* source = daeSafeCast<domSource>(elem); - if (source) - { - - - domName_array* names_source = source->getName_array(); - - if (names_source) - { - domListOfNames &names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j)); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - else - { - domIDREF_array* names_source = source->getIDREF_array(); - if (names_source) - { - xsIDREFS& names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j).getID()); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - } - } - } - else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) - { //found inv_bind_matrix array, fill model->mInvBindMatrix - domSource* source = daeSafeCast<domSource>(input->getSource().getElement()); - if (source) - { - domFloat_array* t = source->getFloat_array(); - if (t) - { - domListOfFloats& transform = t->getValue(); - S32 count = transform.getCount()/16; - - for (S32 k = 0; k < count; ++k) - { - LLMatrix4 mat; - - for (int i = 0; i < 4; i++) - { - for(int j = 0; j < 4; j++) - { - mat.mMatrix[i][j] = transform[k*16 + i + j*4]; - } - } - - model->mSkinInfo.mInvBindMatrix.push_back(mat); - } - } - } - } - } - - //Now that we've parsed the joint array, let's determine if we have a full rig - //(which means we have all the joint sthat are required for an avatar versus - //a skinned asset attached to a node in a file that contains an entire skeleton, - //but does not use the skeleton). - buildJointToNodeMappingFromScene( root ); - mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames ); - - if ( !missingSkeletonOrScene ) - { - //Set the joint translations on the avatar - if it's a full mapping - //The joints are reset in the dtor - if ( mPreview->getRigWithSceneParity() ) - { - std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin(); - std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end(); - for (;masterJointIt!=masterJointItEnd;++masterJointIt ) - { - std::string lookingForJoint = (*masterJointIt).first.c_str(); - - if ( mJointList.find( lookingForJoint ) != mJointList.end() ) - { - //LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL; - LLMatrix4 jointTransform = mJointList[lookingForJoint]; - LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint ); - if ( pJoint ) - { - LLUUID fake_mesh_id; - fake_mesh_id.generate(); - pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, gAgentAvatarp->avString()); - } - else - { - //Most likely an error in the asset. - LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; - } - } - } - } - } //missingSkeletonOrScene - - - //We need to construct the alternate bind matrix (which contains the new joint positions) - //in the same order as they were stored in the joint buffer. The joints associated - //with the skeleton are not stored in the same order as they are in the exported joint buffer. - //This remaps the skeletal joints to be in the same order as the joints stored in the model. - std::vector<std::string> :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); - const int jointCnt = model->mSkinInfo.mJointNames.size(); - for ( int i=0; i<jointCnt; ++i, ++jointIt ) - { - std::string lookingForJoint = (*jointIt).c_str(); - //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key - //and store it in the alternate bind matrix - if ( mJointList.find( lookingForJoint ) != mJointList.end() ) - { - LLMatrix4 jointTransform = mJointList[lookingForJoint]; - LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; - newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); - model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); - } - else - { - LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL; - } - } - - //grab raw position array - - domVertices* verts = mesh->getVertices(); - if (verts) - { - domInputLocal_Array& inputs = verts->getInput_array(); - for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) - { - domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); - if (pos_source) - { - domFloat_array* pos_array = pos_source->getFloat_array(); - if (pos_array) - { - domListOfFloats& pos = pos_array->getValue(); - - for (size_t j = 0; j < pos.getCount(); j += 3) - { - if (pos.getCount() <= j+2) - { - LL_ERRS() << "Invalid position array size." << LL_ENDL; - } - - LLVector3 v(pos[j], pos[j+1], pos[j+2]); - - //transform from COLLADA space to volume space - v = v * inverse_normalized_transformation; - - model->mPosition.push_back(v); - } - } - } - } - } - } - - //grab skin weights array - domSkin::domVertex_weights* weights = skin->getVertex_weights(); - if (weights) - { - domInputLocalOffset_Array& inputs = weights->getInput_array(); - domFloat_array* vertex_weights = NULL; - for (size_t i = 0; i < inputs.getCount(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) - { - domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); - if (weight_source) - { - vertex_weights = weight_source->getFloat_array(); - } - } - } - - if (vertex_weights) - { - domListOfFloats& w = vertex_weights->getValue(); - domListOfUInts& vcount = weights->getVcount()->getValue(); - domListOfInts& v = weights->getV()->getValue(); - - U32 c_idx = 0; - for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) - { //for each vertex - daeUInt count = vcount[vc_idx]; - - //create list of weights that influence this vertex - LLModel::weight_list weight_list; - - for (daeUInt i = 0; i < count; ++i) - { //for each weight - daeInt joint_idx = v[c_idx++]; - daeInt weight_idx = v[c_idx++]; - - if (joint_idx == -1) - { - //ignore bindings to bind_shape_matrix - continue; - } - - F32 weight_value = w[weight_idx]; - - weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); - } - - //sort by joint weight - std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); - - std::vector<LLModel::JointWeight> wght; - - F32 total = 0.f; - - for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) - { //take up to 4 most significant weights - if (weight_list[i].mWeight > 0.f) - { - wght.push_back( weight_list[i] ); - total += weight_list[i].mWeight; - } - } - - F32 scale = 1.f/total; - if (scale != 1.f) - { //normalize weights - for (U32 i = 0; i < wght.size(); ++i) - { - wght[i].mWeight *= scale; - } - } - - model->mSkinWeights[model->mPosition[vc_idx]] = wght; - } - - //add instance to scene for this model - - LLMatrix4 transformation = mTransform; - // adjust the transformation to compensate for mesh normalization - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::map<std::string, LLImportMaterial> materials; - for (U32 i = 0; i < model->mMaterialList.size(); ++i) - { - materials[model->mMaterialList[i]] = LLImportMaterial(); - } - mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - } - } - } - } - - daeElement* scene = root->getDescendant("visual_scene"); - - if (!scene) - { - LL_WARNS() << "document has no visual_scene" << LL_ENDL; - setLoadState( ERROR_PARSING ); - return true; - } - - setLoadState( DONE ); - - bool badElement = false; - - processElement( scene, badElement ); - - if ( badElement ) - { - setLoadState( ERROR_PARSING ); - } - - return true; -} - -void LLModelLoader::setLoadState(U32 state) -{ - if (mPreview) - { - mPreview->setLoadState(state); - } -} - -bool LLModelLoader::loadFromSLM(const std::string& filename) -{ - //only need to populate mScene with data from slm - llstat stat; - - if (LLFile::stat(filename, &stat)) - { //file does not exist - return false; - } - - S32 file_size = (S32) stat.st_size; - - llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary); - LLSD data; - LLSDSerialize::fromBinary(data, ifstream, file_size); - ifstream.close(); - - //build model list for each LoD - model_list model[LLModel::NUM_LODS]; - - if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) - { //unsupported version - return false; - } - - LLSD& mesh = data["mesh"]; - - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - for (U32 i = 0; i < mesh.size(); ++i) - { - std::stringstream str(mesh[i].asString()); - LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod); - if (loaded_model->loadModel(str)) - { - loaded_model->mLocalID = i; - model[lod].push_back(loaded_model); - - if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty()) - { - //check to see if rig is valid - mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames ); - } - } - } - } - - if (model[LLModel::LOD_HIGH].empty()) - { //failed to load high lod - return false; - } - - // Set name. - std::string name = data["name"]; - if (!name.empty()) - { - model[LLModel::LOD_HIGH][0]->mLabel = name; - } - - - //load instance list - model_instance_list instance_list; - - LLSD& instance = data["instance"]; - - for (U32 i = 0; i < instance.size(); ++i) - { - //deserialize instance list - instance_list.push_back(LLModelInstance(instance[i])); - - //match up model instance pointers - S32 idx = instance_list[i].mLocalMeshID; - - for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - if (!model[lod].empty()) - { - instance_list[i].mLOD[lod] = model[lod][idx]; - } - } - - instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; - } - - - //convert instance_list to mScene - mFirstTransform = TRUE; - for (U32 i = 0; i < instance_list.size(); ++i) - { - LLModelInstance& cur_instance = instance_list[i]; - mScene[cur_instance.mTransform].push_back(cur_instance); - stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); - } - - setLoadState( DONE ); - - return true; -} - -//static -bool LLModelLoader::isAlive(LLModelLoader* loader) -{ - if(!loader) - { - return false ; - } - - std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ; - for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; - - return *iter == loader ; -} - -void LLModelLoader::loadModelCallback() -{ - assert_main_thread(); - - if (mPreview) - { - mPreview->loadModelCallback(mLod); - } - - while (!isStopped()) - { //wait until this thread is stopped before deleting self - apr_sleep(100); - } - - //doubel check if "this" is valid before deleting it, in case it is aborted during running. - if(!isAlive(this)) - { - return ; - } - - //cleanup model loader - if (mPreview) - { - mPreview->mModelLoader = NULL; - } - - delete this; -} -//----------------------------------------------------------------------------- -// buildJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot ) -{ - daeElement* pScene = pRoot->getDescendant("visual_scene"); - if ( pScene ) - { - daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); - S32 childCount = children.getCount(); - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast<domNode>(children[i]); - processJointToNodeMapping( pNode ); - } - } -} -//----------------------------------------------------------------------------- -// processJointToNodeMapping() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointToNodeMapping( domNode* pNode ) -{ - if ( isNodeAJoint( pNode ) ) - { - //1.Store the parent - std::string nodeName = pNode->getName(); - if ( !nodeName.empty() ) - { - mJointsFromNode.push_front( pNode->getName() ); - } - //2. Handle the kiddo's - processChildJoints( pNode ); - } - else - { - //Determine if the're any children wrt to this failed node. - //This occurs when an armature is exported and ends up being what essentially amounts to - //as the root for the visual_scene - if ( pNode ) - { - processChildJoints( pNode ); - } - else - { - LL_INFOS()<<"Node is NULL"<<LL_ENDL; - } - - } -} -//----------------------------------------------------------------------------- -// processChildJoint() -//----------------------------------------------------------------------------- -void LLModelLoader::processChildJoints( domNode* pParentNode ) -{ - daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); - if ( pChildNode ) - { - processJointToNodeMapping( pChildNode ); - } - } -} - -//----------------------------------------------------------------------------- -// critiqueRigForUploadApplicability() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ) -{ - critiqueJointToNodeMappingFromScene(); - - //Determines the following use cases for a rig: - //1. It is suitable for upload with skin weights & joint positions, or - //2. It is suitable for upload as standard av with just skin weights - - bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); - bool isRigLegacyOK = isRigLegacy( jointListFromAsset ); - - //It's OK that both could end up being true, both default to false - if ( isJointPositionUploadOK ) - { - setRigValidForJointPositionUpload( true ); - } - - if ( isRigLegacyOK) - { - setLegacyRigValid( true ); - } - -} -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueJointToNodeMappingFromScene( void ) -{ - //Do the actual nodes back the joint listing from the dae? - //if yes then this is a fully rigged asset, otherwise it's just a partial rig - - std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin(); - std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end(); - bool result = true; - - if ( !mJointsFromNode.empty() ) - { - for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt ) - { - std::string name = *jointsFromNodeIt; - if ( mJointTransformMap.find( name ) != mJointTransformMap.end() ) - { - continue; - } - else - { - LL_INFOS()<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<LL_ENDL; - result = false; - } - } - } - else - { - result = false; - } - - //Determines the following use cases for a rig: - //1. Full av rig w/1-1 mapping from the scene and joint array - //2. Partial rig but w/o parity between the scene and joint array - if ( result ) - { - setRigWithSceneParity( true ); - } -} -//----------------------------------------------------------------------------- -// isRigLegacy() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset ) -{ - //No joints in asset - if ( jointListFromAsset.size() == 0 ) - { - return false; - } - - bool result = false; - - std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); - std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); - - std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} -//----------------------------------------------------------------------------- -// isRigSuitableForJointPositionUpload() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ) -{ - bool result = false; - - std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin(); - std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end(); - - std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} - - -//called in the main thread -void LLModelLoader::loadTextures() -{ - BOOL is_paused = isPaused() ; - pause() ; //pause the loader - - for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) - { - for(U32 i = 0 ; i < iter->second.size(); i++) - { - for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin(); - j != iter->second[i].mMaterial.end(); ++j) - { - LLImportMaterial& material = j->second; - - if(!material.mDiffuseMapFilename.empty()) - { - material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); - material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); - material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); - mNumOfFetchingTextures++ ; - } - } - } - } - - if(!is_paused) - { - unpause() ; - } -} - -//----------------------------------------------------------------------------- -// isNodeAJoint() -//----------------------------------------------------------------------------- -bool LLModelLoader::isNodeAJoint( domNode* pNode ) -{ - if ( !pNode ) - { - LL_INFOS()<<"Created node is NULL"<<LL_ENDL; - return false; - } - - if ( pNode->getName() == NULL ) - { - LL_INFOS()<<"Parsed node has no name "<<LL_ENDL; - //Attempt to write the node id, if possible (aids in debugging the visual scene) - if ( pNode->getId() ) - { - LL_INFOS()<<"Parsed node ID: "<<pNode->getId()<<LL_ENDL; - } - return false; - } - - if ( mJointMap.find( pNode->getName() ) != mJointMap.end() ) - { - return true; - } - - return false; -} -//----------------------------------------------------------------------------- -// verifyCount -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyCount( int expected, int result ) -{ - if ( expected != result ) - { - LL_INFOS()<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<LL_ENDL; - return false; - } - return true; -} -//----------------------------------------------------------------------------- -// verifyController -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyController( domController* pController ) -{ - - bool result = true; - - domSkin* pSkin = pController->getSkin(); - - if ( pSkin ) - { - xsAnyURI & uri = pSkin->getSource(); - domElement* pElement = uri.getElement(); - - if ( !pElement ) - { - LL_INFOS()<<"Can't resolve skin source"<<LL_ENDL; - return false; - } - - daeString type_str = pElement->getTypeName(); - if ( stricmp(type_str, "geometry") == 0 ) - { - //Skin is reference directly by geometry and get the vertex count from skin - domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); - U32 vertexWeightsCount = pVertexWeights->getCount(); - domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); - domMesh* pMesh = pGeometry->getMesh(); - - if ( pMesh ) - { - //Get vertex count from geometry - domVertices* pVertices = pMesh->getVertices(); - if ( !pVertices ) - { - LL_INFOS()<<"No vertices!"<<LL_ENDL; - return false; - } - - if ( pVertices ) - { - xsAnyURI src = pVertices->getInput_array()[0]->getSource(); - domSource* pSource = (domSource*) (domElement*) src.getElement(); - U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); - result = verifyCount( verticesCount, vertexWeightsCount ); - if ( !result ) - { - return result; - } - } - } - - U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); - result = verifyCount( vcountCount, vertexWeightsCount ); - if ( !result ) - { - return result; - } - - domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); - U32 sum = 0; - for (size_t i=0; i<vcountCount; i++) - { - sum += pVertexWeights->getVcount()->getValue()[i]; - } - result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() ); - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// extractTranslation() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ) -{ - domFloat3 jointTrans = pTranslate->getValue(); - LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] ); - transform.setTranslation( singleJointTranslation ); -} -//----------------------------------------------------------------------------- -// extractTranslationViaElement() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ) -{ - if ( pTranslateElement ) - { - domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement ); - domFloat3 translateChild = pTranslateChild->getValue(); - LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] ); - transform.setTranslation( singleJointTranslation ); - } -} -//----------------------------------------------------------------------------- -// extractTranslationViaSID() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ) -{ - if ( pElement ) - { - daeSIDResolver resolver( pElement, "./transform" ); - domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() ); - //We are only extracting out the translational component atm - LLMatrix4 workingTransform; - if ( pMatrix ) - { - domFloat4x4 domArray = pMatrix->getValue(); - for ( int i = 0; i < 4; i++ ) - { - for( int j = 0; j < 4; j++ ) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - LLVector3 trans = workingTransform.getTranslation(); - transform.setTranslation( trans ); - } - } - else - { - LL_WARNS()<<"Element is nonexistent - empty/unsupported node."<<LL_ENDL; - } -} -//----------------------------------------------------------------------------- -// processJointNode() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms ) -{ - if (pNode->getName() == NULL) - { - LL_WARNS() << "nameless node, can't process" << LL_ENDL; - return; - } - - //LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL; - - //1. handle the incoming node - extract out translation via SID or element - - LLMatrix4 workingTransform; - - //Pull out the translate id and store it in the jointTranslations map - daeSIDResolver jointResolverA( pNode, "./translate" ); - domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); - daeSIDResolver jointResolverB( pNode, "./location" ); - domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); - - //Translation via SID was successful - if ( pTranslateA ) - { - extractTranslation( pTranslateA, workingTransform ); - } - else - if ( pTranslateB ) - { - extractTranslation( pTranslateB, workingTransform ); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement( pNode, "translate" ); - if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() ) - { - //LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; - daeSIDResolver jointResolver( pNode, "./matrix" ); - domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() ); - if ( pMatrix ) - { - //LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL; - domFloat4x4 domArray = pMatrix->getValue(); - for ( int i = 0; i < 4; i++ ) - { - for( int j = 0; j < 4; j++ ) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - } - else - { - LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL; - } - } - else - { - extractTranslationViaElement( pTranslateElement, workingTransform ); - } - } - - //Store the working transform relative to the nodes name. - jointTransforms[ pNode->getName() ] = workingTransform; - - //2. handle the nodes children - - //Gather and handle the incoming nodes children - daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); - if ( pChildNode ) - { - processJointNode( pChildNode, jointTransforms ); - } - } -} -//----------------------------------------------------------------------------- -// getChildFromElement() -//----------------------------------------------------------------------------- -daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name ) -{ - daeElement* pChildOfElement = pElement->getChild( name.c_str() ); - if ( pChildOfElement ) - { - return pChildOfElement; - } - LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; - return NULL; -} - -void LLModelLoader::processElement( daeElement* element, bool& badElement ) -{ - LLMatrix4 saved_transform = mTransform; - - domTranslate* translate = daeSafeCast<domTranslate>(element); - if (translate) - { - domFloat3 dom_value = translate->getValue(); - - LLMatrix4 translation; - translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); - - translation *= mTransform; - mTransform = translation; - } - - domRotate* rotate = daeSafeCast<domRotate>(element); - if (rotate) - { - domFloat4 dom_value = rotate->getValue(); - - LLMatrix4 rotation; - rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); - - rotation *= mTransform; - mTransform = rotation; - } - - domScale* scale = daeSafeCast<domScale>(element); - if (scale) - { - domFloat3 dom_value = scale->getValue(); - - - LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); - scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes - LLMatrix4 scaling; - scaling.initScale(scale_vector); - - scaling *= mTransform; - mTransform = scaling; - } - - domMatrix* matrix = daeSafeCast<domMatrix>(element); - if (matrix) - { - domFloat4x4 dom_value = matrix->getValue(); - - LLMatrix4 matrix_transform; - - for (int i = 0; i < 4; i++) - { - for(int j = 0; j < 4; j++) - { - matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - matrix_transform *= mTransform; - mTransform = matrix_transform; - } - - domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element); - if (instance_geo) - { - domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()); - if (geo) - { - domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLMatrix4 transformation = mTransform; - - if (mTransform.determinant() < 0) - { //negative scales are not supported - LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << LL_ENDL; - badElement = true; - } - - std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo); - - // adjust the transformation to compensate for mesh normalization - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::string label = getElementLabel(instance_geo); - mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - else - { - LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL; - badElement = true; - } - - } - - domInstance_node* instance_node = daeSafeCast<domInstance_node>(element); - if (instance_node) - { - daeElement* instance = instance_node->getUrl().getElement(); - if (instance) - { - processElement(instance,badElement); - } - } - - //process children - daeTArray< daeSmartRef<daeElement> > children = element->getChildren(); - int childCount = children.getCount(); - for (S32 i = 0; i < childCount; i++) - { - processElement(children[i],badElement); - } - - domNode* node = daeSafeCast<domNode>(element); - if (node) - { //this element was a node, restore transform before processiing siblings - mTransform = saved_transform; - } -} - -std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) -{ - std::map<std::string, LLImportMaterial> materials; - for (int i = 0; i < model->mMaterialList.size(); i++) - { - LLImportMaterial import_material; - - domInstance_material* instance_mat = NULL; - - domBind_material::domTechnique_common* technique = - daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); - - if (technique) - { - daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>(); - for (int j = 0; j < inst_materials.getCount(); j++) - { - std::string symbol(inst_materials[j]->getSymbol()); - - if (symbol == model->mMaterialList[i]) // found the binding - { - instance_mat = inst_materials[j]; - } - } - } - - if (instance_mat) - { - domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement()); - if (material) - { - domInstance_effect* instance_effect = - daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); - if (instance_effect) - { - domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement()); - if (effect) - { - domProfile_COMMON* profile = - daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); - if (profile) - { - import_material = profileToMaterial(profile); - } - } - } - } - } - - import_material.mBinding = model->mMaterialList[i]; - materials[model->mMaterialList[i]] = import_material; - } - - return materials; -} - -LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) -{ - LLImportMaterial mat; - mat.mFullbright = FALSE; - - daeElement* diffuse = material->getDescendant("diffuse"); - if (diffuse) - { - domCommon_color_or_texture_type_complexType::domTexture* texture = - daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture")); - if (texture) - { - domCommon_newparam_type_Array newparams = material->getNewparam_array(); - for (S32 i = 0; i < newparams.getCount(); i++) - { - domFx_surface_common* surface = newparams[i]->getSurface(); - if (surface) - { - domFx_surface_init_common* init = surface->getFx_surface_init_common(); - if (init) - { - domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); - - if (init_from.getCount() > i) - { - domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement()); - if (image) - { - // we only support init_from now - embedded data will come later - domImage::domInit_from* init = image->getInit_from(); - if (init) - { - mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); - mat.mDiffuseMapLabel = getElementLabel(material); - } - } - } - } - } - } - } - - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - mat.mDiffuseColor = value; - } - } - - daeElement* emission = material->getDescendant("emission"); - if (emission) - { - LLColor4 emission_color = getDaeColor(emission); - if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) - { - mat.mFullbright = TRUE; - } - } - - return mat; -} - -// try to get a decent label for this element -std::string LLModelLoader::getElementLabel(daeElement *element) -{ - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -LLColor4 LLModelLoader::getDaeColor(daeElement* element) -{ - LLColor4 value; - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - } - - return value; -} - -//----------------------------------------------------------------------------- // LLModelPreview //----------------------------------------------------------------------------- @@ -3125,7 +1181,9 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) , mPelvisZOffset( 0.0f ) , mLegacyRigValid( false ) , mRigValidJointUpload( false ) +, mPhysicsSearchLOD( LLModel::LOD_PHYSICS ) , mResetJoints( false ) +, mModelNoErrors( true ) , mRigParityWithScene( false ) , mLastJointUpdate( false ) { @@ -3170,51 +1228,20 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) glodInit(); - //move into joint mapper class - //1. joints for joint offset verification - mMasterJointList.push_front("mPelvis"); - mMasterJointList.push_front("mTorso"); - mMasterJointList.push_front("mChest"); - mMasterJointList.push_front("mNeck"); - mMasterJointList.push_front("mHead"); - mMasterJointList.push_front("mCollarLeft"); - mMasterJointList.push_front("mShoulderLeft"); - mMasterJointList.push_front("mElbowLeft"); - mMasterJointList.push_front("mWristLeft"); - mMasterJointList.push_front("mCollarRight"); - mMasterJointList.push_front("mShoulderRight"); - mMasterJointList.push_front("mElbowRight"); - mMasterJointList.push_front("mWristRight"); - mMasterJointList.push_front("mHipRight"); - mMasterJointList.push_front("mKneeRight"); - mMasterJointList.push_front("mFootRight"); - mMasterJointList.push_front("mHipLeft"); - mMasterJointList.push_front("mKneeLeft"); - mMasterJointList.push_front("mFootLeft"); - //2. legacy joint list - used to verify rigs that will not be using joint offsets - mMasterLegacyJointList.push_front("mPelvis"); - mMasterLegacyJointList.push_front("mTorso"); - mMasterLegacyJointList.push_front("mChest"); - mMasterLegacyJointList.push_front("mNeck"); - mMasterLegacyJointList.push_front("mHead"); - mMasterLegacyJointList.push_front("mHipRight"); - mMasterLegacyJointList.push_front("mKneeRight"); - mMasterLegacyJointList.push_front("mFootRight"); - mMasterLegacyJointList.push_front("mHipLeft"); - mMasterLegacyJointList.push_front("mKneeLeft"); - mMasterLegacyJointList.push_front("mFootLeft"); - createPreviewAvatar(); } LLModelPreview::~LLModelPreview() { - if (mModelLoader) - { - mModelLoader->mPreview = NULL; - mModelLoader = NULL; - } - //*HACK : *TODO : turn this back on when we understand why this crashes + // glod apparently has internal mem alignment issues that are angering + // the heap-check code in windows, these should be hunted down in that + // TP code, if possible + // + // kernel32.dll!HeapFree() + 0x14 bytes + // msvcr100.dll!free(void * pBlock) Line 51 C + // glod.dll!glodGetGroupParameteriv() + 0x119 bytes + // glod.dll!glodShutdown() + 0x77 bytes + // //glodShutdown(); } @@ -3284,7 +1311,9 @@ U32 LLModelPreview::calcResourceCost() decomp, mFMP->childGetValue("upload_skin").asBoolean(), mFMP->childGetValue("upload_joints").asBoolean(), - TRUE); + TRUE, + FALSE, + instance.mModel->mSubmodelID); num_hulls += decomp.mHull.size(); for (U32 i = 0; i < decomp.mHull.size(); ++i) @@ -3351,29 +1380,12 @@ void LLModelPreview::rebuildUploadData() F32 max_scale = 0.f; - //reorder materials to match mBaseModel - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) - { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) ) - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable( "calculate_btn" ); - } - } - } - } + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) { //for each transform in scene - LLMatrix4 mat = iter->first; + LLMatrix4 mat = iter->first; // compute position LLVector3 position = LLVector3(0, 0, 0) * mat; @@ -3390,38 +1402,171 @@ void LLModelPreview::rebuildUploadData() mat *= scale_mat; - for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) - { //for each instance with said transform applied - LLModelInstance instance = *model_iter; + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();) + { //for each instance with said transform applied + LLModelInstance instance = *model_iter++; LLModel* base_model = instance.mModel; - if (base_model) + if (base_model && !requested_name.empty()) { base_model->mRequestedLabel = requested_name; base_model->mMetric = metric; } - S32 idx = 0; - for (idx = 0; idx < mBaseModel.size(); ++idx) - { //find reference instance for this model - if (mBaseModel[idx] == base_model) + for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--) + { + LLModel* lod_model = NULL; + if (!legacyMatching) { - break; + // Fill LOD slots by finding matching meshes by label with name extensions + // in the appropriate scene for each LOD. This fixes all kinds of issues + // where the indexed method below fails in spectacular fashion. + // If you don't take the time to name your LOD and PHYS meshes + // with the name of their corresponding mesh in the HIGH LOD, + // then the indexed method will be attempted below. + + LLMatrix4 transform; + + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + int extensionLOD; + if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty()) + { + extensionLOD = i; + } + else + { + //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for + extensionLOD = mPhysicsSearchLOD; + } + + std::string toAdd; + switch (extensionLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == -1) + { + name_to_match += toAdd; + } + + FindModel(mScene[i], name_to_match, lod_model, transform); + + if (!lod_model && i != LLModel::LOD_PHYSICS) + { + if (importerDebug) + { + LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL; + } + + int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; + while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) + { + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + std::string toAdd; + switch (searchLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == -1) + { + name_to_match += toAdd; + } + + // See if we can find an appropriately named model in LOD 'searchLOD' + // + FindModel(mScene[searchLOD], name_to_match, lod_model, transform); + searchLOD++; + } + } } - } + else + { + // Use old method of index-based association + U32 idx = 0; + for (idx = 0; idx < mBaseModel.size(); ++idx) + { + // find reference instance for this model + if (mBaseModel[idx] == base_model) + { + if (importerDebug) + { + LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL; + } + break; + } + } - if(idx < mBaseModel.size()) - { - for (U32 i = 0; i < LLModel::NUM_LODS; i++) - { //fill LOD slots based on reference model index + // If the model list for the current LOD includes that index... + // if (mModel[i].size() > idx) { - instance.mLOD[i] = mModel[i][idx]; + // Assign that index from the model list for our LOD as the LOD model for this instance + // + lod_model = mModel[i][idx]; + if (importerDebug) + { + LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL; + } } - else + else if (importerDebug) { - instance.mLOD[i] = NULL; + LL_INFOS() << "List of models does not include index " << idx << LL_ENDL; + } + } + + if (lod_model) + { + if (importerDebug) + { + if (i == LLModel::LOD_PHYSICS) + { + LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL; + } + else + { + LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL; + } + } + instance.mLOD[i] = lod_model; + } + else if (importerDebug) + { + LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL; + } + } + + LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH]; + if (!high_lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + else + { + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + int refFaceCnt = 0; + int modelFaceCnt = 0; + llassert(instance.mLOD[i]); + if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); } } } @@ -3430,6 +1575,34 @@ void LLModelPreview::rebuildUploadData() } } + for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++) + { + // Search for models that are not included into upload data + // If we found any, that means something we loaded is not a sub-model. + for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind) + { + bool found_model = false; + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) + { + LLModelInstance& instance = *iter; + if (instance.mLOD[lod] == mModel[lod][model_ind]) + { + found_model = true; + break; + } + } + if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID) + { + if (importerDebug) + { + LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." << LL_ENDL; + } + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + } + } + F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale; F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]); @@ -3496,7 +1669,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw meshes.insert(instance.mModel); std::stringstream str; - LLModel::Decomposition& decomp = instance.mLOD[LLModel::LOD_PHYSICS].notNull() ? instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : @@ -3509,8 +1681,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw instance.mLOD[LLModel::LOD_LOW], instance.mLOD[LLModel::LOD_IMPOSTOR], decomp, - save_skinweights, save_joint_positions, FALSE, TRUE); - + save_skinweights, save_joint_positions, + FALSE, TRUE, instance.mModel->mSubmodelID); data["mesh"][instance.mModel->mLocalID] = str.str(); } @@ -3578,13 +1750,28 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable clearGLODGroup(); } - mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode ); + mModelLoader = new LLDAELoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode, + gSavedSettings.getU32("ImporterModelLimit")); if (force_disable_slm) { mModelLoader->mTrySLM = false; } - + else + { + //only try to load from slm if viewer is configured to do so and this is the + //initial model load (not an LoD or physics shape) + mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty(); + } mModelLoader->start(); mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); @@ -3615,6 +1802,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod) if (lod >= 0 && lod <= 3) { + mPhysicsSearchLOD = lod; mModel[LLModel::LOD_PHYSICS] = mModel[lod]; mScene[LLModel::LOD_PHYSICS] = mScene[lod]; mLODFile[LLModel::LOD_PHYSICS].clear(); @@ -3634,11 +1822,14 @@ void LLModelPreview::clearIncompatible(S32 lod) return; } + // at this point we don't care about sub-models, + // different amount of sub-models means face count mismatch, not incompatibility + U32 lod_size = countRootModels(mModel[lod]); for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) { //clear out any entries that aren't compatible with this model if (i != lod) { - if (mModel[i].size() != mModel[lod].size()) + if (countRootModels(mModel[i]) != lod_size) { mModel[i].clear(); mScene[i].clear(); @@ -3673,7 +1864,7 @@ void LLModelPreview::clearGLODGroup() } } -void LLModelPreview::loadModelCallback(S32 lod) +void LLModelPreview::loadModelCallback(S32 loaded_lod) { assert_main_thread(); @@ -3686,12 +1877,18 @@ void LLModelPreview::loadModelCallback(S32 lod) if(getLoadState() >= LLModelLoader::ERROR_PARSING) { mLoading = false ; + mModelLoader = NULL; return ; } + // Copy determinations about rig so UI will reflect them + // + setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); + setLegacyRigValid(mModelLoader->isLegacyRigValid()); + mModelLoader->loadTextures() ; - if (lod == -1) + if (loaded_lod == -1) { //populate all LoDs from model loader scene mBaseModel.clear(); mBaseScene.clear(); @@ -3723,6 +1920,11 @@ void LLModelPreview::loadModelCallback(S32 lod) //override displayed model with current LoD list_iter->mModel = list_iter->mLOD[lod]; + if (!list_iter->mModel) + { + continue; + } + //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index) S32 idx = list_iter->mModel->mLocalID; @@ -3731,7 +1933,7 @@ void LLModelPreview::loadModelCallback(S32 lod) mModel[lod].resize(idx+1); } - mModel[lod][idx] = list_iter->mModel; + mModel[lod][idx] = list_iter->mModel; if (!list_iter->mModel->mSkinWeights.empty()) { skin_weights = true; @@ -3774,31 +1976,108 @@ void LLModelPreview::loadModelCallback(S32 lod) } else { //only replace given LoD - mModel[lod] = mModelLoader->mModelList; - mScene[lod] = mModelLoader->mScene; - mVertexBuffer[lod].clear(); + mModel[loaded_lod] = mModelLoader->mModelList; + mScene[loaded_lod] = mModelLoader->mScene; + mVertexBuffer[loaded_lod].clear(); - setPreviewLOD(lod); + setPreviewLOD(loaded_lod); - if (lod == LLModel::LOD_HIGH) + if (loaded_lod == LLModel::LOD_HIGH) { //save a copy of the highest LOD for automatic LOD manipulation if (mBaseModel.empty()) { //first time we've loaded a model, auto-gen LoD mGenLOD = true; } - mBaseModel = mModel[lod]; + mBaseModel = mModel[loaded_lod]; clearGLODGroup(); - mBaseScene = mScene[lod]; + mBaseScene = mScene[loaded_lod]; mVertexBuffer[5].clear(); } + else + { + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); + if (!legacyMatching) + { + if (!mBaseModel.empty()) + { + BOOL name_based = FALSE; + BOOL has_submodels = FALSE; + for (U32 idx = 0; idx < mBaseModel.size(); ++idx) + { + if (mBaseModel[idx]->mSubmodelID) + { // don't do index-based renaming when the base model has submodels + has_submodels = TRUE; + if (importerDebug) + { + LL_INFOS() << "High LOD has submodels" << LL_ENDL; + } + break; + } + } - clearIncompatible(lod); + for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx) + { + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + LLModel* found_model = NULL; + LLMatrix4 transform; + FindModel(mBaseScene, loaded_name, found_model, transform); + if (found_model) + { // don't rename correctly named models (even if they are placed in a wrong order) + name_based = TRUE; + } + + if (mModel[loaded_lod][idx]->mSubmodelID) + { // don't rename the models when loaded LOD model has submodels + has_submodels = TRUE; + } + } + + if (importerDebug) + { + LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL; + } + + if (!name_based && !has_submodels) + { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601) + // this actually works like "ImporterLegacyMatching" for this particular LOD + for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx) + { + std::string name = mBaseModel[idx]->mLabel; + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + if (loaded_name != name) + { + switch (loaded_lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (importerDebug) + { + LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL; + } + + mModel[loaded_lod][idx]->mLabel = name; + } + } + } + } + } + } + + clearIncompatible(loaded_lod); mDirty = true; - if (lod == LLModel::LOD_HIGH) + if (loaded_lod == LLModel::LOD_HIGH) { resetPreviewTarget(); } @@ -3810,16 +2089,15 @@ void LLModelPreview::loadModelCallback(S32 lod) mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE); if (!mBaseModel.empty()) { - if (mFMP->getChild<LLUICtrl>("description_form")->getValue().asString().empty()) - { - const std::string& model_name = mBaseModel[0]->getName(); - mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name); - } + const std::string& model_name = mBaseModel[0]->getName(); + mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name); } } refresh(); mModelLoadedSignal(); + + mModelLoader = NULL; } void LLModelPreview::resetPreviewTarget() @@ -4168,6 +2446,20 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); + std::string name = base->mLabel; + + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + mModel[lod][mdl_idx]->mLabel = name; + mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID; + GLint* sizes = new GLint[patch_count*2]; glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes); stop_gloderror(); @@ -4280,17 +2572,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim { shader->bind(); } - - /*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty()) - { //build physics scene - mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW]; - mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW]; - - for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]); - } - }*/ } void LLModelPreview::updateStatusMessages() @@ -4307,43 +2588,89 @@ void LLModelPreview::updateStatusMessages() S32 total_verts[LLModel::NUM_LODS]; S32 total_submeshes[LLModel::NUM_LODS]; - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + total_tris[i] = 0; + total_verts[i] = 0; + total_submeshes[i] = 0; + } + + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { - //initialize total for this lod to 0 - total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; + LLModelInstance& instance = *iter; - for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) + LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH]; + if (!model_high_lod) { - for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) - { - LLModel* model = instance->mModel; - if (model) - { - //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; - S32 cur_submeshes = model->getNumVolumeFaces(); + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + continue; + } - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = model->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + LLModel* lod_model = instance.mLOD[i]; + if (!lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + + int refFaceCnt = 0; + int modelFaceCnt = 0; - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; + if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + + if (lod_model) + { + //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = lod_model->getNumVolumeFaces(); - //store this model's counts to asset data - tris[lod].push_back(cur_tris); - verts[lod].push_back(cur_verts); - submeshes[lod].push_back(cur_submeshes); + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = lod_model->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; } + + std::string instance_name = instance.mLabel; + + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + if (importerDebug) + { + // Useful for debugging generalized complaints below about total submeshes which don't have enough + // context to address exactly what needs to be fixed to move towards compliance with the rules. + // + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << LL_ENDL; + + LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin(); + while (mat_iter != lod_model->mMaterialList.end()) + { + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL; + mat_iter++; + } + } + + //add this model to the lod total + total_tris[i] += cur_tris; + total_verts[i] += cur_verts; + total_submeshes[i] += cur_submeshes; + + //store this model's counts to asset data + tris[i].push_back(cur_tris); + verts[i].push_back(cur_verts); + submeshes[i].push_back(cur_submeshes); } } - } + } if (mMaxTriangleLimit == 0) { @@ -4357,37 +2684,48 @@ void LLModelPreview::updateStatusMessages() const LLVector4a scale(0.5f); for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i) { //for each model in the lod - if (mModel[lod][i]->mPhysics.mHull.empty()) + if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty()) { //no decomp exists S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j) { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); - for (S32 k = 0; k < face.mNumIndices && !has_degenerate; ) + LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); + for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; ) { - LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale); + U16 index_a = face.mIndices[k+0]; + U16 index_b = face.mIndices[k+1]; + U16 index_c = face.mIndices[k+2]; + + LLVector4a v1; v1.setMul(face.mPositions[index_a], scale); + LLVector4a v2; v2.setMul(face.mPositions[index_b], scale); + LLVector4a v3; v3.setMul(face.mPositions[index_c], scale); if (ll_is_degenerate(v1,v2,v3)) { has_degenerate = true; } + else + { + k += 3; + } } } } } } - + mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); std::string mesh_status_na = mFMP->getString("mesh_status_na"); S32 upload_status[LLModel::LOD_HIGH+1]; - bool upload_ok = true; + mModelNoErrors = true; - for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) + const U32 lod_high = LLModel::LOD_HIGH; + U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]); + + for (S32 lod = 0; lod <= lod_high; ++lod) { upload_status[lod] = 0; @@ -4400,7 +2738,7 @@ void LLModelPreview::updateStatusMessages() } else { - if (lod == LLModel::LOD_HIGH) + if (lod == lod_high) { upload_status[lod] = 2; message = "mesh_status_missing_lod"; @@ -4421,8 +2759,6 @@ void LLModelPreview::updateStatusMessages() mFMP->childSetValue(lod_vertices_name[lod], mesh_status_na); } - const U32 lod_high = LLModel::LOD_HIGH; - if (lod != lod_high) { if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high]) @@ -4430,6 +2766,13 @@ void LLModelPreview::updateStatusMessages() message = "mesh_status_submesh_mismatch"; upload_status[lod] = 2; } + else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count) + {//number of submodels is different, not all faces are matched correctly. + message = "mesh_status_submesh_mismatch"; + upload_status[lod] = 2; + // Note: Submodels in instance were loaded from higher LOD and as result face count + // returns same value and total_submeshes[lod] is identical to high_lod one. + } else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size()) { //number of meshes is different message = "mesh_status_mesh_mismatch"; @@ -4450,7 +2793,7 @@ void LLModelPreview::updateStatusMessages() { //too many vertices in this lod message = "mesh_status_too_many_vertices"; - upload_status[lod] = 2; + upload_status[lod] = 1; } } } @@ -4462,7 +2805,7 @@ void LLModelPreview::updateStatusMessages() if (upload_status[lod] >= 2) { - upload_ok = false; + mModelNoErrors = false; } if (lod == mPreviewLOD) @@ -4476,23 +2819,41 @@ void LLModelPreview::updateStatusMessages() } - //make sure no hulls have more than 256 points in them - for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) + //warn if hulls have more than 256 points in them + BOOL physExceededVertexLimit = FALSE; + for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) { LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i]; - for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) + if (mdl) { - if (mdl->mPhysics.mHull[j].size() > 256) + for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j) { - upload_ok = false; + if (mdl->mPhysics.mHull[j].size() > 256) + { + physExceededVertexLimit = TRUE; + LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL; + break; + } } } } + mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit); + LLIconCtrl* physStatusIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon"); + physStatusIcon->setVisible(physExceededVertexLimit); + if (physExceededVertexLimit) + { + mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded")); + LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning"); + physStatusIcon->setImage(img); + } - bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; + if (getLoadState() >= LLModelLoader::ERROR_PARSING) + { + mModelNoErrors = false; + LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL; + } - bool skinAndRigOk = true; bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean(); bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); @@ -4500,19 +2861,23 @@ void LLModelPreview::updateStatusMessages() { if ( uploadingJointPositions && !isRigValidForJointPositionUpload() ) { - skinAndRigOk = false; - } + mModelNoErrors = false; + LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL; + } } - - if(upload_ok && mModelLoader) + + if(mModelNoErrors && mModelLoader) { if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) { - upload_ok = false ; + // Some textures are still loading, prevent upload until they are done + mModelNoErrors = false; } } - if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate) + // Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics + // current use of has_degenerate won't block upload permanently - later checks will restore the button + if (!mModelNoErrors || has_degenerate) { mFMP->childDisable("ok_btn"); } @@ -4854,7 +3219,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) LLModel* base_mdl = *base_iter; base_iter++; - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + S32 num_faces = mdl->getNumVolumeFaces(); + for (S32 i = 0; i < num_faces; ++i) { const LLVolumeFace &vf = mdl->getVolumeFace(i); U32 num_vertices = vf.mNumVertices; @@ -4949,23 +3315,23 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) void LLModelPreview::update() { - if (mDirty) + if (mGenLOD) { - mDirty = false; - mResourceCost = calcResourceCost(); + mGenLOD = false; + genLODs(); refresh(); updateStatusMessages(); } - if (mGenLOD) + if (mDirty) { - mGenLOD = false; - genLODs(); + mDirty = false; + mResourceCost = calcResourceCost(); refresh(); updateStatusMessages(); } - } + //----------------------------------------------------------------------------- // getTranslationForJointOffset() //----------------------------------------------------------------------------- @@ -4999,10 +3365,79 @@ void LLModelPreview::createPreviewAvatar( void ) } else { - LL_INFOS()<<"Failed to create preview avatar for upload model window"<<LL_ENDL; + LL_INFOS() << "Failed to create preview avatar for upload model window" << LL_ENDL; } } +//static +U32 LLModelPreview::countRootModels(LLModelLoader::model_list models) +{ + U32 root_models = 0; + model_list::iterator model_iter = models.begin(); + while (model_iter != models.end()) + { + LLModel* mdl = *model_iter; + if (mdl && mdl->mSubmodelID == 0) + { + root_models++; + } + model_iter++; + } + return root_models; +} + +void LLModelPreview::loadedCallback( + LLModelLoader::scene& scene, + LLModelLoader::model_list& model_list, + S32 lod, + void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview && !LLModelPreview::sIgnoreLoadedCallback) + { + pPreview->loadModelCallback(lod); + } +} + +void LLModelPreview::stateChangedCallback(U32 state,void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + pPreview->setLoadState(state); + } +} + +LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + return pPreview->getPreviewAvatar()->getJoint(str); + } + return NULL; +} + +U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque) +{ + (void)opaque; + + if (material.mDiffuseMapFilename.size()) + { + material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >; + LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); + + tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); + tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE); + tex->forceToSaveRawImage(0, F32_MAX); + material.setDiffuseMap(tex->getID()); // record tex ID + return 1; + } + + material.mOpaqueData = NULL; + return 0; +} + void LLModelPreview::addEmptyFace( LLModel* pTarget ) { U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -5138,8 +3573,11 @@ BOOL LLModelPreview::render() mViewOption["show_skin_weight"] = false; fmp->disableViewOption("show_skin_weight"); fmp->disableViewOption("show_joint_positions"); + + skin_weight = false; + mFMP->childSetValue("show_skin_weight", false); + fmp->setViewOptionEnabled("show_skin_weight", skin_weight); } - skin_weight = false; } if (upload_skin && !has_skin_weights) @@ -5243,29 +3681,20 @@ BOOL LLModelPreview::render() const LLVertexBuffer* buff = vb_vec[0]; regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight; } - } - - //make sure material lists all match - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) + else { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) ) - { - mFMP->childDisable( "calculate_btn" ); - } - } + LL_INFOS(" ") << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; } } if (regen) { genBuffers(mPreviewLOD, skin_weight); + { + LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; + } } if (!skin_weight) @@ -5276,62 +3705,63 @@ BOOL LLModelPreview::render() LLModel* model = instance.mLOD[mPreviewLOD]; - if (!model) - { - continue; - } + if (!model) + { + continue; + } - gGL.pushMatrix(); - LLMatrix4 mat = instance.mTransform; + gGL.pushMatrix(); + LLMatrix4 mat = instance.mTransform; - gGL.multMatrix((GLfloat*) mat.mMatrix); + gGL.multMatrix((GLfloat*) mat.mMatrix); - for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - - buffer->setBuffer(type_mask & buffer->getTypeMask()); - if (textures) + U32 num_models = mVertexBuffer[mPreviewLOD][model].size(); + for (U32 i = 0; i < num_models; ++i) { - int materialCnt = instance.mModel->mMaterialList.size(); - if ( i < materialCnt ) + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + + buffer->setBuffer(type_mask & buffer->getTypeMask()); + + if (textures) { - const std::string& binding = instance.mModel->mMaterialList[i]; - const LLImportMaterial& material = instance.mMaterial[binding]; + int materialCnt = instance.mModel->mMaterialList.size(); + if ( i < materialCnt ) + { + const std::string& binding = instance.mModel->mMaterialList[i]; + const LLImportMaterial& material = instance.mMaterial[binding]; - gGL.diffuseColor4fv(material.mDiffuseColor.mV); + gGL.diffuseColor4fv(material.mDiffuseColor.mV); - if (material.mDiffuseMap.notNull()) - { - if (material.mDiffuseMap->getDiscardLevel() > -1) + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); + mTextureSet.insert(tex); } } } - } - else - { - gGL.diffuseColor4f(1,1,1,1); - } - - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); + else + { + gGL.diffuseColor4f(1,1,1,1); + } - if (edges) - { - glLineWidth(3.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); + + if (edges) + { + glLineWidth(3.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glLineWidth(1.f); + } } + gGL.popMatrix(); } - gGL.popMatrix(); - } if (physics) { @@ -5359,97 +3789,99 @@ BOOL LLModelPreview::render() LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS]; - if (!model) - { - continue; - } + if (!model) + { + continue; + } - gGL.pushMatrix(); - LLMatrix4 mat = instance.mTransform; + gGL.pushMatrix(); + LLMatrix4 mat = instance.mTransform; gGL.multMatrix((GLfloat*) mat.mMatrix); - bool render_mesh = true; + bool render_mesh = true; - LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; - if (decomp) - { - LLMutexLock(decomp->mMutex); + LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; + if (decomp) + { + LLMutexLock(decomp->mMutex); - LLModel::Decomposition& physics = model->mPhysics; + LLModel::Decomposition& physics = model->mPhysics; - if (!physics.mHull.empty()) - { - render_mesh = false; + if (!physics.mHull.empty()) + { + render_mesh = false; - if (physics.mMesh.empty()) - { //build vertex buffer for physics mesh - gMeshRepo.buildPhysicsMesh(physics); - } + if (physics.mMesh.empty()) + { //build vertex buffer for physics mesh + gMeshRepo.buildPhysicsMesh(physics); + } - if (!physics.mMesh.empty()) - { //render hull instead of mesh - for (U32 i = 0; i < physics.mMesh.size(); ++i) - { - if (explode > 0.f) + if (!physics.mMesh.empty()) + { //render hull instead of mesh + for (U32 i = 0; i < physics.mMesh.size(); ++i) { - gGL.pushMatrix(); + if (explode > 0.f) + { + gGL.pushMatrix(); - LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; - offset *= explode; + LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; + offset *= explode; - gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); - } + gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); + } - static std::vector<LLColor4U> hull_colors; + static std::vector<LLColor4U> hull_colors; - if (i+1 >= hull_colors.size()) - { - hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); - } + if (i+1 >= hull_colors.size()) + { + hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); + } - gGL.diffuseColor4ubv(hull_colors[i].mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); + gGL.diffuseColor4ubv(hull_colors[i].mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); - if (explode > 0.f) - { - gGL.popMatrix(); + if (explode > 0.f) + { + gGL.popMatrix(); + } } } } } - } - - if (render_mesh) - { - if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) - { - genBuffers(LLModel::LOD_PHYSICS, false); - } - for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) + + if (render_mesh) { - LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) + { + genBuffers(LLModel::LOD_PHYSICS, false); + } + + U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); + for (U32 i = 0; i < num_models; ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); - buffer->setBuffer(type_mask & buffer->getTypeMask()); - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + buffer->setBuffer(type_mask & buffer->getTypeMask()); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - gGL.diffuseColor3f(1.f, 1.f, 0.f); + gGL.diffuseColor3f(1.f, 1.f, 0.f); - glLineWidth(2.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + glLineWidth(2.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glLineWidth(1.f); + } } - } - gGL.popMatrix(); - } + gGL.popMatrix(); + } glLineWidth(3.f); glPointSize(8.f); @@ -5561,7 +3993,7 @@ BOOL LLModelPreview::render() if (!model->mSkinWeights.empty()) { - for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) + for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i) { LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; @@ -5630,19 +4062,20 @@ BOOL LLModelPreview::render() position[j] = v; } + llassert(model->mMaterialList.size() > i); const std::string& binding = instance.mModel->mMaterialList[i]; const LLImportMaterial& material = instance.mMaterial[binding]; buffer->setBuffer(type_mask & buffer->getTypeMask()); gGL.diffuseColor4fv(material.mDiffuseColor.mV); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (material.mDiffuseMap.notNull()) + + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - if (material.mDiffuseMap->getDiscardLevel() > -1) - { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); - } + mTextureSet.insert(tex); } buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); @@ -5757,14 +4190,14 @@ void LLFloaterModelPreview::onReset(void* user_data) LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data; fmp->childDisable("reset_btn"); LLModelPreview* mp = fmp->mModelPreview; - std::string filename = mp->mLODFile[3]; + std::string filename = mp->mLODFile[LLModel::LOD_HIGH]; fmp->resetDisplayOptions(); //reset model preview fmp->initModelPreview(); mp = fmp->mModelPreview; - mp->loadModel(filename,3,true); + mp->loadModel(filename,LLModel::LOD_HIGH,true); } //static @@ -5858,7 +4291,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible) } mUploadBtn->setVisible(!visible); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); if (visible) { @@ -5924,7 +4357,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived() childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger())); childSetVisible("upload_fee", true); childSetVisible("price_breakdown", true); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); } void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) @@ -5948,6 +4381,16 @@ void LLFloaterModelPreview::onModelUploadFailure() mUploadBtn->setEnabled(true); } +bool LLFloaterModelPreview::isModelUploadAllowed() +{ + bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty(); + if (mModelPreview) + { + allow_upload &= mModelPreview->mModelNoErrors; + } + return allow_upload; +} + S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2) { if (mContinue) @@ -5997,8 +4440,8 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) // BAP HACK: handle "" for case that MeshUploadFlag cap is broken. mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); - //mUploadBtn->setEnabled(mHasUploadPerm); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + // isModelUploadAllowed() includes mHasUploadPerm + mUploadBtn->setEnabled(isModelUploadAllowed()); getChild<LLTextBox>("warning_title")->setVisible(!mHasUploadPerm); getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm); } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 618748bd4e..7a518c798b 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -37,6 +37,8 @@ #include "llviewermenufile.h" #include "llfloatermodeluploadbase.h" +#include "lldaeloader.h" + class LLComboBox; class LLJoint; class LLViewerJointMesh; @@ -45,103 +47,18 @@ class LLTextBox; class LLVertexBuffer; class LLModelPreview; class LLFloaterModelPreview; +class DAE; class daeElement; class domProfile_COMMON; class domInstance_geometry; class domNode; class domTranslate; class domController; +class domSkin; +class domMesh; class LLMenuButton; class LLToggleableMenu; -typedef std::map<std::string, LLMatrix4> JointTransformMap; -typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt; - -const S32 NUM_LOD = 4; - -class LLModelLoader : public LLThread -{ -public: - typedef enum - { - STARTING = 0, - READING_FILE, - CREATING_FACES, - GENERATING_VERTEX_BUFFERS, - GENERATING_LOD, - DONE, - ERROR_PARSING, //basically loading failed - ERROR_MATERIALS, - } eLoadState; - - U32 mState; - std::string mFilename; - S32 mLod; - LLModelPreview* mPreview; - LLMatrix4 mTransform; - BOOL mFirstTransform; - LLVector3 mExtents[2]; - bool mTrySLM; - - std::map<daeElement*, LLPointer<LLModel> > mModel; - - typedef std::vector<LLPointer<LLModel> > model_list; - model_list mModelList; - - typedef std::vector<LLModelInstance> model_instance_list; - - typedef std::map<LLMatrix4, model_instance_list > scene; - - scene mScene; - - typedef std::queue<LLPointer<LLModel> > model_queue; - - //queue of models that need a physics rep - model_queue mPhysicsQ; - - LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque<std::string>& jointsFromNodes ); - ~LLModelLoader() ; - - virtual void run(); - bool doLoadModel(); - bool loadFromSLM(const std::string& filename); - void loadModelCallback(); - - void loadTextures() ; //called in the main thread. - void processElement(daeElement* element, bool& badElement); - std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo); - LLImportMaterial profileToMaterial(domProfile_COMMON* material); - std::string getElementLabel(daeElement *element); - LLColor4 getDaeColor(daeElement* element); - - daeElement* getChildFromElement( daeElement* pElement, std::string const & name ); - - bool isNodeAJoint( domNode* pNode ); - void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms ); - void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ); - void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ); - void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ); - - void setLoadState(U32 state); - - void buildJointToNodeMappingFromScene( daeElement* pRoot ); - void processJointToNodeMapping( domNode* pNode ); - void processChildJoints( domNode* pParentNode ); - - //map of avatar joints as named in COLLADA assets to internal joint names - std::map<std::string, std::string> mJointMap; - JointTransformMap& mJointList; - std::deque<std::string>& mJointsFromNode; - - S32 mNumOfFetchingTextures ; //updated in the main thread - bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. - -private: - static std::list<LLModelLoader*> sActiveLoaderList; - static bool isAlive(LLModelLoader* loader) ; -}; - class LLFloaterModelPreview : public LLFloaterModelUploadBase { public: @@ -172,6 +89,7 @@ public: BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); static void onMouseCaptureLostModelPreview(LLMouseHandler*); static void setUploadAmount(S32 amount) { sUploadAmount = amount; } @@ -210,6 +128,8 @@ public: /*virtual*/ void onModelUploadFailure(); + bool isModelUploadAllowed(); + protected: friend class LLModelPreview; friend class LLMeshFilePicker; @@ -359,21 +279,14 @@ public: void setHasPivot( bool val ) { mHasPivot = val; } void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; } - //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) - void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ); - void critiqueJointToNodeMappingFromScene( void ); //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions //Accessors for joint position upload friendly rigs const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } - bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ); - //Determines if a rig is a legacy from the joint list - bool isRigLegacy( const std::vector<std::string> &jointListFromAsset ); + //Accessors for the legacy rigs const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } - void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } - //Verify that a controller matches vertex counts - bool verifyController( domController* pController ); + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); @@ -388,6 +301,16 @@ public: LLVector3 getTranslationForJointOffset( std::string joint ); + static bool sIgnoreLoadedCallback; + +protected: + + static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque); + static void stateChangedCallback(U32 state, void* opaque); + + static LLJoint* lookupJointByName(const std::string&, void* opaque); + static U32 loadTextures(LLImportMaterial& material, void* opaque); + private: //Utility function for controller vertex compare bool verifyCount( int expected, int result ); @@ -395,6 +318,8 @@ private: void createPreviewAvatar( void ); //Accessor for the dummy avatar LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; } + // Count amount of original models, excluding sub-models + static U32 countRootModels(LLModelLoader::model_list models); protected: friend class LLModelLoader; @@ -416,13 +341,15 @@ private: LLVector3 mPreviewTarget; LLVector3 mPreviewScale; S32 mPreviewLOD; + S32 mPhysicsSearchLOD; U32 mResourceCost; std::string mLODFile[LLModel::NUM_LODS]; bool mLoading; U32 mLoadState; bool mResetJoints; bool mRigParityWithScene; - + bool mModelNoErrors; + std::map<std::string, bool> mViewOption; //GLOD object parameters (must rebuild object if these change) @@ -459,7 +386,7 @@ private: U32 mMaxTriangleLimit; LLMeshUploadThread::instance_list mUploadData; - std::set<LLViewerFetchedTexture* > mTextureSet; + std::set<LLViewerFetchedTexture * > mTextureSet; //map of vertex buffers to models (one vertex buffer in vector per face in model std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1]; @@ -478,10 +405,9 @@ private: bool mLastJointUpdate; - std::deque<std::string> mMasterJointList; - std::deque<std::string> mMasterLegacyJointList; - std::deque<std::string> mJointsFromNode; - JointTransformMap mJointTransformMap; + JointSet mJointsFromNode; + JointTransformMap mJointTransformMap; + LLPointer<LLVOAvatar> mPreviewAvatar; }; diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp new file mode 100644 index 0000000000..4b5fe4989a --- /dev/null +++ b/indra/newview/llfloaternotificationstabbed.cpp @@ -0,0 +1,575 @@ +/** + * @file llfloaternotificationstabbed.cpp + * @brief + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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" // must be first include +#include "llfloaternotificationstabbed.h" + +#include "llchiclet.h" +#include "llchicletbar.h" +#include "llflatlistview.h" +#include "llfloaterreg.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" +#include "llscriptfloater.h" +#include "llspeakers.h" +#include "lltoastpanel.h" +#include "lltoastnotifypanel.h" + +//--------------------------------------------------------------------------------- +LLFloaterNotificationsTabbed::LLFloaterNotificationsTabbed(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), + mChannel(NULL), + mSysWellChiclet(NULL), + mGroupInviteMessageList(NULL), + mGroupNoticeMessageList(NULL), + mTransactionMessageList(NULL), + mSystemMessageList(NULL), + mNotificationsSeparator(NULL), + mNotificationsTabContainer(NULL), + NOTIFICATION_TABBED_ANCHOR_NAME("notification_well_panel"), + IM_WELL_ANCHOR_NAME("im_well_panel"), + mIsReshapedByUser(false) + +{ + setOverlapsScreenChannel(true); + mNotificationUpdates.reset(new NotificationTabbedChannel(this)); + mNotificationsSeparator = new LLNotificationSeparator(); +} + +//--------------------------------------------------------------------------------- +BOOL LLFloaterNotificationsTabbed::postBuild() +{ + mGroupInviteMessageList = getChild<LLNotificationListView>("group_invite_notification_list"); + mGroupNoticeMessageList = getChild<LLNotificationListView>("group_notice_notification_list"); + mTransactionMessageList = getChild<LLNotificationListView>("transaction_notification_list"); + mSystemMessageList = getChild<LLNotificationListView>("system_notification_list"); + mNotificationsSeparator->initTaggedList(LLNotificationListItem::getGroupInviteTypes(), mGroupInviteMessageList); + mNotificationsSeparator->initTaggedList(LLNotificationListItem::getGroupNoticeTypes(), mGroupNoticeMessageList); + mNotificationsSeparator->initTaggedList(LLNotificationListItem::getTransactionTypes(), mTransactionMessageList); + mNotificationsSeparator->initUnTaggedList(mSystemMessageList); + mNotificationsTabContainer = getChild<LLTabContainer>("notifications_tab_container"); + + mDeleteAllBtn = getChild<LLButton>("delete_all_button"); + mDeleteAllBtn->setClickedCallback(boost::bind(&LLFloaterNotificationsTabbed::onClickDeleteAllBtn,this)); + + mCollapseAllBtn = getChild<LLButton>("collapse_all_button"); + mCollapseAllBtn->setClickedCallback(boost::bind(&LLFloaterNotificationsTabbed::onClickCollapseAllBtn,this)); + + // get a corresponding channel + initChannel(); + BOOL rv = LLTransientDockableFloater::postBuild(); + + setTitle(getString("title_notification_tabbed_window")); + return rv; +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::setMinimized(BOOL minimize) +{ + LLTransientDockableFloater::setMinimized(minimize); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::handleReshape(const LLRect& rect, bool by_user) +{ + mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user + LLTransientDockableFloater::handleReshape(rect, by_user); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onStartUpToastClick(S32 x, S32 y, MASK mask) +{ + // just set floater visible. Screen channels will be cleared. + setVisible(TRUE); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::setSysWellChiclet(LLSysWellChiclet* chiclet) +{ + mSysWellChiclet = chiclet; + if(NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } +} + +//--------------------------------------------------------------------------------- +LLFloaterNotificationsTabbed::~LLFloaterNotificationsTabbed() +{ +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::removeItemByID(const LLUUID& id, std::string type) +{ + if(mNotificationsSeparator->removeItemByID(type, id)) + { + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } + reshapeWindow(); + updateNotificationCounters(); + } + else + { + LL_WARNS() << "Unable to remove notification from the list, ID: " << id + << LL_ENDL; + } + + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } +} + +//--------------------------------------------------------------------------------- +LLPanel * LLFloaterNotificationsTabbed::findItemByID(const LLUUID& id, std::string type) +{ + return mNotificationsSeparator->findItemByID(type, id); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::initChannel() +{ + LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); + if(NULL == mChannel) + { + LL_WARNS() << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << LL_ENDL; + } + + if(mChannel) + { + mChannel->addOnStoreToastCallback(boost::bind(&LLFloaterNotificationsTabbed::onStoreToast, this, _1, _2)); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::setVisible(BOOL visible) +{ + if (visible) + { + // when Notification channel is cleared, storable toasts will be added into the list. + clearScreenChannels(); + } + if (visible) + { + if (NULL == getDockControl() && getDockTongue().notNull()) + { + setDockControl(new LLDockControl( + LLChicletBar::getInstance()->getChild<LLView>(getAnchorViewName()), this, + getDockTongue(), LLDockControl::BOTTOM)); + } + } + + // do not show empty window + if (NULL == mNotificationsSeparator || isWindowEmpty()) visible = FALSE; + + LLTransientDockableFloater::setVisible(visible); + + // update notification channel state + initChannel(); // make sure the channel still exists + if(mChannel) + { + mChannel->updateShowToastsState(); + mChannel->redrawToasts(); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::setDocked(bool docked, bool pop_on_undock) +{ + LLTransientDockableFloater::setDocked(docked, pop_on_undock); + + // update notification channel state + if(mChannel) + { + mChannel->updateShowToastsState(); + mChannel->redrawToasts(); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::reshapeWindow() +{ + // update notification channel state + // update on a window reshape is important only when a window is visible and docked + if(mChannel && getVisible() && isDocked()) + { + mChannel->updateShowToastsState(); + } +} + +//--------------------------------------------------------------------------------- +bool LLFloaterNotificationsTabbed::isWindowEmpty() +{ + return mNotificationsSeparator->size() == 0; +} + +//--------------------------------------------------------------------------------- +LLFloaterNotificationsTabbed::NotificationTabbedChannel::NotificationTabbedChannel(LLFloaterNotificationsTabbed* notifications_tabbed_window) + : LLNotificationChannel(LLNotificationChannel::Params().name(notifications_tabbed_window->getPathname())), + mNotificationsTabbedWindow(notifications_tabbed_window) +{ + connectToChannel("Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); +} + +// static +//--------------------------------------------------------------------------------- +LLFloaterNotificationsTabbed* LLFloaterNotificationsTabbed::getInstance(const LLSD& key /*= LLSD()*/) +{ + return LLFloaterReg::getTypedInstance<LLFloaterNotificationsTabbed>("notification_well_window", key); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::updateNotificationCounter(S32 panelIndex, S32 counterValue, std::string stringName) +{ + LLStringUtil::format_map_t string_args; + string_args["[COUNT]"] = llformat("%d", counterValue); + std::string label = getString(stringName, string_args); + mNotificationsTabContainer->setPanelTitle(panelIndex, label); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::updateNotificationCounters() +{ + updateNotificationCounter(0, mSystemMessageList->size(), "system_tab_title"); + updateNotificationCounter(1, mTransactionMessageList->size(), "transactions_tab_title"); + updateNotificationCounter(2, mGroupInviteMessageList->size(), "group_invitations_tab_title"); + updateNotificationCounter(3, mGroupNoticeMessageList->size(), "group_notices_tab_title"); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::addItem(LLNotificationListItem::Params p) +{ + // do not add clones + if (mNotificationsSeparator->findItemByID(p.notification_name, p.notification_id)) + return; + LLNotificationListItem* new_item = LLNotificationListItem::create(p); + if (new_item == NULL) + { + return; + } + if (mNotificationsSeparator->addItem(new_item->getNotificationName(), new_item)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + reshapeWindow(); + updateNotificationCounters(); + new_item->setOnItemCloseCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClose, this, _1)); + new_item->setOnItemClickCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClick, this, _1)); + } + else + { + LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id + << ", title: " << new_item->getTitle() + << LL_ENDL; + + new_item->die(); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::closeAll() +{ + // Need to clear notification channel, to add storable toasts into the list. + clearScreenChannels(); + + std::vector<LLNotificationListItem*> items; + mNotificationsSeparator->getItems(items); + std::vector<LLNotificationListItem*>::iterator iter = items.begin(); + for (; iter != items.end(); ++iter) + { + onItemClose(*iter); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::getAllItemsOnCurrentTab(std::vector<LLPanel*>& items) const +{ + switch (mNotificationsTabContainer->getCurrentPanelIndex()) + { + case 0: + mSystemMessageList->getItems(items); + break; + case 1: + mTransactionMessageList->getItems(items); + break; + case 2: + mGroupInviteMessageList->getItems(items); + break; + case 3: + mGroupNoticeMessageList->getItems(items); + break; + default: + break; + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::closeAllOnCurrentTab() +{ + // Need to clear notification channel, to add storable toasts into the list. + clearScreenChannels(); + std::vector<LLPanel*> items; + getAllItemsOnCurrentTab(items); + std::vector<LLPanel*>::iterator iter = items.begin(); + for (; iter != items.end(); ++iter) + { + LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*iter); + if (notify_item) + onItemClose(notify_item); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::collapseAllOnCurrentTab() +{ + std::vector<LLPanel*> items; + getAllItemsOnCurrentTab(items); + std::vector<LLPanel*>::iterator iter = items.begin(); + for (; iter != items.end(); ++iter) + { + LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*iter); + if (notify_item) + notify_item->setExpanded(FALSE); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::clearScreenChannels() +{ + // 1 - remove StartUp toast and channel if present + if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) + { + LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); + } + + // 2 - remove toasts in Notification channel + if(mChannel) + { + mChannel->removeAndStoreAllStorableToasts(); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id) +{ + LLNotificationListItem::Params p; + p.notification_id = id; + p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); + LLNotificationPtr notify = mChannel->getToastByNotificationID(id)->getNotification(); + LLSD payload = notify->getPayload(); + p.notification_name = notify->getName(); + p.transaction_id = payload["transaction_id"]; + p.group_id = payload["group_id"]; + p.fee = payload["fee"]; + p.subject = payload["subject"].asString(); + p.message = payload["message"].asString(); + p.sender = payload["sender_name"].asString(); + p.time_stamp = notify->getDate(); + p.received_time = payload["received_time"].asDate(); + p.paid_from_id = payload["from_id"]; + p.paid_to_id = payload["dest_id"]; + p.inventory_offer = payload["inventory_offer"]; + p.notification_priority = notify->getPriority(); + addItem(p); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onItemClick(LLNotificationListItem* item) +{ + LLUUID id = item->getID(); + if (item->showPopup()) + { + LLFloaterReg::showInstance("inspect_toast", id); + } + else + { + item->setExpanded(TRUE); + } +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onItemClose(LLNotificationListItem* item) +{ + LLUUID id = item->getID(); + + if(mChannel) + { + // removeItemByID() is invoked from killToastByNotificationID() and item will removed; + mChannel->killToastByNotificationID(id); + } + else + { + // removeItemByID() should be called one time for each item to remove it from notification well + removeItemByID(id, item->getNotificationName()); + } + +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onAdd( LLNotificationPtr notify ) +{ + removeItemByID(notify->getID(), notify->getName()); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onClickDeleteAllBtn() +{ + closeAllOnCurrentTab(); +} + +//--------------------------------------------------------------------------------- +void LLFloaterNotificationsTabbed::onClickCollapseAllBtn() +{ + collapseAllOnCurrentTab(); +} + +//--------------------------------------------------------------------------------- +void LLNotificationSeparator::initTaggedList(const std::string& tag, LLNotificationListView* list) +{ + mNotificationListMap.insert(notification_list_map_t::value_type(tag, list)); + mNotificationLists.push_back(list); +} + +//--------------------------------------------------------------------------------- +void LLNotificationSeparator::initTaggedList(const std::set<std::string>& tags, LLNotificationListView* list) +{ + std::set<std::string>::const_iterator it = tags.begin(); + for(;it != tags.end();it++) + { + initTaggedList(*it, list); + } +} + +//--------------------------------------------------------------------------------- +void LLNotificationSeparator::initUnTaggedList(LLNotificationListView* list) +{ + mUnTaggedList = list; +} + +//--------------------------------------------------------------------------------- +bool LLNotificationSeparator::addItem(std::string& tag, LLNotificationListItem* item) +{ + notification_list_map_t::iterator it = mNotificationListMap.find(tag); + if (it != mNotificationListMap.end()) + { + return it->second->addNotification(item); + } + else if (mUnTaggedList != NULL) + { + return mUnTaggedList->addNotification(item); + } + return false; +} + +//--------------------------------------------------------------------------------- +bool LLNotificationSeparator::removeItemByID(std::string& tag, const LLUUID& id) +{ + notification_list_map_t::iterator it = mNotificationListMap.find(tag); + if (it != mNotificationListMap.end()) + { + return it->second->removeItemByValue(id); + } + else if (mUnTaggedList != NULL) + { + return mUnTaggedList->removeItemByValue(id); + } + return false; +} + +//--------------------------------------------------------------------------------- +U32 LLNotificationSeparator::size() const +{ + U32 size = 0; + notification_list_list_t::const_iterator it = mNotificationLists.begin(); + for (; it != mNotificationLists.end(); it++) + { + size = size + (*it)->size(); + } + if (mUnTaggedList != NULL) + { + size = size + mUnTaggedList->size(); + } + return size; +} + +//--------------------------------------------------------------------------------- +LLPanel* LLNotificationSeparator::findItemByID(std::string& tag, const LLUUID& id) +{ + notification_list_map_t::iterator it = mNotificationListMap.find(tag); + if (it != mNotificationListMap.end()) + { + return it->second->getItemByValue(id); + } + else if (mUnTaggedList != NULL) + { + return mUnTaggedList->getItemByValue(id); + } + + return NULL; +} + +//static +//--------------------------------------------------------------------------------- +void LLNotificationSeparator::getItemsFromList(std::vector<LLNotificationListItem*>& items, LLNotificationListView* list) +{ + std::vector<LLPanel*> list_items; + list->getItems(list_items); + std::vector<LLPanel*>::iterator it = list_items.begin(); + for (; it != list_items.end(); ++it) + { + LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*it); + if (notify_item) + items.push_back(notify_item); + } +} + +//--------------------------------------------------------------------------------- +void LLNotificationSeparator::getItems(std::vector<LLNotificationListItem*>& items) const +{ + items.clear(); + notification_list_list_t::const_iterator lists_it = mNotificationLists.begin(); + for (; lists_it != mNotificationLists.end(); lists_it++) + { + getItemsFromList(items, *lists_it); + } + if (mUnTaggedList != NULL) + { + getItemsFromList(items, mUnTaggedList); + } +} + +//--------------------------------------------------------------------------------- +LLNotificationSeparator::LLNotificationSeparator() + : mUnTaggedList(NULL) +{} + +//--------------------------------------------------------------------------------- +LLNotificationSeparator::~LLNotificationSeparator() +{} diff --git a/indra/newview/llfloaternotificationstabbed.h b/indra/newview/llfloaternotificationstabbed.h new file mode 100644 index 0000000000..8dd20b18c4 --- /dev/null +++ b/indra/newview/llfloaternotificationstabbed.h @@ -0,0 +1,174 @@ +/** + * @file llfloaternotificationstabbed.h + * @brief + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_FLOATERNOTIFICATIONSTABBED_H +#define LL_FLOATERNOTIFICATIONSTABBED_H + +#include "llimview.h" +#include "llnotifications.h" +#include "llscreenchannel.h" +#include "llsyswellitem.h" +#include "lltransientdockablefloater.h" +#include "llnotificationlistview.h" +#include "lltabcontainer.h" + +class LLAvatarName; +class LLChiclet; +class LLFlatListView; +class LLIMChiclet; +class LLScriptChiclet; +class LLSysWellChiclet; + +class LLNotificationSeparator +{ +public: + LLNotificationSeparator(); + ~LLNotificationSeparator(); + void initTaggedList(const std::string& tag, LLNotificationListView* list); + void initTaggedList(const std::set<std::string>& tags, LLNotificationListView* list); + void initUnTaggedList(LLNotificationListView* list); + bool addItem(std::string& tag, LLNotificationListItem* item); + LLPanel* findItemByID(std::string& tag, const LLUUID& id); + bool removeItemByID(std::string& tag, const LLUUID& id); + void getItems(std::vector<LLNotificationListItem*>& items) const; + U32 size() const; +private: + static void getItemsFromList(std::vector<LLNotificationListItem*>& items, LLNotificationListView* list); + + typedef std::map<std::string, LLNotificationListView*> notification_list_map_t; + notification_list_map_t mNotificationListMap; + typedef std::list<LLNotificationListView*> notification_list_list_t; + notification_list_list_t mNotificationLists; + LLNotificationListView* mUnTaggedList; +}; + +class LLFloaterNotificationsTabbed : public LLTransientDockableFloater +{ +public: + LOG_CLASS(LLFloaterNotificationsTabbed); + + LLFloaterNotificationsTabbed(const LLSD& key); + virtual ~LLFloaterNotificationsTabbed(); + BOOL postBuild(); + + // other interface functions + // check is window empty + bool isWindowEmpty(); + + // Operating with items + void removeItemByID(const LLUUID& id, std::string type); + LLPanel * findItemByID(const LLUUID& id, std::string type); + void updateNotificationCounters(); + void updateNotificationCounter(S32 panelIndex, S32 counterValue, std::string stringName); + + // Operating with outfit + virtual void setVisible(BOOL visible); + + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // override LLFloater's minimization according to EXT-1216 + /*virtual*/ void setMinimized(BOOL minimize); + /*virtual*/ void handleReshape(const LLRect& rect, bool by_user); + + void onStartUpToastClick(S32 x, S32 y, MASK mask); + /*virtual*/ void onAdd(LLNotificationPtr notify); + + void setSysWellChiclet(LLSysWellChiclet* chiclet); + void closeAll(); + + static LLFloaterNotificationsTabbed* getInstance(const LLSD& key = LLSD()); + + // size constants for the window and for its elements + static const S32 MAX_WINDOW_HEIGHT = 200; + static const S32 MIN_WINDOW_WIDTH = 318; + +private: + // init Window's channel + virtual void initChannel(); + + const std::string NOTIFICATION_TABBED_ANCHOR_NAME; + const std::string IM_WELL_ANCHOR_NAME; + //virtual const std::string& getAnchorViewName() = 0; + + void reshapeWindow(); + + // pointer to a corresponding channel's instance + LLNotificationsUI::LLScreenChannel* mChannel; + + /** + * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 + */ + LLSysWellChiclet* mSysWellChiclet; + + bool mIsReshapedByUser; + + struct NotificationTabbedChannel : public LLNotificationChannel + { + NotificationTabbedChannel(LLFloaterNotificationsTabbed*); + void onDelete(LLNotificationPtr notify) + { + mNotificationsTabbedWindow->removeItemByID(notify->getID(), notify->getName()); + } + + LLFloaterNotificationsTabbed* mNotificationsTabbedWindow; + }; + + LLNotificationChannelPtr mNotificationUpdates; + virtual const std::string& getAnchorViewName() { return NOTIFICATION_TABBED_ANCHOR_NAME; } + + // init Window's channel + // void initChannel(); + void clearScreenChannels(); + // Operating with items + void addItem(LLNotificationListItem::Params p); + void getAllItemsOnCurrentTab(std::vector<LLPanel*>& items) const; + + // Closes all notifications and removes them from the Notification Well + void closeAllOnCurrentTab(); + void collapseAllOnCurrentTab(); + + void onStoreToast(LLPanel* info_panel, LLUUID id); + void onClickDeleteAllBtn(); + void onClickCollapseAllBtn(); + // Handlers + void onItemClick(LLNotificationListItem* item); + void onItemClose(LLNotificationListItem* item); + // ID of a toast loaded by user (by clicking notification well item) + LLUUID mLoadedToastId; + + LLNotificationListView* mGroupInviteMessageList; + LLNotificationListView* mGroupNoticeMessageList; + LLNotificationListView* mTransactionMessageList; + LLNotificationListView* mSystemMessageList; + LLNotificationSeparator* mNotificationsSeparator; + LLTabContainer* mNotificationsTabContainer; + LLButton* mDeleteAllBtn; + LLButton* mCollapseAllBtn; +}; + +#endif // LL_FLOATERNOTIFICATIONSTABBED_H + + + diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index e5efca1102..b7b1634a5f 100755 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -160,6 +160,12 @@ BOOL LLFloaterOutbox::postBuild() mCategoryAddedObserver = new LLOutboxAddedObserver(this); gInventory.addObserver(mCategoryAddedObserver); + // Setup callbacks for importer + LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); + importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2)); + importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); + importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); + return TRUE; } @@ -298,12 +304,8 @@ void LLFloaterOutbox::initializeMarketPlace() // Initialize the marketplace import API // LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); - if (!importer.isInitialized()) { - importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2)); - importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); - importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); importer.initialize(); } } @@ -516,7 +518,7 @@ void LLFloaterOutbox::onImportButtonClicked() { mOutboxInventoryPanel.get()->clearSelection(); } - + mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport(); } @@ -617,3 +619,5 @@ void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) notification_handler->processNotification(notification); } + + diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 40519c8fd2..2cf69fc3cc 100755 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -1,7 +1,6 @@ /** * @file llfloateroutbox.h - * @brief LLFloaterOutbox - * class definition + * @brief Implementation of the merchant outbox window * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -30,6 +29,7 @@ #include "llfloater.h" #include "llfoldertype.h" +#include "llinventoryfilter.h" #include "llnotificationptr.h" diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 042cf47070..04a818c2c0 100755 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -166,15 +166,59 @@ void LLFloaterPermsDefault::onCommitCopy(const LLSD& user_data) xfer->setEnabled(copyable); } -class LLFloaterPermsResponder : public LLHTTPClient::Responder +const int MAX_HTTP_RETRIES = 5; +LLFloaterPermsRequester* LLFloaterPermsRequester::sPermsRequester = NULL; + +LLFloaterPermsRequester::LLFloaterPermsRequester(const std::string url, const LLSD report, + int maxRetries) + : mRetriesCount(0), mMaxRetries(maxRetries), mUrl(url), mReport(report) +{} + +//static +void LLFloaterPermsRequester::init(const std::string url, const LLSD report, int maxRetries) +{ + if (sPermsRequester == NULL) { + sPermsRequester = new LLFloaterPermsRequester(url, report, maxRetries); + } +} + +//static +void LLFloaterPermsRequester::finalize() +{ + if (sPermsRequester != NULL) + { + delete sPermsRequester; + sPermsRequester = NULL; + } +} + +//static +LLFloaterPermsRequester* LLFloaterPermsRequester::instance() +{ + return sPermsRequester; +} + +void LLFloaterPermsRequester::start() { -public: - LLFloaterPermsResponder(): LLHTTPClient::Responder() {} -private: - static std::string sPreviousReason; + ++mRetriesCount; + LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder()); +} + +bool LLFloaterPermsRequester::retry() +{ + if (++mRetriesCount < mMaxRetries) + { + LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder()); + return true; + } + return false; +} - void httpFailure() +void LLFloaterPermsResponder::httpFailure() +{ + if (!LLFloaterPermsRequester::instance() || !LLFloaterPermsRequester::instance()->retry()) { + LLFloaterPermsRequester::finalize(); const std::string& reason = getReason(); // Do not display the same error more than once in a row if (reason != sPreviousReason) @@ -185,27 +229,27 @@ private: LLNotificationsUtil::add("DefaultObjectPermissions", args); } } +} - void httpSuccess() - { - //const LLSD& content = getContent(); - //dump_sequential_xml("perms_responder_result.xml", content); - - // Since we have had a successful POST call be sure to display the next error message - // even if it is the same as a previous one. - sPreviousReason = ""; - LLFloaterPermsDefault::setCapSent(true); - LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL; - } -}; +void LLFloaterPermsResponder::httpSuccess() +{ + //const LLSD& content = getContent(); + //dump_sequential_xml("perms_responder_result.xml", content); - std::string LLFloaterPermsResponder::sPreviousReason; + // Since we have had a successful POST call be sure to display the next error message + // even if it is the same as a previous one. + sPreviousReason = ""; + LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL; +} + +std::string LLFloaterPermsResponder::sPreviousReason; void LLFloaterPermsDefault::sendInitialPerms() { if(!mCapSent) { updateCap(); + setCapSent(true); } } @@ -230,8 +274,8 @@ void LLFloaterPermsDefault::updateCap() LLSDSerialize::toPrettyXML(report, sent_perms_log); LL_CONT << sent_perms_log.str() << LL_ENDL; } - - LLHTTPClient::post(object_url, report, new LLFloaterPermsResponder()); + LLFloaterPermsRequester::init(object_url, report, MAX_HTTP_RETRIES); + LLFloaterPermsRequester::instance()->start(); } else { diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h index 2bb0a19dc1..d3b52c1fe5 100755 --- a/indra/newview/llfloaterperms.h +++ b/indra/newview/llfloaterperms.h @@ -29,6 +29,7 @@ #define LL_LLFLOATERPERMPREFS_H #include "llfloater.h" +#include "llhttpclient.h" class LLFloaterPerms : public LLFloater { @@ -89,4 +90,36 @@ private: bool mNextOwnerTransfer[CAT_LAST]; }; +class LLFloaterPermsRequester +{ +public: + LLFloaterPermsRequester(const std::string url, const LLSD report, int maxRetries); + + static void init(const std::string url, const LLSD report, int maxRetries); + static void finalize(); + static LLFloaterPermsRequester* instance(); + + void start(); + bool retry(); + +private: + int mRetriesCount; + int mMaxRetries; + const std::string mUrl; + const LLSD mReport; +public: + static LLFloaterPermsRequester* sPermsRequester; +}; + +class LLFloaterPermsResponder : public LLHTTPClient::Responder +{ +public: + LLFloaterPermsResponder() : LLHTTPClient::Responder() {} +private: + static std::string sPreviousReason; + + void httpFailure(); + void httpSuccess(); +}; + #endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ee4396758e..dac610eda1 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -49,6 +49,7 @@ //#include "llfirstuse.h" #include "llfloaterreg.h" #include "llfloaterabout.h" +#include "llfavoritesbar.h" #include "llfloaterhardwaresettings.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterimsession.h" @@ -1919,7 +1920,7 @@ BOOL LLPanelPreference::postBuild() } if (hasChild("favorites_on_login_check", TRUE)) { - getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); + getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&handleFavoritesOnLoginChanged, _1, _2)); bool show_favorites_at_login = LLPanelLogin::getShowFavorites(); getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setValue(show_favorites_at_login); } @@ -2004,11 +2005,15 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v } } -void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value) +void LLPanelPreference::handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value) { - if (checkbox && checkbox->getValue()) + if (checkbox) { - LLNotificationsUtil::add("FavoritesOnLogin"); + LLFavoritesOrderStorage::instance().showFavoritesOnLoginChanged(checkbox->getValue().asBoolean()); + if(checkbox->getValue()) + { + LLNotificationsUtil::add("FavoritesOnLogin"); + } } } @@ -2235,6 +2240,11 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key) void LLFloaterPreferenceProxy::onClose(bool app_quitting) { + if(app_quitting) + { + cancel(); + } + if (mSocksSettingsDirty) { @@ -2334,6 +2344,11 @@ void LLFloaterPreferenceProxy::onBtnCancel() cancel(); } +void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting) +{ + cancel(); +} + void LLFloaterPreferenceProxy::cancel() { @@ -2344,7 +2359,7 @@ void LLFloaterPreferenceProxy::cancel() LLSD ctrl_value = iter->second; control->set(ctrl_value); } - + mSocksSettingsDirty = false; closeFloater(); } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 7bf6ae7d79..04e5e37731 100755 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -229,7 +229,7 @@ private: //for "Only friends and groups can call or IM me" static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); //for "Show my Favorite Landmarks at Login" - static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value); + static void handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value); typedef std::map<std::string, LLColor4> string_color_map_t; string_color_map_t mSavedColors; @@ -269,6 +269,7 @@ protected: void saveSettings(); void onBtnOk(); void onBtnCancel(); + void onClickCloseBtn(bool app_quitting = false); void onChangeSocksSettings(); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 5e028e6d43..99a5cf8002 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -35,6 +35,7 @@ #include "llassetstorage.h" #include "llavatarnamecache.h" #include "llcachename.h" +#include "llcheckboxctrl.h" #include "llfontgl.h" #include "llimagej2c.h" #include "llinventory.h" @@ -107,14 +108,6 @@ LLFloaterReporter::LLFloaterReporter(const LLSD& key) { } -// static -void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg) -{ - if ( LLFloaterReg::instanceVisible("reporter") ) - { - LLNotificationsUtil::add("HelpReportAbuseEmailLL"); - }; -} // virtual BOOL LLFloaterReporter::postBuild() { @@ -145,19 +138,10 @@ BOOL LLFloaterReporter::postBuild() mOwnerName = LLStringUtil::null; getChild<LLUICtrl>("summary_edit")->setFocus(TRUE); + getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE); mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString(); - // send a message and ask for information about this region - - // result comes back in processRegionInfo(..) - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RequestRegionInfo"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - gAgent.sendReliableMessage(); - - // abuser name is selected from a list LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit"); le->setEnabled( false ); diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 5eb5c20665..d857528f10 100755 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -100,10 +100,7 @@ public: static void uploadDoneCallback(const LLUUID &uuid, void* user_data, S32 result, LLExtStat ext_status); static void addDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); static void setDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); - - // static - static void processRegionInfo(LLMessageSystem* msg); - + void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id); private: diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index b27a42cb8e..afec981d56 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -448,9 +448,9 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); floater->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" )); + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + && got_bytes + && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); // Update the width and height spinners based on the corresponding resolution combos. (?) switch(shot_type) @@ -600,7 +600,11 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view), TRUE); + LLSnapshotLivePreview* previewp = getPreviewView(view); + if(previewp) + { + previewp->updateSnapshot(TRUE, TRUE); + } updateControls(view); } } @@ -614,7 +618,11 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view), TRUE); + LLSnapshotLivePreview* previewp = getPreviewView(view); + if(previewp) + { + previewp->updateSnapshot(TRUE, TRUE); + } updateControls(view); } } @@ -655,14 +663,20 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); - if (!view || !check_box) + if (!view || !check_box || !previewp) { return; } gSavedSettings.setBOOL("UseFreezeFrame", check_box->get()); + if (check_box->get()) + { + previewp->prepareFreezeFrame(); + } + updateLayout(view); } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 7477b02867..6dbb202c9d 100755 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -92,6 +92,7 @@ // Globals LLFloaterTools *gFloaterTools = NULL; bool LLFloaterTools::sShowObjectCost = true; +bool LLFloaterTools::sPreviousFocusOnAvatar = false; const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] = { @@ -891,6 +892,12 @@ void LLFloaterTools::onClose(bool app_quitting) // prepare content for next call mPanelContents->clearContents(); + + if(sPreviousFocusOnAvatar) + { + sPreviousFocusOnAvatar = false; + gAgentCamera.setAllowChangeToFollow(TRUE); + } } void click_popup_info(void*) diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 189bae46c2..df481b8d4c 100755 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -201,11 +201,13 @@ private: std::map<std::string, std::string> mStatusText; + protected: LLSD mMediaSettings; public: static bool sShowObjectCost; + static bool sPreviousFocusOnAvatar; }; diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index c1c21c593e..ae33acb842 100755 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -141,6 +141,12 @@ BOOL LLFloaterTOS::postBuild() // Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer. // Store the URL separately and navigate here instead. web_browser->navigateTo( getString( "loading_url" ) ); + LLPluginClassMedia* media_plugin = web_browser->getMediaPlugin(); + if (media_plugin) + { + // All links from tos_html should be opened in external browser + media_plugin->setOverrideClickTarget("_external"); + } } return TRUE; diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 1b1c24b19a..ece3e10faa 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -284,12 +284,12 @@ BOOL LLFloaterWorldMap::postBuild() LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); avatar_combo->selectFirstItem(); avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) ); - avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); + avatar_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo); LLSearchEditor *location_editor = getChild<LLSearchEditor>("location"); location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); - location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this)); + location_editor->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this)); getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this)); mListSearchResults = childGetListInterface("search_results"); @@ -297,7 +297,7 @@ BOOL LLFloaterWorldMap::postBuild() LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo"); landmark_combo->selectFirstItem(); landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) ); - landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); + landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo); mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 3271a40ea0..e9f80b795a 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llfolderviewmodelinventory.h" #include "llinventorymodelbackgroundfetch.h" +#include "llinventoryfunctions.h" #include "llinventorypanel.h" #include "lltooldraganddrop.h" #include "llfavoritesbar.h" @@ -108,6 +109,29 @@ bool LLFolderViewModelInventory::contentsReady() return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); } +bool LLFolderViewModelInventory::isFolderComplete(LLFolderViewFolder* folder) +{ + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); + LLUUID cat_id = modelp->getUUID(); + if (cat_id.isNull()) + { + return false; + } + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (cat) + { + // don't need to check version - descendents_server == -1 if we have no data + S32 descendents_server = cat->getDescendentCount(); + S32 descendents_actual = cat->getViewerDescendentCount(); + if (descendents_server == descendents_actual + || (descendents_actual > 0 && descendents_server == -1)) // content was loaded in previous session + { + return true; + } + } + return false; +} + void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); @@ -277,7 +301,7 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate || (mFoldersByName && (a->getSortGroup() != SG_ITEM))); + bool by_name = ((!mByDate || (mFoldersByName && (a->getSortGroup() != SG_ITEM))) && !mFoldersByWeight); if (a->getSortGroup() != b->getSortGroup()) { @@ -309,6 +333,31 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, return (compare < 0); } } + else if (mFoldersByWeight) + { + S32 weight_a = compute_stock_count(a->getUUID()); + S32 weight_b = compute_stock_count(b->getUUID()); + if (weight_a == weight_b) + { + // Equal weight -> use alphabetical order + return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); + } + else if (weight_a == COMPUTE_STOCK_INFINITE) + { + // No stock -> move a at the end of the list + return false; + } + else if (weight_b == COMPUTE_STOCK_INFINITE) + { + // No stock -> move b at the end of the list + return true; + } + else + { + // Lighter is first (sorted in increasing order of weight) + return (weight_a < weight_b); + } + } else { time_t first_create = a->getCreationDate(); diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 8772185ad0..dea54cbe57 100755 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -89,6 +89,7 @@ public: mByDate = (mSortOrder & LLInventoryFilter::SO_DATE); mSystemToTop = (mSortOrder & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); mFoldersByName = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + mFoldersByWeight = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_WEIGHT); } bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; @@ -97,6 +98,7 @@ private: bool mByDate; bool mSystemToTop; bool mFoldersByName; + bool mFoldersByWeight; }; class LLFolderViewModelInventory @@ -113,6 +115,7 @@ public: void sort(LLFolderViewFolder* folder); bool contentsReady(); + bool isFolderComplete(LLFolderViewFolder* folder); bool startDrag(std::vector<LLFolderViewModelItem*>& items); private: diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 119872ec29..950a6cfaef 100755 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -59,10 +59,6 @@ // Longest time, in seconds, to wait for all animations to stop playing const F32 MAX_WAIT_ANIM_SECS = 30.f; -// If this gesture is a link, get the base gesture that this link points to, -// otherwise just return this id. -static const LLUUID& get_linked_uuid(const LLUUID& item_id); - // Lightweight constructor. // init() does the heavy lifting. LLGestureMgr::LLGestureMgr() @@ -253,7 +249,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, BOOL inform_server, BOOL deactivate_similar) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); if( !gAssetStorage ) { @@ -307,7 +303,7 @@ void notify_update_label(const LLUUID& base_item_id) void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) { @@ -353,7 +349,7 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id) { - const LLUUID& base_in_item_id = get_linked_uuid(in_item_id); + const LLUUID& base_in_item_id = gInventory.getLinkedItemID(in_item_id); uuid_vec_t gest_item_ids; // Deactivate all gestures that match @@ -440,7 +436,7 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); return (it != mActive.end()); } @@ -448,7 +444,7 @@ BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id) BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) return FALSE; @@ -471,7 +467,7 @@ BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture) void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) @@ -513,7 +509,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id); if (it == mActive.end()) @@ -608,7 +604,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture) // Convenience function that looks up the item_id for you. void LLGestureMgr::playGesture(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) return; @@ -1297,7 +1293,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) void LLGestureMgr::stopGesture(const LLUUID& item_id) { - const LLUUID& base_item_id = get_linked_uuid(item_id); + const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) return; @@ -1457,14 +1453,4 @@ void LLGestureMgr::done() } } -// static -const LLUUID& get_linked_uuid(const LLUUID &item_id) -{ - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (item && item->getIsLinkType()) - { - return item->getLinkedUUID(); - } - return item_id; -} diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 56e671d902..4d92fee04f 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -239,7 +239,8 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : mRoleMemberDataComplete(false), mGroupPropertiesDataComplete(false), mPendingRoleMemberRequest(false), - mAccessTime(0.0f) + mAccessTime(0.0f), + mPendingBanRequest(false) { mMemberVersion.generate(); } @@ -761,8 +762,69 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id) mBanList.erase(ban_id); } +void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid) +{ + if (!mMemberDataComplete || + !mRoleDataComplete || + !(mRoleMemberDataComplete && mMembers.size())) + { + LL_WARNS() << "No Role-Member data yet, setting ban request to pending." << LL_ENDL; + mPendingBanRequest = true; + mPendingBanMemberID = participant_uuid; + + if (!mMemberDataComplete) + { + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); + } + if (!mRoleDataComplete) + { + LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mID); + } + return; + } + + LLGroupMgrGroupData::member_list_t::iterator mi = mMembers.find((participant_uuid)); + if (mi == mMembers.end()) + { + if (!mPendingBanRequest) + { + mPendingBanRequest = true; + mPendingBanMemberID = participant_uuid; + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); // member isn't in members list, request reloading + } + else + { + mPendingBanRequest = false; + } + + return; + } + + mPendingBanRequest = false; + + LLGroupMemberData* member_data = (*mi).second; + if (member_data && member_data->isInRole(mOwnerRole)) + { + return; // can't ban group owner + } + + std::vector<LLUUID> ids; + ids.push_back(participant_uuid); + + LLGroupBanData ban_data; + createBanEntry(participant_uuid, ban_data); + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mID, LLGroupMgr::BAN_CREATE, ids); + LLGroupMgr::getInstance()->sendGroupMemberEjects(mID, ids); + LLGroupMgr::getInstance()->sendGroupMembersRequest(mID); + LLSD args; + std::string name; + gCacheName->getFullName(participant_uuid, name); + args["AVATAR_NAME"] = name; + args["GROUP_NAME"] = mName; + LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); +} // // LLGroupMgr @@ -1245,6 +1307,11 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data) group_datap->mChanged = TRUE; LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA); + + if (group_datap->mPendingBanRequest) + { + group_datap->banMemberById(group_datap->mPendingBanMemberID); + } } // static @@ -1970,7 +2037,8 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content) LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); if (!gdatap) return; - + + gdatap->clearBanList(); LLSD::map_const_iterator i = content["ban_list"].beginMap(); LLSD::map_const_iterator iEnd = content["ban_list"].endMap(); for(;i != iEnd; ++i) @@ -1992,8 +2060,6 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content) LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST); } - - // Responder class for capability group management class GroupMemberDataResponder : public LLHTTPClient::Responder { @@ -2082,11 +2148,6 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) return; } - // If we have no members, there's no reason to do anything else - S32 num_members = content["member_count"]; - if(num_members < 1) - return; - LLUUID group_id = content["group_id"].asUUID(); LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -2096,6 +2157,18 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) return; } + // If we have no members, there's no reason to do anything else + S32 num_members = content["member_count"]; + if (num_members < 1) + { + LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL; + // Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237 + group_datap->mMemberDataComplete = true; + group_datap->mChanged = TRUE; + LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); + return; + } + group_datap->mMemberCount = num_members; LLSD member_list = content["members"]; diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 2e94e8d9a0..5307c4de92 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -149,7 +149,7 @@ public: const uuid_vec_t& getRoleMembers() const { return mMemberIDs; } S32 getMembersInRole(uuid_vec_t members, BOOL needs_sort = TRUE); - S32 getTotalMembersInRole() { return mMemberIDs.size(); } + S32 getTotalMembersInRole() { return mMemberCount ? mMemberCount : mMemberIDs.size(); } //FIXME: Returns 0 for Everyone role when Member list isn't yet loaded, see MAINT-5225 LLRoleData getRoleData() const { return mRoleData; } void setRoleData(LLRoleData data) { mRoleData = data; } @@ -269,8 +269,8 @@ public: void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData()); void removeBanEntry(const LLUUID& ban_id); + void banMemberById(const LLUUID& participant_uuid); - public: typedef std::map<LLUUID,LLGroupMemberData*> member_list_t; typedef std::map<LLUUID,LLGroupRoleData*> role_list_t; @@ -302,6 +302,9 @@ public: S32 mMemberCount; S32 mRoleCount; + bool mPendingBanRequest; + LLUUID mPendingBanMemberID; + protected: void sendRoleChanges(); void cancelRoleChanges(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5d3a11e245..b8b6bdaa11 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1295,8 +1295,15 @@ void LLIMModel::sendMessage(const std::string& utf8_text, gAgent.sendReliableMessage(); } + bool is_group_chat = false; + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(im_session_id); + if(session) + { + is_group_chat = session->isGroupSessionType(); + } + // If there is a mute list and this is not a group chat... - if ( LLMuteList::getInstance() ) + if ( LLMuteList::getInstance() && !is_group_chat) { // ... the target should not be in our mute list for some message types. // Auto-remove them if present. @@ -1345,7 +1352,6 @@ void LLIMModel::sendMessage(const std::string& utf8_text, if (is_not_group_id) { - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(im_session_id); if( session == 0)//??? shouldn't really happen { LLRecentPeople::instance().add(other_participant_id); diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index d04378daaf..47560341e7 100755 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -47,6 +47,7 @@ public: /*virtual*/ void onOpen(const LLSD& notification_id); /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); + /*virtual*/ void removeChild(LLView* child); private: void onToastDestroy(LLToast * toast); @@ -98,7 +99,7 @@ void LLInspectToast::onOpen(const LLSD& notification_id) panel->setMouseOpaque(FALSE); if(mPanel != NULL && mPanel->getParent() == this) { - removeChild(mPanel); + LLInspect::removeChild(mPanel); } addChild(panel); panel->setFocus(TRUE); @@ -121,6 +122,16 @@ BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask) return LLFloater::handleToolTip(x, y, mask); } +// virtual +void LLInspectToast::removeChild(LLView* child) +{ + if (mPanel == child) + { + mPanel = NULL; + } + LLInspect::removeChild(child); +} + void LLInspectToast::onToastDestroy(LLToast * toast) { closeFloater(false); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a047ed6fee..c990eda074 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -40,6 +40,7 @@ #include "llfavoritesbar.h" // management of favorites folder #include "llfloateropenobject.h" #include "llfloaterreg.h" +#include "llfloatermarketplacelistings.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" #include "llfolderview.h" @@ -65,6 +66,7 @@ #include "llsidepanelappearance.h" #include "lltooldraganddrop.h" #include "lltrans.h" +#include "llurlaction.h" #include "llviewerassettype.h" #include "llviewerfoldertype.h" #include "llviewermenu.h" @@ -80,11 +82,6 @@ void copy_slurl_to_clipboard_callback_inv(const std::string& slurl); -// Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 -#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0 -#define BLOCK_WORN_ITEMS_IN_OUTBOX 1 - typedef std::pair<LLUUID, LLUUID> two_uuids_t; typedef std::list<two_uuids_t> two_uuids_list_t; @@ -124,7 +121,7 @@ bool isAddAction(const std::string& action) bool isRemoveAction(const std::string& action) { - return ("take_off" == action || "detach" == action || "deactivate" == action); + return ("take_off" == action || "detach" == action); } bool isMarketplaceCopyAction(const std::string& action) @@ -206,7 +203,6 @@ const std::string& LLInvFVBridge::getDisplayName() const { buildDisplayName(); } - return mDisplayName; } @@ -270,13 +266,49 @@ BOOL LLInvFVBridge::isLibraryItem() const /** * @brief Adds this item into clipboard storage */ -BOOL LLInvFVBridge::cutToClipboard() const +BOOL LLInvFVBridge::cutToClipboard() +{ + const LLInventoryObject* obj = gInventory.getObject(mUUID); + if (obj && isItemMovable() && isItemRemovable()) + { + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const BOOL cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id); + + if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) || + LLMarketplaceData::instance().isListedAndActive(mUUID))) + { + // Prompt the user if cutting from a marketplace active listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLInvFVBridge::callback_cutToClipboard, this, _1, _2)); + } + else + { + // Otherwise just perform the cut + return perform_cutToClipboard(); + } + } + return FALSE; +} + +// Callback for cutToClipboard if DAMA required... +BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + return perform_cutToClipboard(); + } + return FALSE; +} + +BOOL LLInvFVBridge::perform_cutToClipboard() { const LLInventoryObject* obj = gInventory.getObject(mUUID); if (obj && isItemMovable() && isItemRemovable()) { LLClipboard::instance().setCutMode(true); - return LLClipboard::instance().addToClipboard(mUUID); + BOOL added_to_clipboard = LLClipboard::instance().addToClipboard(mUUID); + removeObject(&gInventory, mUUID); // Always perform the remove even if the object couldn't make it to the clipboard + return added_to_clipboard; } return FALSE; } @@ -291,15 +323,22 @@ BOOL LLInvFVBridge::copyToClipboard() const return FALSE; } -// *TODO: make sure this does the right thing void LLInvFVBridge::showProperties() { - show_item_profile(mUUID); - - // Disable old properties floater; this is replaced by the sidepanel. - /* - LLFloaterReg::showInstance("properties", mUUID); - */ + if (isMarketplaceListingsFolder()) + { + LLFloaterReg::showInstance("item_properties", LLSD().with("id",mUUID),TRUE); + // Force it to show on top as this floater has a tendency to hide when confirmation dialog shows up + LLFloater* floater_properties = LLFloaterReg::findInstance("item_properties", LLSD().with("id",mUUID)); + if (floater_properties) + { + floater_properties->setVisibleAndFrontmost(); + } + } + else + { + show_item_profile(mUUID); + } } void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch) @@ -696,7 +735,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if (!isInboxFolder()) { items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) { disabled_items.push_back(std::string("Rename")); } @@ -734,15 +773,20 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Cut")); } - if (canListOnMarketplace()) + if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder()) { items.push_back(std::string("Marketplace Separator")); - items.push_back(std::string("Merchant Copy")); - if (!canListOnMarketplaceNow()) - { - disabled_items.push_back(std::string("Merchant Copy")); - } + if (gMenuHolder->getChild<LLView>("MarketplaceListings")->getVisible()) + { + items.push_back(std::string("Marketplace Copy")); + items.push_back(std::string("Marketplace Move")); + if (!canListOnMarketplaceNow()) + { + disabled_items.push_back(std::string("Marketplace Copy")); + disabled_items.push_back(std::string("Marketplace Move")); + } + } } } } @@ -863,15 +907,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, return; } - // "Remove link" and "Delete" are the same operation. - if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) - { - items.push_back(std::string("Remove Link")); - } - else - { - items.push_back(std::string("Delete")); - } + items.push_back(std::string("Delete")); if (!isItemRemovable()) { @@ -901,21 +937,130 @@ void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags, { disabled_items.push_back(std::string("Rename")); } - -#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU - if (isOutboxFolderDirectParent()) - { - items.push_back(std::string("Marketplace Separator")); - items.push_back(std::string("Marketplace Send")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Marketplace Send")); - } - } -#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU } +void LLInvFVBridge::addMarketplaceContextMenuOptions(U32 flags, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + S32 depth = depth_nesting_in_marketplace(mUUID); + if (depth == 1) + { + // Options available at the Listing Folder level + items.push_back(std::string("Marketplace Create Listing")); + items.push_back(std::string("Marketplace Associate Listing")); + items.push_back(std::string("Marketplace Check Listing")); + items.push_back(std::string("Marketplace List")); + items.push_back(std::string("Marketplace Unlist")); + if (LLMarketplaceData::instance().isUpdating(mUUID,depth) || ((flags & FIRST_SELECTED_ITEM) == 0)) + { + // During SLM update, disable all marketplace related options + // Also disable all if multiple selected items + disabled_items.push_back(std::string("Marketplace Create Listing")); + disabled_items.push_back(std::string("Marketplace Associate Listing")); + disabled_items.push_back(std::string("Marketplace Check Listing")); + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + } + else + { + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + items.push_back(std::string("Marketplace Get Listing")); + } + if (LLMarketplaceData::instance().isListed(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Create Listing")); + disabled_items.push_back(std::string("Marketplace Associate Listing")); + if (LLMarketplaceData::instance().getVersionFolder(mUUID).isNull()) + { + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + } + else + { + if (LLMarketplaceData::instance().getActivationState(mUUID)) + { + disabled_items.push_back(std::string("Marketplace List")); + } + else + { + disabled_items.push_back(std::string("Marketplace Unlist")); + } + } + } + else + { + disabled_items.push_back(std::string("Marketplace List")); + disabled_items.push_back(std::string("Marketplace Unlist")); + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + disabled_items.push_back(std::string("Marketplace Get Listing")); + } + } + } + } + if (depth == 2) + { + // Options available at the Version Folder levels and only for folders + LLInventoryCategory* cat = gInventory.getCategory(mUUID); + if (cat && LLMarketplaceData::instance().isListed(cat->getParentUUID())) + { + items.push_back(std::string("Marketplace Activate")); + items.push_back(std::string("Marketplace Deactivate")); + if (LLMarketplaceData::instance().isUpdating(mUUID,depth) || ((flags & FIRST_SELECTED_ITEM) == 0)) + { + // During SLM update, disable all marketplace related options + // Also disable all if multiple selected items + disabled_items.push_back(std::string("Marketplace Activate")); + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + else + { + if (LLMarketplaceData::instance().isVersionFolder(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Activate")); + if (LLMarketplaceData::instance().getActivationState(mUUID)) + { + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + } + else + { + disabled_items.push_back(std::string("Marketplace Deactivate")); + } + } + } + } + + items.push_back(std::string("Marketplace Edit Listing")); + LLUUID listing_folder_id = nested_parent_id(mUUID,depth); + LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(listing_folder_id); + + if (depth >= 2) + { + // Prevent creation of new folders if the max count has been reached on this version folder (active or not) + LLUUID local_version_folder_id = nested_parent_id(mUUID,depth-1); + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(local_version_folder_id, categories, items, FALSE); + if (categories.size() >= gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + disabled_items.push_back(std::string("New Folder")); + } + } + + // Options available at all levels on items and categories + if (!LLMarketplaceData::instance().isListed(listing_folder_id) || version_folder_id.isNull()) + { + disabled_items.push_back(std::string("Marketplace Edit Listing")); + } + + // Separator + items.push_back(std::string("Marketplace Listings Separator")); +} + + // *TODO: remove this BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const { @@ -1018,6 +1163,7 @@ BOOL LLInvFVBridge::isCOFFolder() const return LLAppearanceMgr::instance().getIsInCOF(mUUID); } +// *TODO : Suppress isInboxFolder() once Merchant Outbox is fully deprecated BOOL LLInvFVBridge::isInboxFolder() const { const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false); @@ -1030,6 +1176,18 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } +BOOL LLInvFVBridge::isMarketplaceListingsFolder() const +{ + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + + if (folder_id.isNull()) + { + return FALSE; + } + + return gInventory.isObjectDescendentOf(mUUID, folder_id); +} + BOOL LLInvFVBridge::isOutboxFolder() const { const LLUUID outbox_id = getOutboxFolder(); @@ -1191,11 +1349,18 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) { - // Create a link folder handler instead. + // Create a link folder handler instead new_listener = new LLLinkFolderBridge(inventory, root, uuid); - break; } - new_listener = new LLFolderBridge(inventory, root, uuid); + else if (actual_asset_type == LLAssetType::AT_MARKETPLACE_FOLDER) + { + // Create a marketplace folder handler + new_listener = new LLMarketplaceFolderBridge(inventory, root, uuid); + } + else + { + new_listener = new LLFolderBridge(inventory, root, uuid); + } break; case LLAssetType::AT_LINK: case LLAssetType::AT_LINK_FOLDER: @@ -1238,6 +1403,22 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } +void LLInvFVBridge::removeObject(LLInventoryModel *model, const LLUUID &uuid) +{ + // Keep track of the parent + LLInventoryItem* itemp = model->getItem(uuid); + LLUUID parent_id = (itemp ? itemp->getParentUUID() : LLUUID::null); + // Remove the object + model->removeObject(uuid); + // Get the parent updated + if (parent_id.notNull()) + { + LLViewerInventoryCategory* parent_cat = model->getCategory(parent_id); + model->updateCategory(parent_cat); + model->notifyObservers(); + } +} + bool LLInvFVBridge::canShare() const { bool can_share = false; @@ -1268,11 +1449,9 @@ bool LLInvFVBridge::canShare() const bool LLInvFVBridge::canListOnMarketplace() const { -#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - LLInventoryModel * model = getInventoryModel(); - const LLViewerInventoryCategory * cat = model->getCategory(mUUID); + LLViewerInventoryCategory * cat = model->getCategory(mUUID); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { return false; @@ -1283,16 +1462,6 @@ bool LLInvFVBridge::canListOnMarketplace() const return false; } - if (getOutboxFolder().isNull()) - { - return false; - } - - if (isInboxFolder() || isOutboxFolder()) - { - return false; - } - LLViewerInventoryItem * item = model->getItem(mUUID); if (item) { @@ -1308,16 +1477,11 @@ bool LLInvFVBridge::canListOnMarketplace() const } return true; - -#else - return false; -#endif } -bool LLInvFVBridge::canListOnMarketplaceNow() const +// *TODO : Suppress canListOnOutboxNow() once we deprecate Merchant Outbox completely +bool LLInvFVBridge::canListOnOutboxNow() const { -#if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - bool can_list = true; // Do not allow listing while import is in progress @@ -1363,10 +1527,56 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const } return can_list; +} -#else - return false; -#endif +bool LLInvFVBridge::canListOnMarketplaceNow() const +{ + bool can_list = true; + + const LLInventoryObject* obj = getInventoryObject(); + can_list &= (obj != NULL); + + if (can_list) + { + const LLUUID& object_id = obj->getLinkedUUID(); + can_list = object_id.notNull(); + + if (can_list) + { + LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL; + if (object_folderp) + { + can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading(); + } + } + + if (can_list) + { + std::string error_msg; + LLInventoryModel* model = getInventoryModel(); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplacelistings_id.notNull()) + { + LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id); + LLInventoryCategory *cat = model->getCategory(mUUID); + if (cat) + { + can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg); + } + else + { + LLInventoryItem *item = model->getItem(mUUID); + can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false); + } + } + else + { + can_list = false; + } + } + } + + return can_list; } LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const @@ -1458,7 +1668,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - gInventory.removeObject(mUUID); return; } else if ("copy" == action) @@ -1489,16 +1698,14 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard(); return; } - else if (isMarketplaceCopyAction(action)) + else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action)) { - LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL; - LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId()); - } + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + // Note: For a single item, if it's not a copy, then it's a move + move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action)); + } else if ("copy_slurl" == action) { LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem()); @@ -1518,6 +1725,11 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) { doActionOnCurSelectedLandmark(boost::bind(&LLItemBridge::doShowOnMap, this, _1)); } + else if ("marketplace_edit_listing" == action) + { + std::string url = LLMarketplaceData::instance().getListingURL(mUUID); + LLUrlAction::openURL(url); + } } void LLItemBridge::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) @@ -1572,7 +1784,9 @@ void LLItemBridge::restoreItem() if(item) { LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); + bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); + + const LLUUID new_parent = model->findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); // do not restamp on restore. LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); } @@ -1983,6 +2197,22 @@ void LLFolderBridge::buildDisplayName() const } } +std::string LLFolderBridge::getLabelSuffix() const +{ + static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); + + if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()) + { + return llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()); + } + + return LLInvFVBridge::getLabelSuffix(); +} + +LLFontGL::StyleFlags LLFolderBridge::getLabelStyle() const +{ + return LLFontGL::NORMAL; +} void LLFolderBridge::update() { @@ -2039,6 +2269,11 @@ BOOL LLFolderBridge::isItemRemovable() const return FALSE; } } + + if (isMarketplaceListingsFolder() && LLMarketplaceData::instance().getActivationState(mUUID)) + { + return FALSE; + } return TRUE; } @@ -2174,88 +2409,12 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const } -static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg) -{ - // Collapse links directly to items/folders - LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; - LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); - if (linked_item != NULL) - { - inv_item = linked_item; - } - - bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); - if (!allow_transfer) - { - tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); - return false; - } - -#if BLOCK_WORN_ITEMS_IN_OUTBOX - bool worn = get_is_item_worn(inv_item->getUUID()); - if (worn) - { - tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); - return false; - } -#endif - - bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType()); - if (calling_card) - { - tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard"); - return false; - } - - return true; -} - - -int get_folder_levels(LLInventoryCategory* inv_cat) -{ - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); - - int max_child_levels = 0; - - for (S32 i=0; i < cats->size(); ++i) - { - LLInventoryCategory* category = cats->at(i); - max_child_levels = llmax(max_child_levels, get_folder_levels(category)); - } - - return 1 + max_child_levels; -} - -int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id) -{ - int depth = 0; - - if (ancestor_id == descendant_id) return depth; - - const LLInventoryCategory* category = gInventory.getCategory(descendant_id); - - while(category) - { - LLUUID parent_id = category->getParentUUID(); - - if (parent_id.isNull()) break; - - depth++; - - if (parent_id == ancestor_id) return depth; - - category = gInventory.getCategory(parent_id); - } - - LL_WARNS() << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL; - return -1; -} BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, BOOL drop, - std::string& tooltip_msg) + std::string& tooltip_msg, + BOOL is_link, + BOOL user_confirm) { LLInventoryModel* model = getInventoryModel(); @@ -2274,10 +2433,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id); // check to make sure source is agent inventory, and is represented there. LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); @@ -2297,6 +2460,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_current_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_CURRENT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); //-------------------------------------------------------------------------------- @@ -2305,6 +2469,18 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, BOOL is_movable = TRUE; + if (is_movable && (marketplacelistings_id == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotMoveRoot"); + } + if (is_movable && move_is_from_marketplacelistings && LLMarketplaceData::instance().getActivationState(cat_id)) + { + // If the incoming folder is listed and active (and is therefore either the listing or the version folder), + // then moving is *not* allowed + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxDragActive"); + } if (is_movable && (mUUID == cat_id)) { is_movable = FALSE; @@ -2322,14 +2498,30 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } if (is_movable && move_is_into_outfit) { + if((mUUID == my_outifts_id) || (getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE)) + { + is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)); + } + else + { + is_movable = false; + } + } + if(is_movable && move_is_into_current_outfit && is_link) + { is_movable = FALSE; - // tooltip? } if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE))) { is_movable = FALSE; // tooltip? } + if (is_movable && (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)) + { + // One cannot move a folder into a stock folder + is_movable = FALSE; + // tooltip? + } LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; @@ -2397,93 +2589,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - if (is_movable && move_is_into_outbox) + + if (is_movable && (move_is_into_outbox || move_is_into_marketplacelistings)) { - const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); - - if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth")) - { - tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); - is_movable = FALSE; - } - else - { - int dragged_folder_count = descendent_categories.size(); - int existing_item_count = 0; - int existing_folder_count = 0; - - const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); - - if (master_folder != NULL) - { - if (model->isObjectDescendentOf(cat_id, master_folder->getUUID())) - { - // Don't use count because we're already inside the same category anyway - dragged_folder_count = 0; - } - else - { - existing_folder_count = 1; // Include the master folder in the count! - - // If we're in the drop operation as opposed to the drag without drop, we are doing a - // single category at a time so don't block based on the total amount of cargo data items - if (drop) - { - dragged_folder_count += 1; - } - else - { - // NOTE: The cargo id's count is a total of categories AND items but we err on the side of - // prevention rather than letting too many folders into the hierarchy of the outbox, - // when we're dragging the item to a new parent - dragged_folder_count += LLToolDragAndDrop::instance().getCargoCount(); - } - } - - // Tally the total number of categories and items inside the master folder - - LLInventoryModel::cat_array_t existing_categories; - LLInventoryModel::item_array_t existing_items; - - model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); - - existing_folder_count += existing_categories.size(); - existing_item_count += existing_items.size(); - } - else - { - // Assume a single category is being dragged to the outbox since we evaluate one at a time - // when not putting them under a parent item. - dragged_folder_count += 1; - } - - const int nested_folder_count = existing_folder_count + dragged_folder_count; - const int nested_item_count = existing_item_count + descendent_items.size(); - - if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) - { - tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders"); - is_movable = FALSE; - } - else if (nested_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) - { - tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); - is_movable = FALSE; - } - - if (is_movable == TRUE) - { - for (S32 i=0; i < descendent_items.size(); ++i) - { - LLInventoryItem* item = descendent_items[i]; - if (!can_move_to_outbox(item, tooltip_msg)) - { - is_movable = FALSE; - break; - } - } - } - } + const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID)); + LLViewerInventoryCategory * dest_folder = getCategory(); + S32 bundle_size = (drop ? 1 : LLToolDragAndDrop::instance().getCargoCount()); + is_movable = can_move_folder_to_marketplace(master_folder, dest_folder, inv_cat, tooltip_msg, bundle_size); } if (is_movable) @@ -2526,6 +2638,48 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (accept && drop) { + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) + { + if (move_is_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(cat_id) || + LLMarketplaceData::instance().isListedAndActive(cat_id))) + { + if (LLMarketplaceData::instance().isListed(cat_id) || LLMarketplaceData::instance().isVersionFolder(cat_id)) + { + // Move the active version folder or listing folder itself outside marketplace listings will unlist the listing so ask that question specifically + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + } + else + { + // Any other case will simply modify but not unlist an active listed listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + } + return true; + } + if (move_is_from_marketplacelistings && LLMarketplaceData::instance().isVersionFolder(cat_id)) + { + // Moving the version folder from its location will deactivate it. Ask confirmation. + LLNotificationsUtil::add("ConfirmMerchantClearVersion", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; + } + if (move_is_into_marketplacelistings && LLMarketplaceData::instance().isInActiveFolder(mUUID)) + { + // Moving something in an active listed listing will modify it. Ask confirmation. + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; + } + if (move_is_from_marketplacelistings && LLMarketplaceData::instance().isListed(cat_id)) + { + // Moving a whole listing folder will result in archival of SLM data. Ask confirmation. + LLNotificationsUtil::add("ConfirmListingCutOrDelete", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; + } + if (move_is_into_marketplacelistings && !move_is_from_marketplacelistings) + { + LLNotificationsUtil::add("ConfirmMerchantMoveInventory", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropCategoryIntoFolder, this, _1, _2, inv_cat)); + return true; + } + } // Look for any gestures and deactivate them if (move_is_into_trash) { @@ -2539,9 +2693,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } + // if target is current outfit folder we use link if (move_is_into_current_outfit && - inv_cat->getPreferredType() == LLFolderType::FT_NONE) + (inv_cat->getPreferredType() == LLFolderType::FT_NONE || + inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)) { // traverse category and add all contents to currently worn. BOOL append = true; @@ -2551,6 +2707,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId()); } + else if (move_is_into_marketplacelistings) + { + move_folder_to_marketplacelistings(inv_cat, mUUID); + } else { if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false))) @@ -2566,11 +2726,38 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, mUUID, move_is_into_trash); } + if (move_is_from_marketplacelistings) + { + // If we are moving a folder at the listing folder level (i.e. its parent is the marketplace listings folder) + if (from_folder_uuid == marketplacelistings_id) + { + // Clear the folder from the marketplace in case it is a listing folder + if (LLMarketplaceData::instance().isListed(cat_id)) + { + LLMarketplaceData::instance().clearListing(cat_id); + } + } + else + { + // If we move from within an active (listed) listing, checks that it's still valid, if not, unlist + LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + if (!validate_marketplacelistings(cat,NULL)) + { + LLMarketplaceData::instance().activateListing(version_folder_id,false); + } + } + // In all cases, update the listing we moved from so suffix are updated + update_marketplace_category(from_folder_uuid); + } + } } } else if (LLToolDragAndDrop::SOURCE_WORLD == source) { - if (move_is_into_outbox) + if (move_is_into_outbox || move_is_into_marketplacelistings) { tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); accept = FALSE; @@ -2582,7 +2769,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) { - if (move_is_into_outbox) + if (move_is_into_outbox || move_is_into_marketplacelistings) { tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); accept = FALSE; @@ -2952,7 +3139,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - gInventory.removeObject(mUUID); return; } else if ("copy" == action) @@ -2980,33 +3166,151 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) restoreItem(); return; } + else if ("marketplace_list" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 1) + { + LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(mUUID); + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + mMessage = ""; + if (!validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3))) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + else + { + LLMarketplaceData::instance().activateListing(mUUID,true); + } + } + return; + } + else if ("marketplace_activate" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 2) + { + LLInventoryCategory* category = gInventory.getCategory(mUUID); + mMessage = ""; + if (!validate_marketplacelistings(category,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false,2)) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantFolderActivationFailed", subs); + } + else + { + LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID); + } + } + return; + } + else if ("marketplace_unlist" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 1) + { + LLMarketplaceData::instance().activateListing(mUUID,false,1); + } + return; + } + else if ("marketplace_deactivate" == action) + { + if (depth_nesting_in_marketplace(mUUID) == 2) + { + LLInventoryCategory* category = gInventory.getCategory(mUUID); + LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), LLUUID::null, 1); + } + return; + } + else if ("marketplace_create_listing" == action) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(mUUID); + mMessage = ""; + bool validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false); + if (!validates) + { + mMessage = ""; + validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),true); + if (validates) + { + LLNotificationsUtil::add("MerchantForceValidateListing"); + } + } + + if (!validates) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + else + { + LLMarketplaceData::instance().createListing(mUUID); + } + return; + } + else if ("marketplace_disassociate_listing" == action) + { + LLMarketplaceData::instance().clearListing(mUUID); + return; + } + else if ("marketplace_get_listing" == action) + { + // This is used only to exercise the SLM API but won't be shown to end users + LLMarketplaceData::instance().getListing(mUUID); + return; + } + else if ("marketplace_associate_listing" == action) + { + LLFloaterAssociateListing::show(mUUID); + return; + } + else if ("marketplace_check_listing" == action) + { + LLSD data(mUUID); + LLFloaterReg::showInstance("marketplace_validation", data); + return; + } + else if ("marketplace_edit_listing" == action) + { + std::string url = LLMarketplaceData::instance().getListingURL(mUUID); + if (!url.empty()) + { + LLUrlAction::openURL(url); + } + return; + } #ifndef LL_RELEASE_FOR_DOWNLOAD else if ("delete_system_folder" == action) { removeSystemFolder(); } #endif - else if (isMarketplaceCopyAction(action)) + else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action)) { - LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL; - LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); + } +} - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId()); - } -#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU - else if (isMarketplaceSendAction(action)) - { - LL_INFOS() << "Send to marketplace action!" << LL_ENDL; - - LLInventoryCategory * cat = gInventory.getCategory(mUUID); - if (!cat) return; - - send_to_marketplace(cat); - } -#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU +void LLFolderBridge::gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level) +{ + if (log_level >= LLError::LEVEL_ERROR) + { + if (!mMessage.empty()) + { + // Currently, we do not gather all messages as it creates very long alerts + // Users can get to the whole list of errors on a listing using the "Check for Errors" audit button or "Check listing" right click menu + //mMessage += "\n"; + return; + } + // Take the leading spaces out... + std::string::size_type start = message.find_first_not_of(" "); + // Append the message + mMessage += message.substr(start, message.length() - start); + } } void LLFolderBridge::openItem() @@ -3076,25 +3380,24 @@ LLFolderType::EType LLFolderBridge::getPreferredType() const // Icons for folders are based on the preferred type LLUIImagePtr LLFolderBridge::getIcon() const { - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - return getIcon(preferred_type); + return getFolderIcon(FALSE); } -// static -LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) +LLUIImagePtr LLFolderBridge::getIconOpen() const { - return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); + return getFolderIcon(TRUE); } -LLUIImagePtr LLFolderBridge::getIconOpen() const +LLUIImagePtr LLFolderBridge::getFolderIcon(BOOL is_open) const { - return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); + LLFolderType::EType preferred_type = getPreferredType(); + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, is_open)); +} +// static : use by LLLinkFolderBridge to get the closed type icons +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) +{ + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); } LLUIImagePtr LLFolderBridge::getIconOverlay() const @@ -3106,14 +3409,6 @@ LLUIImagePtr LLFolderBridge::getIconOverlay() const return NULL; } -std::string LLFolderBridge::getLabelSuffix() const -{ - static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); - return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay() - ? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()) - : LLStringUtil::null; -} - BOOL LLFolderBridge::renameItem(const std::string& new_name) { @@ -3197,10 +3492,42 @@ void LLFolderBridge::updateHierarchyCreationDate(time_t date) void LLFolderBridge::pasteFromClipboard() { LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) + if (model && isClipboardPasteable()) { - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const BOOL paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + + if (paste_into_marketplacelistings && !LLMarketplaceData::instance().isListed(mUUID) && LLMarketplaceData::instance().isInActiveFolder(mUUID)) + { + // Prompt the user if pasting in a marketplace active version listing (note that pasting right under the listing folder root doesn't need a prompt) + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_pasteFromClipboard, this, _1, _2)); + } + else + { + // Otherwise just do the paste + perform_pasteFromClipboard(); + } + } +} + +// Callback for pasteFromClipboard if DAMA required... +void LLFolderBridge::callback_pasteFromClipboard(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + perform_pasteFromClipboard(); + } +} + +void LLFolderBridge::perform_pasteFromClipboard() +{ + LLInventoryModel* model = getInventoryModel(); + if (model && isClipboardPasteable()) + { + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); @@ -3208,58 +3535,70 @@ void LLFolderBridge::pasteFromClipboard() const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); const BOOL move_is_into_favorites = (mUUID == favorites_id); std::vector<LLUUID> objects; LLClipboard::instance().pasteFromClipboard(objects); - - if (move_is_into_outbox) - { - LLFolderViewItem * outbox_itemp = mInventoryPanel.get()->getItemByID(mUUID); - - if (outbox_itemp) - { - LLToolDragAndDrop::instance().setCargoCount(objects.size()); - - BOOL can_list = TRUE; - - for (std::vector<LLUUID>::const_iterator iter = objects.begin(); - (iter != objects.end()) && (can_list == TRUE); - ++iter) - { - const LLUUID& item_id = (*iter); - LLInventoryItem *item = model->getItem(item_id); - - if (item) - { - MASK mask = 0x0; - BOOL drop = FALSE; - EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType()); - void * cargo_data = (void *) item; - std::string tooltip_msg; - - can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); - } - } - - LLToolDragAndDrop::instance().resetCargoCount(); - - if (can_list == FALSE) - { - // Notify user of failure somehow -- play error sound? modal dialog? - return; - } + + LLViewerInventoryCategory * dest_folder = getCategory(); + if (move_is_into_outbox || move_is_into_marketplacelistings) + { + std::string error_msg; + const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID)); + int index = 0; + for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + LLInventoryCategory *cat = model->getCategory(item_id); + + if (item && !can_move_item_to_marketplace(master_folder, dest_folder, item, error_msg, objects.size() - index, true)) + { + break; + } + if (cat && !can_move_folder_to_marketplace(master_folder, dest_folder, cat, error_msg, objects.size() - index, true, true)) + { + break; + } + ++index; } + if (!error_msg.empty()) + { + LLSD subs; + subs["[ERROR_CODE]"] = error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return; + } } - + else + { + // Check that all items can be moved into that folder : for the moment, only stock folder mismatch is checked + for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + LLInventoryCategory *cat = model->getCategory(item_id); + + if ((item && !dest_folder->acceptItem(item)) || (cat && (dest_folder->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK))) + { + std::string error_msg = LLTrans::getString("TooltipOutboxMixedStock"); + LLSD subs; + subs["[ERROR_CODE]"] = error_msg; + LLNotificationsUtil::add("StockPasteFailed", subs); + return; + } + } + } + const LLUUID parent_id(mUUID); - + for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { const LLUUID& item_id = (*iter); - + LLInventoryItem *item = model->getItem(item_id); LLInventoryObject *obj = model->getObject(item_id); if (obj) @@ -3287,21 +3626,44 @@ void LLFolderBridge::pasteFromClipboard() LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); llassert(vicat); if (vicat) - { - //changeCategoryParent() implicity calls dirtyFilter - changeCategoryParent(model, vicat, parent_id, FALSE); + { + // Clear the cut folder from the marketplace if it is a listing folder + if (LLMarketplaceData::instance().isListed(item_id)) + { + LLMarketplaceData::instance().clearListing(item_id); + } + if (move_is_into_marketplacelistings) + { + move_folder_to_marketplacelistings(vicat, parent_id); + } + else + { + //changeCategoryParent() implicity calls dirtyFilter + changeCategoryParent(model, vicat, parent_id, FALSE); + } } } else - { - LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); - llassert(viitem); - if (viitem) - { - //changeItemParent() implicity calls dirtyFilter - changeItemParent(model, viitem, parent_id, FALSE); - } - } + { + LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); + llassert(viitem); + if (viitem) + { + if (move_is_into_marketplacelistings) + { + if (!move_item_to_marketplacelistings(viitem, parent_id)) + { + // Stop pasting into the marketplace as soon as we get an error + break; + } + } + else + { + //changeItemParent() implicity calls dirtyFilter + changeItemParent(model, viitem, parent_id, FALSE); + } + } + } } else { @@ -3312,22 +3674,45 @@ void LLFolderBridge::pasteFromClipboard() llassert(vicat); if (vicat) { - copy_inventory_category(model, vicat, parent_id); + if (move_is_into_marketplacelistings) + { + move_folder_to_marketplacelistings(vicat, parent_id, true); + } + else + { + copy_inventory_category(model, vicat, parent_id); + } } } - else - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - } - } - } + else + { + LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); + llassert(viitem); + if (viitem) + { + if (move_is_into_marketplacelistings) + { + if (!move_item_to_marketplacelistings(viitem, parent_id, true)) + { + // Stop pasting into the marketplace as soon as we get an error + break; + } + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + } + } + } + } + } + } // Change mode to paste for next paste LLClipboard::instance().setCutMode(false); } @@ -3340,14 +3725,16 @@ void LLFolderBridge::pasteLinkFromClipboard() { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); - if (move_is_into_outbox) + if (move_is_into_outbox || move_is_into_marketplacelistings) { // Notify user of failure somehow -- play error sound? modal dialog? return; @@ -3407,9 +3794,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items LLInventoryModel* model = getInventoryModel(); llassert(model != NULL); - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - const LLUUID favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); if (lost_and_found_id == mUUID) { @@ -3427,6 +3815,35 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { disabled_items.push_back(std::string("New Folder")); } + if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + if (LLMarketplaceData::instance().isUpdating(mUUID)) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("Rename")); + disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("Copy")); + disabled_items.push_back(std::string("Paste")); + disabled_items.push_back(std::string("Delete")); + } + } + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("New Script")); + disabled_items.push_back(std::string("New Note")); + disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Clothes")); + disabled_items.push_back(std::string("New Body Parts")); + } + if (marketplace_listings_id == mUUID) + { + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("Rename")); + disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("Delete")); + } if(trash_id == mUUID) { // This is the trash. @@ -3456,12 +3873,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { items.push_back(std::string("New Folder")); } - - items.push_back(std::string("New Script")); - items.push_back(std::string("New Note")); - items.push_back(std::string("New Gesture")); - items.push_back(std::string("New Clothes")); - items.push_back(std::string("New Body Parts")); + if (!isMarketplaceListingsFolder()) + { + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); + } } getClipboardEntries(false, items, disabled_items, flags); } @@ -3495,9 +3914,9 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items LLIsType is_object( LLAssetType::AT_OBJECT ); LLIsType is_gesture( LLAssetType::AT_GESTURE ); - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) + if (checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) { mWearables=TRUE; } @@ -3509,7 +3928,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("Delete System Folder")); } - if (!isOutboxFolder()) + if (!isOutboxFolder() && !isMarketplaceListingsFolder()) { items.push_back(std::string("Share")); if (!canShare()) @@ -3519,7 +3938,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items } // Add menu items that are dependent on the contents of the folder. LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); - if (category) + if (category && (marketplace_listings_id != mUUID)) { uuid_vec_t folders; folders.push_back(category->getUUID()); @@ -3538,8 +3957,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { // it's all on its way - add an observer, and the inventory will call done for us when everything is here. gInventory.addObserver(fetch); - } -} + } + } } void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) @@ -3556,6 +3975,12 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& if (isItemInTrash()) return; if (!isAgentInventory()) return; if (isOutboxFolder()) return; + + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + if (isMarketplaceListingsFolder()) return; LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); @@ -3575,11 +4000,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& } } - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type)) { @@ -3701,7 +4121,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); if (linked_category) { - accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg); + accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg, TRUE); } } else @@ -3868,6 +4288,121 @@ void LLFolderBridge::modifyOutfit(BOOL append) LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append ); } +// +=================================================+ +// | LLMarketplaceFolderBridge | +// +=================================================+ + +// LLMarketplaceFolderBridge is a specialized LLFolderBridge for use in Marketplace Inventory panels +LLMarketplaceFolderBridge::LLMarketplaceFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid) : +LLFolderBridge(inventory, root, uuid) +{ + m_depth = depth_nesting_in_marketplace(mUUID); + m_stockCountCache = COMPUTE_STOCK_NOT_EVALUATED; +} + +LLUIImagePtr LLMarketplaceFolderBridge::getIcon() const +{ + return getMarketplaceFolderIcon(FALSE); +} + +LLUIImagePtr LLMarketplaceFolderBridge::getIconOpen() const +{ + return getMarketplaceFolderIcon(TRUE); +} + +LLUIImagePtr LLMarketplaceFolderBridge::getMarketplaceFolderIcon(BOOL is_open) const +{ + LLFolderType::EType preferred_type = getPreferredType(); + if (!LLMarketplaceData::instance().isUpdating(getUUID())) + { + // Skip computation (expensive) if we're waiting for updates. Use the old value in that case. + m_depth = depth_nesting_in_marketplace(mUUID); + } + if ((preferred_type == LLFolderType::FT_NONE) && (m_depth == 2)) + { + // We override the type when in the marketplace listings folder and only for version folder + preferred_type = LLFolderType::FT_MARKETPLACE_VERSION; + } + return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, is_open)); +} + +std::string LLMarketplaceFolderBridge::getLabelSuffix() const +{ + static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); + + if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()) + { + return llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()); + } + + std::string suffix = ""; + // Listing folder case + if (LLMarketplaceData::instance().isListed(getUUID())) + { + suffix = llformat("%d",LLMarketplaceData::instance().getListingID(getUUID())); + if (suffix.empty()) + { + suffix = LLTrans::getString("MarketplaceNoID"); + } + suffix = " (" + suffix + ")"; + if (LLMarketplaceData::instance().getActivationState(getUUID())) + { + suffix += " (" + LLTrans::getString("MarketplaceLive") + ")"; + } + } + // Version folder case + else if (LLMarketplaceData::instance().isVersionFolder(getUUID())) + { + suffix += " (" + LLTrans::getString("MarketplaceActive") + ")"; + } + // Add stock amount + bool updating = LLMarketplaceData::instance().isUpdating(getUUID()); + if (!updating) + { + // Skip computation (expensive) if we're waiting for update anyway. Use the old value in that case. + m_stockCountCache = compute_stock_count(getUUID()); + } + if (m_stockCountCache == 0) + { + suffix += " (" + LLTrans::getString("MarketplaceNoStock") + ")"; + } + else if (m_stockCountCache != COMPUTE_STOCK_INFINITE) + { + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + suffix += " (" + LLTrans::getString("MarketplaceStock"); + } + else + { + suffix += " (" + LLTrans::getString("MarketplaceMax"); + } + if (m_stockCountCache == COMPUTE_STOCK_NOT_EVALUATED) + { + suffix += "=" + LLTrans::getString("MarketplaceUpdating") + ")"; + } + else + { + suffix += "=" + llformat("%d", m_stockCountCache) + ")"; + } + } + // Add updating suffix + if (updating) + { + suffix += " (" + LLTrans::getString("MarketplaceUpdating") + ")"; + } + return LLInvFVBridge::getLabelSuffix() + suffix; +} + +LLFontGL::StyleFlags LLMarketplaceFolderBridge::getLabelStyle() const +{ + return (LLMarketplaceData::instance().getActivationState(getUUID()) ? LLFontGL::BOLD : LLFontGL::NORMAL); +} + + + + // helper stuff bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) { @@ -3988,12 +4523,35 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c } } +// Callback for drop item if DAMA required... +void LLFolderBridge::callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + std::string tooltip_msg; + dragItemIntoFolder(inv_item, TRUE, tooltip_msg, FALSE); + } +} + +// Callback for drop category if DAMA required... +void LLFolderBridge::callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + std::string tooltip_msg; + dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE, FALSE); + } +} + // This is used both for testing whether an item can be dropped // into the folder, as well as performing the actual drop, depending // if drop == TRUE. BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, - std::string& tooltip_msg) + std::string& tooltip_msg, + BOOL user_confirm) { LLInventoryModel* model = getInventoryModel(); @@ -4011,7 +4569,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID from_folder_uuid = inv_item->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_favorites = (mUUID == favorites_id); @@ -4020,6 +4580,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; @@ -4073,59 +4635,45 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, //-------------------------------------------------------------------------------- // Determine if item can be moved & dropped - // + // Note: if user_confirm is false, we already went through those accept logic test and can skip them accept = TRUE; - if (!is_movable) + if (user_confirm && !is_movable) { accept = FALSE; } - else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + else if (user_confirm && (mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) { accept = FALSE; } - else if (move_is_into_current_outfit || move_is_into_outfit) + else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit)) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_favorites || move_is_into_landmarks) + else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks)) { accept = can_move_to_landmarks(inv_item); } - else if (move_is_into_outbox) + else if (user_confirm && (move_is_into_outbox || move_is_into_marketplacelistings)) { - accept = can_move_to_outbox(inv_item, tooltip_msg); - - if (accept) - { - const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); - - int existing_item_count = LLToolDragAndDrop::instance().getCargoCount(); - - if (master_folder != NULL) - { - LLInventoryModel::cat_array_t existing_categories; - LLInventoryModel::item_array_t existing_items; - - gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); - - existing_item_count += existing_items.size(); - } - - if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) - { - tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); - accept = FALSE; - } - } + const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID)); + LLViewerInventoryCategory * dest_folder = getCategory(); + accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex()); } + // Check that the folder can accept this item based on folder/item type compatibility (e.g. stock folder compatibility) + if (user_confirm && accept) + { + LLViewerInventoryCategory * dest_folder = getCategory(); + accept = dest_folder->acceptItem(inv_item); + } + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); // Check whether the item being dragged from active inventory panel // passes the filter of the destination panel. - if (accept && active_panel && use_filter) + if (user_confirm && accept && active_panel && use_filter) { LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; @@ -4145,9 +4693,25 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // RN: a better solution would be to deselect automatically when an item is moved // and then select any item that is dropped only in the panel that it is dropped in if (active_panel && (destination_panel != active_panel)) - { - active_panel->unSelectAll(); - } + { + active_panel->unSelectAll(); + } + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) + { + if ((move_is_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(inv_item->getUUID()) + || LLMarketplaceData::instance().isListedAndActive(inv_item->getUUID()))) || + (move_is_into_marketplacelistings && LLMarketplaceData::instance().isInActiveFolder(mUUID))) + { + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropItemIntoFolder, this, _1, _2, inv_item)); + return true; + } + if (move_is_into_marketplacelistings && !move_is_from_marketplacelistings) + { + LLNotificationsUtil::add("ConfirmMerchantMoveInventory", LLSD(), LLSD(), boost::bind(&LLFolderBridge::callback_dropItemIntoFolder, this, _1, _2, inv_item)); + return true; + } + } //-------------------------------------------------------------------------------- // Destination folder logic @@ -4160,7 +4724,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem(); if (itemp) { - LLUUID srcItemId = inv_item->getUUID(); + LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId); } @@ -4178,6 +4742,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } + // MERCHANT OUTBOX folder + // Move the item else if (move_is_into_outbox) { if (move_is_from_outbox) @@ -4189,6 +4755,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId()); } } + // MARKETPLACE LISTINGS folder + // Move the item + else if (move_is_into_marketplacelistings) + { + move_item_to_marketplacelistings(inv_item, mUUID); + } // NORMAL or TRASH folder // (move the item, restamp if into trash) else @@ -4205,8 +4777,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, mUUID, move_is_into_trash); } - - // + + if (move_is_from_marketplacelistings) + { + // If we move from an active (listed) listing, checks that it's still valid, if not, unlist + LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); + if (!validate_marketplacelistings(cat,NULL)) + { + LLMarketplaceData::instance().activateListing(version_folder_id,false); + } + } + } + + // //-------------------------------------------------------------------------------- } } @@ -4255,7 +4841,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = FALSE; } - else if (move_is_into_outbox) + else if (move_is_into_outbox || move_is_into_marketplacelistings) { tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); accept = FALSE; @@ -4293,7 +4879,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { - if (move_is_into_outbox) + if (move_is_into_outbox || move_is_into_marketplacelistings) { tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); accept = FALSE; @@ -4327,7 +4913,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = TRUE; - if (move_is_into_outbox) + if (move_is_into_outbox || move_is_into_marketplacelistings) { tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); accept = FALSE; @@ -4500,6 +5086,12 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addOutboxContextMenuOptions(flags, items, disabled_items); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { items.push_back(std::string("Share")); @@ -4567,6 +5159,12 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addOutboxContextMenuOptions(flags, items, disabled_items); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { if (isItemInTrash()) @@ -4642,6 +5240,12 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addOutboxContextMenuOptions(flags, items, disabled_items); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { if(isItemInTrash()) @@ -4934,6 +5538,12 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Delete")); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { items.push_back(std::string("Share")); @@ -5066,6 +5676,25 @@ void LLNotecardBridge::openItem() } } +void LLNotecardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LL_DEBUGS() << "LLNotecardBridge::buildContextMenu()" << LL_ENDL; + + if (isMarketplaceListingsFolder()) + { + menuentry_vec_t items; + menuentry_vec_t disabled_items; + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + hide_context_entries(menu, items, disabled_items); + } + else + { + LLItemBridge::buildContextMenu(menu, flags); + } +} + // +=================================================+ // | LLGestureBridge | // +=================================================+ @@ -5111,7 +5740,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action) gInventory.updateItem(item); gInventory.notifyObservers(); } - else if (isRemoveAction(action)) + else if ("deactivate" == action || isRemoveAction(action)) { LLGestureMgr::instance().deactivateGesture(mUUID); @@ -5201,6 +5830,12 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Delete")); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { items.push_back(std::string("Share")); @@ -5255,6 +5890,12 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Delete")); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { if(isItemInTrash()) @@ -5434,13 +6075,11 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach // Check for duplicate request. if (isAgentAvatarValid() && - (gAgentAvatarp->attachmentWasRequested(item_id) || - gAgentAvatarp->isWearingAttachment(item_id))) + gAgentAvatarp->isWearingAttachment(item_id)) { - LL_WARNS() << "duplicate attachment request, ignoring" << LL_ENDL; + LL_WARNS() << "ATT duplicate attachment request, ignoring" << LL_ENDL; return; } - gAgentAvatarp->addAttachmentRequest(item_id); S32 attach_pt = 0; if (isAgentAvatarValid() && attachment) @@ -5490,36 +6129,14 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) if (itemp) { - /* - { - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - return false; - } - */ - // Queue up attachments to be sent in next idle tick, this way the // attachments are batched up all into one message versus each attachment // being sent in its own separate attachments message. U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); BOOL is_add = notification["payload"]["is_add"].asBoolean(); - LLAttachmentsMgr::instance().addAttachment(item_id, - attachment_pt, - is_add); + LL_DEBUGS("Avatar") << "ATT calling addAttachmentRequest " << (itemp ? itemp->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + LLAttachmentsMgr::instance().addAttachmentRequest(item_id, attachment_pt, is_add); } } return false; @@ -5538,6 +6155,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Delete")); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { items.push_back(std::string("Share")); @@ -5739,12 +6362,8 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action void LLWearableBridge::openItem() { - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } + performAction(getInventoryModel(), + get_is_item_worn(mUUID) ? "take_off" : "wear"); } void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) @@ -5760,6 +6379,12 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Delete")); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM); @@ -6060,6 +6685,12 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addOutboxContextMenuOptions(flags, items, disabled_items); } + else if (isMarketplaceListingsFolder()) + { + addMarketplaceContextMenuOptions(flags, items, disabled_items); + items.push_back(std::string("Properties")); + getClipboardEntries(false, items, disabled_items, flags); + } else { items.push_back(std::string("Properties")); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 300cef7deb..03e19cc4da 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -77,6 +77,7 @@ public: bool canShare() const; bool canListOnMarketplace() const; + bool canListOnOutboxNow() const; bool canListOnMarketplaceNow() const; //-------------------------------------------------------------------- @@ -115,7 +116,7 @@ public: virtual void move(LLFolderViewModelItem* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; - virtual BOOL cutToClipboard() const; + virtual BOOL cutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} @@ -147,6 +148,9 @@ protected: virtual void addOutboxContextMenuOptions(U32 flags, menuentry_vec_t &items, menuentry_vec_t &disabled_items); + virtual void addMarketplaceContextMenuOptions(U32 flags, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items); protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); @@ -161,6 +165,7 @@ protected: BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox BOOL isOutboxFolderDirectParent() const; + BOOL isMarketplaceListingsFolder() const; // true if descendant of Marketplace listings folder const LLUUID getOutboxFolder() const; virtual BOOL isItemPermissive() const; @@ -173,6 +178,9 @@ protected: const LLUUID& new_parent, BOOL restamp); void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch); + + BOOL callback_cutToClipboard(const LLSD& notification, const LLSD& response); + BOOL perform_cutToClipboard(); public: BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox @@ -188,6 +196,7 @@ protected: mutable std::string mSearchableName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); + void removeObject(LLInventoryModel *model, const LLUUID &uuid); virtual void buildDisplayName() const {} }; @@ -264,8 +273,10 @@ public: mIsLoading(false) {} - BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); - BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); + BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE); + BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE); + void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item); + void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category); virtual void buildDisplayName() const; @@ -280,10 +291,9 @@ public: virtual LLUIImagePtr getIcon() const; virtual LLUIImagePtr getIconOpen() const; virtual LLUIImagePtr getIconOverlay() const; - static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); - virtual std::string getLabelSuffix() const; + virtual LLFontGL::StyleFlags getLabelStyle() const; virtual BOOL renameItem(const std::string& new_name); @@ -355,12 +365,17 @@ public: static LLHandle<LLFolderBridge> sSelf; static void staticFolderOptionsMenu(); -private: +protected: + void callback_pasteFromClipboard(const LLSD& notification, const LLSD& response); + void perform_pasteFromClipboard(); + void gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level); + LLUIImagePtr getFolderIcon(BOOL is_open) const; bool mCallingCards; bool mWearables; bool mIsLoading; LLTimer mTimeSinceRequestStart; + std::string mMessage; LLRootHandle<LLFolderBridge> mHandle; }; @@ -441,6 +456,7 @@ public: const LLUUID& uuid) : LLItemBridge(inventory, root, uuid) {} virtual void openItem(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); }; class LLGestureBridge : public LLItemBridge @@ -484,6 +500,7 @@ public: virtual LLUIImagePtr getIcon() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); + virtual BOOL isItemWearable() const { return TRUE; } virtual std::string getLabelSuffix() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL renameItem(const std::string& new_name); @@ -516,6 +533,7 @@ public: virtual LLUIImagePtr getIcon() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); + virtual BOOL isItemWearable() const { return TRUE; } virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual std::string getLabelSuffix() const; virtual BOOL renameItem(const std::string& new_name); @@ -669,6 +687,31 @@ public: U32 flags = 0x00) const; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Marketplace Inventory Panel related classes +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLMarketplaceFolderBridge : public LLFolderBridge +{ +public: + // Overloads some display related methods specific to folders in a marketplace floater context + LLMarketplaceFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid); + + virtual LLUIImagePtr getIcon() const; + virtual LLUIImagePtr getIconOpen() const; + virtual std::string getLabelSuffix() const; + virtual LLFontGL::StyleFlags getLabelStyle() const; + +private: + LLUIImagePtr getMarketplaceFolderIcon(BOOL is_open) const; + // Those members are mutable because they are cached variablse to speed up display, not a state variables + mutable S32 m_depth; + mutable S32 m_stockCountCache; +}; + + void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace = false); @@ -690,6 +733,12 @@ void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries); +// Helper functions to classify actions. +bool isAddAction(const std::string& action); +bool isRemoveAction(const std::string& action); +bool isMarketplaceCopyAction(const std::string& action); +bool isMarketplaceSendAction(const std::string& action); + class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel { public: diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c66e9da4a9..003bbcafed 100755 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -33,6 +33,8 @@ #include "llfolderviewitem.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" +#include "llinventoryfunctions.h" +#include "llmarketplacefunctions.h" #include "llviewercontrol.h" #include "llfolderview.h" #include "llinventorybridge.h" @@ -68,7 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) : mName(p.name), mFilterModified(FILTER_NONE), mEmptyLookupMessage("InventoryNoMatchingItems"), - mFilterOps(p.filter_ops), + mFilterOps(p.filter_ops), + mBackupFilterOps(mFilterOps), mFilterSubString(p.substring), mCurrentGeneration(0), mFirstRequiredGeneration(0), @@ -136,12 +139,64 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const } // when applying a filter, matching folders get their contents downloaded first - if (mFilterSubString.size() + if (isNotDefault() && !gInventory.isCategoryComplete(folder_id)) { LLInventoryModelBackgroundFetch::instance().start(folder_id); } + // Marketplace folder filtering + const U32 filterTypes = mFilterOps.mFilterTypes; + const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE | + FILTERTYPE_MARKETPLACE_UNASSOCIATED | FILTERTYPE_MARKETPLACE_LISTING_FOLDER | + FILTERTYPE_NO_MARKETPLACE_ITEMS; + if (filterTypes & marketplace_filter) + { + S32 depth = depth_nesting_in_marketplace(folder_id); + + if (filterTypes & FILTERTYPE_NO_MARKETPLACE_ITEMS) + { + if (depth >= 0) + { + return false; + } + } + + if (filterTypes & FILTERTYPE_MARKETPLACE_LISTING_FOLDER) + { + if (depth > 1) + { + return false; + } + } + + if (depth > 0) + { + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + if (filterTypes & FILTERTYPE_MARKETPLACE_ACTIVE) + { + if (!LLMarketplaceData::instance().getActivationState(listing_uuid)) + { + return false; + } + } + else if (filterTypes & FILTERTYPE_MARKETPLACE_INACTIVE) + { + if (!LLMarketplaceData::instance().isListed(listing_uuid) || LLMarketplaceData::instance().getActivationState(listing_uuid)) + { + return false; + } + } + else if (filterTypes & FILTERTYPE_MARKETPLACE_UNASSOCIATED) + { + if (LLMarketplaceData::instance().isListed(listing_uuid)) + { + return false; + } + } + } + } + // show folder links LLViewerInventoryItem* item = gInventory.getItem(folder_id); if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) @@ -501,6 +556,40 @@ void LLInventoryFilter::setFilterEmptySystemFolders() mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS; } +void LLInventoryFilter::setFilterMarketplaceActiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_ACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceInactiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_INACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceUnassociatedFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_UNASSOCIATED; +} + +void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_listing_folders) +{ + if (select_only_listing_folders) + { + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_LISTING_FOLDER; + setModified(FILTER_MORE_RESTRICTIVE); + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_MARKETPLACE_LISTING_FOLDER; + setModified(FILTER_LESS_RESTRICTIVE); + } +} + +void LLInventoryFilter::setFilterNoMarketplaceFolder() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS; +} + void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) { if (mFilterOps.mFilterUUID == LLUUID::null) @@ -546,6 +635,21 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) setModified(FILTER_RESTART); } + // Cancel out filter links once the search string is modified + if (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) + { + if (mBackupFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) + { + // we started viewer/floater in 'only links' mode + mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS; + } + else + { + mFilterOps = mBackupFilterOps; + setModified(FILTER_RESTART); + } + } + // Cancel out UUID once the search string is modified if (mFilterOps.mFilterTypes == FILTERTYPE_UUID) { @@ -553,11 +657,6 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) mFilterOps.mFilterUUID = LLUUID::null; setModified(FILTER_RESTART); } - - // Cancel out filter links once the search string is modified - { - mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS; - } } } @@ -748,6 +847,22 @@ void LLInventoryFilter::setShowFolderState(EFolderShow state) } } +void LLInventoryFilter::setFindAllLinksMode(const std::string &search_name, const LLUUID& search_id) +{ + // Save a copy of settings so that we will be able to restore it later + // but make sure we are not searching for links already + if(mFilterOps.mFilterLinks != FILTERLINK_ONLY_LINKS) + { + mBackupFilterOps = mFilterOps; + } + + // set search options + setFilterSubString(search_name); + setFilterUUID(search_id); + setShowFolderState(SHOW_NON_EMPTY_FOLDERS); + setFilterLinks(FILTERLINK_ONLY_LINKS); +} + void LLInventoryFilter::markDefault() { mDefaultFilterOps = mFilterOps; diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 5e18ad4d20..eee36b7e40 100755 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -52,7 +52,12 @@ public: FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it FILTERTYPE_DATE = 0x1 << 3, // search by date range FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type - FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if + FILTERTYPE_EMPTYFOLDERS = 0x1 << 5, // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_MARKETPLACE_ACTIVE = 0x1 << 6, // pass if folder is a marketplace active folder + FILTERTYPE_MARKETPLACE_INACTIVE = 0x1 << 7, // pass if folder is a marketplace inactive folder + FILTERTYPE_MARKETPLACE_UNASSOCIATED = 0x1 << 8, // pass if folder is a marketplace non associated (no market ID) folder + FILTERTYPE_MARKETPLACE_LISTING_FOLDER = 0x1 << 9, // pass iff folder is a listing folder + FILTERTYPE_NO_MARKETPLACE_ITEMS = 0x1 << 10 // pass iff folder is not under the marketplace }; enum EFilterDateDirection @@ -73,7 +78,8 @@ public: SO_NAME = 0, // Sort inventory by name SO_DATE = 0x1, // Sort inventory by date SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name - SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top + SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2,// Force system folders to be on top + SO_FOLDERS_BY_WEIGHT = 0x1 << 3, // Force folder sort by weight, usually, amount of some elements in their descendents }; struct FilterOps @@ -170,6 +176,11 @@ public: void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); void setFilterEmptySystemFolders(); + void setFilterMarketplaceActiveFolders(); + void setFilterMarketplaceInactiveFolders(); + void setFilterMarketplaceUnassociatedFolders(); + void setFilterMarketplaceListingFolders(bool select_only_listing_folders); + void setFilterNoMarketplaceFolder(); void updateFilterTypes(U64 types, U64& current_types); void setFilterSubString(const std::string& string); @@ -193,6 +204,9 @@ public: void setFilterLinks(U64 filter_link); U64 getFilterLinks() const; + // sets params for Link-only search and backs up search settings for future restoration + void setFindAllLinksMode(const std::string &search_name, const LLUUID& search_id); + // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ @@ -267,6 +281,7 @@ private: FilterOps mFilterOps; FilterOps mDefaultFilterOps; + FilterOps mBackupFilterOps; // for backup purposes when leaving 'search link' mode std::string mFilterSubString; std::string mFilterSubStringOrig; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 2546db546b..6aaf45c35d 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -60,6 +60,7 @@ #include "llinventorypanel.h" #include "lllineeditor.h" #include "llmarketplacenotifications.h" +#include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" #include "llpanelmaininventory.h" @@ -90,6 +91,126 @@ BOOL LLInventoryState::sWearNewClothing = FALSE; LLUUID LLInventoryState::sWearNewClothingTransactionID; +std::list<LLUUID> LLInventoryAction::sMarketplaceFolders; + +// Helper function : callback to update a folder after inventory action happened in the background +void update_folder_cb(const LLUUID& dest_folder) +{ + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + gInventory.updateCategory(dest_cat); + gInventory.notifyObservers(); +} + +// Helper function : Count only the copyable items, i.e. skip the stock items (which are no copy) +S32 count_copyable_items(LLInventoryModel::item_array_t& items) +{ + S32 count = 0; + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + LLViewerInventoryItem* item = *it; + if (item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + count++; + } + } + return count; +} + +// Helper function : Count only the non-copyable items, i.e. the stock items, skip the others +S32 count_stock_items(LLInventoryModel::item_array_t& items) +{ + S32 count = 0; + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + LLViewerInventoryItem* item = *it; + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + count++; + } + } + return count; +} + +// Helper function : Count the number of stock folders +S32 count_stock_folders(LLInventoryModel::cat_array_t& categories) +{ + S32 count = 0; + for (LLInventoryModel::cat_array_t::const_iterator it = categories.begin(); it != categories.end(); ++it) + { + LLInventoryCategory* cat = *it; + if (cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + count++; + } + } + return count; +} + +// Helper funtion : Count the number of items (not folders) in the descending hierarchy +S32 count_descendants_items(const LLUUID& cat_id) +{ + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array); + + S32 count = item_array->size(); + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + count += count_descendants_items(category->getUUID()); + } + + return count; +} + +// Helper function : Returns true if the hierarchy contains nocopy items +bool contains_nocopy_items(const LLUUID& id) +{ + LLInventoryCategory* cat = gInventory.getCategory(id); + + if (cat) + { + // Get the content + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(id,cat_array,item_array); + + // Check all the items: returns true upon encountering a nocopy item + for (LLInventoryModel::item_array_t::iterator iter = item_array->begin(); iter != item_array->end(); iter++) + { + LLInventoryItem* item = *iter; + LLViewerInventoryItem * inv_item = (LLViewerInventoryItem *) item; + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + return true; + } + } + + // Check all the sub folders recursively + for (LLInventoryModel::cat_array_t::iterator iter = cat_array->begin(); iter != cat_array->end(); iter++) + { + LLViewerInventoryCategory* cat = *iter; + if (contains_nocopy_items(cat->getUUID())) + { + return true; + } + } + } + else + { + LLInventoryItem* item = gInventory.getItem(id); + LLViewerInventoryItem * inv_item = (LLViewerInventoryItem *) item; + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + return true; + } + } + + // Exit without meeting a nocopy item + return false; +} // Generates a string containing the path to the item specified by // item_id. @@ -112,6 +233,139 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } +void update_marketplace_folder_hierarchy(const LLUUID cat_id) +{ + // When changing the marketplace status of a folder, the only thing that needs to happen is + // for all observers of the folder to, possibly, change the display label of the folder + // so that's the only thing we change on the update mask. + gInventory.addChangedMask(LLInventoryObserver::LABEL, cat_id); + + // Update all descendent folders down + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array); + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + update_marketplace_folder_hierarchy(category->getUUID()); + } + return; +} + +void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistency_enforcement) +{ + // When changing the marketplace status of an item, we usually have to change the status of all + // folders in the same listing. This is because the display of each folder is affected by the + // overall status of the whole listing. + // Consequently, the only way to correctly update an item anywhere in the marketplace is to + // update the whole listing from its listing root. + // This is not as bad as it seems as we only update folders, not items, and the folder nesting depth + // is limited to 4. + // We also take care of degenerated cases so we don't update all folders in the inventory by mistake. + + if (cur_uuid.isNull()) + { + return; + } + + // Grab marketplace listing data for this item + S32 depth = depth_nesting_in_marketplace(cur_uuid); + if (depth > 0) + { + // Retrieve the listing uuid this object is in + LLUUID listing_uuid = nested_parent_id(cur_uuid, depth); + + // Verify marketplace data consistency for this listing + if (perform_consistency_enforcement && LLMarketplaceData::instance().isListed(listing_uuid)) + { + LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolder(listing_uuid); + S32 version_depth = depth_nesting_in_marketplace(version_folder_uuid); + if (version_folder_uuid.notNull() && (!gInventory.isObjectDescendentOf(version_folder_uuid, listing_uuid) || (version_depth != 2))) + { + LL_INFOS("SLM") << "Unlist and clear version folder as the version folder is not at the right place anymore!!" << LL_ENDL; + LLMarketplaceData::instance().setVersionFolder(listing_uuid, LLUUID::null,1); + } + else if (version_folder_uuid.notNull() && LLMarketplaceData::instance().getActivationState(version_folder_uuid) && (count_descendants_items(version_folder_uuid) == 0) && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth)) + { + LL_INFOS("SLM") << "Unlist as the version folder is empty of any item!!" << LL_ENDL; + LLNotificationsUtil::add("AlertMerchantVersionFolderEmpty"); + LLMarketplaceData::instance().activateListing(listing_uuid, false,1); + } + } + + // Check if the count on hand needs to be updated on SLM + if (perform_consistency_enforcement && (compute_stock_count(listing_uuid) != LLMarketplaceData::instance().getCountOnHand(listing_uuid))) + { + LLMarketplaceData::instance().updateCountOnHand(listing_uuid,1); + } + // Update all descendents starting from the listing root + update_marketplace_folder_hierarchy(listing_uuid); + } + else if (depth == 0) + { + // If this is the marketplace listings root itself, update all descendents + if (gInventory.getCategory(cur_uuid)) + { + update_marketplace_folder_hierarchy(cur_uuid); + } + } + else + { + // If the folder is outside the marketplace listings root, clear its SLM data if needs be + if (perform_consistency_enforcement && LLMarketplaceData::instance().isListed(cur_uuid)) + { + LL_INFOS("SLM") << "Disassociate as the listing folder is not under the marketplace folder anymore!!" << LL_ENDL; + LLMarketplaceData::instance().clearListing(cur_uuid); + } + // Update all descendents if this is a category + if (gInventory.getCategory(cur_uuid)) + { + update_marketplace_folder_hierarchy(cur_uuid); + } + } + + return; +} + +// Iterate through the marketplace and flag for label change all categories that countain a stock folder (i.e. stock folders and embedding folders up the hierarchy) +void update_all_marketplace_count(const LLUUID& cat_id) +{ + // Get all descendent folders down + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array); + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + if (category->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + // Listing containing stock folders needs to be updated but not others + // Note: we take advantage of the fact that stock folder *do not* contain sub folders to avoid a recursive call here + update_marketplace_category(category->getUUID()); + } + else + { + // Explore the contained folders recursively + update_all_marketplace_count(category->getUUID()); + } + } +} + +void update_all_marketplace_count() +{ + // Get the marketplace root and launch the recursive exploration + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (!marketplace_listings_uuid.isNull()) + { + update_all_marketplace_count(marketplace_listings_uuid); + } + return; +} + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; @@ -132,7 +386,8 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, - const LLUUID& root_copy_id) + const LLUUID& root_copy_id, + bool move_no_copy_items ) { // Create the initial folder LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName()); @@ -145,19 +400,42 @@ void copy_inventory_category(LLInventoryModel* model, LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + + // If root_copy_id is null, tell the marketplace model we'll be waiting for new items to be copied over for this folder + if (root_copy_id.isNull()) + { + LLMarketplaceData::instance().setValidationWaiting(root_id,count_descendants_items(cat->getUUID())); + } // Copy all the items LLInventoryModel::item_array_t item_array_copy = *item_array; for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) { LLInventoryItem* item = *iter; - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - new_cat_uuid, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_uuid)); + + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // If the item is nocopy, we do nothing or, optionally, move it + if (move_no_copy_items) + { + // Reparent the item + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item; + gInventory.changeItemParent(viewer_inv_item, new_cat_uuid, true); + } + // Decrement the count in root_id since that one item won't be copied over + LLMarketplaceData::instance().decrementValidationWaiting(root_id); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + new_cat_uuid, + std::string(), + cb); + } } // Copy all the folders @@ -167,7 +445,7 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* category = *iter; if (category->getUUID() != root_id) { - copy_inventory_category(model, category, new_cat_uuid, root_id); + copy_inventory_category(model, category, new_cat_uuid, root_id, move_no_copy_items); } } } @@ -231,7 +509,7 @@ BOOL get_is_item_worn(const LLUUID& id) return FALSE; // Consider the item as worn if it has links in COF. - if (LLAppearanceMgr::instance().isLinkInCOF(id)) + if (LLAppearanceMgr::instance().isLinkedInCOF(id)) { return TRUE; } @@ -265,7 +543,7 @@ BOOL get_can_item_be_worn(const LLUUID& id) if (!item) return FALSE; - if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID())) + if (LLAppearanceMgr::instance().isLinkedInCOF(item->getLinkedUUID())) { // an item having links in COF (i.e. a worn item) return FALSE; @@ -459,7 +737,7 @@ void show_item_original(const LLUUID& item_uuid) { return; } - active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_NO); + active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES); if(do_reset_inventory_filter) { @@ -509,14 +787,22 @@ void open_outbox() LLFloaterReg::showInstance("outbox"); } -LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id) +void open_marketplace_listings() +{ + LLFloaterReg::showInstance("marketplace_listings"); +} + +// Create a new folder in destFolderId with the same name as the item name and return the uuid of the new folder +// Note: this is used locally in various situation where we need to wrap an item into a special folder +LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId) { llassert(item); llassert(destFolderId.notNull()); LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName()); gInventory.notifyObservers(); - + + // *TODO : Create different notifications for the various cases LLNotificationsUtil::add("OutboxFolderCreated"); return created_folder_id; @@ -532,8 +818,7 @@ void move_to_outbox_cb_action(const LLSD& payload) // when moving item directly into outbox create folder with that name if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) { - S32 operation_id = payload["operation_id"].asInteger(); - dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id); + dest_folder_id = create_folder_for_item(viitem, dest_folder_id); } LLUUID parent = viitem->getParentUUID(); @@ -604,7 +889,7 @@ void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LL // when moving item directly into outbox create folder with that name if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) { - dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); + dest_folder = create_folder_for_item(inv_item, dest_folder); } copy_inventory_item(gAgent.getID(), @@ -634,7 +919,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 // when moving item directly into outbox create folder with that name if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) { - dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); + dest_folder = create_folder_for_item(inv_item, dest_folder); } LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; @@ -675,6 +960,1003 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold } ///---------------------------------------------------------------------------- +// Marketplace functions +// +// Handles Copy and Move to or within the Marketplace listings folder. +// Handles creation of stock folders, nesting of listings and version folders, +// permission checking and listings validation. +///---------------------------------------------------------------------------- + +S32 depth_nesting_in_marketplace(LLUUID cur_uuid) +{ + // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplace_listings_uuid.isNull()) + { + return -1; + } + // If not a descendent of the marketplace listings root, then the nesting depth is -1 by definition + if (!gInventory.isObjectDescendentOf(cur_uuid, marketplace_listings_uuid)) + { + return -1; + } + + // Iterate through the parents till we hit the marketplace listings root + // Note that the marketplace listings root itself will return 0 + S32 depth = 0; + LLInventoryObject* cur_object = gInventory.getObject(cur_uuid); + while (cur_uuid != marketplace_listings_uuid) + { + depth++; + cur_uuid = cur_object->getParentUUID(); + cur_object = gInventory.getCategory(cur_uuid); + } + return depth; +} + +// Returns the UUID of the marketplace listing this object is in +LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth) +{ + if (depth < 1) + { + // For objects outside the marketplace listings root (or root itself), we return a NULL UUID + return LLUUID::null; + } + else if (depth == 1) + { + // Just under the root, we return the passed UUID itself if it's a folder, NULL otherwise (not a listing) + LLViewerInventoryCategory* cat = gInventory.getCategory(cur_uuid); + return (cat ? cur_uuid : LLUUID::null); + } + + // depth > 1 + LLInventoryObject* cur_object = gInventory.getObject(cur_uuid); + while (depth > 1) + { + depth--; + cur_uuid = cur_object->getParentUUID(); + cur_object = gInventory.getCategory(cur_uuid); + } + return cur_uuid; +} + +S32 compute_stock_count(LLUUID cat_uuid, bool force_count /* false */) +{ + // Handle the case of the folder being a stock folder immediately + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_uuid); + if (!cat) + { + // Not a category so no stock count to speak of + return COMPUTE_STOCK_INFINITE; + } + if (cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // If the folder is not completely fetched, we do not want to return any confusing value that could lead to unlisting + // "COMPUTE_STOCK_NOT_EVALUATED" denotes that a stock folder has a count that cannot be evaluated at this time (folder not up to date) + return COMPUTE_STOCK_NOT_EVALUATED; + } + // Note: stock folders are *not* supposed to have nested subfolders so we stop recursion here but we count only items (subfolders will be ignored) + // Note: we *always* give a stock count for stock folders, it's useful even if the listing is unassociated + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array); + return item_array->size(); + } + + // When force_count is true, we do not do any verification of the marketplace status and simply compute + // the stock amount based on the descendent hierarchy. This is used specifically when creating a listing. + if (!force_count) + { + // Grab marketplace data for this folder + S32 depth = depth_nesting_in_marketplace(cat_uuid); + LLUUID listing_uuid = nested_parent_id(cat_uuid, depth); + if (!LLMarketplaceData::instance().isListed(listing_uuid)) + { + // If not listed, the notion of stock is meaningless so it won't be computed for any level + return COMPUTE_STOCK_INFINITE; + } + + LLUUID version_folder_uuid = LLMarketplaceData::instance().getVersionFolder(listing_uuid); + // Handle the case of the first 2 levels : listing and version folders + if (depth == 1) + { + if (version_folder_uuid.notNull()) + { + // If there is a version folder, the stock value for the listing is the version folder stock + return compute_stock_count(version_folder_uuid, true); + } + else + { + // If there's no version folder associated, the notion of stock count has no meaning + return COMPUTE_STOCK_INFINITE; + } + } + else if (depth == 2) + { + if (version_folder_uuid.notNull() && (version_folder_uuid != cat_uuid)) + { + // If there is a version folder but we're not it, our stock count is meaningless + return COMPUTE_STOCK_INFINITE; + } + } + } + + // In all other cases, the stock count is the min of stock folders count found in the descendents + // "COMPUTE_STOCK_NOT_EVALUATED" denotes that a stock folder in the hierarchy has a count that cannot be evaluated at this time (folder not up to date) + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array); + + // "COMPUTE_STOCK_INFINITE" denotes a folder that doesn't countain any stock folders in its descendents + S32 curr_count = COMPUTE_STOCK_INFINITE; + + // Note: marketplace listings have a maximum depth nesting of 4 + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + S32 count = compute_stock_count(category->getUUID(), true); + if ((curr_count == COMPUTE_STOCK_INFINITE) || ((count != COMPUTE_STOCK_INFINITE) && (count < curr_count))) + { + curr_count = count; + } + } + + return curr_count; +} + +// local helper +bool can_move_to_marketplace(LLInventoryItem* inv_item, std::string& tooltip_msg, bool resolve_links) +{ + // Collapse links directly to items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory(); + + // Linked items and folders cannot be put for sale + if (linked_category || linked_item) + { + tooltip_msg = LLTrans::getString("TooltipOutboxLinked"); + return false; + } + + // A category is always considered as passing... + if (linked_category != NULL) + { + return true; + } + + // Take the linked item if necessary + if (linked_item != NULL) + { + inv_item = linked_item; + } + + // Check that the agent has transfer permission on the item: this is required as a resident cannot + // put on sale items she cannot transfer. Proceed with move if we have permission. + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + if (!allow_transfer) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + return false; + } + + // Check worn/not worn status: worn items cannot be put on the marketplace + bool worn = get_is_item_worn(inv_item->getUUID()); + if (worn) + { + tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + return false; + } + + // Check library status: library items cannot be put on the marketplace + if (!gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.getRootFolderID())) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + return false; + } + + // Check type: for the moment, calling cards cannot be put on the marketplace + bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType()); + if (calling_card) + { + tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard"); + return false; + } + + return true; +} + +// local helper +// Returns the max tree length (in folder nodes) down from the argument folder +int get_folder_levels(LLInventoryCategory* inv_cat) +{ + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); + + int max_child_levels = 0; + + for (S32 i=0; i < cats->size(); ++i) + { + LLInventoryCategory* category = cats->at(i); + max_child_levels = llmax(max_child_levels, get_folder_levels(category)); + } + + return 1 + max_child_levels; +} + +// local helper +// Returns the distance (in folder nodes) between the ancestor and its descendant. Returns -1 if not related. +int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id) +{ + int depth = 0; + + if (ancestor_id == descendant_id) return depth; + + const LLInventoryCategory* category = gInventory.getCategory(descendant_id); + + while (category) + { + LLUUID parent_id = category->getParentUUID(); + + if (parent_id.isNull()) break; + + depth++; + + if (parent_id == ancestor_id) return depth; + + category = gInventory.getCategory(parent_id); + } + + LL_WARNS("SLM") << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL; + return -1; +} + +// local helper +// Returns true if all items within the argument folder are fit for sale, false otherwise +bool has_correct_permissions_for_sale(LLInventoryCategory* cat, std::string& error_msg) +{ + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + + LLInventoryModel::item_array_t item_array_copy = *item_array; + + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + if (!can_move_to_marketplace(item, error_msg, false)) + { + return false; + } + } + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + if (!has_correct_permissions_for_sale(category, error_msg)) + { + return false; + } + } + return true; +} + +// Returns true if inv_item can be dropped in dest_folder, a folder nested in marketplace listings (or merchant inventory) under the root_folder root +// If returns is false, tooltip_msg contains an error message to display to the user (localized and all). +// bundle_size is the amount of sibling items that are getting moved to the marketplace at the same time. +bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size, bool from_paste) +{ + // Check stock folder type matches item type in marketplace listings or merchant outbox (even if of no use there for the moment) + LLViewerInventoryCategory* view_folder = dynamic_cast<LLViewerInventoryCategory*>(dest_folder); + bool move_in_stock = (view_folder && (view_folder->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)); + bool accept = (view_folder && view_folder->acceptItem(inv_item)); + if (!accept) + { + tooltip_msg = LLTrans::getString("TooltipOutboxMixedStock"); + } + + // Check that the item has the right type and permissions to be sold on the marketplace + if (accept) + { + accept = can_move_to_marketplace(inv_item, tooltip_msg, true); + } + + // Check that the total amount of items won't violate the max limit on the marketplace + if (accept) + { + // If the dest folder is a stock folder, we do not count the incoming items toward the total (stock items are seen as one) + int existing_item_count = (move_in_stock ? 0 : bundle_size); + + // If the dest folder is a stock folder, we do assume that the incoming items are also stock items (they should anyway) + int existing_stock_count = (move_in_stock ? bundle_size : 0); + + int existing_folder_count = 0; + + // Get the version folder: that's where the counts start from + const LLViewerInventoryCategory * version_folder = ((root_folder && (root_folder != dest_folder)) ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL); + + if (version_folder) + { + if (!from_paste && gInventory.isObjectDescendentOf(inv_item->getUUID(), version_folder->getUUID())) + { + // Clear those counts or they will be counted twice because we're already inside the version category + existing_item_count = 0; + } + + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; + + gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories); + existing_stock_count += count_stock_items(existing_items); + existing_folder_count += existing_categories.size(); + + // If the incoming item is a nocopy (stock) item, we need to consider that it will create a stock folder + if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && !move_in_stock) + { + // Note : we do not assume that all incoming items are nocopy of different kinds... + existing_folder_count += 1; + } + } + + if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects", args); + accept = false; + } + else if (existing_stock_count > gSavedSettings.getU32("InventoryOutboxMaxStockItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxStockItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyStockItems", args); + accept = false; + } + else if (existing_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders", args); + accept = false; + } + } + + return accept; +} + +// Returns true if inv_cat can be dropped in dest_folder, a folder nested in marketplace listings (or merchant inventory) under the root_folder root +// If returns is false, tooltip_msg contains an error message to display to the user (localized and all). +// bundle_size is the amount of sibling items that are getting moved to the marketplace at the same time. +bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size, bool check_items, bool from_paste) +{ + bool accept = true; + + // Compute the nested folders level we'll add into with that incoming folder + int incoming_folder_depth = get_folder_levels(inv_cat); + // Compute the nested folders level we're inserting ourselves in + // Note: add 1 when inserting under a listing folder as we need to take the root listing folder in the count + int insertion_point_folder_depth = (root_folder ? get_folder_path_length(root_folder->getUUID(), dest_folder->getUUID()) + 1 : 0); + + // Get the version folder: that's where the folders and items counts start from + const LLViewerInventoryCategory * version_folder = (insertion_point_folder_depth >= 2 ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL); + + // Compare the whole with the nested folders depth limit + // Note: substract 2 as we leave root and version folder out of the count threshold + if ((incoming_folder_depth + insertion_point_folder_depth - 2) > (S32)(gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"))) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderDepth"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels", args); + accept = false; + } + + if (accept) + { + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents(inv_cat->getUUID(), descendent_categories, descendent_items, FALSE); + + int dragged_folder_count = descendent_categories.size() + bundle_size; // Note: We assume that we're moving a bunch of folders in. That might be wrong... + int dragged_item_count = count_copyable_items(descendent_items) + count_stock_folders(descendent_categories); + int dragged_stock_count = count_stock_items(descendent_items); + int existing_item_count = 0; + int existing_stock_count = 0; + int existing_folder_count = 0; + + if (version_folder) + { + if (!from_paste && gInventory.isObjectDescendentOf(inv_cat->getUUID(), version_folder->getUUID())) + { + // Clear those counts or they will be counted twice because we're already inside the version category + dragged_folder_count = 0; + dragged_item_count = 0; + dragged_stock_count = 0; + } + + // Tally the total number of categories and items inside the root folder + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; + gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_folder_count += existing_categories.size(); + existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories); + existing_stock_count += count_stock_items(existing_items); + } + + const int total_folder_count = existing_folder_count + dragged_folder_count; + const int total_item_count = existing_item_count + dragged_item_count; + const int total_stock_count = existing_stock_count + dragged_stock_count; + + if (total_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxFolderCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders", args); + accept = false; + } + else if (total_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects", args); + accept = false; + } + else if (total_stock_count > gSavedSettings.getU32("InventoryOutboxMaxStockItemCount")) + { + LLStringUtil::format_map_t args; + U32 amount = gSavedSettings.getU32("InventoryOutboxMaxStockItemCount"); + args["[AMOUNT]"] = llformat("%d",amount); + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyStockItems", args); + accept = false; + } + + // Now check that each item in the folder can be moved in the marketplace + if (accept && check_items) + { + for (S32 i=0; i < descendent_items.size(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_marketplace(item, tooltip_msg, false)) + { + accept = false; + break; + } + } + } + } + + return accept; +} + +bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy) +{ + // Get the marketplace listings depth of the destination folder, exit with error if not under marketplace + S32 depth = depth_nesting_in_marketplace(dest_folder); + if (depth < 0) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Merchant"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + // We will collapse links into items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory(); + + if (linked_category != NULL) + { + // Move the linked folder directly + return move_folder_to_marketplacelistings(linked_category, dest_folder, copy); + } + else + { + // Grab the linked item if any + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + viewer_inv_item = (linked_item != NULL ? linked_item : viewer_inv_item); + + // If we want to copy but the item is no copy, fail silently (this is a common case that doesn't warrant notification) + if (copy && !viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + return false; + } + + // Check that the agent has transfer permission on the item: this is required as a resident cannot + // put on sale items she cannot transfer. Proceed with move if we have permission. + std::string error_msg; + if (can_move_to_marketplace(inv_item, error_msg, true)) + { + // When moving an isolated item, we might need to create the folder structure to support it + if (depth == 0) + { + // We need a listing folder + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); + depth++; + } + if (depth == 1) + { + // We need a version folder + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); + depth++; + } + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && + (dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK)) + { + // We need to create a stock folder to move a no copy item + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName()); + dest_cat = gInventory.getCategory(dest_folder); + depth++; + } + + // Verify we can have this item in that destination category + if (!dest_cat->acceptItem(viewer_inv_item)) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + // Get the parent folder of the moved item : we may have to update it + LLUUID src_folder = viewer_inv_item->getParentUUID(); + + if (copy) + { + // Copy the item + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder)); + copy_inventory_item( + gAgent.getID(), + viewer_inv_item->getPermissions().getOwner(), + viewer_inv_item->getUUID(), + dest_folder, + std::string(), + cb); + } + else + { + // Reparent the item + gInventory.changeItemParent(viewer_inv_item, dest_folder, true); + } + } + else + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + } + + open_marketplace_listings(); + return true; +} + +bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy, bool move_no_copy_items) +{ + // Check that we have adequate permission on all items being moved. Proceed if we do. + std::string error_msg; + if (has_correct_permissions_for_sale(inv_cat, error_msg)) + { + // Get the destination folder + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); + + // Check it's not a stock folder + if (dest_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + // Get the parent folder of the moved item : we may have to update it + LLUUID src_folder = inv_cat->getParentUUID(); + + LLViewerInventoryCategory * viewer_inv_cat = (LLViewerInventoryCategory *) inv_cat; + if (copy) + { + // Copy the folder + copy_inventory_category(&gInventory, viewer_inv_cat, dest_folder, LLUUID::null, move_no_copy_items); + } + else + { + // Reparent the folder + gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false); + // Check the destination folder recursively for no copy items and promote the including folders if any + validate_marketplacelistings(dest_cat); + } + + // Update the modified folders + update_marketplace_category(src_folder); + update_marketplace_category(dest_folder); + gInventory.notifyObservers(); + } + else + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + error_msg; + LLNotificationsUtil::add("MerchantPasteFailed", subs); + return false; + } + + open_marketplace_listings(); + return true; +} + +bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCategory* cat2) +{ + return cat1->getName().compare(cat2->getName()) < 0; +} + +void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level) +{ + llinfos << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << llendl; +} + +// Make all relevant business logic checks on the marketplace listings starting with the folder as argument. +// This function does no deletion of listings but a mere audit and raises issues to the user (through the +// optional callback cb). It also returns a boolean, true if things validate, false if issues are raised. +// The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders. +bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_t cb, bool fix_hierarchy, S32 depth) +{ +#if 0 + // Used only for debug + if (!cb) + { + cb = boost::bind(&dump_trace, _1, _2, _3); + } +#endif + // Folder is valid unless issue is raised + bool result = true; + + // Get the type and the depth of the folder + LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat); + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (depth < 0) + { + // If the depth argument was not provided, evaluate the depth directly + depth = depth_nesting_in_marketplace(cat->getUUID()); + } + if (depth < 0) + { + // If the folder is not under the marketplace listings root, we run validation as if it was a listing folder and prevent any hierarchy fix + // This allows the function to be used to pre-validate a folder anywhere in the inventory + depth = 1; + fix_hierarchy = false; + } + + // Set the indentation for print output (typically, audit button in marketplace folder floater) + std::string indent; + for (int i = 1; i < depth; i++) + { + indent += " "; + } + + // Check out that version folders are marketplace ready + if (depth == 2) + { + std::string message; + // Note: if we fix the hierarchy, we want to check the items individually, hence the last argument here + if (!can_move_folder_to_marketplace(cat, cat, cat, message, 0, fix_hierarchy)) + { + result = false; + if (cb) + { + message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + message; + cb(message,depth,LLError::LEVEL_ERROR); + } + } + } + + // Check out that stock folders are at the right level + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth <= 2)) + { + if (fix_hierarchy) + { + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); + cb(message,depth,LLError::LEVEL_WARN); + } + // Nest the stock folder one level deeper in a normal folder and restart from there + LLUUID parent_uuid = cat->getParentUUID(); + LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName()); + LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid); + gInventory.changeCategoryParent(viewer_cat, folder_uuid, false); + result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1); + return result; + } + else + { + result = false; + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); + cb(message,depth,LLError::LEVEL_ERROR); + } + } + } + + // Item sorting and validation : sorting and moving the various stock items is complicated as the set of constraints is high + // We need to: + // * separate non stock items, stock items per types in different folders + // * have stock items nested at depth 2 at least + // * never ever move the non-stock items + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + + // We use a composite (type,permission) key on that map to store UUIDs of items of same (type,permissions) + std::map<U32, std::vector<LLUUID> > items_vector; + + // Parse the items and create vectors of item UUIDs sorting copyable items and stock items of various types + bool has_bad_items = false; + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item; + + // Test but skip items that shouldn't be there to start with, raise an error message for those + std::string error_msg; + if (!can_move_to_marketplace(item, error_msg, false)) + { + has_bad_items = true; + if (cb && fix_hierarchy) + { + std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; + cb(message,depth,LLError::LEVEL_ERROR); + } + continue; + } + // Update the appropriate vector item for that type + LLInventoryType::EType type = LLInventoryType::IT_COUNT; // Default value for non stock items + U32 perms = 0; + if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // Get the item type for stock items + type = viewer_inv_item->getInventoryType(); + perms = viewer_inv_item->getPermissions().getMaskNextOwner(); + } + U32 key = (((U32)(type) & 0xFF) << 24) | (perms & 0xFFFFFF); + items_vector[key].push_back(viewer_inv_item->getUUID()); + } + + // How many types of items? Which type is it if only one? + S32 count = items_vector.size(); + U32 default_key = (U32)(LLInventoryType::IT_COUNT) << 24; // This is the key for any normal copyable item + U32 unique_key = (count == 1 ? items_vector.begin()->first : default_key); // The key in the case of one item type only + + // If we have no items in there (only folders or empty), analyze a bit further + if ((count == 0) && !has_bad_items) + { + if (cat_array->size() == 0) + { + // So we have no item and no folder. That's at least a warning. + if (depth == 2) + { + // If this is an empty version folder, warn only (listing won't be delivered by AIS, but only AIS should unlist) + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Version"); + cb(message,depth,LLError::LEVEL_WARN); + } + } + else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2)) + { + // If this is a legit but empty stock folder, warn only (listing must stay searchable when out of stock) + if (cb) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Stock"); + cb(message,depth,LLError::LEVEL_WARN); + } + } + else if (cb) + { + // We warn if there's nothing in a regular folder (may be it's an under construction listing) + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning Empty"); + cb(message,depth,LLError::LEVEL_WARN); + } + } + else + { + // Done with that folder : Print out the folder name unless we already found an error here + if (cb && result && (depth >= 1)) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message,depth,LLError::LEVEL_INFO); + } + } + } + // If we have a single type of items of the right type in the right place, we're done + else if ((count == 1) && !has_bad_items && (((unique_key == default_key) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2) && (cat_array->size() == 0)))) + { + // Done with that folder : Print out the folder name unless we already found an error here + if (cb && result && (depth >= 1)) + { + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message,depth,LLError::LEVEL_INFO); + } + } + else + { + if (fix_hierarchy && !has_bad_items) + { + // Alert the user when an existing stock folder has to be split + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && ((count >= 2) || (cat_array->size() > 0))) + { + LLNotificationsUtil::add("AlertMerchantStockFolderSplit"); + } + // If we have more than 1 type of items or we are at the listing level or we have stock/no stock type mismatch, wrap the items in subfolders + if ((count > 1) || (depth == 1) || + ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (unique_key == default_key)) || + ((folder_type != LLFolderType::FT_MARKETPLACE_STOCK) && (unique_key != default_key))) + { + // Create one folder per vector at the right depth and of the right type + std::map<U32, std::vector<LLUUID> >::iterator items_vector_it = items_vector.begin(); + while (items_vector_it != items_vector.end()) + { + // Create a new folder + LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID()); + LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); + std::string folder_name = (depth >= 1 ? viewer_cat->getName() : viewer_inv_item->getName()); + LLFolderType::EType new_folder_type = (items_vector_it->first == default_key ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK); + if (cb) + { + std::string message = ""; + if (new_folder_type == LLFolderType::FT_MARKETPLACE_STOCK) + { + message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Stock"); + } + else + { + message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Version"); + } + cb(message,depth,LLError::LEVEL_WARN); + } + LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, new_folder_type, folder_name); + + // Move each item to the new folder + while (!items_vector_it->second.empty()) + { + LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); + if (cb) + { + std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move"); + cb(message,depth,LLError::LEVEL_WARN); + } + gInventory.changeItemParent(viewer_inv_item, folder_uuid, true); + items_vector_it->second.pop_back(); + } + + // Next type + update_marketplace_category(parent_uuid); + update_marketplace_category(folder_uuid); + gInventory.notifyObservers(); + items_vector_it++; + } + } + // Stock folder should have no sub folder so reparent those up + if (folder_type == LLFolderType::FT_MARKETPLACE_STOCK) + { + LLUUID parent_uuid = cat->getParentUUID(); + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter); + gInventory.changeCategoryParent(viewer_cat, parent_uuid, false); + result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth); + } + } + } + else if (cb) + { + // We are not fixing the hierarchy but reporting problems, report everything we can find + // Print the folder name + if (result && (depth >= 1)) + { + if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (count >= 2)) + { + // Report if a stock folder contains a mix of items + result = false; + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Mixed Stock"); + cb(message,depth,LLError::LEVEL_ERROR); + } + else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (cat_array->size() != 0)) + { + // Report if a stock folder contains subfolders + result = false; + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Subfolder In Stock"); + cb(message,depth,LLError::LEVEL_ERROR); + } + else + { + // Simply print the folder name + std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); + cb(message,depth,LLError::LEVEL_INFO); + } + } + // Scan each item and report if there's a problem + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item; + std::string error_msg; + if (!can_move_to_marketplace(item, error_msg, false)) + { + // Report items that shouldn't be there to start with + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; + cb(message,depth,LLError::LEVEL_ERROR); + } + else if ((!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) && (folder_type != LLFolderType::FT_MARKETPLACE_STOCK)) + { + // Report stock items that are misplaced + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error Stock Item"); + cb(message,depth,LLError::LEVEL_ERROR); + } + else if (depth == 1) + { + // Report items not wrapped in version folder + result = false; + std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Unwrapped Item"); + cb(message,depth,LLError::LEVEL_ERROR); + } + } + } + + // Clean up + if (viewer_cat->getDescendentCount() == 0) + { + // Remove the current folder if it ends up empty + if (cb) + { + std::string message = indent + viewer_cat->getName() + LLTrans::getString("Marketplace Validation Warning Delete"); + cb(message,depth,LLError::LEVEL_WARN); + } + gInventory.removeCategory(cat->getUUID()); + gInventory.notifyObservers(); + return result && !has_bad_items; + } + } + + // Recursion : Perform the same validation on each nested folder + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + // Sort the folders in alphabetical order first + std::sort(cat_array_copy.begin(), cat_array_copy.end(), sort_alpha); + + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLInventoryCategory* category = *iter; + result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1); + } + + update_marketplace_category(cat->getUUID()); + gInventory.notifyObservers(); + return result && !has_bad_items; +} + +///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- @@ -1061,18 +2343,138 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) } } -void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action) +// Callback for doToSelected if DAMA required... +void LLInventoryAction::callback_doToSelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES + { + doToSelected(model, root, action, FALSE); + } +} + +void LLInventoryAction::callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // YES, Move no copy item(s) + { + doToSelected(model, root, "copy_or_move_to_marketplace_listings", FALSE); + } + else if (option == 1) // NO, Don't move no copy item(s) (leave them behind) + { + doToSelected(model, root, "copy_to_marketplace_listings", FALSE); + } +} + +// Succeeds iff all selected items are bridges to objects, in which +// case returns their corresponding uuids. +bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids) +{ + uuid_vec_t results; + S32 non_object = 0; + LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); + for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + LLObjectBridge *view_model = dynamic_cast<LLObjectBridge *>((*it)->getViewModelItem()); + + if(view_model && view_model->getUUID().notNull()) + { + results.push_back(view_model->getUUID()); + } + else + { + non_object++; + } + } + if (non_object == 0) + { + ids = results; + return true; + } + return false; +} + + +void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm) { + std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); + + // Prompt the user and check for authorization for some marketplace active listing edits + if (user_confirm && (("delete" == action) || ("cut" == action) || ("rename" == action) || ("properties" == action) || ("task_properties" == action) || ("open" == action))) + { + std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); + LLFolderViewModelItemInventory * viewModel = NULL; + for (; set_iter != selected_items.end(); ++set_iter) + { + viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem()); + if (viewModel && (depth_nesting_in_marketplace(viewModel->getUUID()) >= 0)) + { + break; + } + } + if (set_iter != selected_items.end()) + { + if ("open" == action) + { + if (get_can_item_be_worn(viewModel->getUUID())) + { + // Wearing an object from any listing, active or not, is verbotten + LLNotificationsUtil::add("AlertMerchantListingCannotWear"); + return; + } + // Note: we do not prompt for change when opening items (e.g. textures or note cards) on the marketplace... + } + else if (LLMarketplaceData::instance().isInActiveFolder(viewModel->getUUID()) || + LLMarketplaceData::instance().isListedAndActive(viewModel->getUUID())) + { + // If item is in active listing, further confirmation is required + if ((("cut" == action) || ("delete" == action)) && (LLMarketplaceData::instance().isListed(viewModel->getUUID()) || LLMarketplaceData::instance().isVersionFolder(viewModel->getUUID()))) + { + // Cut or delete of the active version folder or listing folder itself will unlist the listing so ask that question specifically + LLNotificationsUtil::add("ConfirmMerchantUnlist", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, model, root, action)); + return; + } + // Any other case will simply modify but not unlist a listing + LLNotificationsUtil::add("ConfirmMerchantActiveChange", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, model, root, action)); + return; + } + // Cutting or deleting a whole listing needs confirmation as SLM will be archived and inaccessible to the user + else if (LLMarketplaceData::instance().isListed(viewModel->getUUID()) && (("cut" == action) || ("delete" == action))) + { + LLNotificationsUtil::add("ConfirmListingCutOrDelete", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_doToSelected, _1, _2, model, root, action)); + return; + } + } + } + // Copying to the marketplace needs confirmation if nocopy items are involved + if (user_confirm && ("copy_to_marketplace_listings" == action)) + { + std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); + LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem()); + if (contains_nocopy_items(viewModel->getUUID())) + { + LLNotificationsUtil::add("ConfirmCopyToMarketplace", LLSD(), LLSD(), boost::bind(&LLInventoryAction::callback_copySelected, _1, _2, model, root, action)); + return; + } + } + + // Keep track of the marketplace folders that will need update of their status/name after the operation is performed + buildMarketplaceFolders(root); + if ("rename" == action) { root->startRenamingSelectedItem(); + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); return; } + if ("delete" == action) { LLSD args; args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); + // Note: marketplace listings will be updated in the callback if delete confirmed return; } if (("copy" == action) || ("cut" == action)) @@ -1090,12 +2492,12 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID()); if (!cat) return; cat->changeType(new_folder_type); + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); return; } - std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); - LLMultiPreview* multi_previewp = NULL; LLMultiProperties* multi_propertiesp = NULL; @@ -1115,7 +2517,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root LLFloater::setFloaterHost(multi_propertiesp); } - std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs(); uuid_vec_t ids; std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); @@ -1128,7 +2529,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { wear_multiple(ids, false); } - else if (action == "take_off" || action == "detach") + else if (isRemoveAction(action)) { LLAppearanceMgr::instance().removeItemsFromAvatar(ids); } @@ -1145,6 +2546,9 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } } + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); + LLFloater::setFloaterHost(NULL); if (multi_previewp) { @@ -1179,14 +2583,71 @@ void LLInventoryAction::removeItemFromDND(LLFolderView* root) } } -void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) +void LLInventoryAction::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) + if (option == 0 && !root.isDead() && !root.get()->isDead()) { - //Need to remove item from DND before item is removed from root folder view - //because once removed from root folder view the item is no longer a selected item - removeItemFromDND(root); - root->removeSelectedItems(); + LLFolderView* folder_root = root.get(); + //Need to remove item from DND before item is removed from root folder view + //because once removed from root folder view the item is no longer a selected item + removeItemFromDND(folder_root); + folder_root->removeSelectedItems(); + + // Update the marketplace listings that have been affected by the operation + updateMarketplaceFolders(); } } + +void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) +{ + // Make a list of all marketplace folders containing the elements in the selected list + // as well as the elements themselves. + // Once those elements are updated (cut, delete in particular but potentially any action), their + // containing folder will need to be updated as well as their initially containing folder. For + // instance, moving a stock folder from a listed folder to another will require an update of the + // target listing *and* the original listing. So we need to keep track of both. + // Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt. + sMarketplaceFolders.clear(); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplacelistings_id.isNull()) + { + return; + } + + std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); + std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); + LLFolderViewModelItemInventory * viewModel = NULL; + for (; set_iter != selected_items.end(); ++set_iter) + { + viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*set_iter)->getViewModelItem()); + if (!viewModel || !viewModel->getInventoryObject()) continue; + if (gInventory.isObjectDescendentOf(viewModel->getInventoryObject()->getParentUUID(), marketplacelistings_id)) + { + const LLUUID &parent_id = viewModel->getInventoryObject()->getParentUUID(); + if (parent_id != marketplacelistings_id) + { + sMarketplaceFolders.push_back(parent_id); + } + const LLUUID &curr_id = viewModel->getInventoryObject()->getUUID(); + if (curr_id != marketplacelistings_id) + { + sMarketplaceFolders.push_back(curr_id); + } + } + } + // Suppress dupes in the list so we won't update listings twice + sMarketplaceFolders.sort(); + sMarketplaceFolders.unique(); +} + +void LLInventoryAction::updateMarketplaceFolders() +{ + while (!sMarketplaceFolders.empty()) + { + update_marketplace_category(sMarketplaceFolders.back()); + sMarketplaceFolders.pop_back(); + } +} + + diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 6b3861aa79..b93bf9a163 100755 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -30,8 +30,13 @@ #include "llinventorymodel.h" #include "llinventory.h" +#include "llhandle.h" #include "llwearabletype.h" +// compute_stock_count() return error code +const S32 COMPUTE_STOCK_INFINITE = -1; +const S32 COMPUTE_STOCK_NOT_EVALUATED = -2; + /******************************************************************************** ** ** ** MISCELLANEOUS GLOBAL FUNCTIONS @@ -58,18 +63,33 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); void reset_inventory_filter(); +// Nudge the listing categories in the inventory to signal that their marketplace status changed +void update_marketplace_category(const LLUUID& cat_id, bool perform_consistency_enforcement = true); +// Nudge all listing categories to signal that their marketplace status changed +void update_all_marketplace_count(); + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); -void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null); +void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false); // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id); void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id); - void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id); +typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t; + +bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false); +bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false); +bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false); +bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false); +bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1); +S32 depth_nesting_in_marketplace(LLUUID cur_uuid); +LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); +S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); + /** Miscellaneous global functions ** ** *******************************************************************************/ @@ -425,7 +445,8 @@ public: *******************************************************************************/ class LLFolderViewItem; class LLFolderViewFolder; - +class LLInventoryModel; +class LLFolderView; class LLInventoryState { @@ -437,10 +458,16 @@ public: struct LLInventoryAction { - static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); + static void doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm = TRUE); + static void callback_doToSelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action); + static void callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action); + static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root); + static void removeItemFromDND(LLFolderView* root); - static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root); - static void removeItemFromDND(LLFolderView* root); +private: + static void buildMarketplaceFolders(LLFolderView* root); + static void updateMarketplaceFolders(); + static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed }; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index f92332dea5..0bad4702e0 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -41,6 +41,7 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llnotificationsutil.h" +#include "llmarketplacefunctions.h" #include "llwindow.h" #include "llviewercontrol.h" #include "llpreview.h" @@ -1023,7 +1024,7 @@ LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLU // an existing item with the matching id, or it will add the category. void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask) { - if(cat->getUUID().isNull()) + if(!cat || cat->getUUID().isNull()) { return; } @@ -1037,7 +1038,8 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 LLPointer<LLViewerInventoryCategory> old_cat = getCategory(cat->getUUID()); if(old_cat) { - // We already have an old category, modify it's values + // We already have an old category, modify its values + U32 mask = LLInventoryObserver::NONE; LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) @@ -1061,7 +1063,13 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 { mask |= LLInventoryObserver::LABEL; } - old_cat->copyViewerCategory(cat); + // Under marketplace, category labels are quite complex and need extra upate + const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id)) + { + mask |= LLInventoryObserver::LABEL; + } + old_cat->copyViewerCategory(cat); addChangedMask(mask, cat->getUUID()); } else @@ -1411,6 +1419,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo LLPointer<LLViewerInventoryCategory> cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj); vector_replace_with_last(*cat_list, cat); } + + // Note : We need to tell the inventory observers that those things are going to be deleted *before* the tree is cleared or they won't know what to delete (in views and view models) + addChangedMask(LLInventoryObserver::REMOVE, id); + gInventory.notifyObservers(); + item_list = getUnlockedItemArray(id); if(item_list) { @@ -1558,10 +1571,11 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) } } - mModifyMask |= mask; - if (referent.notNull()) + mModifyMask |= mask; + if (referent.notNull() && (mChangedItemIDs.find(referent) == mChangedItemIDs.end())) { mChangedItemIDs.insert(referent); + update_marketplace_category(referent, false); if (mask & LLInventoryObserver::ADD) { @@ -1981,17 +1995,22 @@ bool LLInventoryModel::loadSkeleton( // we can safely ignore anything loaded from file, but // not sent down in the skeleton. Must have been removed from inventory. - if(cit == not_cached) + if (cit == not_cached) { continue; } - if(cat->getVersion() != tcat->getVersion()) + else if (cat->getVersion() != tcat->getVersion()) { // if the cached version does not match the server version, // throw away the version we have so we can fetch the // correct contents the next time the viewer opens the folder. tcat->setVersion(NO_VERSION); } + else if (tcat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + // Do not trust stock folders being updated + tcat->setVersion(NO_VERSION); + } else { cached_ids.insert(tcat->getUUID()); @@ -3046,7 +3065,18 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' (" << tfolder->getUUID() << ") in " << tfolder->getParentUUID() << LL_ENDL; - if(tfolder->getUUID().notNull()) + + // If the folder is a listing or a version folder, all we need to do is update the SLM data + int depth_folder = depth_nesting_in_marketplace(tfolder->getUUID()); + if ((depth_folder == 1) || (depth_folder == 2)) + { + // Trigger an SLM listing update + LLUUID listing_uuid = (depth_folder == 1 ? tfolder->getUUID() : tfolder->getParentUUID()); + S32 listing_id = LLMarketplaceData::instance().getListingID(listing_uuid); + LLMarketplaceData::instance().getListing(listing_id); + // In that case, there is no item to update so no callback -> we skip the rest of the update + } + else if(tfolder->getUUID().notNull()) { folders.push_back(tfolder); LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 4a230accb6..5194cba891 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -193,6 +193,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) p.show_empty_message = mShowEmptyMessage; p.show_item_link_overlays = mShowItemLinkOverlays; p.root = NULL; + p.allow_drop = mParams.allow_drop_on_root; p.options_menu = "menu_inventory.xml"; return LLUICtrlFactory::create<LLFolderView>(p); @@ -292,7 +293,12 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); } - + // hide marketplace listing box, unless we are a marketplace panel + if (!gSavedSettings.getBOOL("InventoryOutboxMakeVisible") && !mParams.use_marketplace_folders) + { + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS)); + } + // set the filter for the empty folder if the debug setting is on if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders")) { @@ -601,13 +607,13 @@ void LLInventoryPanel::modelChanged(U32 mask) LLUUID LLInventoryPanel::getRootFolderID() { + LLUUID root_id; if (mFolderRoot.get() && mFolderRoot.get()->getViewModelItem()) { - return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot.get()->getViewModelItem())->getUUID(); + root_id = static_cast<LLFolderViewModelItemInventory*>(mFolderRoot.get()->getViewModelItem())->getUUID(); } else { - LLUUID root_id; if (mParams.start_folder.id.isChosen()) { root_id = mParams.start_folder.id; @@ -635,8 +641,8 @@ LLUUID LLInventoryPanel::getRootFolderID() } } } - return root_id; } + return root_id; } // static @@ -758,7 +764,7 @@ void LLInventoryPanel::initializeViews() } -LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) +LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop) { LLFolderViewFolder::Params params(mParams.folder); @@ -766,6 +772,7 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br params.root = mFolderRoot.get(); params.listener = bridge; params.tool_tip = params.name; + params.allow_drop = allow_drop; params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); @@ -794,37 +801,56 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { LLInventoryObject const* objectp = gInventory.getObject(id); - if (!objectp) return NULL; + if (!objectp) + { + return NULL; + } LLFolderViewItem* folder_view_item = getItemByID(id); - const LLUUID &parent_id = objectp->getParentUUID(); + const LLUUID &parent_id = objectp->getParentUUID(); LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + // Force the creation of an extra root level folder item if required by the inventory panel (default is "false") + bool allow_drop = true; + bool create_root = false; + if (mParams.show_root_folder) + { + LLUUID root_id = getRootFolderID(); + if (root_id == id) + { + // We insert an extra level that's seen by the UI but has no influence on the model + parent_folder = dynamic_cast<LLFolderViewFolder*>(folder_view_item); + folder_view_item = NULL; + allow_drop = mParams.allow_drop_on_root; + create_root = true; + } + } + if (!folder_view_item && parent_folder) { if (objectp->getType() <= LLAssetType::AT_NONE || objectp->getType() >= LLAssetType::AT_COUNT) { LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " - << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() - << LL_ENDL; + << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() + << LL_ENDL; return NULL; } if ((objectp->getType() == LLAssetType::AT_CATEGORY) && (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, + (mParams.use_marketplace_folders ? LLAssetType::AT_MARKETPLACE_FOLDER : LLAssetType::AT_CATEGORY), LLInventoryType::IT_CATEGORY, this, - &mInventoryViewModel, + &mInventoryViewModel, mFolderRoot.get(), objectp->getUUID()); if (new_listener) { - folder_view_item = createFolderViewFolder(new_listener); + folder_view_item = createFolderViewFolder(new_listener,allow_drop); } } else @@ -847,11 +873,16 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) } if (folder_view_item) - { + { llassert(parent_folder != NULL); folder_view_item->addToFolder(parent_folder); addItemID(id, folder_view_item); - } + // In the case of the root folder been shown, open that folder by default once the widget is created + if (create_root) + { + folder_view_item->setOpen(TRUE); + } + } } // If this is a folder, add the children of the folder and recursively add any @@ -960,7 +991,7 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // If folder view is empty the (x, y) point won't be in its rect // so the handler must be called explicitly. // but only if was not handled before. See EXT-6746. - if (!handled && !mFolderRoot.get()->hasVisibleChildren()) + if (!handled && mParams.allow_drop_on_root && !mFolderRoot.get()->hasVisibleChildren()) { handled = mFolderRoot.get()->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } @@ -1482,6 +1513,8 @@ public: LLInventoryPanel::initFromParams(p); // turn on inbox for recent items getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); + // turn off marketplace for recent items + getFilter().setFilterNoMarketplaceFolder(); } protected: @@ -1525,5 +1558,8 @@ namespace LLInitParam declare(LLFolderType::lookup(LLFolderType::FT_INBOX) , LLFolderType::FT_INBOX); declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX) , LLFolderType::FT_OUTBOX); declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT) , LLFolderType::FT_BASIC_ROOT); + declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_LISTINGS) , LLFolderType::FT_MARKETPLACE_LISTINGS); + declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_STOCK), LLFolderType::FT_MARKETPLACE_STOCK); + declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_VERSION), LLFolderType::FT_MARKETPLACE_VERSION); } } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index bc4c10e441..b69edd8b93 100755 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -97,6 +97,9 @@ public: Optional<StartFolder> start_folder; Optional<bool> use_label_suffix; Optional<bool> show_empty_message; + Optional<bool> show_root_folder; + Optional<bool> allow_drop_on_root; + Optional<bool> use_marketplace_folders; Optional<LLScrollContainer::Params> scroll; Optional<bool> accepts_drag_and_drop; Optional<LLFolderView::Params> folder_view; @@ -111,7 +114,10 @@ public: filter("filter"), start_folder("start_folder"), use_label_suffix("use_label_suffix", true), - show_empty_message("show_empty_message", true), + show_empty_message("show_empty_message", true), + show_root_folder("show_root_folder", false), + allow_drop_on_root("allow_drop_on_root", true), + use_marketplace_folders("use_marketplace_folders", false), scroll("scroll"), accepts_drag_and_drop("accepts_drag_and_drop"), folder_view("folder_view"), @@ -185,6 +191,7 @@ public: LLFolderView* getRootFolder() { return mFolderRoot.get(); } LLUUID getRootFolderID(); LLScrollContainer* getScrollableContainer() { return mScroller; } + bool getAllowDropOnRoot() { return mParams.allow_drop_on_root; } void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); @@ -293,7 +300,7 @@ protected: BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; virtual LLFolderView * createFolderRoot(LLUUID root_id ); - virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); + virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop); virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge); private: bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 1380345164..46c1ffa789 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -128,7 +128,7 @@ LLLocalBitmap::LLLocalBitmap(std::string filename) LLLocalBitmap::~LLLocalBitmap() { // replace IDs with defaults, if set to do so. - if(LL_LOCAL_REPLACE_ON_DEL && mValid) // fix for STORM-1837 + if(LL_LOCAL_REPLACE_ON_DEL && mValid && gAgentAvatarp) // fix for STORM-1837 { replaceIDs(mWorldID, IMG_DEFAULT); LLLocalBitmapMgr::doRebake(); @@ -515,7 +515,7 @@ void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id) { LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLSculptParams new_params(*old_params); - new_params.setSculptTexture(new_id); + new_params.setSculptTexture(new_id, (*old_params).getSculptType()); object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE); } } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 7ddacf3033..4116e38f11 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -804,6 +804,22 @@ bool LLLogChat::isNearbyTranscriptExist() return false; } +bool LLLogChat::isAdHocTranscriptExist(std::string file_name) +{ + std::vector<std::string> list_of_transcriptions; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + + file_name = makeLogFileName(file_name); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + { + if (transcript_file_name == file_name) + { + return true; + } + } + return false; +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) //Example, an object's name can be written like "Object <actual_object's_name>" diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index ca597599dd..6022e539a9 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -120,6 +120,7 @@ public: static void deleteTranscripts(); static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false); static bool isNearbyTranscriptExist(); + static bool isAdHocTranscriptExist(std::string file_name); static bool historyThreadsFinished(LLUUID session_id); static LLLoadHistoryThread* getLoadHistoryThread(LLUUID session_id); diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 407613d32c..85faa70552 100755 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -1677,12 +1677,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side1))); LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple1 + i) * smallest_subdivision1); - F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - - if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) + //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) + //F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + /*if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) { continue; - } + }*/ F32 tick_scale = 1.f; for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) @@ -1710,12 +1710,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side2))); LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2); - F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - - if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) + //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) + //F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); + /*if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) { continue; - } + }*/ F32 tick_scale = 1.f; for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 394db71fb9..b4259a456c 100755 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1285,12 +1285,12 @@ void LLManipTranslate::renderSnapGuides() { tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); - F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); - - if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) + //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) + //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); + /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) { continue; - } + }*/ // add in off-axis offset tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 4a7a4e268d..d5bfe1df4a 100755 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -29,14 +29,22 @@ #include "llmarketplacefunctions.h" #include "llagent.h" +#include "llbufferstream.h" #include "llhttpclient.h" +#include "llinventoryfunctions.h" +#include "llinventoryobserver.h" +#include "llnotificationsutil.h" #include "llsdserialize.h" #include "lltimer.h" #include "lltrans.h" #include "llviewercontrol.h" +#include "llviewerinventory.h" #include "llviewermedia.h" #include "llviewernetwork.h" +#include "llviewerregion.h" +#include "reader.h" // JSON +#include "writer.h" // JSON // // Helpers @@ -93,6 +101,550 @@ LLSD getMarketplaceStringSubstitutions() return marketplace_sub_map; } +// Get the version folder: if there is only one subfolder, we will use it as a version folder +LLUUID getVersionFolderIfUnique(const LLUUID& folder_id) +{ + LLUUID version_id = LLUUID::null; + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(folder_id, categories, items); + if (categories->size() == 1) + { + version_id = categories->begin()->get()->getUUID(); + } + else + { + LLNotificationsUtil::add("AlertMerchantListingActivateRequired"); + } + return version_id; +} + +/////////////////////////////////////////////////////////////////////////////// +// SLM Responders +void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description) +{ + LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << description << LL_ENDL; + if ((status == 422) && (description == "[\"You must have an English description to list the product\", \"You must choose a category for your product before it can be listed\", \"Listing could not change state.\", \"Price can't be blank\"]")) + { + // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing + LLNotificationsUtil::add("MerchantUnprocessableEntity"); + } + else + { + // Prompt the user with the warning (so they know why things are failing) + LLSD subs; + subs["[ERROR_REASON]"] = reason; + // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though. + subs["[ERROR_DESCRIPTION]"] = (description.length() <= 512 ? description : ""); + LLNotificationsUtil::add("MerchantTransactionFailed", subs); + } +} +void log_SLM_infos(const std::string& request, U32 status, const std::string& body) +{ + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL; + } +} +void log_SLM_infos(const std::string& request, const std::string& url, const std::string& body) +{ + if (gSavedSettings.getBOOL("MarketplaceListingsLogging")) + { + LL_INFOS("SLM") << "SLM API : Sending " << request << ". url : " << url << ", body : " << body << LL_ENDL; + } +} + +class LLSLMGetMerchantResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMGetMerchantResponder); +public: + + LLSLMGetMerchantResponder() {} + +protected: + virtual void httpFailure() + { + if (HTTP_NOT_FOUND == getStatus()) + { + log_SLM_infos("Get /merchant", getStatus(), "User is not a merchant"); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT); + } + else if (HTTP_SERVICE_UNAVAILABLE == getStatus()) + { + log_SLM_infos("Get /merchant", getStatus(), "Merchant is not migrated"); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT); + } + else + { + log_SLM_warning("Get /merchant", getStatus(), getReason(), getContent().get("error_code"), getContent().get("error_description")); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + } + } + + virtual void httpSuccess() + { + log_SLM_infos("Get /merchant", getStatus(), "User is a merchant"); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT); + } + +}; + +class LLSLMGetListingsResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMGetListingsResponder); +public: + + LLSLMGetListingsResponder(const LLUUID& folder_id) + { + mExpectedFolderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + log_SLM_warning("Get /listings", getStatus(), getReason(), "", body); + LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Get /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Get /listings", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + bool is_listed = listing["is_listed"].asBool(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInt(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + if (folder_id.notNull()) + { + LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count); + } + it++; + } + + // Update all folders under the root + LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + } +private: + LLUUID mExpectedFolderId; +}; + +class LLSLMCreateListingsResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMCreateListingsResponder); +public: + + LLSLMCreateListingsResponder(const LLUUID& folder_id) + { + mExpectedFolderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + log_SLM_warning("Post /listings", getStatus(), getReason(), "", body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Post /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Post /listings", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + bool is_listed = listing["is_listed"].asBool(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInt(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count); + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + it++; + } + } +private: + LLUUID mExpectedFolderId; +}; + +class LLSLMGetListingResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMGetListingResponder); +public: + + LLSLMGetListingResponder(const LLUUID& folder_id) + { + mExpectedFolderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + if (getStatus() == 404) + { + // That listing does not exist -> delete its record from the local SLM data store + LLMarketplaceData::instance().deleteListing(mExpectedFolderId, false); + } + else + { + log_SLM_warning("Get /listing", getStatus(), getReason(), "", body); + } + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Get /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Get /listing", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + bool is_listed = listing["is_listed"].asBool(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInt(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + + // Update that listing + LLMarketplaceData::instance().setListingID(folder_id, listing_id, false); + LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false); + LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false); + LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false); + LLMarketplaceData::instance().setCountOnHand(folder_id,count,false); + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + + it++; + } + } +private: + LLUUID mExpectedFolderId; +}; + +class LLSLMUpdateListingsResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMUpdateListingsResponder); +public: + + LLSLMUpdateListingsResponder(const LLUUID& folder_id, bool expected_listed_state, const LLUUID& expected_version_id) + { + mExpectedFolderId = folder_id; + mExpectedListedState = expected_listed_state; + mExpectedVersionUUID = expected_version_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + log_SLM_warning("Put /listing", getStatus(), getReason(), "", body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Put /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Put /listing", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + bool is_listed = listing["is_listed"].asBool(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInt(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + + // Update that listing + LLMarketplaceData::instance().setListingID(folder_id, listing_id, false); + LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false); + LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false); + LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false); + LLMarketplaceData::instance().setCountOnHand(folder_id,count,false); + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + + // Show a notification alert if what we got is not what we expected + // (this actually doesn't result in an error status from the SLM API protocol) + if ((mExpectedListedState != is_listed) || (mExpectedVersionUUID != version_id)) + { + LLSD subs; + subs["[URL]"] = edit_url; + LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs); + } + + it++; + } + } +private: + LLUUID mExpectedFolderId; + bool mExpectedListedState; + LLUUID mExpectedVersionUUID; +}; + +class LLSLMAssociateListingsResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMAssociateListingsResponder); +public: + + LLSLMAssociateListingsResponder(const LLUUID& folder_id, const LLUUID& source_folder_id) + { + mExpectedFolderId = folder_id; + mSourceFolderId = source_folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + LLMarketplaceData::instance().setUpdating(mSourceFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), "", body); + update_marketplace_category(mExpectedFolderId, false); + update_marketplace_category(mSourceFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Put /associate_inventory", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + update_marketplace_category(mExpectedFolderId, false); + update_marketplace_category(mSourceFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Put /associate_inventory", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + bool is_listed = listing["is_listed"].asBool(); + std::string edit_url = listing["edit_url"].asString(); + std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString(); + std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString(); + int count = listing["inventory_info"]["count_on_hand"].asInt(); + + LLUUID folder_id(folder_uuid_string); + LLUUID version_id(version_uuid_string); + + // Check that the listing ID is not already associated to some other record + LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id); + if (old_listing.notNull()) + { + // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID) + LLMarketplaceData::instance().deleteListing(old_listing); + } + + // Add the new association + LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count); + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + + // The stock count needs to be updated with the new local count now + LLMarketplaceData::instance().updateCountOnHand(folder_id,1); + + it++; + } + + // Always update the source folder so its widget updates + update_marketplace_category(mSourceFolderId, false); + } +private: + LLUUID mExpectedFolderId; // This is the folder now associated with the id. + LLUUID mSourceFolderId; // This is the folder initially associated with the id. Can be LLUUI::null +}; + +class LLSLMDeleteListingsResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLSLMDeleteListingsResponder); +public: + + LLSLMDeleteListingsResponder(const LLUUID& folder_id) + { + mExpectedFolderId = folder_id; + } + + virtual void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false); + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (!isGoodStatus()) + { + log_SLM_warning("Delete /listing", getStatus(), getReason(), "", body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body,root)) + { + log_SLM_warning("Delete /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body); + update_marketplace_category(mExpectedFolderId, false); + gInventory.notifyObservers(); + return; + } + + log_SLM_infos("Delete /listing", getStatus(), body); + + // Extract the info from the Json string + Json::ValueIterator it = root["listings"].begin(); + + while (it != root["listings"].end()) + { + Json::Value listing = *it; + + int listing_id = listing["id"].asInt(); + LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id); + LLMarketplaceData::instance().deleteListing(folder_id); + + it++; + } + } +private: + LLUUID mExpectedFolderId; +}; + +// SLM Responders End +/////////////////////////////////////////////////////////////////////////////// + namespace LLMarketplaceImport { // Basic interface for this namespace @@ -156,7 +708,7 @@ namespace LLMarketplaceImport { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - LL_INFOS() << " SLM POST clearing marketplace cookie due to client or server error" << LL_ENDL; + LL_INFOS() << " SLM POST : Clearing marketplace cookie due to client or server error" << LL_ENDL; } sMarketplaceCookie.clear(); } @@ -236,7 +788,7 @@ namespace LLMarketplaceImport S32 getResultStatus() { - return sImportResultStatus; + return sImportResultStatus; } const LLSD& getResults() @@ -427,15 +979,15 @@ void LLMarketplaceInventoryImporter::initialize() return; } - if (!LLMarketplaceImport::hasSessionCookie()) - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; - LLMarketplaceImport::establishMarketplaceSessionCookie(); - } - else - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; - } + if (!LLMarketplaceImport::hasSessionCookie()) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; + LLMarketplaceImport::establishMarketplaceSessionCookie(); + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; + } } void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport() @@ -479,54 +1031,957 @@ void LLMarketplaceInventoryImporter::updateImport() // If we are no longer in progress if (!mImportInProgress) { - if (mInitialized) - { - // Report results - if (mStatusReportSignal) - { - (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); - } - } - else - { - // Look for results success - mInitialized = LLMarketplaceImport::hasSessionCookie(); - - if (mInitialized) - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; - // Follow up with auto trigger of import - if (mAutoTriggerImport) - { - mAutoTriggerImport = false; - mImportInProgress = triggerImport(); - } - } - else - { - U32 status = LLMarketplaceImport::getResultStatus(); - if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || - (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; - } - else - { - mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; - } - if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) - { - (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); - } - } - } - } + // Look for results success + mInitialized = LLMarketplaceImport::hasSessionCookie(); - // Make sure we trigger the status change with the final state (in case of auto trigger after initialize) - if (mStatusChangedSignal) - { - (*mStatusChangedSignal)(mImportInProgress); + // Report results + if (mStatusReportSignal) + { + (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + + if (mInitialized) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; + // Follow up with auto trigger of import + if (mAutoTriggerImport) + { + mAutoTriggerImport = false; + mImportInProgress = triggerImport(); + } + } + else + { + U32 status = LLMarketplaceImport::getResultStatus(); + if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || + (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; + } + else if (status == MarketplaceErrorCodes::IMPORT_SERVER_API_DISABLED) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT; + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; + } + if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) + { + (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + } } } + + // Make sure we trigger the status change with the final state (in case of auto trigger after initialize) + if (mStatusChangedSignal) + { + (*mStatusChangedSignal)(mImportInProgress); + } +} + +// +// Direct Delivery : Marketplace tuples and data +// +class LLMarketplaceInventoryObserver : public LLInventoryObserver +{ +public: + LLMarketplaceInventoryObserver() {} + virtual ~LLMarketplaceInventoryObserver() {} + virtual void changed(U32 mask); +}; + +void LLMarketplaceInventoryObserver::changed(U32 mask) +{ + // When things are added to the marketplace, we might need to re-validate and fix the containing listings + if (mask & LLInventoryObserver::ADD) + { + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + + std::set<LLUUID>::const_iterator id_it = changed_items.begin(); + std::set<LLUUID>::const_iterator id_end = changed_items.end(); + // First, count the number of items in this list... + S32 count = 0; + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj && (LLAssetType::AT_CATEGORY != obj->getType())) + { + count++; + } + } + // Then, decrement the folders of that amount + // Note that of all of those, only one folder will be a listing folder (if at all). + // The other will be ignored by the decrement method. + id_it = changed_items.begin(); + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj && (LLAssetType::AT_CATEGORY == obj->getType())) + { + LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(),count); + } + } + } + + // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: + // * stock counts changing : no copy items coming in and out will change the stock count on folders + // * version and listing folders : moving those might invalidate the marketplace data itself + // Since we should cannot raise inventory change while the observer is called (the list will be cleared + // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. + + if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) + { + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + + std::set<LLUUID>::const_iterator id_it = changed_items.begin(); + std::set<LLUUID>::const_iterator id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj) + { + if (LLAssetType::AT_CATEGORY == obj->getType()) + { + // If it's a folder known to the marketplace, let's check it's in proper shape + if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it)) + { + LLInventoryCategory* cat = (LLInventoryCategory*)(obj); + validate_marketplacelistings(cat); + } + } + else + { + // If it's not a category, it's an item... + LLInventoryItem* item = (LLInventoryItem*)(obj); + // If it's a no copy item, we may need to update the label count of marketplace listings + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + LLMarketplaceData::instance().setDirtyCount(); + } + } + } + } + } +} + +// Tuple == Item +LLMarketplaceTuple::LLMarketplaceTuple() : + mListingFolderId(), + mListingId(0), + mVersionFolderId(), + mIsActive(false), + mEditURL("") +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id) : + mListingFolderId(folder_id), + mListingId(0), + mVersionFolderId(), + mIsActive(false), + mEditURL("") +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed) : + mListingFolderId(folder_id), + mListingId(listing_id), + mVersionFolderId(version_id), + mIsActive(is_listed), + mEditURL("") +{ +} + + +// Data map +LLMarketplaceData::LLMarketplaceData() : + mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED), + mMarketPlaceDataFetched(MarketplaceFetchCodes::MARKET_FETCH_NOT_DONE), + mStatusUpdatedSignal(NULL), + mDataFetchedSignal(NULL), + mDirtyCount(false) +{ + mInventoryObserver = new LLMarketplaceInventoryObserver; + gInventory.addObserver(mInventoryObserver); +} + +LLMarketplaceData::~LLMarketplaceData() +{ + gInventory.removeObserver(mInventoryObserver); +} + +void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb) +{ + if (mStatusUpdatedSignal == NULL) + { + mStatusUpdatedSignal = new status_updated_signal_t(); + } + mStatusUpdatedSignal->connect(cb); + + if (mMarketPlaceStatus != MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) + { + // If already initialized, just confirm the status so the callback gets called + setSLMStatus(mMarketPlaceStatus); + } + else + { + // Initiate SLM connection and set responder + std::string url = getSLMConnectURL("/merchant"); + if (url != "") + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; + log_SLM_infos("LLHTTPClient::get", url, ""); + LLHTTPClient::get(url, new LLSLMGetMerchantResponder(), LLSD()); + } + } +} + +void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot_type& cb) +{ + if (mDataFetchedSignal == NULL) + { + mDataFetchedSignal = new status_updated_signal_t(); + } + mDataFetchedSignal->connect(cb); +} + +// Get/Post/Put requests to the SLM Server using the SLM API +void LLMarketplaceData::getSLMListings() +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + // Send request + std::string url = getSLMConnectURL("/listings"); + log_SLM_infos("LLHTTPClient::get", url, ""); + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + setUpdating(marketplacelistings_id,true); + LLHTTPClient::get(url, new LLSLMGetListingsResponder(marketplacelistings_id), headers); +} + +void LLMarketplaceData::getSLMListing(S32 listing_id) +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + // Send request + std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id); + log_SLM_infos("LLHTTPClient::get", url, ""); + LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id); + setUpdating(folder_id,true); + LLHTTPClient::get(url, new LLSLMGetListingResponder(folder_id), headers); +} + +void LLMarketplaceData::createSLMListing(const LLUUID& folder_id, const LLUUID& version_id, S32 count) +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + // Build the json message + Json::Value root; + Json::FastWriter writer; + + LLViewerInventoryCategory* category = gInventory.getCategory(folder_id); + root["listing"]["name"] = category->getName(); + root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString(); + root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString(); + root["listing"]["inventory_info"]["count_on_hand"] = count; + + std::string json_str = writer.write(root); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.size(); + U8 *data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + // Send request + std::string url = getSLMConnectURL("/listings"); + log_SLM_infos("LLHTTPClient::postRaw", url, json_str); + setUpdating(folder_id,true); + LLHTTPClient::postRaw(url, data, size, new LLSLMCreateListingsResponder(folder_id), headers); +} + +void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count) +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + Json::Value root; + Json::FastWriter writer; + + // Note : auto unlist if the count is 0 (out of stock) + if (is_listed && (count == 0)) + { + is_listed = false; + LLNotificationsUtil::add("AlertMerchantStockFolderEmpty"); + } + + // Note : we're assuming that sending unchanged info won't break anything server side... + root["listing"]["id"] = listing_id; + root["listing"]["is_listed"] = is_listed; + root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString(); + root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString(); + root["listing"]["inventory_info"]["count_on_hand"] = count; + + std::string json_str = writer.write(root); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.size(); + U8 *data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + // Send request + std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id); + log_SLM_infos("LLHTTPClient::putRaw", url, json_str); + setUpdating(folder_id,true); + LLHTTPClient::putRaw(url, data, size, new LLSLMUpdateListingsResponder(folder_id, is_listed, version_id), headers); +} + +void LLMarketplaceData::associateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, const LLUUID& source_folder_id) +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + Json::Value root; + Json::FastWriter writer; + + // Note : we're assuming that sending unchanged info won't break anything server side... + root["listing"]["id"] = listing_id; + root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString(); + root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString(); + + std::string json_str = writer.write(root); + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = json_str.size(); + U8 *data = new U8[size]; + memcpy(data, (U8*)(json_str.c_str()), size); + + // Send request + std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d",listing_id); + log_SLM_infos("LLHTTPClient::putRaw", url, json_str); + setUpdating(folder_id,true); + setUpdating(source_folder_id,true); + LLHTTPClient::putRaw(url, data, size, new LLSLMAssociateListingsResponder(folder_id,source_folder_id), headers); +} + +void LLMarketplaceData::deleteSLMListing(S32 listing_id) +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + // Send request + std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id); + log_SLM_infos("LLHTTPClient::del", url, ""); + LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id); + setUpdating(folder_id,true); + LLHTTPClient::del(url, new LLSLMDeleteListingsResponder(folder_id), headers); +} + +std::string LLMarketplaceData::getSLMConnectURL(const std::string& route) +{ + std::string url(""); + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + // Get DirectDelivery cap + url = regionp->getCapability("DirectDelivery"); + if (url != "") + { + url += route; + } + } + return url; +} + +void LLMarketplaceData::setSLMStatus(U32 status) +{ + mMarketPlaceStatus = status; + if (mStatusUpdatedSignal) + { + (*mStatusUpdatedSignal)(); + } +} + +void LLMarketplaceData::setSLMDataFetched(U32 status) +{ + mMarketPlaceDataFetched = status; + if (mDataFetchedSignal) + { + (*mDataFetchedSignal)(); + } +} + +// Creation / Deletion / Update +// Methods publicly called +bool LLMarketplaceData::createListing(const LLUUID& folder_id) +{ + if (isListed(folder_id)) + { + // Listing already exists -> exit with error + return false; + } + + // Get the version folder: if there is only one subfolder, we will set it as a version folder immediately + S32 count = -1; + LLUUID version_id = getVersionFolderIfUnique(folder_id); + if (version_id.notNull()) + { + count = compute_stock_count(version_id, true); + } + + // Validate the count on hand + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated, we will consider it empty (out of stock) at creation time + // It will get reevaluated and updated once the items are fetched + count = 0; + } + + // Post the listing creation request to SLM + createSLMListing(folder_id, version_id, count); + + return true; +} + +bool LLMarketplaceData::clearListing(const LLUUID& folder_id, S32 depth) +{ + if (folder_id.isNull()) + { + // Folder doesn't exists -> exit with error + return false; + } + + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = (isListed(folder_id) ? folder_id : nested_parent_id(folder_id, depth)); + S32 listing_id = getListingID(listing_uuid); + + if (listing_id == 0) + { + // Listing doesn't exists -> exit with error + return false; + } + + // Update the SLM Server so that this listing is deleted (actually, archived...) + deleteSLMListing(listing_id); + + return true; +} + +bool LLMarketplaceData::getListing(const LLUUID& folder_id, S32 depth) +{ + if (folder_id.isNull()) + { + // Folder doesn't exists -> exit with error + return false; + } + + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = (isListed(folder_id) ? folder_id : nested_parent_id(folder_id, depth)); + S32 listing_id = getListingID(listing_uuid); + + if (listing_id == 0) + { + // Listing doesn't exists -> exit with error + return false; + } + + // Get listing data from SLM + getSLMListing(listing_id); + + return true; +} + +bool LLMarketplaceData::getListing(S32 listing_id) +{ + if (listing_id == 0) + { + return false; + } + + // Get listing data from SLM + getSLMListing(listing_id); + return true; +} + +bool LLMarketplaceData::activateListing(const LLUUID& folder_id, bool activate, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exists -> exit with error + return false; + } + + if (getActivationState(listing_uuid) == activate) + { + // If activation state is unchanged, no point spamming SLM with an update + return true; + } + + LLUUID version_uuid = getVersionFolder(listing_uuid); + + // Also update the count on hand + S32 count = compute_stock_count(folder_id); + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated locally, we should not change that SLM value + // We are assuming that this issue is local and should not modify server side values + count = getCountOnHand(listing_uuid); + } + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_uuid, activate, count); + + return true; +} + +bool LLMarketplaceData::setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exists -> exit with error + return false; + } + + if (getVersionFolder(listing_uuid) == version_id) + { + // If version folder is unchanged, no point spamming SLM with an update + return true; + } + + // Note: if the version_id is cleared, we need to unlist the listing, otherwise, state unchanged + bool is_listed = (version_id.isNull() ? false : getActivationState(listing_uuid)); + + // Also update the count on hand + S32 count = compute_stock_count(version_id); + if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If the count on hand cannot be evaluated, we will consider it empty (out of stock) when resetting the version folder + // It will get reevaluated and updated once the items are fetched + count = 0; + } + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_id, is_listed, count); + + return true; +} + +bool LLMarketplaceData::updateCountOnHand(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + // Folder id can be the root of the listing or not so we need to retrieve the root first + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + S32 listing_id = getListingID(listing_uuid); + if (listing_id == 0) + { + // Listing doesn't exists -> exit with error + return false; + } + + // Compute the new count on hand + S32 count = compute_stock_count(folder_id); + + if (count == getCountOnHand(listing_uuid)) + { + // If count on hand is unchanged, no point spamming SLM with an update + return true; + } + else if (count == COMPUTE_STOCK_NOT_EVALUATED) + { + // If local count on hand is not known at that point, do *not* force an update to SLM + return false; + } + + // Get the unchanged values + bool is_listed = getActivationState(listing_uuid); + LLUUID version_uuid = getVersionFolder(listing_uuid); + + + // Post the listing update request to SLM + updateSLMListing(listing_uuid, listing_id, version_uuid, is_listed, count); + + // Force the local value as it prevents spamming (count update may occur in burst when restocking) + // Note that if SLM has a good reason to return a different value, it'll be updated by the responder + setCountOnHand(listing_uuid, count, false); + + return true; +} + +bool LLMarketplaceData::associateListing(const LLUUID& folder_id, const LLUUID& source_folder_id, S32 listing_id) +{ + if (isListed(folder_id)) + { + // Listing already exists -> exit with error + return false; + } + + // Get the version folder: if there is only one subfolder, we will set it as a version folder immediately + LLUUID version_id = getVersionFolderIfUnique(folder_id); + + // Post the listing associate request to SLM + associateSLMListing(folder_id, listing_id, version_id, source_folder_id); + + return true; +} + +// Methods privately called or called by SLM responders to perform changes +bool LLMarketplaceData::addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count) +{ + mMarketplaceItems[folder_id] = LLMarketplaceTuple(folder_id, listing_id, version_id, is_listed); + mMarketplaceItems[folder_id].mEditURL = edit_url; + mMarketplaceItems[folder_id].mCountOnHand = count; + if (version_id.notNull()) + { + mVersionFolders[version_id] = folder_id; + } + return true; +} + +bool LLMarketplaceData::deleteListing(const LLUUID& folder_id, bool update) +{ + LLUUID version_folder = getVersionFolder(folder_id); + + if (mMarketplaceItems.erase(folder_id) != 1) + { + return false; + } + mVersionFolders.erase(version_folder); + + if (update) + { + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::deleteListing(S32 listing_id, bool update) +{ + if (listing_id == 0) + { + return false; + } + + LLUUID folder_id = getListingFolder(listing_id); + return deleteListing(folder_id, update); +} + +// Accessors +bool LLMarketplaceData::getActivationState(const LLUUID& folder_id) +{ + // Listing folder case + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it != mMarketplaceItems.end()) + { + return (it->second).mIsActive; + } + // Version folder case + version_folders_list_t::iterator it_version = mVersionFolders.find(folder_id); + if (it_version != mVersionFolders.end()) + { + marketplace_items_list_t::iterator it = mMarketplaceItems.find(it_version->second); + if (it != mMarketplaceItems.end()) + { + return (it->second).mIsActive; + } + } + return false; +} + +S32 LLMarketplaceData::getListingID(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? 0 : (it->second).mListingId); +} + +S32 LLMarketplaceData::getCountOnHand(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? -1 : (it->second).mCountOnHand); +} + +LLUUID LLMarketplaceData::getVersionFolder(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? LLUUID::null : (it->second).mVersionFolderId); } +// Reverse lookup : find the listing folder id from the listing id +LLUUID LLMarketplaceData::getListingFolder(S32 listing_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.begin(); + while (it != mMarketplaceItems.end()) + { + if ((it->second).mListingId == listing_id) + { + return (it->second).mListingFolderId; + } + it++; + } + return LLUUID::null; +} + +std::string LLMarketplaceData::getListingURL(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + + } + + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + + marketplace_items_list_t::iterator it = mMarketplaceItems.find(listing_uuid); + return (it == mMarketplaceItems.end() ? "" : (it->second).mEditURL); +} + +bool LLMarketplaceData::isListed(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it != mMarketplaceItems.end()); +} + +bool LLMarketplaceData::isListedAndActive(const LLUUID& folder_id) +{ + return (isListed(folder_id) && getActivationState(folder_id)); +} + +bool LLMarketplaceData::isVersionFolder(const LLUUID& folder_id) +{ + version_folders_list_t::iterator it = mVersionFolders.find(folder_id); + return (it != mVersionFolders.end()); +} + +bool LLMarketplaceData::isInActiveFolder(const LLUUID& obj_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(obj_id); + + } + + LLUUID listing_uuid = nested_parent_id(obj_id, depth); + bool active = getActivationState(listing_uuid); + LLUUID version_uuid = getVersionFolder(listing_uuid); + return (active && ((obj_id == version_uuid) || gInventory.isObjectDescendentOf(obj_id, version_uuid))); +} + +LLUUID LLMarketplaceData::getActiveFolder(const LLUUID& obj_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(obj_id); + + } + + LLUUID listing_uuid = nested_parent_id(obj_id, depth); + return (getActivationState(listing_uuid) ? getVersionFolder(listing_uuid) : LLUUID::null); +} + +bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) +{ + // Evaluate the depth if it wasn't passed as a parameter + if (depth < 0) + { + depth = depth_nesting_in_marketplace(folder_id); + } + if ((depth <= 0) || (depth > 2)) + { + // Only listing and version folders though are concerned by that status + return false; + } + else + { + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + std::set<LLUUID>::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid); + if (it != mPendingUpdateSet.end()) + { + // If we're waiting for data for the marketplace listings root, we are in the updating process for all + return true; + } + else + { + // Check if the listing folder is waiting or data + LLUUID listing_uuid = nested_parent_id(folder_id, depth); + it = mPendingUpdateSet.find(listing_uuid); + return (it != mPendingUpdateSet.end()); + } + } +} + +void LLMarketplaceData::setUpdating(const LLUUID& folder_id, bool isUpdating) +{ + std::set<LLUUID>::iterator it = mPendingUpdateSet.find(folder_id); + if (it != mPendingUpdateSet.end()) + { + mPendingUpdateSet.erase(it); + } + if (isUpdating) + { + mPendingUpdateSet.insert(folder_id); + } +} + +void LLMarketplaceData::setValidationWaiting(const LLUUID& folder_id, S32 count) +{ + mValidationWaitingList[folder_id] = count; +} + +void LLMarketplaceData::decrementValidationWaiting(const LLUUID& folder_id, S32 count) +{ + waiting_list_t::iterator found = mValidationWaitingList.find(folder_id); + if (found != mValidationWaitingList.end()) + { + found->second -= count; + if (found->second <= 0) + { + mValidationWaitingList.erase(found); + LLInventoryCategory *cat = gInventory.getCategory(folder_id); + validate_marketplacelistings(cat); + update_marketplace_category(folder_id); + gInventory.notifyObservers(); + } + } +} + +// Private Modifiers +bool LLMarketplaceData::setListingID(const LLUUID& folder_id, S32 listing_id, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mListingId = listing_id; + + if (update) + { + update_marketplace_category(folder_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setCountOnHand(const LLUUID& folder_id, S32 count, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mCountOnHand = count; + + return true; +} + +bool LLMarketplaceData::setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + LLUUID old_version_id = (it->second).mVersionFolderId; + if (old_version_id == version_id) + { + return false; + } + + (it->second).mVersionFolderId = version_id; + mVersionFolders.erase(old_version_id); + if (version_id.notNull()) + { + mVersionFolders[version_id] = folder_id; + } + + if (update) + { + update_marketplace_category(old_version_id, false); + update_marketplace_category(version_id, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setActivationState(const LLUUID& folder_id, bool activate, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mIsActive = activate; + + if (update) + { + update_marketplace_category((it->second).mListingFolderId, false); + gInventory.notifyObservers(); + } + return true; +} + +bool LLMarketplaceData::setListingURL(const LLUUID& folder_id, const std::string& edit_url, bool update) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + + (it->second).mEditURL = edit_url; + return true; +} + + + diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index abe60890a3..f8e7ed4364 100755 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -66,8 +66,21 @@ namespace MarketplaceStatusCodes MARKET_PLACE_NOT_INITIALIZED = 0, MARKET_PLACE_INITIALIZING = 1, MARKET_PLACE_CONNECTION_FAILURE = 2, - MARKET_PLACE_MERCHANT = 3, - MARKET_PLACE_NOT_MERCHANT = 4, + MARKET_PLACE_NOT_MERCHANT = 3, + MARKET_PLACE_MERCHANT = 4, + MARKET_PLACE_NOT_MIGRATED_MERCHANT = 5, + MARKET_PLACE_MIGRATED_MERCHANT = 6 + }; +} + +namespace MarketplaceFetchCodes +{ + enum sCode + { + MARKET_FETCH_NOT_DONE = 0, + MARKET_FETCH_LOADING = 1, + MARKET_FETCH_FAILED = 2, + MARKET_FETCH_DONE = 3 }; } @@ -109,6 +122,166 @@ private: }; +// Classes handling the data coming from and going to the Marketplace SLM Server DB: +// * implement the Marketplace API +// * cache the current Marketplace data (tuples) +// * provide methods to get Marketplace data on any inventory item +// * set Marketplace data +// * signal Marketplace updates to inventory +namespace SLMErrorCodes +{ + enum eCode + { + SLM_SUCCESS = 200, + SLM_RECORD_CREATED = 201, + SLM_MALFORMED_PAYLOAD = 400, + SLM_NOT_FOUND = 404, + }; +} + +class LLMarketplaceData; +class LLInventoryObserver; + +// A Marketplace item is known by its tuple +class LLMarketplaceTuple +{ +public: + friend class LLMarketplaceData; + + LLMarketplaceTuple(); + LLMarketplaceTuple(const LLUUID& folder_id); + LLMarketplaceTuple(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed = false); + +private: + // Representation of a marketplace item in the Marketplace DB (well, what we know of it...) + LLUUID mListingFolderId; + S32 mListingId; + LLUUID mVersionFolderId; + bool mIsActive; + S32 mCountOnHand; + std::string mEditURL; +}; +// Notes: +// * The mListingFolderId is used as a key to this map. It could therefore be taken off the LLMarketplaceTuple objects themselves. +// * The SLM DB however uses mListingId as its primary key and it shows in its API. In the viewer though, the mListingFolderId is what we use to grab an inventory record. +typedef std::map<LLUUID, LLMarketplaceTuple> marketplace_items_list_t; +typedef std::map<LLUUID, LLUUID> version_folders_list_t; + +// Session cache of all Marketplace tuples +// Notes: +// * There's one and only one possible set of Marketplace dataset per agent and per session thus making it an LLSingleton +// * Some of those records might correspond to folders that do not exist in the inventory anymore. We do not clear them out though. They just won't show up in the UI. + +class LLSLMGetMerchantResponder; +class LLSLMGetListingsResponder; +class LLSLMCreateListingsResponder; +class LLSLMGetListingResponder; +class LLSLMUpdateListingsResponder; +class LLSLMAssociateListingsResponder; +class LLSLMDeleteListingsResponder; + +class LLMarketplaceData + : public LLSingleton<LLMarketplaceData> +{ +public: + friend class LLSLMGetMerchantResponder; + friend class LLSLMGetListingsResponder; + friend class LLSLMCreateListingsResponder; + friend class LLSLMGetListingResponder; + friend class LLSLMUpdateListingsResponder; + friend class LLSLMAssociateListingsResponder; + friend class LLSLMDeleteListingsResponder; + + LLMarketplaceData(); + virtual ~LLMarketplaceData(); + + // Public SLM API : Initialization and status + typedef boost::signals2::signal<void ()> status_updated_signal_t; + void initializeSLM(const status_updated_signal_t::slot_type& cb); + U32 getSLMStatus() const { return mMarketPlaceStatus; } + void setSLMStatus(U32 status); + void getSLMListings(); + bool isEmpty() { return (mMarketplaceItems.size() == 0); } + void setDataFetchedSignal(const status_updated_signal_t::slot_type& cb); + void setSLMDataFetched(U32 status); + U32 getSLMDataFetched() { return mMarketPlaceDataFetched; } + + // High level create/delete/set Marketplace data: each method returns true if the function succeeds, false if error + bool createListing(const LLUUID& folder_id); + bool activateListing(const LLUUID& folder_id, bool activate, S32 depth = -1); + bool clearListing(const LLUUID& folder_id, S32 depth = -1); + bool setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id, S32 depth = -1); + bool associateListing(const LLUUID& folder_id, const LLUUID& source_folder_id, S32 listing_id); + bool updateCountOnHand(const LLUUID& folder_id, S32 depth = -1); + bool getListing(const LLUUID& folder_id, S32 depth = -1); + bool getListing(S32 listing_id); + bool deleteListing(S32 listing_id, bool update = true); + + // Probe the Marketplace data set to identify folders + bool isListed(const LLUUID& folder_id); // returns true if folder_id is a Listing folder + bool isListedAndActive(const LLUUID& folder_id); // returns true if folder_id is an active (listed) Listing folder + bool isVersionFolder(const LLUUID& folder_id); // returns true if folder_id is a Version folder + bool isInActiveFolder(const LLUUID& obj_id, S32 depth = -1); // returns true if the obj_id is buried in an active version folder + LLUUID getActiveFolder(const LLUUID& obj_id, S32 depth = -1); // returns the UUID of the active version folder obj_id is in + bool isUpdating(const LLUUID& folder_id, S32 depth = -1); // returns true if we're waiting from SLM incoming data for folder_id + + // Access Marketplace data set : each method returns a default value if the argument can't be found + bool getActivationState(const LLUUID& folder_id); + S32 getListingID(const LLUUID& folder_id); + LLUUID getVersionFolder(const LLUUID& folder_id); + std::string getListingURL(const LLUUID& folder_id, S32 depth = -1); + LLUUID getListingFolder(S32 listing_id); + S32 getCountOnHand(const LLUUID& folder_id); + + // Used to flag if stock count values for Marketplace have to be updated + bool checkDirtyCount() { if (mDirtyCount) { mDirtyCount = false; return true; } else { return false; } } + void setDirtyCount() { mDirtyCount = true; } + void setUpdating(const LLUUID& folder_id, bool isUpdating); + + // Used to decide when to run a validation on listing folders + void setValidationWaiting(const LLUUID& folder_id, S32 count); + void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1); + +private: + // Modify Marketplace data set : each method returns true if the function succeeds, false if error + // Used internally only by SLM Responders when data are received from the SLM Server + bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count); + bool deleteListing(const LLUUID& folder_id, bool update = true); + bool setListingID(const LLUUID& folder_id, S32 listing_id, bool update = true); + bool setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id, bool update = true); + bool setActivationState(const LLUUID& folder_id, bool activate, bool update = true); + bool setListingURL(const LLUUID& folder_id, const std::string& edit_url, bool update = true); + bool setCountOnHand(const LLUUID& folder_id, S32 count, bool update = true); + + // Private SLM API : package data and get/post/put requests to the SLM Server through the SLM API + void createSLMListing(const LLUUID& folder_id, const LLUUID& version_id, S32 count); + void getSLMListing(S32 listing_id); + void updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count); + void associateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, const LLUUID& source_folder_id); + void deleteSLMListing(S32 listing_id); + std::string getSLMConnectURL(const std::string& route); + + // Handling Marketplace connection and inventory connection + U32 mMarketPlaceStatus; + status_updated_signal_t* mStatusUpdatedSignal; + LLInventoryObserver* mInventoryObserver; + bool mDirtyCount; // If true, stock count value need to be updated at the next check + + // Update data + U32 mMarketPlaceDataFetched; + status_updated_signal_t* mDataFetchedSignal; + std::set<LLUUID> mPendingUpdateSet; + + // Listing folders waiting for validation + typedef std::map<LLUUID,S32> waiting_list_t; + waiting_list_t mValidationWaitingList; + + // The cache of SLM data (at last...) + marketplace_items_list_t mMarketplaceItems; + // We need a list (version folder -> listing folder) because such reverse lookups are frequent + version_folders_list_t mVersionFolders; +}; + #endif // LL_LLMARKETPLACEFUNCTIONS_H diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index b96bdd73ff..73faed7ef5 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -95,6 +95,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mStretchToFill( true ), mMaintainAspectRatio ( true ), mDecoupleTextureSize ( false ), + mUpdateScrolls( false ), mTextureWidth ( 1024 ), mTextureHeight ( 1024 ), mClearCache(false), @@ -682,7 +683,13 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } if(mClearCache) { @@ -720,10 +727,11 @@ void LLMediaCtrl::draw() { F32 alpha = getDrawContext().mAlpha; - if ( gRestoreGL == 1 ) + if ( gRestoreGL == 1 || mUpdateScrolls) { LLRect r = getRect(); reshape( r.getWidth(), r.getHeight(), FALSE ); + mUpdateScrolls = false; return; } @@ -765,7 +773,12 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -970,11 +983,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CLICK_LINK_HREF: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; // retrieve the event parameters std::string url = self->getClickURL(); - std::string target = self->getClickTarget(); + std::string target = self->isOverrideClickTarget() ? self->getOverrideClickTarget() : self->getClickTarget(); std::string uuid = self->getClickUUID(); + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL; LLNotification::Params notify_params; notify_params.name = "PopupAttempt"; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 785c57b78a..988733b85a 100755 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -192,7 +192,8 @@ public: mHidingInitialLoad, mClearCache, mHoverTextChanged, - mDecoupleTextureSize; + mDecoupleTextureSize, + mUpdateScrolls; std::string mHomePageUrl, mHomePageMimeType, diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 648056484e..55b94aa141 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -72,6 +72,7 @@ #include "bufferstream.h" #include "llfasttimer.h" #include "llcorehttputil.h" +#include "lltrans.h" #include "boost/lexical_cast.hpp" @@ -492,6 +493,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, } } +LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) +{ + LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); + return ppTex ? (*ppTex).get() : NULL; +} + volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0; volatile S32 LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; @@ -586,16 +593,16 @@ public: LLMeshLODHandler(const LLVolumeParams & mesh_params, S32 lod, U32 offset, U32 requested_bytes) : LLMeshHandlerBase(offset, requested_bytes), mLOD(lod) - { + { mMeshParams = mesh_params; LLMeshRepoThread::incActiveLODRequests(); } virtual ~LLMeshLODHandler(); - + protected: LLMeshLODHandler(const LLMeshLODHandler &); // Not defined void operator=(const LLMeshLODHandler &); // Not defined - + public: virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size); virtual void processFailure(LLCore::HttpStatus status); @@ -693,12 +700,16 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content, args["MESSAGE"] = message; args["IDENTIFIER"] = identifier; args["LABEL"] = model_name; - gMeshRepo.uploadError(args); // Log details. LL_WARNS(LOG_MESH) << "Error in stage: " << stage << ", Reason: " << status.toString() << " (" << status.toTerseString() << ")" << LL_ENDL; + + std::ostringstream details; + typedef std::set<std::string> mav_errors_set_t; + mav_errors_set_t mav_errors; + if (content.has("error")) { const LLSD& err = content["error"]; @@ -708,8 +719,11 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content, << "', message '" << err["message"].asString() << "', id '" << err["identifier"].asString() << "'" << LL_ENDL; + if (err.has("errors")) { + details << std::endl << std::endl; + S32 error_num = 0; const LLSD& err_list = err["errors"]; for (LLSD::array_const_iterator it = err_list.beginArray(); @@ -717,6 +731,13 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content, ++it) { const LLSD& err_entry = *it; + std::string message = err_entry["message"]; + + if (message.length() > 0) + { + mav_errors.insert(message); + } + LL_WARNS(LOG_MESH) << " error[" << error_num << "]:" << LL_ENDL; for (LLSD::map_const_iterator map_it = err_entry.beginMap(); map_it != err_entry.endMap(); @@ -733,6 +754,21 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content, { LL_WARNS(LOG_MESH) << "Bad response to mesh request, no additional error information available." << LL_ENDL; } + + mav_errors_set_t::iterator mav_errors_it = mav_errors.begin(); + for (; mav_errors_it != mav_errors.end(); ++mav_errors_it) + { + std::string mav_details = "Mav_Details_" + *mav_errors_it; + details << "Message: '" << *mav_errors_it << "': " << LLTrans::getString(mav_details) << std::endl << std::endl; + } + + std::string details_str = details.str(); + if (details_str.length() > 0) + { + args["DETAILS"] = details_str; + } + + gMeshRepo.uploadError(args); } LLMeshRepoThread::LLMeshRepoThread() @@ -766,7 +802,7 @@ LLMeshRepoThread::LLMeshRepoThread() mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH); } - + LLMeshRepoThread::~LLMeshRepoThread() { LL_INFOS(LOG_MESH) << "Small GETs issued: " << LLMeshRepository::sHTTPRequestCount @@ -835,16 +871,16 @@ void LLMeshRepoThread::run() { break; } - + if (! mHttpRequestSet.empty()) { // Dispatch all HttpHandler notifications mHttpRequest->update(0L); } sRequestWaterLevel = mHttpRequestSet.size(); // Stats data update - - // NOTE: order of queue processing intentionally favors LOD requests over header requests + // NOTE: order of queue processing intentionally favors LOD requests over header requests + while (!mLODReqQ.empty() && mHttpRequestSet.size() < sRequestHighWater) { if (! mMutex) @@ -908,7 +944,7 @@ void LLMeshRepoThread::run() mSkinRequests.erase(iter); mMutex->unlock(); - if (!fetchMeshSkinInfo(mesh_id)) + if (! fetchMeshSkinInfo(mesh_id)) { incomplete.insert(mesh_id); } @@ -937,7 +973,7 @@ void LLMeshRepoThread::run() mDecompositionRequests.erase(iter); mMutex->unlock(); - if (!fetchMeshDecomposition(mesh_id)) + if (! fetchMeshDecomposition(mesh_id)) { incomplete.insert(mesh_id); } @@ -963,7 +999,7 @@ void LLMeshRepoThread::run() mPhysicsShapeRequests.erase(iter); mMutex->unlock(); - if (!fetchMeshPhysicsShape(mesh_id)) + if (! fetchMeshPhysicsShape(mesh_id)) { incomplete.insert(mesh_id); } @@ -1189,7 +1225,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) } ++LLMeshRepository::sMeshRequestCount; - bool ret = true ; + bool ret = true; U32 header_size = mMeshHeaderSize[mesh_id]; if (header_size > 0) @@ -1237,7 +1273,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) constructUrl(mesh_id, &http_url, &cap_version); if (!http_url.empty()) - { + { LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size); LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) @@ -1283,7 +1319,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) ++LLMeshRepository::sMeshRequestCount; U32 header_size = mMeshHeaderSize[mesh_id]; - bool ret = true ; + bool ret = true; if (header_size > 0) { @@ -1329,9 +1365,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) int cap_version(2); std::string http_url; constructUrl(mesh_id, &http_url, &cap_version); - + if (!http_url.empty()) - { + { LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size); LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) @@ -1377,7 +1413,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) ++LLMeshRepository::sMeshRequestCount; U32 header_size = mMeshHeaderSize[mesh_id]; - bool ret = true ; + bool ret = true; if (header_size > 0) { @@ -1422,9 +1458,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) int cap_version(2); std::string http_url; constructUrl(mesh_id, &http_url, &cap_version); - + if (!http_url.empty()) - { + { LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size); LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) @@ -1513,11 +1549,11 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) } //either cache entry doesn't exist or is corrupt, request header from simulator - bool retval = true ; + bool retval = true; int cap_version(2); std::string http_url; constructUrl(mesh_params.getSculptID(), &http_url, &cap_version); - + if (!http_url.empty()) { //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits @@ -1605,9 +1641,9 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) int cap_version(2); std::string http_url; constructUrl(mesh_id, &http_url, &cap_version); - + if (!http_url.empty()) - { + { LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size); LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler); if (LLCORE_HTTP_HANDLE_INVALID == handle) @@ -1879,7 +1915,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, mOrigin += gAgent.getAtAxis() * scale.magVec(); - mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ; + mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut"); mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; @@ -1947,14 +1983,14 @@ void LLMeshUploadThread::preStart() void LLMeshUploadThread::discard() { - LLMutexLock lock(mMutex) ; + LLMutexLock lock(mMutex); mDiscarded = true; } bool LLMeshUploadThread::isDiscarded() const { - LLMutexLock lock(mMutex) ; - return mDiscarded ; + LLMutexLock lock(mMutex); + return mDiscarded; } void LLMeshUploadThread::run() @@ -2019,6 +2055,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLMeshUploadData data; data.mBaseModel = iter->first; + + if (data.mBaseModel->mSubmodelID) + { + // These are handled below to insure correct parenting order on creation + // due to map walking being based on model address (aka random) + continue; + } + LLModelInstance& first_instance = *(iter->second.begin()); for (S32 i = 0; i < 5; i++) { @@ -2056,7 +2100,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) data.mModel[LLModel::LOD_IMPOSTOR], decomp, mUploadSkin, - mUploadJoints); + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); data.mAssetData = ostr.str(); std::string str = ostr.str(); @@ -2090,17 +2137,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) instance_entry["scale"] = ll_sd_from_vector3(scale); instance_entry["material"] = LL_MCODE_WOOD; - instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); instance_entry["mesh"] = mesh_index[data.mBaseModel]; instance_entry["face_list"] = LLSD::emptyArray(); - S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + for (S32 face_num = 0; face_num < end; face_num++) { LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; LLSD face_entry = LLSD::emptyMap(); - LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } if ((texture != NULL) && (textures.find(texture) == textures.end())) @@ -2115,9 +2171,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); } } + } + + if (texture != NULL && + mUploadTextures && + texture_index.find(texture) == texture_index.end()) + { + texture_index[texture] = texture_num; + std::string str = texture_str.str(); + res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); + texture_num++; + } + + // Subset of TextureEntry fields. + if (texture != NULL && mUploadTextures) + { + face_entry["image"] = texture_index[texture]; + face_entry["scales"] = 1.0; + face_entry["scalet"] = 1.0; + face_entry["offsets"] = 0.0; + face_entry["offsett"] = 0.0; + face_entry["imagerot"] = 0.0; + } + face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); + face_entry["fullbright"] = material.mFullbright; + instance_entry["face_list"][face_num] = face_entry; + } + + res["instance_list"][instance_num] = instance_entry; + instance_num++; + } + } + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + if (!data.mBaseModel->mSubmodelID) + { + // These were handled above already... + // + continue; + } + + LLModelInstance& first_instance = *(iter->second.begin()); + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = first_instance.mLOD[i]; + } + + if (mesh_index.find(data.mBaseModel) == mesh_index.end()) + { + // Have not seen this model before - create a new mesh_list entry for it. + if (model_name.empty()) + { + model_name = data.mBaseModel->getName(); + } + + if (model_metric.empty()) + { + model_metric = data.mBaseModel->getMetric(); + } + + std::stringstream ostr; + + LLModel::Decomposition& decomp = + data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysics : + data.mBaseModel->mPhysics; + + decomp.mBaseHull = mHullMap[data.mBaseModel]; + + LLSD mesh_header = LLModel::writeModel( + ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + decomp, + mUploadSkin, + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); + + data.mAssetData = ostr.str(); + std::string str = ostr.str(); + + res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); + mesh_index[data.mBaseModel] = mesh_num; + mesh_num++; + } + + // For all instances that use this model + for (instance_list::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + + LLModelInstance& instance = *instance_iter; + + LLSD instance_entry; + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + LLVector3 pos, scale; + LLQuaternion rot; + LLMatrix4 transformation = instance.mTransform; + decomposeMeshMatrix(transformation,pos,rot,scale); + instance_entry["position"] = ll_sd_from_vector3(pos); + instance_entry["rotation"] = ll_sd_from_quaternion(rot); + instance_entry["scale"] = ll_sd_from_vector3(scale); + + instance_entry["material"] = LL_MCODE_WOOD; + instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE); + instance_entry["mesh"] = mesh_index[data.mBaseModel]; + + instance_entry["face_list"] = LLSD::emptyArray(); + + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + + for (S32 face_num = 0; face_num < end; face_num++) + { + LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; + LLSD face_entry = LLSD::emptyMap(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } + + if ((texture != NULL) && + (textures.find(texture) == textures.end())) + { + textures.insert(texture); + } + + std::stringstream texture_str; + if (texture != NULL && include_textures && mUploadTextures) + { + if(texture->hasSavedRawImage()) + { + LLPointer<LLImageJ2C> upload_file = + LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { + texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); + } + } + } if (texture != NULL && mUploadTextures && @@ -2205,7 +2423,7 @@ void LLMeshUploadThread::generateHulls() } } - if(has_valid_requests) + if (has_valid_requests) { // *NOTE: Interesting livelock condition on shutdown. If there // is an upload request in generateHulls() when shutdown starts, @@ -2310,7 +2528,7 @@ void LLMeshUploadThread::requestWholeModelFee() else { U32 sleep_time(10); - + mHttpRequest->update(0); while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) { @@ -2405,7 +2623,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp // model fee case LLWholeModelFeeObserver* observer(mFeeObserverHandle.get()); mWholeModelUploadURL.clear(); - + if (! status) { LL_WARNS(LOG_MESH) << "Fee request failed. Reason: " << reason @@ -2435,7 +2653,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp LLCoreHttpUtil::responseToLLSD(response, true, body); } dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num)); - + if (body["state"].asString() == "upload") { mWholeModelUploadURL = body["uploader"].asString(); @@ -2506,7 +2724,7 @@ void LLMeshRepoThread::notifyLoadedMeshes() LODRequest req = mUnavailableQ.front(); mUnavailableQ.pop(); mMutex->unlock(); - + update_metrics = true; gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); } @@ -2642,7 +2860,7 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) { mProcessed = true; - + unsigned int retries(0U); response->getRetries(NULL, &retries); LLMeshRepository::sHTTPRetryCount += retries; @@ -2698,7 +2916,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo // 200 case, typically offset = 0; } - + // *DEBUG: To test validation below // offset += 1; @@ -2814,7 +3032,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b const std::string & lod_name = header_lod[i]; lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); } - + // just in case skin info or decomposition is at the end of the file (which it shouldn't be) lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); @@ -2822,7 +3040,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; S32 bytes = lod_bytes + header_bytes; - + // It's possible for the remote asset to have more data than is needed for the local cache // only allocate as much space in the VFS as is needed for the local cache data_size = llmin(data_size, bytes); @@ -2834,11 +3052,11 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b ++LLMeshRepository::sCacheWrites; file.write(data, data_size); - + // zero out the rest of the file U8 block[MESH_HEADER_SIZE]; memset(block, 0, sizeof(block)); - + while (bytes-file.tell() > sizeof(block)) { file.write(block, sizeof(block)); @@ -2864,8 +3082,8 @@ LLMeshLODHandler::~LLMeshLODHandler() gMeshRepo.mThread->lockAndLoadMeshLOD(mMeshParams, mLOD); } LLMeshRepoThread::decActiveLODRequests(); - } } +} void LLMeshLODHandler::processFailure(LLCore::HttpStatus status) { @@ -2883,7 +3101,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body { if ((! MESH_LOD_PROCESS_FAILED) && gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) { - //good fetch from sim, write to VFS for caching + // good fetch from sim, write to VFS for caching LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); S32 offset = mOffset; @@ -2928,7 +3146,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* { if ((! MESH_SKIN_INFO_PROCESS_FAILED) && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) { - //good fetch from sim, write to VFS for caching + // good fetch from sim, write to VFS for caching LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); S32 offset = mOffset; @@ -3252,7 +3470,7 @@ void LLMeshRepository::notifyLoadedMeshes() REQUEST2_LOW_WATER_MIN, REQUEST2_LOW_WATER_MAX); } - + //clean up completed upload threads for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); ) { @@ -3329,7 +3547,7 @@ void LLMeshRepository::notifyLoadedMeshes() //call completed callbacks on finished decompositions mDecompThread->notifyCompleted(); - + // For major operations, attempt to get the required locks // without blocking and punt if they're not available. The // longest run of holdoffs is kept in sMaxLockHoldoffs just @@ -3348,12 +3566,12 @@ void LLMeshRepository::notifyLoadedMeshes() return; } hold_offs = 0; - + if (gAgent.getRegion()) { // Update capability urls static std::string region_name("never name a region this"); - + if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived()) { region_name = gAgent.getRegion()->getName(); @@ -3369,7 +3587,7 @@ void LLMeshRepository::notifyLoadedMeshes() << LL_ENDL; } } - + //popup queued error messages from background threads while (!mUploadErrorQ.empty()) { @@ -3724,7 +3942,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, - bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, + bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer) { LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url, @@ -3795,37 +4013,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation, result_rot = quat_rotation; } -bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const -{ - if (mDiffuseMap != rhs.mDiffuseMap) - { - return mDiffuseMap < rhs.mDiffuseMap; - } - - if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) - { - return mDiffuseMapFilename < rhs.mDiffuseMapFilename; - } - - if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) - { - return mDiffuseMapLabel < rhs.mDiffuseMapLabel; - } - - if (mDiffuseColor != rhs.mDiffuseColor) - { - return mDiffuseColor < rhs.mDiffuseColor; - } - - if (mBinding != rhs.mBinding) - { - return mBinding < rhs.mBinding; - } - - return mFullbright < rhs.mFullbright; -} - - void LLMeshRepository::updateInventory(inventory_data data) { LLMutexLock lock(mMeshMutex); @@ -4223,7 +4410,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull() setMeshData(mesh, true); LLCDResult ret = decomp->buildSingleHull() ; - if(ret) + if (ret) { LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL; make_box(mCurRequest); @@ -4411,60 +4598,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg) mStatusMessage = msg; } -LLModelInstance::LLModelInstance(LLSD& data) -{ - mLocalMeshID = data["mesh_id"].asInteger(); - mLabel = data["label"].asString(); - mTransform.setValue(data["transform"]); - - for (U32 i = 0; i < data["material"].size(); ++i) - { - LLImportMaterial mat(data["material"][i]); - mMaterial[mat.mBinding] = mat; - } -} - - -LLSD LLModelInstance::asLLSD() -{ - LLSD ret; - - ret["mesh_id"] = mModel->mLocalID; - ret["label"] = mLabel; - ret["transform"] = mTransform.getValue(); - - U32 i = 0; - for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) - { - ret["material"][i++] = iter->second.asLLSD(); - } - - return ret; -} - -LLImportMaterial::LLImportMaterial(LLSD& data) -{ - mDiffuseMapFilename = data["diffuse"]["filename"].asString(); - mDiffuseMapLabel = data["diffuse"]["label"].asString(); - mDiffuseColor.setValue(data["diffuse"]["color"]); - mFullbright = data["fullbright"].asBoolean(); - mBinding = data["binding"].asString(); -} - - -LLSD LLImportMaterial::asLLSD() -{ - LLSD ret; - - ret["diffuse"]["filename"] = mDiffuseMapFilename; - ret["diffuse"]["label"] = mDiffuseMapLabel; - ret["diffuse"]["color"] = mDiffuseColor.getValue(); - ret["fullbright"] = mFullbright; - ret["binding"] = mBinding; - - return ret; -} - void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp) { decomp.mMesh.resize(decomp.mHull.size()); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 39280bea3a..688cd01a87 100755 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -90,54 +90,6 @@ public: } }; -class LLImportMaterial -{ -public: - LLPointer<LLViewerFetchedTexture> mDiffuseMap; - std::string mDiffuseMapFilename; - std::string mDiffuseMapLabel; - std::string mBinding; - LLColor4 mDiffuseColor; - bool mFullbright; - - bool operator<(const LLImportMaterial ¶ms) const; - - LLImportMaterial() - : mFullbright(false) - { - mDiffuseColor.set(1,1,1,1); - } - - LLImportMaterial(LLSD& data); - - LLSD asLLSD(); -}; - -class LLModelInstance -{ -public: - LLPointer<LLModel> mModel; - LLPointer<LLModel> mLOD[5]; - - std::string mLabel; - - LLUUID mMeshID; - S32 mLocalMeshID; - - LLMatrix4 mTransform; - std::map<std::string, LLImportMaterial> mMaterial; - - LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials) - : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) - { - mLocalMeshID = -1; - } - - LLModelInstance(LLSD& data); - - LLSD asLLSD(); -}; - class LLPhysicsDecomp : public LLThread { public: @@ -483,6 +435,8 @@ public: // Inherited from LLCore::HttpHandler virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material); + private: LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle; LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle; diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index fe562baf96..70035bcc74 100755 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -303,7 +303,15 @@ void LLFloaterMove::onFlyButtonClick() void LLFloaterMove::setMovementMode(const EMovementMode mode) { mCurrentMode = mode; - gAgent.setFlying(MM_FLY == mode); + + if(MM_FLY == mode) + { + LLAgent::toggleFlying(); + } + else + { + gAgent.setFlying(FALSE); + } // attempts to set avatar flying can not set it real flying in some cases. // For ex. when avatar fell down & is standing up. diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 65ac11092c..d79baf90e7 100755 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -646,6 +646,22 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c return legacy_it != mLegacyMutes.end(); } +BOOL LLMuteList::isMuted(const std::string& username, U32 flags) const +{ + mute_set_t::const_iterator mute_iter = mMutes.begin(); + while(mute_iter != mMutes.end()) + { + // can't convert "leha.test" into "LeHa TesT" so username comparison is more reliable + if (mute_iter->mType == LLMute::AGENT + && LLCacheName::buildUsername(mute_iter->mName) == username) + { + return TRUE; + } + mute_iter++; + } + return FALSE; +} + //----------------------------------------------------------------------------- // requestFromServer() //----------------------------------------------------------------------------- diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 3e998b4f0e..4e7b6ee880 100755 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -101,7 +101,10 @@ public: // Name is required to test against legacy text-only mutes. BOOL isMuted(const LLUUID& id, const std::string& name = LLStringUtil::null, U32 flags = 0) const; - + + // Workaround for username-based mute search, a lot of string conversions so use cautiously + BOOL isMuted(const std::string& username, U32 flags = 0) const; + // Alternate (convenience) form for places we don't need to pass the name, but do need flags BOOL isMuted(const LLUUID& id, U32 flags) const { return isMuted(id, LLStringUtil::null, flags); }; diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 54e4c6c1da..5510598ae7 100755 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -70,7 +70,7 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) // public LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, - BOOL enabled, const std::string& suffix) + BOOL enabled, const std::string& suffix, const std::string& prefix) { //LL_INFOS() << "LLNameListCtrl::addNameItem " << agent_id << LL_ENDL; @@ -79,7 +79,7 @@ LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPositi item.enabled = enabled; item.target = INDIVIDUAL; - return addNameItemRow(item, pos, suffix); + return addNameItemRow(item, pos, suffix, prefix); } // virtual, public @@ -130,8 +130,14 @@ BOOL LLNameListCtrl::handleDragAndDrop( return handled; } -void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group) +void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience) { + if(is_experience) + { + LLFloaterReg::showInstance("experience_profile", avatar_id, true); + return; + } + if (is_group) LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id)); else @@ -230,10 +236,11 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) // Should we show a group or an avatar inspector? bool is_group = hit_item->isGroup(); + bool is_experience = hit_item->isExperience(); LLToolTip::Params params; params.background_visible( false ); - params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) ); + params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience) ); params.delay_time(0.0f); // spawn instantly on hover params.image( icon ); params.message(""); @@ -291,10 +298,11 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition p LLScrollListItem* LLNameListCtrl::addNameItemRow( const LLNameListCtrl::NameItem& name_item, EAddPosition pos, - const std::string& suffix) + const std::string& suffix, + const std::string& prefix) { LLUUID id = name_item.value().asUUID(); - LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP); + LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE); if (!item) return NULL; @@ -352,6 +360,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( } break; } + case EXPERIENCE: + // just use supplied name default: break; } @@ -365,7 +375,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( LLScrollListCell* cell = item->getColumn(mNameColumnIndex); if (cell) { - cell->setValue(fullname); + cell->setValue(prefix + fullname); } dirtyColumns(); diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 2c40eeaaca..19ce3c7aed 100755 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -44,22 +44,30 @@ class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameLi public: bool isGroup() const { return mIsGroup; } void setIsGroup(bool is_group) { mIsGroup = is_group; } + bool isExperience() const { return mIsExperience; } + void setIsExperience(bool is_experience) { mIsExperience = is_experience; } protected: friend class LLNameListCtrl; LLNameListItem( const LLScrollListItem::Params& p ) - : LLScrollListItem(p), mIsGroup(false) + : LLScrollListItem(p), mIsGroup(false), mIsExperience(false) { } LLNameListItem( const LLScrollListItem::Params& p, bool is_group ) - : LLScrollListItem(p), mIsGroup(is_group) + : LLScrollListItem(p), mIsGroup(is_group), mIsExperience(false) + { + } + + LLNameListItem( const LLScrollListItem::Params& p, bool is_group, bool is_experience ) + : LLScrollListItem(p), mIsGroup(is_group), mIsExperience(is_experience) { } private: bool mIsGroup; + bool mIsExperience; }; @@ -73,7 +81,8 @@ public: { INDIVIDUAL, GROUP, - SPECIAL + SPECIAL, + EXPERIENCE } ENameType; // provide names for enums @@ -129,11 +138,12 @@ public: // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. LLScrollListItem* addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, - BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null); + BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null, const std::string& prefix = LLStringUtil::null); LLScrollListItem* addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); - LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null); + LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null, + const std::string& prefix = LLStringUtil::null); // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. @@ -159,7 +169,7 @@ public: /*virtual*/ void mouseOverHighlightNthItem( S32 index ); private: - void showInspector(const LLUUID& avatar_id, bool is_group); + void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item); private: diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp new file mode 100644 index 0000000000..8cdc2d7c0b --- /dev/null +++ b/indra/newview/llnotificationlistitem.cpp @@ -0,0 +1,645 @@ +/** + * @file llnotificationlistitem.cpp + * @brief + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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" // must be first include + +#include "llnotificationlistitem.h" + +#include "llagent.h" +#include "llgroupactions.h" +#include "llinventoryicon.h" +#include "llwindow.h" +#include "v4color.h" +#include "lltrans.h" +#include "lluicolortable.h" +#include "message.h" +#include "llnotificationsutil.h" +#include <boost/regex.hpp> + +LLNotificationListItem::LLNotificationListItem(const Params& p) : LLPanel(p), + mParams(p), + mTitleBox(NULL), + mExpandBtn(NULL), + mCondenseBtn(NULL), + mCloseBtn(NULL), + mCondensedViewPanel(NULL), + mExpandedViewPanel(NULL), + mCondensedHeight(0), + mExpandedHeight(0), + mExpandedHeightResize(0), + mExpanded(false) +{ + mNotificationName = p.notification_name; +} + +BOOL LLNotificationListItem::postBuild() +{ + BOOL rv = LLPanel::postBuild(); + mTitleBox = getChild<LLTextBox>("notification_title"); + mTitleBoxExp = getChild<LLTextBox>("notification_title_exp"); + mNoticeTextExp = getChild<LLChatEntry>("notification_text_exp"); + + mTimeBox = getChild<LLTextBox>("notification_time"); + mTimeBoxExp = getChild<LLTextBox>("notification_time_exp"); + mExpandBtn = getChild<LLButton>("expand_btn"); + mCondenseBtn = getChild<LLButton>("condense_btn"); + mCloseBtn = getChild<LLButton>("close_btn"); + mCloseBtnExp = getChild<LLButton>("close_expanded_btn"); + + mTitleBox->setValue(mParams.title); + mTitleBoxExp->setValue(mParams.title); + mNoticeTextExp->setValue(mParams.title); + mNoticeTextExp->setEnabled(FALSE); + mNoticeTextExp->setTextExpandedCallback(boost::bind(&LLNotificationListItem::reshapeNotification, this)); + + mTitleBox->setContentTrusted(false); + mTitleBoxExp->setContentTrusted(false); + mNoticeTextExp->setContentTrusted(false); + + mTimeBox->setValue(buildNotificationDate(mParams.time_stamp)); + mTimeBoxExp->setValue(buildNotificationDate(mParams.time_stamp)); + + mExpandBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickExpandBtn,this)); + mCondenseBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCondenseBtn,this)); + + //mCloseBtn and mCloseExpandedBtn share the same callback + mCloseBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCloseBtn,this)); + mCloseBtnExp->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCloseBtn,this)); + + mCondensedViewPanel = getChild<LLPanel>("layout_panel_condensed_view"); + mExpandedViewPanel = getChild<LLPanel>("layout_panel_expanded_view"); + + std::string expanded_height_str = getString("item_expanded_height"); + std::string condensed_height_str = getString("item_condensed_height"); + + mExpandedHeight = (S32)atoi(expanded_height_str.c_str()); + mCondensedHeight = (S32)atoi(condensed_height_str.c_str()); + + setExpanded(FALSE); + + return rv; +} + +LLNotificationListItem::~LLNotificationListItem() +{ +} + +//static +std::string LLNotificationListItem::buildNotificationDate(const LLDate& time_stamp, ETimeType time_type) +{ + std::string timeStr; + switch(time_type) + { + case Local: + timeStr = "[" + LLTrans::getString("LTimeMthNum") + "]/[" + +LLTrans::getString("LTimeDay")+"]/[" + +LLTrans::getString("LTimeYear")+"] [" + +LLTrans::getString("LTimeHour")+"]:[" + +LLTrans::getString("LTimeMin")+ "]"; + break; + case UTC: + timeStr = "[" + LLTrans::getString("UTCTimeMth") + "]/[" + +LLTrans::getString("UTCTimeDay")+"]/[" + +LLTrans::getString("UTCTimeYr")+"] [" + +LLTrans::getString("UTCTimeHr")+"]:[" + +LLTrans::getString("UTCTimeMin")+"] [" + +LLTrans::getString("UTCTimeTimezone")+"]"; + break; + case SLT: + default: + timeStr = "[" + LLTrans::getString("TimeMonth") + "]/[" + +LLTrans::getString("TimeDay")+"]/[" + +LLTrans::getString("TimeYear")+"] [" + +LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"]"; + break; + } + LLSD substitution; + substitution["datetime"] = time_stamp; + LLStringUtil::format(timeStr, substitution); + return timeStr; +} + +void LLNotificationListItem::onClickCloseBtn() +{ + mOnItemClose(this); + close(); +} + +BOOL LLNotificationListItem::handleMouseUp(S32 x, S32 y, MASK mask) +{ + BOOL res = LLPanel::handleMouseUp(x, y, mask); + mOnItemClick(this); + return res; +} + +void LLNotificationListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" )); + mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" )); +} + +void LLNotificationListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" )); + mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" )); +} + +//static +LLNotificationListItem* LLNotificationListItem::create(const Params& p) +{ + if (LLNotificationListItem::getGroupInviteTypes().count(p.notification_name)) + { + return new LLGroupInviteNotificationListItem(p); + } + else if (LLNotificationListItem::getGroupNoticeTypes().count(p.notification_name)) + { + return new LLGroupNoticeNotificationListItem(p); + } + else if (LLNotificationListItem::getTransactionTypes().count(p.notification_name)) + { + return new LLTransactionNotificationListItem(p); + } + return new LLSystemNotificationListItem(p); +} + +//static +std::set<std::string> LLNotificationListItem::getGroupInviteTypes() +{ + return LLGroupInviteNotificationListItem::getTypes(); +} + + +std::set<std::string> LLNotificationListItem::getGroupNoticeTypes() +{ + return LLGroupNoticeNotificationListItem::getTypes(); +} + +//static +std::set<std::string> LLNotificationListItem::getTransactionTypes() +{ + return LLTransactionNotificationListItem::getTypes(); +} + +void LLNotificationListItem::onClickExpandBtn() +{ + setExpanded(TRUE); +} + +void LLNotificationListItem::onClickCondenseBtn() +{ + setExpanded(FALSE); +} + +void LLNotificationListItem::reshapeNotification() +{ + if(mExpanded) + { + S32 width = this->getRect().getWidth(); + this->reshape(width, mNoticeTextExp->getRect().getHeight() + mExpandedHeight, FALSE); + } +} + +void LLNotificationListItem::setExpanded(BOOL value) +{ + mCondensedViewPanel->setVisible(!value); + mExpandedViewPanel->setVisible(value); + S32 width = this->getRect().getWidth(); + + if (value) + { + this->reshape(width, mNoticeTextExp->getRect().getHeight() + mExpandedHeight, FALSE); + } + else + { + this->reshape(width, mCondensedHeight, FALSE); + } + mExpanded = value; + +} + +std::set<std::string> LLGroupInviteNotificationListItem::getTypes() +{ + std::set<std::string> types; + types.insert("JoinGroup"); + return types; +} + +std::set<std::string> LLGroupNoticeNotificationListItem::getTypes() +{ + std::set<std::string> types; + types.insert("GroupNotice"); + return types; +} + +std::set<std::string> LLTransactionNotificationListItem::getTypes() +{ + std::set<std::string> types; + types.insert("PaymentReceived"); + types.insert("PaymentSent"); + return types; +} + +LLGroupNotificationListItem::LLGroupNotificationListItem(const Params& p) + : LLNotificationListItem(p), + mSenderOrFeeBox(NULL) +{ +} + +LLGroupInviteNotificationListItem::LLGroupInviteNotificationListItem(const Params& p) + : LLGroupNotificationListItem(p) +{ + buildFromFile("panel_notification_list_item.xml"); +} + +BOOL LLGroupInviteNotificationListItem::postBuild() +{ + BOOL rv = LLGroupNotificationListItem::postBuild(); + setFee(mParams.fee); + mInviteButtonPanel = getChild<LLPanel>("button_panel"); + mInviteButtonPanel->setVisible(TRUE); + mJoinBtn = getChild<LLButton>("join_btn"); + mDeclineBtn = getChild<LLButton>("decline_btn"); + mInfoBtn = getChild<LLButton>("info_btn"); + + //invitation with any non-default group role, doesn't have newline characters at the end unlike simple invitations + std::string invitation_desc = mNoticeTextExp->getValue().asString(); + boost::regex pattern = boost::regex("\n\n$", boost::regex::perl|boost::regex::icase); + boost::match_results<std::string::const_iterator> matches; + if(!boost::regex_search(invitation_desc, matches, pattern)) + { + invitation_desc += "\n\n"; + mNoticeTextExp->setValue(invitation_desc); + } + + mJoinBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickJoinBtn,this)); + mDeclineBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickDeclineBtn,this)); + mInfoBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickInfoBtn,this)); + + std::string expanded_height_resize_str = getString("expanded_height_resize_for_attachment"); + mExpandedHeightResize = (S32)atoi(expanded_height_resize_str.c_str()); + + return rv; +} + +void LLGroupInviteNotificationListItem::onClickJoinBtn() +{ + if (!gAgent.canJoinGroups()) + { + LLNotificationsUtil::add("JoinedTooManyGroups"); + return; + } + + if(mParams.fee > 0) + { + LLSD args; + args["COST"] = llformat("%d", mParams.fee); + // Set the fee for next time to 0, so that we don't keep + // asking about a fee. + LLSD next_payload; + next_payload["group_id"]= mParams.group_id; + next_payload["transaction_id"]= mParams.transaction_id; + next_payload["fee"] = 0; + LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload); + } + else + { + send_improved_im(mParams.group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + IM_GROUP_INVITATION_ACCEPT, + mParams.transaction_id); + } + LLNotificationListItem::onClickCloseBtn(); +} + +void LLGroupInviteNotificationListItem::onClickDeclineBtn() +{ + send_improved_im(mParams.group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + IM_GROUP_INVITATION_DECLINE, + mParams.transaction_id); + LLNotificationListItem::onClickCloseBtn(); +} + +void LLGroupInviteNotificationListItem::onClickInfoBtn() +{ + LLGroupActions::show(mParams.group_id); +} + +void LLGroupInviteNotificationListItem::setFee(S32 fee) +{ + LLStringUtil::format_map_t string_args; + string_args["[GROUP_FEE]"] = llformat("%d", fee); + std::string fee_text = getString("group_fee_text", string_args); + mSenderOrFeeBox->setValue(fee_text); + mSenderOrFeeBoxExp->setValue(fee_text); + mSenderOrFeeBox->setVisible(TRUE); + mSenderOrFeeBoxExp->setVisible(TRUE); +} + +LLGroupNoticeNotificationListItem::LLGroupNoticeNotificationListItem(const Params& p) + : LLGroupNotificationListItem(p), + mAttachmentPanel(NULL), + mAttachmentTextBox(NULL), + mAttachmentIcon(NULL), + mAttachmentIconExp(NULL), + mInventoryOffer(NULL) +{ + if (mParams.inventory_offer.isDefined()) + { + mInventoryOffer = new LLOfferInfo(mParams.inventory_offer); + } + + buildFromFile("panel_notification_list_item.xml"); +} + +LLGroupNoticeNotificationListItem::~LLGroupNoticeNotificationListItem() +{ + LLGroupMgr::getInstance()->removeObserver(this); +} + +BOOL LLGroupNoticeNotificationListItem::postBuild() +{ + BOOL rv = LLGroupNotificationListItem::postBuild(); + + mAttachmentTextBox = getChild<LLTextBox>("attachment_text"); + mAttachmentIcon = getChild<LLIconCtrl>("attachment_icon"); + mAttachmentIconExp = getChild<LLIconCtrl>("attachment_icon_exp"); + mAttachmentPanel = getChild<LLPanel>("attachment_panel"); + mAttachmentPanel->setVisible(FALSE); + + + mTitleBox->setValue(mParams.subject); + mTitleBoxExp->setValue(mParams.subject); + mNoticeTextExp->setValue(mParams.message); + + mTimeBox->setValue(buildNotificationDate(mParams.time_stamp, UTC)); + mTimeBoxExp->setValue(buildNotificationDate(mParams.time_stamp, UTC)); + //Workaround: in case server timestamp is 0 - we use the time when notification was actually received + if (mParams.time_stamp.isNull()) + { + mTimeBox->setValue(buildNotificationDate(mParams.received_time, UTC)); + mTimeBoxExp->setValue(buildNotificationDate(mParams.received_time, UTC)); + } + setSender(mParams.sender); + + if (mInventoryOffer != NULL) + { + mAttachmentTextBox->setValue(mInventoryOffer->mDesc); + mAttachmentTextBox->setVisible(TRUE); + mAttachmentIcon->setVisible(TRUE); + + std::string icon_name = LLInventoryIcon::getIconName(mInventoryOffer->mType, + LLInventoryType::IT_TEXTURE); + mAttachmentIconExp->setValue(icon_name); + mAttachmentIconExp->setVisible(TRUE); + + mAttachmentTextBox->setClickedCallback(boost::bind( + &LLGroupNoticeNotificationListItem::onClickAttachment, this)); + + std::string expanded_height_resize_str = getString("expanded_height_resize_for_attachment"); + mExpandedHeightResize = (S32)atoi(expanded_height_resize_str.c_str()); + + mAttachmentPanel->setVisible(TRUE); + } + return rv; +} + +BOOL LLGroupNotificationListItem::postBuild() +{ + BOOL rv = LLNotificationListItem::postBuild(); + + mGroupIcon = getChild<LLGroupIconCtrl>("group_icon"); + mGroupIconExp = getChild<LLGroupIconCtrl>("group_icon_exp"); + mGroupNameBoxExp = getChild<LLTextBox>("group_name_exp"); + + mGroupIcon->setValue(mParams.group_id); + mGroupIconExp->setValue(mParams.group_id); + + mGroupIcon->setVisible(TRUE); + mGroupIconExp->setVisible(TRUE); + + mGroupId = mParams.group_id; + + mSenderOrFeeBox = getChild<LLTextBox>("sender_or_fee_box"); + mSenderOrFeeBoxExp = getChild<LLTextBox>("sender_or_fee_box_exp"); + + LLSD value(mParams.group_id); + setGroupId(value); + + return rv; +} + +void LLGroupNotificationListItem::changed(LLGroupChange gc) +{ + if (GC_PROPERTIES == gc) + { + updateFromCache(); + LLGroupMgr::getInstance()->removeObserver(this); + } +} + +bool LLGroupNotificationListItem::updateFromCache() +{ + LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId); + if (!group_data) return false; + setGroupName(group_data->mName); + return true; +} + +void LLGroupNotificationListItem::setGroupId(const LLUUID& value) +{ + LLGroupMgr* gm = LLGroupMgr::getInstance(); + if (mGroupId.notNull()) + { + gm->removeObserver(this); + + + mID = mGroupId; + + // Check if cache already contains image_id for that group + if (!updateFromCache()) + { + gm->addObserver(this); + gm->sendGroupPropertiesRequest(mGroupId); + } + } +} + +void LLGroupNotificationListItem::setGroupName(std::string name) +{ + if (!name.empty()) + { + LLStringUtil::format_map_t string_args; + string_args["[GROUP_NAME]"] = llformat("%s", name.c_str()); + std::string group_box_str = getString("group_name_text", string_args); + mGroupNameBoxExp->setValue(group_box_str); + mGroupNameBoxExp->setVisible(TRUE); + } + else + { + mGroupNameBoxExp->setValue(LLStringUtil::null); + mGroupNameBoxExp->setVisible(FALSE); + } +} + +void LLGroupNoticeNotificationListItem::setSender(std::string sender) +{ + if (!sender.empty()) + { + LLStringUtil::format_map_t string_args; + string_args["[SENDER_RESIDENT]"] = llformat("%s", sender.c_str()); + std::string sender_text = getString("sender_resident_text", string_args); + mSenderOrFeeBox->setValue(sender_text); + mSenderOrFeeBoxExp->setValue(sender_text); + mSenderOrFeeBox->setVisible(TRUE); + mSenderOrFeeBoxExp->setVisible(TRUE); + } else { + mSenderOrFeeBox->setValue(LLStringUtil::null); + mSenderOrFeeBoxExp->setValue(LLStringUtil::null); + mSenderOrFeeBox->setVisible(FALSE); + mSenderOrFeeBoxExp->setVisible(FALSE); + } +} +void LLGroupNoticeNotificationListItem::close() +{ + // The group notice dialog may be an inventory offer. + // If it has an inventory save button and that button is still enabled + // Then we need to send the inventory declined message + if (mInventoryOffer != NULL) + { + mInventoryOffer->forceResponse(IOR_DECLINE); + mInventoryOffer = NULL; + } + LLGroupMgr::getInstance()->removeObserver(this); +} + +void LLGroupNoticeNotificationListItem::onClickAttachment() +{ + if (mInventoryOffer != NULL) { + mInventoryOffer->forceResponse(IOR_ACCEPT); + + static const LLUIColor textColor = LLUIColorTable::instance().getColor( + "GroupNotifyDimmedTextColor"); + mAttachmentTextBox->setColor(textColor); + mAttachmentIconExp->setEnabled(FALSE); + + //if attachment isn't openable - notify about saving + if (!isAttachmentOpenable(mInventoryOffer->mType)) { + LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD()); + } + + mInventoryOffer = NULL; + } +} + +//static +bool LLGroupNoticeNotificationListItem::isAttachmentOpenable(LLAssetType::EType type) +{ + switch (type) + { + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_NOTECARD: + case LLAssetType::AT_IMAGE_JPEG: + case LLAssetType::AT_IMAGE_TGA: + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_TEXTURE_TGA: + return true; + default: + return false; + } +} + +LLTransactionNotificationListItem::LLTransactionNotificationListItem(const Params& p) + : LLNotificationListItem(p), + mAvatarIcon(NULL) +{ + buildFromFile("panel_notification_list_item.xml"); +} + +BOOL LLTransactionNotificationListItem::postBuild() +{ + BOOL rv = LLNotificationListItem::postBuild(); + mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon"); + mAvatarIconExp = getChild<LLAvatarIconCtrl>("avatar_icon_exp"); + mAvatarIcon->setValue("System_Notification"); + mAvatarIconExp->setValue("System_Notification"); + + mAvatarIcon->setVisible(TRUE); + mAvatarIconExp->setVisible(TRUE); + if((GOVERNOR_LINDEN_ID == mParams.paid_to_id) || + (GOVERNOR_LINDEN_ID == mParams.paid_from_id)) + { + return rv; + } + + if (mParams.notification_name == "PaymentReceived") + { + mAvatarIcon->setValue(mParams.paid_from_id); + mAvatarIconExp->setValue(mParams.paid_from_id); + } + else if (mParams.notification_name == "PaymentSent") + { + mAvatarIcon->setValue(mParams.paid_to_id); + mAvatarIconExp->setValue(mParams.paid_to_id); + } + + return rv; +} + +LLSystemNotificationListItem::LLSystemNotificationListItem(const Params& p) + : LLNotificationListItem(p), + mSystemNotificationIcon(NULL), + mIsCaution(false) +{ + buildFromFile("panel_notification_list_item.xml"); + mIsCaution = p.notification_priority >= NOTIFICATION_PRIORITY_HIGH; + if (mIsCaution) + { + mTitleBox->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); + mTitleBoxExp->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); + mNoticeTextExp->setReadOnlyColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); + mTimeBox->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); + mTimeBoxExp->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); + } +} + +BOOL LLSystemNotificationListItem::postBuild() +{ + BOOL rv = LLNotificationListItem::postBuild(); + mSystemNotificationIcon = getChild<LLIconCtrl>("system_notification_icon"); + mSystemNotificationIconExp = getChild<LLIconCtrl>("system_notification_icon_exp"); + if (mSystemNotificationIcon) + mSystemNotificationIcon->setVisible(TRUE); + if (mSystemNotificationIconExp) + mSystemNotificationIconExp->setVisible(TRUE); + return rv; +} diff --git a/indra/newview/llnotificationlistitem.h b/indra/newview/llnotificationlistitem.h new file mode 100644 index 0000000000..9a4ce2be4b --- /dev/null +++ b/indra/newview/llnotificationlistitem.h @@ -0,0 +1,250 @@ +/** + * @file llnotificationlistitem.h + * @brief + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_LLNOTIFICATIONLISTITEM_H +#define LL_LLNOTIFICATIONLISTITEM_H + +#include "llpanel.h" +#include "lllayoutstack.h" +#include "lltextbox.h" +#include "llviewertexteditor.h" +#include "llbutton.h" +#include "llgroupiconctrl.h" +#include "llavatariconctrl.h" +#include "llchatentry.h" +#include "llgroupmgr.h" +#include "llviewermessage.h" + +#include <string> + +class LLNotificationListItem : public LLPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + { + LLUUID notification_id; + LLUUID transaction_id; + LLUUID group_id; + LLUUID paid_from_id; + LLUUID paid_to_id; + std::string notification_name; + std::string title; + std::string subject; + std::string message; + std::string sender; + S32 fee; + LLDate time_stamp; + LLDate received_time; + LLSD inventory_offer; + e_notification_priority notification_priority; + Params() {}; + }; + + static LLNotificationListItem* create(const Params& p); + + static std::set<std::string> getTransactionTypes(); + static std::set<std::string> getGroupInviteTypes(); + static std::set<std::string> getGroupNoticeTypes(); + + // title + void setTitle( std::string title ); + + // get item's ID + LLUUID getID() { return mParams.notification_id; } + std::string& getTitle() { return mTitle; } + std::string& getNotificationName() { return mNotificationName; } + + // handlers + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + //callbacks + typedef boost::function<void (LLNotificationListItem* item)> item_callback_t; + typedef boost::signals2::signal<void (LLNotificationListItem* item)> item_signal_t; + item_signal_t mOnItemClose; + item_signal_t mOnItemClick; + boost::signals2::connection setOnItemCloseCallback(item_callback_t cb) { return mOnItemClose.connect(cb); } + boost::signals2::connection setOnItemClickCallback(item_callback_t cb) { return mOnItemClick.connect(cb); } + + virtual bool showPopup() { return true; } + void setExpanded(BOOL value); + virtual BOOL postBuild(); + void reshapeNotification(); + + typedef enum e_time_type + { + SLT = 1, + Local = 2, + UTC = 3, + }ETimeType; + +protected: + LLNotificationListItem(const Params& p); + virtual ~LLNotificationListItem(); + + static std::string buildNotificationDate(const LLDate& time_stamp, ETimeType time_type = SLT); + void onClickExpandBtn(); + void onClickCondenseBtn(); + void onClickCloseBtn(); + virtual void close() {}; + + Params mParams; + LLTextBox* mTitleBox; + LLTextBox* mTitleBoxExp; + LLChatEntry* mNoticeTextExp; + LLTextBox* mTimeBox; + LLTextBox* mTimeBoxExp; + LLButton* mExpandBtn; + LLButton* mCondenseBtn; + LLButton* mCloseBtn; + LLButton* mCloseBtnExp; + LLPanel* mCondensedViewPanel; + LLPanel* mExpandedViewPanel; + std::string mTitle; + std::string mNotificationName; + S32 mCondensedHeight; + S32 mExpandedHeight; + S32 mExpandedHeightResize; + bool mExpanded; +}; + +class LLGroupNotificationListItem + : public LLNotificationListItem, public LLGroupMgrObserver +{ +public: + virtual BOOL postBuild(); + + void setGroupId(const LLUUID& value); + // LLGroupMgrObserver observer trigger + virtual void changed(LLGroupChange gc); + + friend class LLNotificationListItem; +protected: + LLGroupNotificationListItem(const Params& p); + + LLGroupIconCtrl* mGroupIcon; + LLGroupIconCtrl* mGroupIconExp; + LLUUID mGroupId; + LLTextBox* mSenderOrFeeBox; + LLTextBox* mSenderOrFeeBoxExp; + LLTextBox* mGroupNameBoxExp; + +private: + LLGroupNotificationListItem(const LLGroupNotificationListItem &); + LLGroupNotificationListItem & operator=(LLGroupNotificationListItem &); + + void setGroupName(std::string name); + bool updateFromCache(); +}; + +class LLGroupInviteNotificationListItem + : public LLGroupNotificationListItem +{ +public: + static std::set<std::string> getTypes(); + virtual BOOL postBuild(); + + /*virtual*/ bool showPopup() { return false; } + +private: + friend class LLNotificationListItem; + LLGroupInviteNotificationListItem(const Params& p); + LLGroupInviteNotificationListItem(const LLGroupInviteNotificationListItem &); + LLGroupInviteNotificationListItem & operator=(LLGroupInviteNotificationListItem &); + + void setFee(S32 fee); + + void onClickJoinBtn(); + void onClickDeclineBtn(); + void onClickInfoBtn(); + + LLPanel* mInviteButtonPanel; + LLButton* mJoinBtn; + LLButton* mDeclineBtn; + LLButton* mInfoBtn; +}; + +class LLGroupNoticeNotificationListItem + : public LLGroupNotificationListItem +{ +public: + ~LLGroupNoticeNotificationListItem(); + static std::set<std::string> getTypes(); + virtual BOOL postBuild(); + + /*virtual*/ bool showPopup() { return false; } + +private: + friend class LLNotificationListItem; + LLGroupNoticeNotificationListItem(const Params& p); + LLGroupNoticeNotificationListItem(const LLGroupNoticeNotificationListItem &); + LLGroupNoticeNotificationListItem & operator=(LLGroupNoticeNotificationListItem &); + + void setSender(std::string sender); + void onClickAttachment(); + /*virtual*/ void close(); + + static bool isAttachmentOpenable(LLAssetType::EType); + + LLPanel* mAttachmentPanel; + LLTextBox* mAttachmentTextBox; + LLIconCtrl* mAttachmentIcon; + LLIconCtrl* mAttachmentIconExp; + LLOfferInfo* mInventoryOffer; +}; + +class LLTransactionNotificationListItem : public LLNotificationListItem +{ +public: + static std::set<std::string> getTypes(); + virtual BOOL postBuild(); +private: + friend class LLNotificationListItem; + LLTransactionNotificationListItem(const Params& p); + LLTransactionNotificationListItem(const LLTransactionNotificationListItem &); + LLTransactionNotificationListItem & operator=(LLTransactionNotificationListItem &); + LLAvatarIconCtrl* mAvatarIcon; + LLAvatarIconCtrl* mAvatarIconExp; +}; + +class LLSystemNotificationListItem : public LLNotificationListItem +{ +public: + virtual BOOL postBuild(); +private: + friend class LLNotificationListItem; + LLSystemNotificationListItem(const Params& p); + LLSystemNotificationListItem(const LLSystemNotificationListItem &); + LLSystemNotificationListItem & operator=(LLSystemNotificationListItem &); + LLIconCtrl* mSystemNotificationIcon; + LLIconCtrl* mSystemNotificationIconExp; + bool mIsCaution; +}; + +#endif // LL_LLNOTIFICATIONLISTITEM_H + + diff --git a/indra/newview/llnotificationlistview.cpp b/indra/newview/llnotificationlistview.cpp new file mode 100644 index 0000000000..9dce68c9c6 --- /dev/null +++ b/indra/newview/llnotificationlistview.cpp @@ -0,0 +1,44 @@ +/** + * @file llnotificationlistview.cpp + * @brief + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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 "llnotificationlistview.h" + +static const LLDefaultChildRegistry::Register<LLNotificationListView> notification_list_view("notification_list_view"); + +LLNotificationListView::LLNotificationListView(const Params& p) + : LLFlatListView(p) +{} + +LLNotificationListView::~LLNotificationListView() +{} + +bool LLNotificationListView::addNotification(LLNotificationListItem * item) +{ + return LLFlatListView::addItem(item, item->getID(), ADD_TOP); +} + +//EOF diff --git a/indra/newview/llnotificationlistview.h b/indra/newview/llnotificationlistview.h new file mode 100644 index 0000000000..307ad87789 --- /dev/null +++ b/indra/newview/llnotificationlistview.h @@ -0,0 +1,49 @@ +/** + * @file llnotificationlistview.h + * @brief LLNotificationListView class to support notifications list contained in enclosing floater. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_LLNOTIFICATIONLISTVIEW_H +#define LL_LLNOTIFICATIONLISTVIEW_H + +#include "llflatlistview.h" +#include "llnotificationlistitem.h" + +/** + * Notification list + */ +class LLNotificationListView : public LLFlatListView +{ + LOG_CLASS(LLNotificationListView); +public: + struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> {}; + + LLNotificationListView(const Params& p); + ~LLNotificationListView(); + friend class LLUICtrlFactory; + + virtual bool addNotification(LLNotificationListItem * item); +}; + +#endif diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 9bd6007772..b7e1b2d3a4 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1168,6 +1168,8 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO targetPanel->setVisible(show); toggleTypeSpecificControls(type); + // Update type controls here + updateTypeSpecificControls(type); if (show) { @@ -1179,7 +1181,6 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO mNameEditor->setText(mWearableItem->getName()); updatePanelPickerControls(type); - updateTypeSpecificControls(type); // clear and rebuild visual param list U8 num_subparts = wearable_entry->mSubparts.size(); diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..7c07301762 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -33,6 +33,7 @@ #include "llfloaterexperiencepicker.h" #include "llfloaterreg.h" #include "llhandle.h" +#include "llnamelistctrl.h" #include "llscrolllistctrl.h" #include "llviewerregion.h" #include "llagent.h" @@ -54,7 +55,7 @@ LLPanelExperienceListEditor::LLPanelExperienceListEditor() BOOL LLPanelExperienceListEditor::postBuild() { - mItems = getChild<LLScrollListCtrl>("experience_list"); + mItems = getChild<LLNameListCtrl>("experience_list"); mAdd = getChild<LLButton>("btn_add"); mRemove = getChild<LLButton>("btn_remove"); mProfile = getChild<LLButton>("btn_profile"); @@ -178,12 +179,13 @@ void LLPanelExperienceListEditor::onItems() { const LLUUID& experience = *it; item["id"]=experience; + item["target"] = LLNameListCtrl::EXPERIENCE; LLSD& columns = item["columns"]; columns[0]["column"] = "experience_name"; columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle<LLPanelExperienceListEditor>(), _1)); } diff --git a/indra/newview/llpanelexperiencelisteditor.h b/indra/newview/llpanelexperiencelisteditor.h index f69f0509be..bc9867752d 100644 --- a/indra/newview/llpanelexperiencelisteditor.h +++ b/indra/newview/llpanelexperiencelisteditor.h @@ -31,6 +31,7 @@ #include "lluuid.h" #include <set> +class LLNameListCtrl; class LLScrollListCtrl; class LLButton; class LLFloaterExperiencePicker; @@ -82,7 +83,7 @@ private: uuid_list_t mExperienceIds; - LLScrollListCtrl* mItems; + LLNameListCtrl* mItems; filter_list mFilters; LLButton* mAdd; LLButton* mRemove; diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index 70d826a407..43dc7569a4 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -42,6 +42,7 @@ #include "llviewercontrol.h" #include "llfloater.h" #include "lltrans.h" +#include <boost/regex.hpp> #define BTN_FIND "find" #define BTN_OK "ok_btn" @@ -147,6 +148,46 @@ void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* u void LLPanelExperiencePicker::onBtnFind() { mCurrentPage=1; + boost::cmatch what; + std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString(); + const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile"); + if (boost::regex_match(text.c_str(), what, expression)) + { + LLURI uri(text); + LLSD path_array = uri.pathArray(); + if (path_array.size() == 4) + { + std::string exp_id = path_array.get(2).asString(); + LLUUID experience_id(exp_id); + if (!experience_id.isNull()) + { + const LLSD& experience_details = LLExperienceCache::get(experience_id); + if(!experience_details.isUndefined()) + { + std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); + if(!experience_name_string.empty()) + { + getChild<LLUICtrl>(TEXT_EDIT)->setValue(experience_name_string); + } + } + else + { + getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems(); + getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching")); + + getChildView(BTN_OK)->setEnabled(FALSE); + getChildView(BTN_PROFILE)->setEnabled(FALSE); + + getChildView(BTN_RIGHT)->setEnabled(FALSE); + getChildView(BTN_LEFT)->setEnabled(FALSE); + LLExperienceCache::get(experience_id, boost::bind(&LLPanelExperiencePicker::onBtnFind, this)); + return; + } + } + } + } + + find(); } @@ -183,7 +224,6 @@ void LLPanelExperiencePicker::find() getChildView(BTN_LEFT)->setEnabled(FALSE); } - bool LLPanelExperiencePicker::isSelectButtonEnabled() { LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS); diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 9823e84cd9..d7e89b4832 100755 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -307,7 +307,7 @@ private: LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material); } - object->setTEMaterialParams(face, new_material); + object->setTEMaterialParams(face, new_material, TRUE); return new_material; } return NULL; diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index f67a90fd01..342b57ba4a 100755 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -338,7 +338,7 @@ void LLPanelGroup::update(LLGroupChange gc) group_name_ctrl->setToolTip(group_name); LLGroupData agent_gdatap; - bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike(); + bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery(); bool join_btn_visible = !is_member && gdatap->mOpenEnrollment; mButtonJoin->setVisible(join_btn_visible); @@ -470,7 +470,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) } LLGroupData agent_gdatap; - bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike(); + bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery(); tab_roles->setVisible(is_member); tab_notices->setVisible(is_member); diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp index 76792cc6fd..cffda02aa0 100644 --- a/indra/newview/llpanelgroupbulk.cpp +++ b/indra/newview/llpanelgroupbulk.cpp @@ -97,6 +97,7 @@ void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata) if(picker) { root_floater->addDependentFloater(picker); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(panelp->mImplementation->mGroupID); } } } diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 7ffaa05919..b2164c1f21 100755 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -287,11 +287,6 @@ void LLPanelGroupGeneral::activate() { LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID); LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); - - if (!gdatap || !gdatap->isMemberDataComplete() ) - { - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - } mFirstUse = FALSE; } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index e662a05dfc..866cb8dbef 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -243,56 +243,59 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap) LLGroupMgrGroupData::member_list_t::iterator agent_iter = gdatap->mMembers.find(gAgent.getID()); + //loop over the agent's roles in the group + //then add those roles to the list of roles that the agent + //can invite people to be. + //if the user is the owner then we add + //all of the roles in the group, + //else if they have the add to roles power + //we add every role but owner, + //else if they have the limited add to roles power + //we add every role the user is in, + //else we just add to everyone + bool is_owner = FALSE; + bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, + GP_ROLE_ASSIGN_MEMBER); + bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, + GP_ROLE_ASSIGN_MEMBER_LIMITED); + LLGroupMemberData* member_data = NULL; //get the member data for the agent if it exists - if ( agent_iter != gdatap->mMembers.end() ) + if (agent_iter != gdatap->mMembers.end()) { - LLGroupMemberData* member_data = (*agent_iter).second; - - //loop over the agent's roles in the group - //then add those roles to the list of roles that the agent - //can invite people to be - if ( member_data && mRoleNames) + member_data = (*agent_iter).second; + if (member_data && mRoleNames) { - //if the user is the owner then we add - //all of the roles in the group - //else if they have the add to roles power - //we add every role but owner, - //else if they have the limited add to roles power - //we add every role the user is in - //else we just add to everyone - bool is_owner = member_data->isOwner(); - bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, - GP_ROLE_ASSIGN_MEMBER); - bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, - GP_ROLE_ASSIGN_MEMBER_LIMITED); + is_owner = member_data->isOwner(); + }//end if member data is not null + }//end if agent is in the group + - LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin(); - LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); - //populate the role list - for ( ; rit != end; ++rit) + LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin(); + LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); + + //populate the role list: + for ( ; rit != end; ++rit) + { + LLUUID role_id = (*rit).first; + LLRoleData rd; + if ( gdatap->getRoleData(role_id,rd) ) + { + // Owners can add any role. + if ( is_owner + // Even 'can_assign_any' can't add owner role. + || (can_assign_any && role_id != gdatap->mOwnerRole) + // Add all roles user is in + || (can_assign_limited && member_data && member_data->isInRole(role_id)) + // Everyone role. + || role_id == LLUUID::null ) { - LLUUID role_id = (*rit).first; - LLRoleData rd; - if ( gdatap->getRoleData(role_id,rd) ) - { - // Owners can add any role. - if ( is_owner - // Even 'can_assign_any' can't add owner role. - || (can_assign_any && role_id != gdatap->mOwnerRole) - // Add all roles user is in - || (can_assign_limited && member_data->isInRole(role_id)) - // Everyone role. - || role_id == LLUUID::null ) - { - mRoleNames->add(rd.mRoleName, - role_id, - ADD_BOTTOM); - } - } + mRoleNames->add(rd.mRoleName, + role_id, + ADD_BOTTOM); } - }//end if member data is not null - }//end if agent is in the group + } + } } //static @@ -579,7 +582,8 @@ void LLPanelGroupInvite::updateLists() { waiting = true; } - if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete()) + if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() + && (gdatap->isRoleMemberDataComplete() || !gdatap->mMembers.size())) // MAINT-5270: large groups receives an empty members list without some powers, so RoleMemberData wouldn't be complete for them { if ( mImplementation->mRoleNames ) { diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index c3a10b3fa0..00c204e702 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -350,12 +350,10 @@ void LLPanelGroupRoles::update(LLGroupChange gc) void LLPanelGroupRoles::activate() { + if (!gAgent.isInGroup(mGroupID)) return; + // Start requesting member and role data if needed. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); - if (!gdatap || !gdatap->isMemberDataComplete() ) - { - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - } if (!gdatap || !gdatap->isRoleDataComplete() ) { @@ -364,13 +362,7 @@ void LLPanelGroupRoles::activate() LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID); } - - // Check role-member mapping data. - if (!gdatap || !gdatap->isRoleMemberDataComplete() ) - { - LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); - } - + // Need this to get base group member powers if (!gdatap || !gdatap->isGroupPropertiesDataComplete() ) { @@ -1163,7 +1155,37 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata) if ( selfp ) { - selfp->handleEjectMembers(); + selfp->confirmEjectMembers(); + } +} + +void LLPanelGroupMembersSubTab::confirmEjectMembers() +{ + std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); + if (selection.empty()) return; + + S32 selection_count = selection.size(); + if (selection_count == 1) + { + LLSD args; + std::string fullname; + gCacheName->getFullName(mMembersList->getValue(), fullname); + args["AVATAR_NAME"] = fullname; + LLSD payload; + LLNotificationsUtil::add("EjectGroupMemberWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); + } + else + { + LLSD args; + args["COUNT"] = llformat("%d", selection_count); + LLSD payload; + LLNotificationsUtil::add("EjectGroupMembersWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); } } @@ -1190,6 +1212,16 @@ void LLPanelGroupMembersSubTab::handleEjectMembers() LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members); } +bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) // Eject button + { + handleEjectMembers(); + } + return false; +} + void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members) { LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -1327,15 +1359,26 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick() void LLPanelGroupMembersSubTab::activate() { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + LLPanelGroupSubTab::activate(); if(!mActivated) { + if (!gdatap || !gdatap->isMemberDataComplete()) + { + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + } + + if (!gdatap || !gdatap->isRoleMemberDataComplete()) + { + LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); + } + update(GC_ALL); mActivated = true; } else { - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); // Members can be removed outside of this tab, checking changes if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount())) { @@ -1636,7 +1679,13 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc) { // Build a string with info on retrieval progress. std::ostringstream retrieved; - if ( !gdatap->isMemberDataComplete() ) + + if ( gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && !gdatap->mMembers.size() ) + { + // MAINT-5237 + retrieved << "Member list not available."; + } + else if ( !gdatap->isMemberDataComplete() ) { // Still busy retreiving member list. retrieved << "Retrieving member list (" << gdatap->mMembers.size() @@ -1783,7 +1832,7 @@ void LLPanelGroupMembersSubTab::updateMembers() { mMembersList->setEnabled(TRUE); } - else + else if (gdatap->mMembers.size()) { mMembersList->setEnabled(FALSE); mMembersList->setCommentText(std::string("No match.")); @@ -1801,7 +1850,47 @@ void LLPanelGroupMembersSubTab::updateMembers() void LLPanelGroupMembersSubTab::onBanMember(void* user_data) { LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data); - self->handleBanMember(); + self->confirmBanMembers(); +} + +void LLPanelGroupMembersSubTab::confirmBanMembers() +{ + std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); + if (selection.empty()) return; + + S32 selection_count = selection.size(); + if (selection_count == 1) + { + LLSD args; + std::string fullname; + gCacheName->getFullName(mMembersList->getValue(), fullname); + args["AVATAR_NAME"] = fullname; + LLSD payload; + LLNotificationsUtil::add("BanGroupMemberWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2)); + } + else + { + LLSD args; + args["COUNT"] = llformat("%d", selection_count); + LLSD payload; + LLNotificationsUtil::add("BanGroupMembersWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2)); + } +} + +bool LLPanelGroupMembersSubTab::handleBanCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) // Eject button + { + handleBanMember(); + } + return false; } void LLPanelGroupMembersSubTab::handleBanMember() @@ -2111,20 +2200,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) mDeleteRoleButton->setEnabled(FALSE); } } - - if(!mFirstOpen) - { - if (!gdatap || !gdatap->isMemberDataComplete()) - { - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - } - - if (!gdatap || !gdatap->isRoleMemberDataComplete()) - { - LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); - } - } - + if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc) && gdatap && gdatap->isMemberDataComplete() diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 540b24ada6..9a696124a8 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -171,6 +171,7 @@ public: void handleEjectMembers(); void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members); bool handleEjectCallback(const LLSD& notification, const LLSD& response); + void confirmEjectMembers(); static void onRoleCheck(LLUICtrl* check, void* user_data); void handleRoleCheck(const LLUUID& role_id, @@ -178,6 +179,8 @@ public: static void onBanMember(void* user_data); void handleBanMember(); + bool handleBanCallback(const LLSD& notification, const LLSD& response); + void confirmBanMembers(); void applyMemberChanges(); diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index a660cb3b21..06bb886ae8 100755 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -128,6 +128,10 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); std::string name = parcel_mgr->getAgentParcelName(); LLVector3 agent_pos = gAgent.getPositionAgent(); + + std::string desc; + LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, agent_pos); + mNotesEditor->setText(desc); if (name.empty()) { @@ -143,7 +147,8 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) } else { - region_name = getString("unknown"); + LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos); + region_name = desc; } mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)", @@ -154,10 +159,6 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) mLandmarkTitleEditor->setText(name); } - std::string desc; - LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, agent_pos); - mNotesEditor->setText(desc); - // Moved landmark creation here from LLPanelLandmarkInfo::processParcelInfo() // because we use only agent's current coordinates instead of waiting for // remote parcel request to complete. diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index cc8c3edd51..953f234a53 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -229,7 +229,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, } } server_choice_combo->sortByName(); - server_choice_combo->addSeparator(ADD_TOP); LL_DEBUGS("AppInit")<<"adding current "<<current_grid<<LL_ENDL; server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(), current_grid, diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 17c0b226d0..4229419fce 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -604,7 +604,7 @@ void LLPanelMainInventory::updateItemcountText() } else { - text = getString("ItemcountUnknown"); + text = getString("ItemcountUnknown", string_args); } mCounterCtrl->setValue(text); @@ -1134,14 +1134,12 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const std::string &item_name = current_item->getViewModelItem()->getName(); mFilterSubString = item_name; + LLInventoryFilter &filter = mActivePanel->getFilter(); - filter.setFilterSubString(item_name); - mFilterEditor->setText(item_name); + filter.setFindAllLinksMode(item_name, item_id); + mFilterEditor->setText(item_name); mFilterEditor->setFocus(TRUE); - filter.setFilterUUID(item_id); - filter.setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - filter.setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS); } } diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index f7c2f629ec..c5fda3c136 100755 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -62,7 +62,7 @@ LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params LLInboxInventoryPanel::~LLInboxInventoryPanel() {} -LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) +LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop) { LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); @@ -74,6 +74,7 @@ LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge params.tool_tip = params.name; params.font_color = item_color; params.font_highlight_color = item_color; + params.allow_drop = allow_drop; return LLUICtrlFactory::create<LLInboxFolderViewFolder>(params); } diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index c05e18c300..66aafe83d1 100755 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -46,7 +46,7 @@ public: ~LLInboxInventoryPanel(); // virtual - LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); + LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop); LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); }; diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 2856ea9db1..d7c43c224c 100755 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -319,6 +319,10 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media // Helper to set media control to media URL as required void LLPanelMediaSettingsGeneral::updateMediaPreview() { + if(LLTrans::getString("Multiple Media") == mHomeURL->getValue().asString()) + { + return; + } if ( mHomeURL->getValue().asString().length() > 0 ) { if(mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString()) diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index dcd0aab3ab..5dd44b4444 100755 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1739,9 +1739,10 @@ void LLPanelObject::sendSculpt() return; LLSculptParams sculpt_params; + LLUUID sculpt_id = LLUUID::null; if (mCtrlSculptTexture) - sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID()); + sculpt_id = mCtrlSculptTexture->getImageAssetID(); U8 sculpt_type = 0; @@ -1765,7 +1766,7 @@ void LLPanelObject::sendSculpt() if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get())) sculpt_type |= LL_SCULPT_FLAG_INVERT; - sculpt_params.setSculptType(sculpt_type); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); } @@ -2000,7 +2001,11 @@ void LLPanelObject::onCancelSculpt(const LLSD& data) LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); if(!mTextureCtrl) return; - + + if(mSculptTextureRevert == LLUUID::null) + { + mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE); + } mTextureCtrl->setImageAssetID(mSculptTextureRevert); sendSculpt(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index bf15f56b44..c8af5b6718 100755 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -130,7 +130,7 @@ public: virtual void move(LLFolderViewModelItem* parent_listener); virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; - virtual BOOL cutToClipboard() const; + virtual BOOL cutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); @@ -542,7 +542,7 @@ BOOL LLTaskInvFVBridge::copyToClipboard() const return FALSE; } -BOOL LLTaskInvFVBridge::cutToClipboard() const +BOOL LLTaskInvFVBridge::cutToClipboard() { return FALSE; } @@ -1163,7 +1163,13 @@ void LLTaskNotecardBridge::openItem() { return; } - if(object->permModify() || gAgent.isGodlike()) + + // Note: even if we are not allowed to modify copyable notecard, we should be able to view it + LLInventoryItem *item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID)); + BOOL item_copy = item && gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); + if( item_copy + || object->permModify() + || gAgent.isGodlike()) { LLPreviewNotecard* preview = LLFloaterReg::showTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(mUUID), TAKE_FOCUS_YES); if (preview) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 5977d558d3..de4efc8612 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -85,6 +85,8 @@ 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"; +const S32 BASE_MAX_AGENT_GROUPS = 42; +const S32 PREMIUM_MAX_AGENT_GROUPS = 60; extern S32 gMaxAgentGroups; @@ -585,6 +587,7 @@ BOOL LLPanelPeople::postBuild() 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)); + getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this)); mTabContainer = getChild<LLTabContainer>("tabs"); mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); @@ -902,8 +905,11 @@ void LLPanelPeople::updateButtons() LLPanel* groups_panel = mTabContainer->getCurrentPanel(); groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected - groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size())); - groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.size()))); + + U32 groups_count = gAgent.mGroups.size(); + U32 groups_ramaining = gMaxAgentGroups > groups_count ? gMaxAgentGroups - groups_count : 0; + groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d", groups_count)); + groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_ramaining)); } else { @@ -1114,6 +1120,14 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) } } +void LLPanelPeople::onGroupLimitInfo() +{ + LLSD args; + args["MAX_BASIC"] = BASE_MAX_AGENT_GROUPS; + args["MAX_PREMIUM"] = PREMIUM_MAX_AGENT_GROUPS; + LLNotificationsUtil::add("GroupLimitInfo", args); +} + void LLPanelPeople::onTabSelected(const LLSD& param) { std::string tab_name = getChild<LLPanel>(param.asString())->getName(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index c1d7a134fa..eb7e76a772 100755 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -93,6 +93,7 @@ private: // UI callbacks void onFilterEdit(const std::string& search_string); + void onGroupLimitInfo(); void onTabSelected(const LLSD& param); void onAddFriendButtonClicked(); void onAddFriendWizButtonClicked(); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index d73a5b402e..55c09d85ea 100755 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -432,7 +432,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) mNoPicks = !mPicksList->size(); } - else if(APT_CLASSIFIEDS == type) + else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) { LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); if(c_info && getAvatarId() == c_info->target_id) diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index e853b2d050..1a665d4c1d 100755 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -53,6 +53,8 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" +const F64 COVENANT_REFRESH_TIME_SEC = 60.0f; + static LLPanelInjector<LLPanelPlaceProfile> t_place_profile("panel_place_profile"); // Statics for textures filenames @@ -76,6 +78,7 @@ static std::string icon_see_avs_off; LLPanelPlaceProfile::LLPanelPlaceProfile() : LLPanelPlaceInfo(), + mNextCovenantUpdateTime(0), mForSalePanel(NULL), mYouAreHerePanel(NULL), mSelectedParcelID(-1), @@ -162,6 +165,9 @@ BOOL LLPanelPlaceProfile::postBuild() icon_see_avs_on = getString("icon_SeeAVs_On"); icon_see_avs_off = getString("icon_SeeAVs_Off"); + mLastSelectedRegionID = LLUUID::null; + mNextCovenantUpdateTime = 0; + return TRUE; } @@ -170,6 +176,9 @@ void LLPanelPlaceProfile::resetLocation() { LLPanelPlaceInfo::resetLocation(); + mLastSelectedRegionID = LLUUID::null; + mNextCovenantUpdateTime = 0; + mForSalePanel->setVisible(FALSE); mYouAreHerePanel->setVisible(FALSE); @@ -330,13 +339,20 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, if (!region || !parcel) return; - // send EstateCovenantInfo message - LLMessageSystem *msg = gMessageSystem; - msg->newMessage("EstateCovenantRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); - msg->sendReliable(region->getHost()); + if (mLastSelectedRegionID != region->getRegionID() + || mNextCovenantUpdateTime < LLTimer::getElapsedSeconds()) + { + // send EstateCovenantInfo message + // Note: LLPanelPlaceProfile doesn't change Covenant's content and any + // changes made by Estate floater should be requested by Estate floater + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("EstateCovenantRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->sendReliable(region->getHost()); + mNextCovenantUpdateTime = LLTimer::getElapsedSeconds() + COVENANT_REFRESH_TIME_SEC; + } LLParcelData parcel_data; diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index 4547e14b2e..3d2654fc12 100755 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -71,6 +71,7 @@ private: */ S32 mSelectedParcelID; LLUUID mLastSelectedRegionID; + F64 mNextCovenantUpdateTime; //seconds since client start LLPanel* mForSalePanel; LLPanel* mYouAreHerePanel; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 4bcd932d4b..a9a0c30e26 100755 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -921,7 +921,12 @@ void LLPanelPlaces::onBackButtonClicked() void LLPanelPlaces::togglePickPanel(BOOL visible) { if (mPickPanel) + { mPickPanel->setVisible(visible); + mPlaceProfile->setVisible(!visible); + updateVerbs(); + } + } void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) @@ -1141,16 +1146,21 @@ void LLPanelPlaces::updateVerbs() bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE; bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; + bool is_pick_panel_visible = false; + if(mPickPanel) + { + is_pick_panel_visible = mPickPanel->isInVisibleChain(); + } bool have_3d_pos = ! mPosGlobal.isExactlyZero(); - mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); - mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); + mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn); mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn); mSaveBtn->setVisible(isLandmarkEditModeOn); mCancelBtn->setVisible(isLandmarkEditModeOn); mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); - mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn); + mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos); diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index c8a201a5c8..c55e230b5e 100755 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -48,6 +48,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + void onResolutionCommit(LLUICtrl* ctrl); + private: /*virtual*/ std::string getWidthSpinnerName() const { return "inventory_snapshot_width"; } /*virtual*/ std::string getHeightSpinnerName() const { return "inventory_snapshot_height"; } @@ -72,6 +74,8 @@ BOOL LLPanelSnapshotInventory::postBuild() { getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(FALSE); getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE); + + getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1)); return LLPanelSnapshot::postBuild(); } @@ -89,6 +93,13 @@ void LLPanelSnapshotInventory::updateControls(const LLSD& info) getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); } +void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) +{ + BOOL current_window_selected = (getChild<LLComboBox>(getImageSizeComboName())->getCurrentIndex() == 3); + getChild<LLSpinCtrl>(getWidthSpinnerName())->setVisible(!current_window_selected); + getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected); +} + void LLPanelSnapshotInventory::onSend() { LLFloaterSnapshot::saveTexture(); diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 43e38b95e2..01dfdc4ece 100755 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -58,6 +58,8 @@ private: /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; /*virtual*/ void updateControls(const LLSD& info); + S32 mLocalFormat; + void onFormatComboCommit(LLUICtrl* ctrl); void onQualitySliderCommit(LLUICtrl* ctrl); void onSaveFlyoutCommit(LLUICtrl* ctrl); @@ -67,6 +69,7 @@ static LLPanelInjector<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal") LLPanelSnapshotLocal::LLPanelSnapshotLocal() { + mLocalFormat = gSavedSettings.getS32("SnapshotFormat"); mCommitCallbackRegistrar.add("Local.Cancel", boost::bind(&LLPanelSnapshotLocal::cancel, this)); } @@ -83,6 +86,10 @@ BOOL LLPanelSnapshotLocal::postBuild() // virtual void LLPanelSnapshotLocal::onOpen(const LLSD& key) { + if(gSavedSettings.getS32("SnapshotFormat") != mLocalFormat) + { + getChild<LLComboBox>("local_format_combo")->selectNthItem(mLocalFormat); + } LLPanelSnapshot::onOpen(key); } @@ -129,6 +136,7 @@ void LLPanelSnapshotLocal::updateControls(const LLSD& info) void LLPanelSnapshotLocal::onFormatComboCommit(LLUICtrl* ctrl) { + mLocalFormat = getImageFormat(); // will call updateControls() LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); } diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp index 8e37b1418c..8e37b1418c 100755..100644 --- a/indra/newview/llpanelsnapshotpostcard.cpp +++ b/indra/newview/llpanelsnapshotpostcard.cpp diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index bf2652cb49..fb21b980dc 100755 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -49,6 +49,7 @@ #include "llviewerinventory.h" #include "llviewerwindow.h" #include "lltrans.h" +#include "roles_constants.h" // Constants @@ -230,8 +231,23 @@ void LLPreview::refreshFromItem() } getChild<LLUICtrl>("desc")->setValue(item->getDescription()); - BOOL can_agent_manipulate = item->getPermissions().allowModifyBy(gAgent.getID()); - getChildView("desc")->setEnabled(can_agent_manipulate); + getChildView("desc")->setEnabled(canModify(mObjectUUID, item)); +} + +// static +BOOL LLPreview::canModify(const LLUUID taskUUID, const LLInventoryItem* item) +{ + if (taskUUID.notNull()) + { + LLViewerObject* object = gObjectList.findObject(taskUUID); + if(object && !object->permModify()) + { + // No permission to edit in-world inventory + return FALSE; + } + } + + return item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); } // static diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 759430c3a5..49c114720b 100755 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -105,7 +105,11 @@ public: // llview /*virtual*/ void draw(); void refreshFromItem(); - + + // We can't modify Item or description in preview if either in-world Object + // or Item itself is unmodifiable + static BOOL canModify(const LLUUID taskUUID, const LLInventoryItem* item); + protected: virtual void onCommit(); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 1308d1e9a7..9f88b0db5f 100755 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -218,7 +218,7 @@ void LLPreviewNotecard::loadAsset() LLPermissions perm(item->getPermissions()); BOOL is_owner = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_MANIPULATE); BOOL allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE); - BOOL allow_modify = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE); + BOOL allow_modify = canModify(mObjectUUID, item); if (allow_copy || gAgent.isGodlike()) { @@ -338,10 +338,7 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, } previewEditor->makePristine(); - - const LLInventoryItem* item = preview->getItem(); - BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY, - item->getPermissions(), GP_OBJECT_MANIPULATE); + BOOL modifiable = preview->canModify(preview->mObjectID, preview->getItem()); preview->setEnabled(modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 1bbb22416d..67832c5994 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1391,6 +1391,8 @@ void LLLiveLSLEditor::buildExperienceList() else { mExperiences->setEnabled(TRUE); + mExperiences->sortByName(TRUE); + mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex()); getChild<LLButton>("view_profile")->setVisible(TRUE); } } @@ -2621,8 +2623,12 @@ void LLLiveLSLEditor::onLoad(void* userdata) void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) { LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; - self->mCloseAfterSave = close_after_save; - self->saveIfNeeded(); + if(self) + { + self->mCloseAfterSave = close_after_save; + self->mScriptEd->mErrorList->setCommentText(""); + self->saveIfNeeded(); + } } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index f91a18d8d3..c8cf0faa15 100755 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -618,4 +618,5 @@ void LLPreviewTexture::setObjectID(const LLUUID& object_id) mAssetStatus = PREVIEW_ASSET_UNLOADED; loadAsset(); } + refreshFromItem(); } diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 179a73413e..02912f12a9 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -39,6 +39,7 @@ #include "llspatialpartition.h" #include "llagent.h" #include "pipeline.h" +#include "llviewerparcelmgr.h" #include "llviewerpartsim.h" LLSceneMonitorView* gSceneMonitorView = NULL; @@ -702,6 +703,13 @@ LLSceneMonitorView::LLSceneMonitorView(const LLRect& rect) setCanMinimize(false); setCanClose(true); + + sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLSceneMonitorView::onTeleportFinished, this)); +} + +LLSceneMonitorView::~LLSceneMonitorView() +{ + sTeleportFinishConnection.disconnect(); } void LLSceneMonitorView::onClose(bool app_quitting) @@ -714,6 +722,14 @@ void LLSceneMonitorView::onClickCloseBtn(bool app_quitting) setVisible(false); } +void LLSceneMonitorView::onTeleportFinished() +{ + if(isInVisibleChain()) + { + LLSceneMonitor::getInstance()->reset(); + } +} + void LLSceneMonitorView::onVisibilityChange(BOOL visible) { if (!LLGLSLShader::sNoFixedFunction && visible) diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 5bde3b5aab..2b6ea57b96 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -64,10 +64,12 @@ public: void dumpToFile(std::string file_name); bool hasResults() const { return mSceneLoadRecording.getResults().getDuration() != S32Seconds(0);} + void reset(); + private: void freezeScene(); void unfreezeScene(); - void reset(); + LLRenderTarget& getCaptureTarget(); void generateDitheringTexture(S32 width, S32 height); @@ -109,7 +111,7 @@ class LLSceneMonitorView : public LLFloater { public: LLSceneMonitorView(const LLRect& rect); - + ~LLSceneMonitorView(); virtual void draw(); virtual void onVisibilityChange(BOOL visible); @@ -117,6 +119,8 @@ public: protected: virtual void onClose(bool app_quitting=false); virtual void onClickCloseBtn(bool app_quitting=false); + void onTeleportFinished(); + boost::signals2::connection sTeleportFinishConnection; }; extern LLSceneMonitorView* gSceneMonitorView; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index fdc95c7784..55bcb3dc65 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -52,6 +52,7 @@ // viewer includes #include "llagent.h" #include "llagentcamera.h" +#include "llattachmentsmgr.h" #include "llviewerwindow.h" #include "lldrawable.h" #include "llfloaterinspect.h" @@ -619,10 +620,33 @@ bool LLSelectMgr::linkObjects() bool LLSelectMgr::unlinkObjects() { + S32 min_objects_for_confirm = gSavedSettings.getS32("MinObjectsForUnlinkConfirm"); + S32 unlink_object_count = mSelectedObjects->getObjectCount(); // clears out nodes with NULL objects + if (unlink_object_count >= min_objects_for_confirm + && unlink_object_count > mSelectedObjects->getRootObjectCount()) + { + // total count > root count means that there are childer inside and that there are linksets that will be unlinked + LLNotificationsUtil::add("ConfirmUnlink", LLSD(), LLSD(), boost::bind(&LLSelectMgr::confirmUnlinkObjects, this, _1, _2)); + return true; + } + LLSelectMgr::getInstance()->sendDelink(); return true; } +void LLSelectMgr::confirmUnlinkObjects(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + LLSelectMgr::getInstance()->sendDelink(); + return; +} + // in order to link, all objects must have the same owner, and the // agent must have the ability to modify all of the objects. However, // we're not answering that question with this method. The question @@ -2103,7 +2127,7 @@ void LLSelectMgr::selectionRemoveMaterial() { LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; LLMaterialMgr::getInstance()->remove(object->getID(),face); - object->setTEMaterialParams(face, NULL); + object->setTEMaterialParams(face, NULL, FALSE); } return true; } @@ -2343,6 +2367,7 @@ void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search) "ObjectIncludeInSearch", packAgentAndSessionID, packObjectIncludeInSearch, + logNoOp, &include_in_search, SEND_ONLY_ROOTS); } @@ -2392,6 +2417,7 @@ void LLSelectMgr::selectionSetClickAction(U8 action) sendListToRegions("ObjectClickAction", packAgentAndSessionID, packObjectClickAction, + logNoOp, &action, SEND_INDIVIDUALS); } @@ -2427,7 +2453,7 @@ void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::stri } else { - sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS); + sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, logNoOp, &data, SEND_ONLY_ROOTS); } } @@ -2456,6 +2482,23 @@ void LLSelectMgr::packGodlikeHead(void* user_data) } // static +void LLSelectMgr::logNoOp(LLSelectNode* node, void *) +{ +} + +// static +void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *) +{ + LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID); +} + +// static +void LLSelectMgr::logDetachRequest(LLSelectNode* node, void *) +{ + LLAttachmentsMgr::instance().onDetachRequested(node->mItemID); +} + +// static void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) { std::string buf = llformat("%u", node->getObject()->getLocalID()); @@ -3561,10 +3604,11 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, // attempt to derez into the trash. LLDeRezInfo info(DRD_TRASH, trash_id); LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", - packDeRezHeader, - packObjectLocalID, - (void*) &info, - SEND_ONLY_ROOTS); + packDeRezHeader, + packObjectLocalID, + logNoOp, + (void*) &info, + SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) { @@ -3596,6 +3640,7 @@ void LLSelectMgr::selectForceDelete() "ObjectDelete", packDeleteHeader, packObjectLocalID, + logNoOp, (void*)TRUE, SEND_ONLY_ROOTS); } @@ -3766,7 +3811,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) data.offset = offset; data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); if (select_copy) { @@ -3821,7 +3866,7 @@ void LLSelectMgr::repeatDuplicate() data.offset = LLVector3::zero; data.flags = 0x0; - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); // move current selection based on delta from duplication position and update duplication position for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); @@ -3900,7 +3945,7 @@ void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); sendListToRegions("ObjectDuplicateOnRay", - packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); + packDuplicateOnRayHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); if (select_copy) { @@ -3950,6 +3995,7 @@ void LLSelectMgr::sendMultipleUpdate(U32 type) "MultipleObjectUpdate", packAgentAndSessionID, packMultipleUpdate, + logNoOp, &type, send_type); } @@ -4013,7 +4059,7 @@ void LLSelectMgr::sendOwner(const LLUUID& owner_id, data.group_id = group_id; data.override = override; - sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); } // static @@ -4037,7 +4083,7 @@ void LLSelectMgr::packOwnerHead(void *user_data) void LLSelectMgr::sendGroup(const LLUUID& group_id) { LLUUID local_group_id(group_id); - sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS); + sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, logNoOp, &local_group_id, SEND_ONLY_ROOTS); } @@ -4061,7 +4107,7 @@ void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, con LLBuyData buy; buy.mCategoryID = category_id; buy.mSaleInfo = sale_info; - sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS); + sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, logNoOp, &buy, SEND_ONLY_ROOTS); } // static @@ -4105,7 +4151,7 @@ void LLSelectMgr::selectionSetObjectPermissions(U8 field, data.mMask = mask; data.mOverride = override; - sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, logNoOp, &data, SEND_ONLY_ROOTS); } void LLSelectMgr::packPermissionsHead(void* user_data) @@ -4148,6 +4194,7 @@ void LLSelectMgr::deselectAll() "ObjectDeselect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); @@ -4178,6 +4225,7 @@ void LLSelectMgr::deselectAllForStandingUp() "ObjectDeselect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); @@ -4259,6 +4307,7 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name) sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, + logNoOp, (void*)(&name_copy), SEND_ONLY_ROOTS); } @@ -4267,6 +4316,7 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name) sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, + logNoOp, (void*)(&name_copy), SEND_INDIVIDUALS); } @@ -4282,6 +4332,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, + logNoOp, (void*)(&desc_copy), SEND_ONLY_ROOTS); } @@ -4290,6 +4341,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, + logNoOp, (void*)(&desc_copy), SEND_INDIVIDUALS); } @@ -4303,6 +4355,7 @@ void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) sendListToRegions("ObjectCategory", packAgentAndSessionID, packObjectCategory, + logNoOp, (void*)(&category), SEND_ONLY_ROOTS); } @@ -4312,6 +4365,7 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) sendListToRegions("ObjectSaleInfo", packAgentAndSessionID, packObjectSaleInfo, + logNoOp, (void*)(&sale_info), SEND_ONLY_ROOTS); } @@ -4345,6 +4399,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace) "ObjectAttach", packAgentIDAndSessionAndAttachment, packObjectIDAndRotation, + logAttachmentRequest, &attachment_point, SEND_ONLY_ROOTS ); if (!build_mode) @@ -4365,6 +4420,7 @@ void LLSelectMgr::sendDetach() "ObjectDetach", packAgentAndSessionID, packObjectLocalID, + logDetachRequest, NULL, SEND_ONLY_ROOTS ); } @@ -4381,6 +4437,7 @@ void LLSelectMgr::sendDropAttachment() "ObjectDrop", packAgentAndSessionID, packObjectLocalID, + logDetachRequest, NULL, SEND_ONLY_ROOTS); } @@ -4400,6 +4457,7 @@ void LLSelectMgr::sendLink() "ObjectLink", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_ONLY_ROOTS); } @@ -4437,6 +4495,7 @@ void LLSelectMgr::sendDelink() "ObjectDelink", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); } @@ -4489,6 +4548,7 @@ void LLSelectMgr::sendSelect() "ObjectSelect", packAgentAndSessionID, packObjectLocalID, + logNoOp, NULL, SEND_INDIVIDUALS); } @@ -4885,10 +4945,12 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data) void LLSelectMgr::sendListToRegions(const std::string& message_name, void (*pack_header)(void *user_data), void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), void *user_data, ESendType send_type) { LLSelectNode* node; + LLSelectNode* linkset_root = NULL; LLViewerRegion* last_region; LLViewerRegion* current_region; @@ -4896,6 +4958,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, S32 packets_sent = 0; S32 objects_in_this_packet = 0; + bool link_operation = message_name == "ObjectLink"; + //clear update override data (allow next update through) struct f : public LLSelectedNodeFunctor { @@ -5004,8 +5068,16 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, && (! gMessageSystem->isSendFull(NULL)) && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) { + if (link_operation && linkset_root == NULL) + { + // linksets over 254 will be split into multiple messages, + // but we need to provide same root for all messages or we will get separate linksets + linkset_root = node; + } // add another instance of the body of the data (*pack_body)(node, user_data); + // do any related logging + (*log_func)(node, user_data); ++objects_sent; ++objects_in_this_packet; @@ -5030,6 +5102,22 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, gMessageSystem->newMessage(message_name.c_str()); (*pack_header)(user_data); + if (linkset_root != NULL) + { + if (current_region != last_region) + { + // root should be in one region with the child, reset it + linkset_root = NULL; + } + else + { + // add root instance into new message + (*pack_body)(linkset_root, user_data); + ++objects_sent; + ++objects_in_this_packet; + } + } + // don't move to the next object, we still need to add the // body data. } @@ -6656,7 +6744,7 @@ void LLSelectMgr::undo() { BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- @@ -6674,7 +6762,7 @@ void LLSelectMgr::redo() { BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 23c41e4cc1..87d25e3a8c 100755 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -506,6 +506,8 @@ public: bool unlinkObjects(); + void confirmUnlinkObjects(const LLSD& notification, const LLSD& response); + bool enableLinkObjects(); bool enableUnlinkObjects(); @@ -759,6 +761,7 @@ private: void sendListToRegions( const std::string& message_name, void (*pack_header)(void *user_data), void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), void *user_data, ESendType send_type); @@ -794,6 +797,9 @@ private: static void packHingeHead(void *user_data); static void packPermissionsHead(void* user_data); static void packGodlikeHead(void* user_data); + static void logNoOp(LLSelectNode* node, void *user_data); + static void logAttachmentRequest(LLSelectNode* node, void *user_data); + static void logDetachRequest(LLSelectNode* node, void *user_data); static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); // Get the first ID that matches test and whether or not all ids are identical in selected objects. diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 17ecfab4fb..2548d730f0 100755 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -370,18 +370,25 @@ void LLSidepanelTaskInfo::refresh() // Update creator text field getChildView("Creator:")->setEnabled(TRUE); + std::string creator_name; - LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); + LLUUID creator_id; + LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_name); - getChild<LLUICtrl>("Creator Name")->setValue(creator_name); - getChildView("Creator Name")->setEnabled(TRUE); + if(creator_id != mCreatorID ) + { + mDACreatorName->setValue(creator_name); + mCreatorID = creator_id; + } + mDACreatorName->setEnabled(TRUE); // Update owner text field getChildView("Owner:")->setEnabled(TRUE); std::string owner_name; - const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); - if (mOwnerID.isNull()) + LLUUID owner_id; + const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); + if (owner_id.isNull()) { if (LLSelectMgr::getInstance()->selectIsGroupOwned()) { @@ -402,7 +409,12 @@ void LLSidepanelTaskInfo::refresh() } } } - getChild<LLUICtrl>("Owner Name")->setValue(owner_name); + + if(owner_id.isNull() || (owner_id != mOwnerID)) + { + mDAOwnerName->setValue(owner_name); + mOwnerID = owner_id; + } getChildView("Owner Name")->setEnabled(TRUE); // update group text field diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index 728fc69723..a8e012bfa1 100755 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -271,7 +271,14 @@ LLSLURL::LLSLURL(const std::string& slurl) // at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z // are collectively optional // are optional + mRegion = LLURI::unescape(path_array[0].asString()); + + if(LLStringUtil::containsNonprintable(mRegion)) + { + LLStringUtil::stripNonprintable(mRegion); + } + path_array.erase(0); // parse the x, y, and optionally z diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 0ae8a338e0..6af9d61a54 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -195,7 +195,8 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail // Stop shining animation. mShineAnimTimer.stop(); mSnapshotDelayTimer.start(); - mSnapshotDelayTimer.setTimerExpirySec(delay); + mSnapshotDelayTimer.resetWithExpiry(delay); + mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); @@ -670,10 +671,27 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) return FALSE; } - // If we're in freeze-frame mode and camera has moved, update snapshot. + if (previewp->mSnapshotDelayTimer.getStarted()) // Wait for a snapshot delay timer + { + if (!previewp->mSnapshotDelayTimer.hasExpired()) + { + return FALSE; + } + previewp->mSnapshotDelayTimer.stop(); + } + + if (LLToolCamera::getInstance()->hasMouseCapture()) // Hide full-screen preview while camming, either don't take snapshots while ALT-zoom active + { + previewp->setVisible(FALSE); + return FALSE; + } + + // If we're in freeze-frame and/or auto update mode and camera has moved, update snapshot. LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); - if (previewp->mForceUpdateSnapshot || (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview && + if (previewp->mForceUpdateSnapshot || + (((gSavedSettings.getBOOL("AutoSnapshot") && LLView::isAvailable(previewp->mViewContainer)) || + (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview)) && (new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))) { previewp->mCameraPos = new_camera_pos; @@ -688,11 +706,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mForceUpdateSnapshot = FALSE; } - // 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 && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate()) + if (previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate()) { return FALSE; } @@ -706,6 +720,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mPreviewImage = new LLImageRaw; } + previewp->mSnapshotActive = TRUE; + previewp->setVisible(FALSE); previewp->setEnabled(FALSE); @@ -734,40 +750,9 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // Full size preview is set: get the decoded image result and save it for animation if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview) { - // Get the decoded version of the formatted image - previewp->getEncodedImage(); - - // We need to scale that a bit for display... - 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); - curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); - curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - - previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame - } + previewp->prepareFreezeFrame(); } + // The snapshot is updated now... previewp->mSnapshotUpToDate = TRUE; @@ -777,7 +762,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } previewp->getWindow()->decBusyCount(); previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode - previewp->mSnapshotDelayTimer.stop(); previewp->mSnapshotActive = FALSE; LL_DEBUGS() << "done creating snapshot" << LL_ENDL; } @@ -796,6 +780,47 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) return TRUE; } +void LLSnapshotLivePreview::prepareFreezeFrame() +{ + // Get the decoded version of the formatted image + getEncodedImage(); + + // We need to scale that a bit for display... + LLPointer<LLImageRaw> scaled = new LLImageRaw( + mPreviewImageEncoded->getData(), + mPreviewImageEncoded->getWidth(), + mPreviewImageEncoded->getHeight(), + mPreviewImageEncoded->getComponents()); + + if (!scaled->isBufferInvalid()) + { + // leave original image dimensions, just scale up texture buffer + if (mPreviewImageEncoded->getWidth() > 1024 || mPreviewImageEncoded->getHeight() > 1024) + { + // go ahead and shrink image to appropriate power of 2 for display + scaled->biasedScaleToPowerOfTwo(1024); + setImageScaled(TRUE); + } + else + { + // expand image but keep original image data intact + scaled->expandToPowerOfTwo(1024, FALSE); + } + + mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); + LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex]; + gGL.getTexUnit(0)->bind(curr_preview_image); + curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); + curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); + + + if (gSavedSettings.getBOOL("UseFreezeFrame") && mAllowFullScreenPreview) + { + mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame + } + } +} + S32 LLSnapshotLivePreview::getEncodedImageWidth() const { S32 width = getWidth(); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index fed33bf37c..57e5d83f8e 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -119,7 +119,7 @@ public: void generateThumbnailImage(BOOL force_update = FALSE) ; void resetThumbnailImage() { mThumbnailImage = NULL ; } void drawPreviewRect(S32 offset_x, S32 offset_y) ; - + void prepareFreezeFrame(); LLViewerTexture* getBigThumbnailImage(); S32 getBigThumbnailWidth() const { return mBigThumbnailWidth ; } diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 7867e1573c..44c980c96f 100755 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -547,21 +547,8 @@ void LLSpeakerMgr::updateSpeakerList() // For groups, we need to hit the group manager. // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); - F32 large_group_delay = 0.f; - if (gdatap) - { - //This is a viewer-side bandaid for maint-4414 it does not fix the core issue. - large_group_delay = (F32)(gdatap->mMemberCount / 5000); - } - - const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout") + large_group_delay; - - if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout)) - { - // Request the data the first time around - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); - } - else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) + + if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) { // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d7bfd22cc9..965aad517d 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -242,7 +242,8 @@ static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f); static std::string gAgentStartLocation = "safe"; static bool mLoginStatePastUI = false; -const S32 DEFAULT_MAX_AGENT_GROUPS = 25; +const S32 DEFAULT_MAX_AGENT_GROUPS = 42; +const S32 ALLOWED_MAX_AGENT_GROUPS = 500; boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); @@ -420,9 +421,7 @@ bool idle_startup() gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); gSavedSettings.setString("LastGPUString", thisGPU); - // load dynamic GPU/feature tables from website (S3) - LLFeatureManager::getInstance()->fetchHTTPTables(); - + std::string xml_file = LLUI::locateSkin("xui_version.xml"); LLXMLNodePtr root; bool xml_ok = false; @@ -1880,6 +1879,11 @@ bool idle_startup() } display_startup(); + + // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp) + //check_merchant_status(); + + display_startup(); if (gSavedSettings.getBOOL("HelpFloaterOpen")) { @@ -3232,6 +3236,23 @@ bool process_login_success_response() LLStringUtil::trim(gDisplayName); } } + std::string first_name; + if(response.has("first_name")) + { + first_name = response["first_name"].asString(); + LLStringUtil::replaceChar(first_name, '"', ' '); + LLStringUtil::trim(first_name); + gAgentUsername = first_name; + } + + if(response.has("last_name") && !gAgentUsername.empty() && (gAgentUsername != "Resident")) + { + std::string last_name = response["last_name"].asString(); + LLStringUtil::replaceChar(last_name, '"', ' '); + LLStringUtil::trim(last_name); + gAgentUsername = gAgentUsername + " " + last_name; + } + if(gDisplayName.empty()) { if(response.has("first_name")) @@ -3252,6 +3273,7 @@ bool process_login_success_response() gDisplayName += text; } } + if(gDisplayName.empty()) { gDisplayName.assign(gUserCredential->asString()); @@ -3504,15 +3526,24 @@ bool process_login_success_response() LLViewerMedia::openIDSetup(openid_url, openid_token); } - if(response.has("max-agent-groups")) { - std::string max_agent_groups(response["max-agent-groups"]); - gMaxAgentGroups = atoi(max_agent_groups.c_str()); - LL_INFOS("LLStartup") << "gMaxAgentGroups read from login.cgi: " - << gMaxAgentGroups << LL_ENDL; + gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS; + if(response.has("max-agent-groups")) + { + S32 agent_groups = atoi(std::string(response["max-agent-groups"]).c_str()); + if (agent_groups > 0 && agent_groups <= ALLOWED_MAX_AGENT_GROUPS) + { + gMaxAgentGroups = agent_groups; + LL_INFOS("LLStartup") << "gMaxAgentGroups read from login.cgi: " + << gMaxAgentGroups << LL_ENDL; + } + else + { + LL_INFOS("LLStartup") << "Invalid value received, using defaults for gMaxAgentGroups: " + << gMaxAgentGroups << LL_ENDL; + } } else { - gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS; - LL_INFOS("LLStartup") << "using gMaxAgentGroups default: " + LL_INFOS("LLStartup") << "Missing max-agent-groups, using default value for gMaxAgentGroups: " << gMaxAgentGroups << LL_ENDL; } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 8babb874f8..8f64cff47c 100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -296,158 +296,6 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas } /************************************************************************/ -/* LLNotificationWellWindow implementation */ -/************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// PUBLIC METHODS -LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) -: LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), - mWellWindow(well_window) -{ - connectToChannel("Notifications"); - connectToChannel("Group Notifications"); - connectToChannel("Offer"); -} - -LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) -{ - mNotificationUpdates.reset(new WellNotificationChannel(this)); -} - -// static -LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/) -{ - return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key); -} - -// virtual -BOOL LLNotificationWellWindow::postBuild() -{ - BOOL rv = LLSysWellWindow::postBuild(); - setTitle(getString("title_notification_well_window")); - return rv; -} - -// virtual -void LLNotificationWellWindow::setVisible(BOOL visible) -{ - if (visible) - { - // when Notification channel is cleared, storable toasts will be added into the list. - clearScreenChannels(); - } - - LLSysWellWindow::setVisible(visible); -} - -//--------------------------------------------------------------------------------- -void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) -{ - LLSD value = p.notification_id; - // do not add clones - if( mMessageList->getItemByValue(value)) - return; - - LLSysWellItem* new_item = new LLSysWellItem(p); - if (mMessageList->addItem(new_item, value, ADD_TOP)) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - reshapeWindow(); - new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); - new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); - } - else - { - LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id - << ", title: " << p.title - << LL_ENDL; - - new_item->die(); - } -} - -void LLNotificationWellWindow::closeAll() -{ - // Need to clear notification channel, to add storable toasts into the list. - clearScreenChannels(); - std::vector<LLPanel*> items; - mMessageList->getItems(items); - for (std::vector<LLPanel*>::iterator - iter = items.begin(), - iter_end = items.end(); - iter != iter_end; ++iter) - { - LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter); - if (sys_well_item) - onItemClose(sys_well_item); - } -} - -////////////////////////////////////////////////////////////////////////// -// PRIVATE METHODS -void LLNotificationWellWindow::initChannel() -{ - LLSysWellWindow::initChannel(); - if(mChannel) - { - mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); - } -} - -void LLNotificationWellWindow::clearScreenChannels() -{ - // 1 - remove StartUp toast and channel if present - if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) - { - LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); - } - - // 2 - remove toasts in Notification channel - if(mChannel) - { - mChannel->removeAndStoreAllStorableToasts(); - } -} - -void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) -{ - LLSysWellItem::Params p; - p.notification_id = id; - p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); - addItem(p); -} - -void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) -{ - LLUUID id = item->getID(); - LLFloaterReg::showInstance("inspect_toast", id); -} - -void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) -{ - LLUUID id = item->getID(); - - if(mChannel) - { - // removeItemByID() is invoked from killToastByNotificationID() and item will removed; - mChannel->killToastByNotificationID(id); - } - else - { - // removeItemByID() should be called one time for each item to remove it from notification well - removeItemByID(id); - } - -} - -void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) -{ - removeItemByID(notify->getID()); -} - -/************************************************************************/ /* LLIMWellWindow implementation */ /************************************************************************/ diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 71b41476f5..d02293e6ff 100755 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -96,57 +96,6 @@ protected: }; /** - * Class intended to manage incoming notifications. - * - * It contains a list of notifications that have not been responded to. - */ -class LLNotificationWellWindow : public LLSysWellWindow -{ -public: - LLNotificationWellWindow(const LLSD& key); - static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD()); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void onAdd(LLNotificationPtr notify); - // Operating with items - void addItem(LLSysWellItem::Params p); - - // Closes all notifications and removes them from the Notification Well - void closeAll(); - -protected: - struct WellNotificationChannel : public LLNotificationChannel - { - WellNotificationChannel(LLNotificationWellWindow*); - void onDelete(LLNotificationPtr notify) - { - mWellWindow->removeItemByID(notify->getID()); - } - - LLNotificationWellWindow* mWellWindow; - }; - - LLNotificationChannelPtr mNotificationUpdates; - /*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; } - -private: - // init Window's channel - void initChannel(); - void clearScreenChannels(); - - void onStoreToast(LLPanel* info_panel, LLUUID id); - - // Handlers - void onItemClick(LLSysWellItem* item); - void onItemClose(LLSysWellItem* item); - - // ID of a toast loaded by user (by clicking notification well item) - LLUUID mLoadedToastId; - -}; - -/** * Class intended to manage incoming messages in IM chats. * * It contains a list list of all active IM sessions. diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index ef852bc905..bcdf8360ed 100755 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1544,17 +1544,20 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) { std::string dirname = mTexturesDirName + delem + subdirs[i]; LL_INFOS() << "Deleting files in directory: " << dirname << LL_ENDL; - gDirUtilp->deleteFilesInDir(dirname, mask); if (purge_directories) { - LLFile::rmdir(dirname); + gDirUtilp->deleteDirAndContents(dirname); + } + else + { + gDirUtilp->deleteFilesInDir(dirname, mask); } } if (purge_directories) { gDirUtilp->deleteFilesInDir(mTexturesDirName, mask); LLFile::rmdir(mTexturesDirName); - } + } } mHeaderIDMap.clear(); mTexturesSizeMap.clear(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 717807f513..980810835e 100755 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -188,6 +188,7 @@ protected: private: bool mCanApply; bool mCanPreview; + bool mPreviewSettingChanged; texture_selected_callback mTextureSelectedCallback; }; @@ -215,7 +216,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mContextConeOpacity(0.f), mSelectedItemPinned( FALSE ), mCanApply(true), - mCanPreview(true) + mCanPreview(true), + mPreviewSettingChanged(false) { buildFromFile("floater_texture_ctrl.xml"); mCanApplyImmediately = can_apply_immediately; @@ -823,6 +825,16 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem } setImageID(itemp->getAssetUUID(),false); mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if(!mPreviewSettingChanged) + { + mCanPreview = gSavedSettings.getBOOL("TextureLivePreview"); + } + else + { + mPreviewSettingChanged = false; + } + if (user_action && mCanPreview) { // only commit intentional selections, not implicit ones @@ -979,6 +991,7 @@ void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) mCanApply = can_apply; mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false; + mPreviewSettingChanged = true; } void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 0a9453534b..530bd9a18f 100755 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -67,19 +67,19 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLabel(notification->getName()), mLineEditor(NULL) { - // EXP-1822 - // save currently focused view, so that return focus to it - // on destroying this toast. - LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); - while(current_selection) - { - if (current_selection->isFocusRoot()) - { - mPreviouslyFocusedView = current_selection->getHandle(); - break; - } - current_selection = current_selection->getParent(); - } + // EXP-1822 + // save currently focused view, so that return focus to it + // on destroying this toast. + LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); + while(current_selection) + { + if (current_selection->isFocusRoot()) + { + mPreviouslyFocusedView = current_selection->getHandle(); + break; + } + current_selection = current_selection->getParent(); + } const LLFontGL* font = LLFontGL::getFontSansSerif(); const S32 LINE_HEIGHT = font->getLineHeight(); @@ -431,7 +431,24 @@ LLToastAlertPanel::~LLToastAlertPanel() // return focus to the previously focused view if the viewer is not exiting if (mPreviouslyFocusedView.get() && !LLApp::isExiting()) { - mPreviouslyFocusedView.get()->setFocus(TRUE); + LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); + while(current_selection) + { + if (current_selection->isFocusRoot()) + { + break; + } + current_selection = current_selection->getParent(); + } + if (current_selection) + { + // If the focus moved to some other view though, move the focus there + current_selection->setFocus(TRUE); + } + else + { + mPreviouslyFocusedView.get()->setFocus(TRUE); + } } } diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index e00b18dedb..e22f527a65 100755 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -92,7 +92,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notifi +LLTrans::getString("UTCTimeSec")+"] [" +LLTrans::getString("UTCTimeTimezone")+"]"; const LLDate timeStamp = notification->getDate(); - LLDate notice_date = timeStamp.notNull() ? timeStamp : LLDate::now(); + LLDate notice_date = timeStamp.notNull() ? timeStamp : payload["received_time"].asDate(); LLSD substitution; substitution["datetime"] = (S32) notice_date.secondsSinceEpoch(); LLStringUtil::format(timeStr, substitution); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 526f8d1cd8..5c9aedcf8f 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -821,6 +821,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { + // *TODO: Suppress the "outbox" case once "marketplace" is used everywhere for everyone // Disallow drag and drop to 3D from the outbox const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); if (outbox_id.notNull()) @@ -835,6 +836,20 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, } } } + // Disallow drag and drop to 3D from the marketplace + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + if (marketplacelistings_id.notNull()) + { + for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) + { + if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], marketplacelistings_id)) + { + *acceptance = ACCEPT_NO; + mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld"); + return; + } + } + } dragOrDrop3D( x, y, mask, drop, acceptance ); } @@ -994,9 +1009,15 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return TRUE; } - // In case the inventory has not been updated (e.g. due to some recent operation - // causing a dirty inventory), stall the user while fetching the inventory. - if (hit_obj->isInventoryDirty()) + // In case the inventory has not been loaded (e.g. due to some recent operation + // causing a dirty inventory) and we can do an update, stall the user + // while fetching the inventory. + // + // Note: fetch only if inventory is both dirty and not present since previously checked faces + // could have requested new fetch for same item (removed inventory and marked as dirty=false). + // Objects without listeners (dirty==true and inventory!=NULL. In this specific case - before + // first fetch) shouldn't be updated either since we won't receive any changes. + if (hit_obj->isInventoryDirty() && hit_obj->getInventoryRoot() == NULL) { hit_obj->fetchInventoryFromServer(); LLSD args; @@ -1134,8 +1155,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, } LLSculptParams sculpt_params; - sculpt_params.setSculptTexture(asset_id); - sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH); + sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH); hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); dialog_refresh_all(); diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index de501ea32a..63be1ef09b 100755 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -89,6 +89,7 @@ public: void setCargoCount(U32 count) { mCargoCount = count; } void resetCargoCount() { mCargoCount = 0; } U32 getCargoCount() const { return (mCargoCount > 0) ? mCargoCount : mCargoIDs.size(); } + S32 getCargoIndex() const { return mCurItemIndex; } static S32 getOperationId() { return sOperationId; } diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h index 4e22732124..5d24c8813e 100755 --- a/indra/newview/lltoolgrab.h +++ b/indra/newview/lltoolgrab.h @@ -78,6 +78,8 @@ public: // Certain grabs should not highlight the "Build" toolbar button BOOL getHideBuildHighlight() { return mHideBuildHighlight; } + void setClickedInMouselook(BOOL is_clickedInMouselook) {mClickedInMouselook = is_clickedInMouselook;} + static void pickCallback(const LLPickInfo& pick_info); private: LLVector3d getGrabPointGlobal(); diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 175227173f..3ecb4015ce 100755 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -37,6 +37,7 @@ #include "llfloaterinspect.h" #include "lltool.h" #include "llmanipscale.h" +#include "llmarketplacefunctions.h" #include "llselectmgr.h" #include "lltoolbrush.h" #include "lltoolcomp.h" @@ -83,6 +84,8 @@ LLToolMgr::LLToolMgr() LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2)); + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Marketplace.Enabled", boost::bind(&LLToolMgr::canAccessMarketplace, this)); + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Marketplace.Toggle", boost::bind(&LLToolMgr::toggleMarketplace, this, _2)); gToolNull = new LLTool(LLStringUtil::null); // Does nothing setCurrentTool(gToolNull); @@ -345,6 +348,23 @@ bool LLToolMgr::inBuildMode() return b; } +bool LLToolMgr::canAccessMarketplace() +{ + return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT) || gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"); +} + +void LLToolMgr::toggleMarketplace(const LLSD& sdname) +{ + const std::string& param = sdname.asString(); + + if ((param != "marketplace") || !canAccessMarketplace()) + { + return; + } + + LLFloaterReg::toggleInstanceOrBringToFront("marketplace_listings"); +} + void LLToolMgr::setTransientTool(LLTool* tool) { if (!tool) diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index e7d1c56c83..a3c1045aac 100755 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -54,7 +54,9 @@ public: bool inEdit(); bool canEdit(); + bool canAccessMarketplace(); void toggleBuildMode(const LLSD& sdname); + void toggleMarketplace(const LLSD& sdname); /* Determines if we are in Build mode or not. */ bool inBuildMode(); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index e4353aafaa..2081297717 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -319,6 +319,7 @@ BOOL LLToolPie::handleLeftClickPick() { gGrabTransientTool = this; mMouseButtonDown = false; + LLToolGrab::getInstance()->setClickedInMouselook(gAgentCamera.cameraMouselook()); LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); return LLToolGrab::getInstance()->handleObjectHit( mPick ); } diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp index cad5769042..8a61114852 100755 --- a/indra/newview/llurllineeditorctrl.cpp +++ b/indra/newview/llurllineeditorctrl.cpp @@ -84,7 +84,7 @@ void LLURLLineEditor::copyEscapedURLToClipboard() const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length)); LLWString text_to_copy; // *HACK: Because LLSLURL is currently broken we cannot use it to check if unescaped_text is a valid SLURL (see EXT-8335). - if (LLStringUtil::startsWith(unescaped_text, "http://")) // SLURL + if (LLStringUtil::startsWith(unescaped_text, "http://") || LLStringUtil::startsWith(unescaped_text, "secondlife://")) // SLURL text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text)); else // human-readable location text_to_copy = utf8str_to_wstring(unescaped_text); diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 5cc7d7bed3..e53de8be32 100755 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -29,6 +29,7 @@ #include <iostream> #include <sstream> #include "llversioninfo.h" +#include <boost/regex.hpp> #if ! defined(LL_VIEWER_CHANNEL) \ || ! defined(LL_VIEWER_VERSION_MAJOR) \ @@ -131,3 +132,43 @@ void LLVersionInfo::resetChannel(const std::string& channel) sWorkingChannelName = channel; sVersionChannel.clear(); // Reset version and channel string til next use. } + +//static +LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity() +{ + ViewerMaturity maturity; + + std::string channel = getChannel(); + + static const boost::regex is_test_channel("\\bTest\\b"); + static const boost::regex is_beta_channel("\\bBeta\\b"); + static const boost::regex is_project_channel("\\bProject\\b"); + static const boost::regex is_release_channel("\\bRelease\\b"); + + if (boost::regex_search(channel, is_release_channel)) + { + maturity = RELEASE_VIEWER; + } + else if (boost::regex_search(channel, is_beta_channel)) + { + maturity = BETA_VIEWER; + } + else if (boost::regex_search(channel, is_project_channel)) + { + maturity = PROJECT_VIEWER; + } + else if (boost::regex_search(channel, is_test_channel)) + { + maturity = TEST_VIEWER; + } + else + { + LL_WARNS() << "Channel '" << channel + << "' does not follow naming convention, assuming Test" + << LL_ENDL; + maturity = TEST_VIEWER; + } + return maturity; +} + + diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h index 077105cae8..4e75535ec5 100755 --- a/indra/newview/llversioninfo.h +++ b/indra/newview/llversioninfo.h @@ -68,6 +68,15 @@ public: /// reset the channel name used by the viewer. static void resetChannel(const std::string& channel); + + typedef enum + { + TEST_VIEWER, + PROJECT_VIEWER, + BETA_VIEWER, + RELEASE_VIEWER + } ViewerMaturity; + static ViewerMaturity getViewerMaturity(); }; #endif diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1dad9dd506..14a2627f27 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -84,11 +84,13 @@ #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" +#include "llfloatermarketplacelistings.h" #include "llfloatermediasettings.h" #include "llfloatermemleak.h" #include "llfloatermodelpreview.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" +#include "llfloaternotificationstabbed.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" #include "llfloateroutbox.h" @@ -186,6 +188,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>); LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>); LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); + LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>); LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>); LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>); LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>); @@ -238,6 +241,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); LLFloaterReg::add("inventory", "floater_my_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>); + LLFloaterReg::add("item_properties", "floater_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterItemProperties>); LLInspectAvatarUtil::registerFloater(); LLInspectGroupUtil::registerFloater(); LLInspectObjectUtil::registerFloater(); @@ -256,6 +260,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); } LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>); + LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>); + LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>); @@ -263,7 +269,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>); LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); - LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>); + + LLFloaterReg::add("notification_well_window", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>); LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 0401de7e69..158cacbc81 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -140,7 +140,11 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); - + + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new ViewerFolderEntry("Marketplace Listings", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); + addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new ViewerFolderEntry("New Stock", "Inv_StockFolderOpen", "Inv_StockFolderClosed", FALSE, false, "default")); + addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new ViewerFolderEntry("New Version", "Inv_VersionFolderOpen","Inv_VersionFolderClosed", FALSE, false, "default")); + addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false, "default")); for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d112118082..24096e3222 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -808,6 +808,36 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const return true; } +bool LLViewerInventoryCategory::acceptItem(LLInventoryItem* inv_item) +{ + if (!inv_item) + { + return false; + } + + // Only stock folders have limitation on which item they will accept + bool accept = true; + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + // If the item is copyable (i.e. non stock) do not accept the drop in a stock folder + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + accept = false; + } + else + { + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(getUUID(),cat_array,item_array); + // Destination stock folder must be empty OR types of incoming and existing items must be identical and have the same permissions + accept = (!item_array->size() || + ((item_array->at(0)->getInventoryType() == inv_item->getInventoryType()) && + (item_array->at(0)->getPermissions().getMaskNextOwner() == inv_item->getPermissions().getMaskNextOwner()))); + } + } + return accept; +} + void LLViewerInventoryCategory::determineFolderType() { /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. @@ -2306,5 +2336,3 @@ BOOL LLViewerInventoryItem::regenerateLink() gInventory.notifyObservers(); return TRUE; } - - diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index ca92565600..4e91e4110a 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -228,6 +228,9 @@ public: void changeType(LLFolderType::EType new_folder_type); virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); virtual BOOL unpackMessage(const LLSD& category); + + // returns true if the category object will accept the incoming item + bool acceptItem(LLInventoryItem* inv_item); private: friend class LLInventoryModel; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 6803adfaa2..1ce42e97b8 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -248,6 +248,7 @@ public: void setHomeURL(const std::string& home_url, const std::string& mime_type = LLStringUtil::null) { mHomeURL = home_url; mHomeMimeType = mime_type;}; void clearCache(); void setPageZoomFactor( double factor ); + double getPageZoomFactor() {return mZoomFactor;} std::string getMimeType() { return mMimeType; } void scaleMouse(S32 *mouse_x, S32 *mouse_y); void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3b0adcf7f4..38d62dee5e 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -57,6 +57,7 @@ #include "llfacebookconnect.h" #include "llfilepicker.h" #include "llfirstuse.h" +#include "llfloaterabout.h" #include "llfloaterbuy.h" #include "llfloaterbuycontents.h" #include "llbuycurrencyhtml.h" @@ -88,6 +89,7 @@ #include "llinventoryfunctions.h" #include "llpanellogin.h" #include "llpanelblockedlist.h" +#include "llmarketplacefunctions.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" #include "llparcel.h" @@ -98,6 +100,7 @@ #include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "lltextureview.h" +#include "lltoolbarview.h" #include "lltoolcomp.h" #include "lltoolmgr.h" #include "lltoolpie.h" @@ -386,6 +389,66 @@ void set_underclothes_menu_options() } } +void set_merchant_SLM_menu() +{ + // DD-170 : SLM Alpha and Beta program : for the moment, we always show the SLM menu and + // tools so that all merchants can try out the UI, even if not migrated. + // *TODO : Keep SLM UI hidden for non migrated merchant in released viewer + + //if (LLMarketplaceData::instance().getSLMStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT) + //{ + // Merchant not migrated: show only the old Merchant Outbox menu + // gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE); + //} + //else + //{ + // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool + gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(TRUE); + LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); + gToolBarView->enableCommand(command->id(), true); + //} +} + +void set_merchant_outbox_menu(U32 status, const LLSD& content) +{ + // If the merchant is fully migrated, the API is disabled (503) and we won't show the old menu item. + // In all other cases, we show it. + if (status != MarketplaceErrorCodes::IMPORT_SERVER_API_DISABLED) + { + gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE); + } +} + +void check_merchant_status() +{ + if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth")) + { + // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); + + // Hide SLM related menu item + gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE); + + // Also disable the toolbar button for Marketplace Listings + LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); + gToolBarView->enableCommand(command->id(), false); + + // Launch an SLM test connection to get the merchant status + LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu)); + + // Do the Merchant Outbox init only once per session + if (LLMarketplaceInventoryImporter::instance().getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) + { + // Hide merchant outbox related menu item + gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(FALSE); + + // Launch a Merchant Outbox test connection to get the migration status + LLMarketplaceInventoryImporter::instance().setStatusReportCallback(boost::bind(&set_merchant_outbox_menu,_1, _2)); + LLMarketplaceInventoryImporter::instance().initialize(); + } + } +} + void init_menus() { // Initialize actions @@ -2077,6 +2140,22 @@ class LLAdvancedCheckShowObjectUpdates : public view_listener_t +/////////////////////// +// CHECK FOR UPDATES // +/////////////////////// + + + +class LLAdvancedCheckViewerUpdates : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloaterAboutUtil::checkUpdatesAndNotify(); + return true; + } +}; + + //////////////////// // COMPRESS IMAGE // //////////////////// @@ -2695,6 +2774,7 @@ void handle_object_edit() if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) { + LLFloaterTools::sPreviousFocusOnAvatar = true; LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) @@ -6632,7 +6712,7 @@ class LLAttachmentDetachFromPoint : public view_listener_t LLViewerObject *attached_object = (*iter); ids_to_remove.push_back(attached_object->getAttachmentItemID()); } - } + } if (!ids_to_remove.empty()) { LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); @@ -7077,11 +7157,10 @@ void handle_selected_texture_info(void*) { msg.append( llformat("%d ", (S32)(it->second[i]))); } - - LLSD args; - args["MESSAGE"] = msg; - LLNotificationsUtil::add("SystemMessage", args); } + LLSD args; + args["MESSAGE"] = msg; + LLNotificationsUtil::add("SystemMessage", args); } } @@ -8857,6 +8936,7 @@ void initialize_menus() // Advanced (toplevel) view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates"); view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); + view_listener_t::addMenu(new LLAdvancedCheckViewerUpdates(), "Advanced.CheckViewerUpdates"); view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings"); view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 7f09fc2d8f..b7bdf00157 100755 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -83,6 +83,7 @@ BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); BOOL enable_god_basic(void* user_data); void set_underclothes_menu_options(); +void check_merchant_status(); void exchange_callingcard(const LLUUID& dest_id); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 459bdca8df..6ba10373b9 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -57,6 +57,7 @@ #include "llcallingcard.h" #include "llbuycurrencyhtml.h" #include "llfirstuse.h" +#include "llfloaterbump.h" #include "llfloaterbuyland.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" @@ -71,6 +72,7 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llfloaterimnearbychat.h" +#include "llmarketplacefunctions.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpanelgrouplandmoney.h" @@ -2348,7 +2350,8 @@ static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::s LLNotificationsUtil::add("GodMessage", args); // Treat like a system message and put in chat history. - chat.mText = av_name.getCompleteName() + ": " + message; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = message; LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) @@ -2680,6 +2683,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["sender_name"] = name; payload["group_id"] = group_id; payload["inventory_name"] = item_name; + payload["received_time"] = LLDate::now(); if(info && info->asLLSD()) { payload["inventory_offer"] = info->asLLSD(); @@ -2706,6 +2710,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_GROUP_INVITATION: { + if (!is_muted) + { + // group is not blocked, but we still need to check agent that sent the invitation + // and we have no agent's id + // Note: server sends username "first.last". + is_muted |= LLMuteList::getInstance()->isMuted(name); + } if (is_do_not_disturb || is_muted) { send_do_not_disturb_message(msg, from_id); @@ -2852,6 +2863,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_FROM_TASK: { + if (is_do_not_disturb && !is_owned_by_me) { return; @@ -2935,17 +2947,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["from_id"] = from_id; payload["slurl"] = location; payload["name"] = name; - std::string session_name; + if (from_group) { payload["group_owned"] = "true"; } - LLNotification::Params params("ServerObjectMessage"); - params.substitutions = substitutions; - params.payload = payload; - - LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group); + LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload); } break; @@ -3600,6 +3608,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && LLMuteList::getInstance()->isLinden(from_name); + if (is_muted && (chat.mSourceType == CHAT_SOURCE_OBJECT)) + { + return; + } + BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); chatter = gObjectList.findObject(from_id); if (chatter) @@ -3776,11 +3789,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } } - LLSD msg_notify = LLSD(LLSD::emptyMap()); - msg_notify["session_id"] = LLUUID(); - msg_notify["from_id"] = chat.mFromID; - msg_notify["source_type"] = chat.mSourceType; - on_new_message(msg_notify); + if (mesg != "") + { + LLSD msg_notify = LLSD(LLSD::emptyMap()); + msg_notify["session_id"] = LLUUID(); + msg_notify["from_id"] = chat.mFromID; + msg_notify["source_type"] = chat.mSourceType; + on_new_message(msg_notify); + } + } } @@ -5622,6 +5639,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) } } final_args["MESSAGE"] = message; + payload["dest_id"] = dest_id; notification = success ? "PaymentSent" : "PaymentFailure"; } else { @@ -5910,7 +5928,7 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) LL_WARNS() << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; } } - + handle_trusted_experiences_notification(llsdBlock); @@ -5994,7 +6012,25 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) make_ui_sound("UISndRestart"); } - + + // Special Marketplace update notification + if (notificationID == "SLM_UPDATE_FOLDER") + { + std::string state = llsdBlock["state"].asString(); + if (state == "deleted") + { + // Perform the deletion viewer side, no alert shown in this case + LLMarketplaceData::instance().deleteListing(llsdBlock["listing_id"].asInteger()); + return true; + } + else + { + // In general, no message will be displayed, all we want is to get the listing updated in the marketplace floater + // If getListing() fails though, the message of the alert will be shown by the caller of attempt_standard_notification() + return LLMarketplaceData::instance().getListing(llsdBlock["listing_id"].asInteger()); + } + } + LLNotificationsUtil::add(notificationID, llsdBlock); return true; } @@ -6232,6 +6268,11 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3)); } } + LLFloaterBump* bumps_floater = LLFloaterBump::getInstance(); + if(bumps_floater && bumps_floater->isInVisibleChain()) + { + bumps_floater->populateCollisionList(); + } } void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index faa58d423f..6666aecca2 100755 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -119,14 +119,14 @@ void LLGridManager::initialize(const std::string& grid_file) mGridFile = grid_file; // as we don't want an attacker to override our grid list // to point the default grid to an invalid grid - addSystemGrid("Second Life Main Grid (Agni)", + addSystemGrid(LLTrans::getString("AgniGridLabel"), MAINGRID, MAIN_GRID_LOGIN_URI, "https://secondlife.com/helpers/", DEFAULT_LOGIN_PAGE, SL_UPDATE_QUERY_URL, "Agni"); - addSystemGrid("Second Life Beta Test Grid (Aditi)", + addSystemGrid(LLTrans::getString("AditiGridLabel"), "util.aditi.lindenlab.com", "https://login.aditi.lindenlab.com/cgi-bin/login.cgi", "http://aditi-secondlife.webdev.lindenlab.com/helpers/", diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a2c0a91ea6..05d116704e 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1958,6 +1958,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead()) { + if (((LLViewerObject*)sent_parentp)->isAvatar()) + { + //LL_DEBUGS("Avatar") << "ATT got object update for attachment " << LL_ENDL; + } + // // We have a viewer object for the parent, and it's not dead. // Do the actual reparenting here. @@ -2880,6 +2885,9 @@ struct LLFilenameAndTask { LLUUID mTaskID; std::string mFilename; + + // for sequencing in case of multiple updates + S16 mSerial; #ifdef _DEBUG static S32 sCount; LLFilenameAndTask() @@ -2915,9 +2923,17 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) return; } - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); LLFilenameAndTask* ft = new LLFilenameAndTask; ft->mTaskID = task_id; + // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial); + + if (ft->mSerial < object->mInventorySerialNum) + { + // viewer did some changes to inventory that were not saved yet. + LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL; + object->mInventorySerialNum = ft->mSerial; + } std::string unclean_filename; msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename); @@ -2957,9 +2973,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS { LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data; LLViewerObject* object = NULL; - if(ft && (0 == error_code) && - (object = gObjectList.findObject(ft->mTaskID))) + + if (ft + && (0 == error_code) + && (object = gObjectList.findObject(ft->mTaskID)) + && ft->mSerial >= object->mInventorySerialNum) { + object->mInventorySerialNum = ft->mSerial; if (object->loadTaskInvFile(ft->mFilename)) { @@ -2990,7 +3010,7 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS } else { - // This Occurs When to requests were made, and the first one + // This Occurs When two requests were made, and the first one // has already handled it. LL_DEBUGS() << "Problem loading task inventory. Return code: " << error_code << LL_ENDL; @@ -4632,7 +4652,7 @@ S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID return retval; } -S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer) { S32 retval = 0; const LLTextureEntry *tep = getTE(te); @@ -4642,13 +4662,14 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri return 0; } - retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); + setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); + setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); + + retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams, isInitFromServer); LL_DEBUGS("Material") << "Changing material params for te " << (S32)te << ", object " << mID << " (" << retval << ")" << LL_ENDL; - setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); - setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); refreshMaterials(); return retval; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 05c87c153b..db2749f413 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -330,7 +330,7 @@ public: /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); - /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer); // Used by Materials update functions to properly kick off rebuilds // of VBs etc when materials updates require changes. diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 7c36b30dd1..75732a1e19 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -474,13 +474,13 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { U32 flags = 0; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - + if(flags & FLAGS_TEMPORARY_ON_REZ) { - compressed_dp.unpackUUID(fullid, "ID"); - compressed_dp.unpackU32(local_id, "LocalID"); - compressed_dp.unpackU8(pcode, "PCode"); - } + compressed_dp.unpackUUID(fullid, "ID"); + compressed_dp.unpackU32(local_id, "LocalID"); + compressed_dp.unpackU8(pcode, "PCode"); + } else //send to object cache { regionp->cacheFullUpdate(compressed_dp, flags); @@ -497,7 +497,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, gMessageSystem->getSenderPort()); if (fullid.isNull()) { - // LL_WARNS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; + LL_DEBUGS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; mNumUnknownUpdates++; } } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 59f57c218e..2a6b105cab 100755 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1602,8 +1602,14 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use } else if (local_id == parcel_mgr.mAgentParcel->getLocalID()) { - // updated agent parcel - parcel_mgr.mAgentParcel->unpackMessage(msg); + // Parcels in different regions can have same ids. + LLViewerRegion* parcel_region = LLWorld::getInstance()->getRegion( msg->getSender() ); + LLViewerRegion* agent_region = gAgent.getRegion(); + if (parcel_region && agent_region && parcel_region->getRegionID() == agent_region->getRegionID()) + { + // updated agent parcel + parcel_mgr.mAgentParcel->unpackMessage(msg); + } } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ec28461201..6af3e40f01 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -828,7 +828,6 @@ void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) LLRegionInfoModel::instance().update(msg); LLFloaterGodTools::processRegionInfo(msg); LLFloaterRegionInfo::processRegionInfo(msg); - LLFloaterReporter::processRegionInfo(msg); } void LLViewerRegion::setCacheID(const LLUUID& id) @@ -2718,6 +2717,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("DirectDelivery"); capabilityNames.append("EnvironmentSettings"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index f60829e9e8..24a6758312 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -60,6 +60,7 @@ #include "llfeaturemanager.h" #include "llviewernetwork.h" #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived +#include "llsdserialize.h" namespace LLStatViewer { @@ -616,8 +617,10 @@ void send_stats() body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames"); body["MinimalSkin"] = false; - + LLViewerStats::getInstance()->addToMessage(body); + + LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; LLHTTPClient::post(url, body, new ViewerStatsResponder()); LLViewerStats::instance().getRecording().resume(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e317989f04..ba84d7aa2c 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2336,12 +2336,6 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) LLSD args; LLColor4 new_bg_color; - // no l10n problem because channel is always an english string - std::string channel = LLVersionInfo::getChannel(); - static const boost::regex is_beta_channel("\\bBeta\\b"); - static const boost::regex is_project_channel("\\bProject\\b"); - static const boost::regex is_test_channel("\\bTest$"); - // god more important than project, proj more important than grid if ( god_mode ) { @@ -2354,27 +2348,35 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); } } - else if (boost::regex_search(channel, is_beta_channel)) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBetaBgColor" ); - } - else if (boost::regex_search(channel, is_project_channel)) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" ); - } - else if (boost::regex_search(channel, is_test_channel)) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarTestBgColor" ); - } - else if(!LLGridManager::getInstance()->isInProductionGrid()) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); - } - else - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); - } - + else + { + switch (LLVersionInfo::getViewerMaturity()) + { + case LLVersionInfo::TEST_VIEWER: + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarTestBgColor" ); + break; + + case LLVersionInfo::PROJECT_VIEWER: + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" ); + break; + + case LLVersionInfo::BETA_VIEWER: + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBetaBgColor" ); + break; + + case LLVersionInfo::RELEASE_VIEWER: + if(!LLGridManager::getInstance()->isInProductionGrid()) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); + } + else + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); + } + break; + } + } + if(gMenuBarView) { gMenuBarView->setBackgroundColor( new_bg_color ); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a573b16954..b97a1bde99 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -160,6 +160,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; const S32 MORPH_MASK_REQUESTED_DISCARD = 0; +const F32 MAX_STANDOFF_FROM_ORIGIN = 3; +const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32; + // Discard level at which to switch to baked textures // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB const S32 SWITCH_TO_BAKED_DISCARD = 5; @@ -722,7 +725,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); - LL_DEBUGS("Avatar") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; + LL_DEBUGS("Avatar","Message") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; mPelvisp = NULL; @@ -2132,7 +2135,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) // animate the character // store off last frame's root position to be consistent with camera position - LLVector3 root_pos_last = mRoot->getWorldPosition(); + mLastRootPos = mRoot->getWorldPosition(); BOOL detailed_update = updateCharacter(agent); static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false); @@ -2150,7 +2153,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) idleUpdateWindEffect(); } - idleUpdateNameTag( root_pos_last ); + idleUpdateNameTag( mLastRootPos ); idleUpdateRenderCost(); } @@ -5734,12 +5737,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent) void LLVOAvatar::addChild(LLViewerObject *childp) { childp->extractAttachmentItemID(); // find the inventory item this object is associated with. + if (isSelf()) + { + const LLUUID& item_id = childp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + + } + LLViewerObject::addChild(childp); if (childp->mDrawable) { if (!attachObject(childp)) { - LL_WARNS() << "addChild() failed for " + LL_WARNS() << "ATT addChild() failed for " << childp->getID() << " item " << childp->getAttachmentItemID() << LL_ENDL; @@ -5809,10 +5820,21 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi //----------------------------------------------------------------------------- const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object) { + if (isSelf()) + { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); if (!attachment || !attachment->addObject(viewer_object)) { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_WARNS("Avatar") << "ATT attach failed " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; return 0; } @@ -5872,6 +5894,13 @@ void LLVOAvatar::lazyAttach() LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i]; if (cur_attachment->mDrawable) { + if (isSelf()) + { + const LLUUID& item_id = cur_attachment->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } if (!attachObject(cur_attachment)) { // Drop it LL_WARNS() << "attachObject() failed for " @@ -6054,10 +6083,10 @@ void LLVOAvatar::getOffObject() { return; } - + LLViewerObject* sit_object = (LLViewerObject*)getParent(); - if (sit_object) + if (sit_object) { stopMotionFromSource(sit_object->getID()); LLFollowCamMgr::setCameraActive(sit_object->getID(), FALSE); @@ -6074,9 +6103,19 @@ void LLVOAvatar::getOffObject() } // assumes that transform will not be updated with drawable still having a parent + // or that drawable had no parent from the start LLVector3 cur_position_world = mDrawable->getWorldPosition(); LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); + if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN + && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN + || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) + { + // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent + // restore coordinates from cache + cur_position_world = mLastRootPos; + } + // set *local* position based on last *world* position, since we're unparenting the avatar mDrawable->mXform.setPosition(cur_position_world); mDrawable->mXform.setRotation(cur_rotation_world); @@ -6252,6 +6291,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color) BOOL LLVOAvatar::isVisible() const { return mDrawable.notNull() + && (!mOrphaned || isSelf()) && (mDrawable->isVisible() || mIsDummy); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 1c3f4f2aa7..5b4379165a 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -869,6 +869,8 @@ public: private: // set this property only with LLVOAvatar::sitDown method BOOL mIsSitting; + // position backup in case of missing data + LLVector3 mLastRootPos; /** Hierarchy ** ** diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 56997c928a..c1ca0aed69 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -38,6 +38,7 @@ #include "pipeline.h" #include "llagent.h" // Get state values from here +#include "llattachmentsmgr.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llhudeffecttrail.h" @@ -1118,44 +1119,6 @@ BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const } //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const -{ - const F32 REQUEST_EXPIRATION_SECONDS = 5.0; // any request older than this is ignored/removed. - std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.find(inv_item_id); - if (it != mAttachmentRequests.end()) - { - const LLTimer& request_time = it->second; - F32 request_time_elapsed = request_time.getElapsedTimeF32(); - if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS) - { - mAttachmentRequests.erase(it); - return FALSE; - } - else - { - return TRUE; - } - } - else - { - return FALSE; - } -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id) -{ - LLTimer current_time; - mAttachmentRequests[inv_item_id] = current_time; -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id) -{ - mAttachmentRequests.erase(inv_item_id); -} - -//----------------------------------------------------------------------------- // getWornAttachment() //----------------------------------------------------------------------------- LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) @@ -1221,8 +1184,6 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view { const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); LLAppearanceMgr::instance().registerAttachment(attachment_id); - // Clear any pending requests once the attachment arrives. - removeAttachmentRequest(attachment_id); updateLODRiggedAttachments(); } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index dc5e64d547..257a760eeb 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -109,6 +109,7 @@ private: private: LLUUID mInitialBakeIDs[6]; + //bool mInitialBakesLoaded; /******************************************************************************** @@ -291,19 +292,12 @@ protected: public: void updateAttachmentVisibility(U32 camera_mode); BOOL isWearingAttachment(const LLUUID& inv_item_id) const; - BOOL attachmentWasRequested(const LLUUID& inv_item_id) const; - void addAttachmentRequest(const LLUUID& inv_item_id); - void removeAttachmentRequest(const LLUUID& inv_item_id); LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); bool getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); -private: - // Track attachments that have been requested but have not arrived yet. - mutable std::map<LLUUID,LLTimer> mAttachmentRequests; - //-------------------------------------------------------------------- // HUDs //-------------------------------------------------------------------- diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 0432f6f27c..19d61f6e33 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1624,6 +1624,66 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives"); static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +{ + bool regen_faces = false; + + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces; + + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces(); + old_volumep = NULL; + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } + + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces(); + new_volumep = NULL; + + if ((new_lod != old_lod) || mSculptChanged) + { + compiled = TRUE; + sNumLODChanges += new_num_faces; + + if ((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + + return regen_faces; +} + BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); @@ -1664,83 +1724,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } - if (mVolumeChanged || mFaceMappingChanged ) + if (mVolumeChanged || mFaceMappingChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - compiled = TRUE; + bool was_regen_faces = false; if (mVolumeChanged) { - LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); + was_regen_faces = lodOrSculptChanged(drawable, compiled); drawable->setState(LLDrawable::REBUILD_VOLUME); } - + else if (mSculptChanged || mLODChanged) { + compiled = TRUE; + was_regen_faces = lodOrSculptChanged(drawable, compiled); + } + + if (!was_regen_faces) { LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); regenFaces(); - genBBoxes(FALSE); } + + genBBoxes(FALSE); } - else if ((mLODChanged) || (mSculptChanged)) + else if (mLODChanged || mSculptChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces ; - - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces() ; - old_volumep = NULL ; - - { - LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } - - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces() ; - new_volumep = NULL ; - - if ((new_lod != old_lod) || mSculptChanged) - { - compiled = TRUE; - sNumLODChanges += new_num_faces ; - - if((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } - - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - - { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs()) - { - regenFaces(); - } - genBBoxes(FALSE); - - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } - + compiled = TRUE; + lodOrSculptChanged(drawable, compiled); genBBoxes(FALSE); } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local @@ -2010,7 +2022,7 @@ void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLM LLTextureEntry* texture_entry = pVol->getTE(te); if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) { - pVol->setTEMaterialParams(te, pMaterialParams); + pVol->setTEMaterialParams(te, pMaterialParams, FALSE); } } } @@ -2081,7 +2093,7 @@ bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) { LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE); } //clear wait-list @@ -2158,7 +2170,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) { LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE); } //clear wait-list @@ -2167,7 +2179,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) return 0 != new_material.size(); } -S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer) { LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams); @@ -2264,7 +2276,7 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa } } - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial, isInitFromServer); LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" ) @@ -4163,7 +4175,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } //build matrix palette - static const size_t kMaxJoints = 64; + static const size_t kMaxJoints = 52; LLMatrix4a mp[kMaxJoints]; LLMatrix4* mat = (LLMatrix4*) mp; @@ -4172,6 +4184,12 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons for (U32 j = 0; j < maxJoints; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (!joint) + { + // Fall back to a point inside the avatar if mesh is + // rigged to an unknown joint. + joint = avatar->getJoint("mPelvis"); + } if (joint) { mat[j] = skin->mInvBindMatrix[j]; @@ -4216,8 +4234,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons wght[k] = w - floorf(w); scale += wght[k]; } - - wght *= 1.f/scale; + // This is enforced in unpackVolumeFaces() + llassert(scale>0.f); + wght *= 1.f / scale; for (U32 k = 0; k < 4; k++) { @@ -4225,9 +4244,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons LLMatrix4a src; // Insure ref'd bone is in our clamped array of mats - llassert(idx[k] < kMaxJoints); - // clamp k to kMaxJoints to avoid reading garbage off stack in release - src.setMul(mp[idx[(k < kMaxJoints) ? k : 0]], w); + // clamp idx to maxJoints to avoid reading garbage off stack in release + S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1); + src.setMul(mp[index], w); final_mat.add(src); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index bbaca316b0..ff7438ac09 100755 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -192,7 +192,7 @@ public: static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te); - /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); @@ -339,6 +339,10 @@ protected: void cleanUpMediaImpls(); void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; void removeMediaImpl(S32 texture_index) ; + +private: + bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); + public: static S32 getRenderComplexityMax() {return mRenderComplexity_last;} diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 888ead0613..1c3808ce68 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -124,7 +124,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, // We don't use get_is_item_worn() here because this update is triggered by // an inventory observer upon link in COF beind added or removed so actual // worn status of a linked item may still remain unchanged. - if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkInCOF(mInventoryItemUUID)) + if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) { search_label += LLTrans::getString("worn"); item_state = IS_WORN; diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index bfae142812..837b30586b 100755 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -383,6 +383,7 @@ void LLWorldMap::reloadItems(bool force) LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT); LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT); LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT); } } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index bdc884885f..8533625e50 100755 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -873,8 +873,11 @@ <color name="ToolbarDropZoneColor" value=".48 .69 1 .5" /> - - <!-- Generic color names (legacy) --> + <color + name="PanelNotificationListItem" + value="0.3 0.3 0.3 .3" /> + + <!-- Generic color names (legacy) --> <color name="white" value="1 1 1 1"/> diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png Binary files differnew file mode 100644 index 0000000000..0732a33d93 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png Binary files differnew file mode 100644 index 0000000000..8124554902 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png Binary files differnew file mode 100644 index 0000000000..4d245eb57a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png Binary files differnew file mode 100644 index 0000000000..186822da43 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png diff --git a/indra/newview/skins/default/textures/icons/Inv_StockFolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_StockFolderClosed.png Binary files differnew file mode 100644 index 0000000000..4dc484dc22 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_StockFolderClosed.png diff --git a/indra/newview/skins/default/textures/icons/Inv_StockFolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_StockFolderOpen.png Binary files differnew file mode 100644 index 0000000000..0d140b56a7 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_StockFolderOpen.png diff --git a/indra/newview/skins/default/textures/icons/Inv_VersionFolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_VersionFolderClosed.png Binary files differnew file mode 100644 index 0000000000..e89a4d7f31 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_VersionFolderClosed.png diff --git a/indra/newview/skins/default/textures/icons/Inv_VersionFolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_VersionFolderOpen.png Binary files differnew file mode 100644 index 0000000000..659d7d392f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_VersionFolderOpen.png diff --git a/indra/newview/skins/default/textures/icons/System_Notification_Large.png b/indra/newview/skins/default/textures/icons/System_Notification_Large.png Binary files differnew file mode 100644 index 0000000000..434ce3e8b6 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/System_Notification_Large.png diff --git a/indra/newview/skins/default/textures/icons/System_Notification_Small.png b/indra/newview/skins/default/textures/icons/System_Notification_Small.png Binary files differnew file mode 100644 index 0000000000..027a8446d8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/System_Notification_Small.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 408ee39f9b..e453d94883 100755 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -140,6 +140,7 @@ with the same filename but different name <texture name="Command_Inventory_Icon" file_name="toolbar_icons/inventory.png" preload="true" /> <texture name="Command_Map_Icon" file_name="toolbar_icons/map.png" preload="true" /> <texture name="Command_Marketplace_Icon" file_name="toolbar_icons/marketplace.png" preload="true" /> + <texture name="Command_MktListings_Icon" file_name="toolbar_icons/mktlistings.png" preload="true" /> <texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" /> <texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" /> <texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" /> @@ -306,6 +307,8 @@ with the same filename but different name <texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" /> <texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" /> <texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" /> + <texture name="Inv_StockFolderClosed" file_name="icons/Inv_StockFolderClosed.png" preload="false" /> + <texture name="Inv_StockFolderOpen" file_name="icons/Inv_StockFolderOpen.png" preload="false" /> <texture name="Inv_SysClosed" file_name="icons/Inv_SysClosed.png" preload="false" /> <texture name="Inv_SysOpen" file_name="icons/Inv_SysOpen.png" preload="false" /> <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" /> @@ -317,6 +320,8 @@ with the same filename but different name <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" /> <texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" /> <texture name="Inv_Invalid" file_name="icons/Inv_Invalid.png" preload="false" /> + <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" /> + <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" /> <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/> <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/> @@ -334,6 +339,7 @@ with the same filename but different name <texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" /> + <texture name="Marketplace_Dropzone_Background" file_name="widgets/Marketplace_Dropzone_Background.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" /> @@ -798,4 +804,9 @@ with the same filename but different name <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/> <texture name="NavBar Separator" file_name="navbar/separator.png"/> + <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/> + <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/> + <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/> + <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/> + <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/> </textures> diff --git a/indra/newview/skins/default/textures/toolbar_icons/mktlistings.png b/indra/newview/skins/default/textures/toolbar_icons/mktlistings.png Binary files differnew file mode 100644 index 0000000000..a6f90461d7 --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/mktlistings.png diff --git a/indra/newview/skins/default/textures/widgets/Marketplace_Dropzone_Background.png b/indra/newview/skins/default/textures/widgets/Marketplace_Dropzone_Background.png Binary files differnew file mode 100644 index 0000000000..9478f7b813 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Marketplace_Dropzone_Background.png diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml index aa6bc53672..299322001b 100755 --- a/indra/newview/skins/default/xui/da/menu_viewer.xml +++ b/indra/newview/skins/default/xui/da/menu_viewer.xml @@ -37,7 +37,7 @@ <menu_item_separator/> <menu_item_call label="Profil for sted" name="Place Profile"/> <menu_item_call label="Om land" name="About Land"/> - <menu_item_call label="Region/Estate" name="Region/Estate"/> + <menu_item_call label="Region/Estate" name="RegionEstate"/> <menu_item_call label="Køb dette land" name="Buy Land"/> <menu_item_call label="Mit land" name="My Land"/> <menu label="Vis" name="LandShow"> diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 33b876bdb9..aad3b9d062 100755 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1311,9 +1311,6 @@ Prøv igen om lidt. <notification name="NoValidCircuit"> Ingen gyldig kode for kredsløb. </notification> - <notification name="NoValidTimestamp"> - Ikke et gyldigt klokkeslæt. - </notification> <notification name="NoPendingConnection"> Kunne ikke skabe fast forbindelse. </notification> diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index bc0eae7c5d..ee631476cb 100755 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -1,74 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="INFO ÃœBER [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - Kompiliert mit [COMPILER] version [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Sie befinden sich an [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL: <nolink>[SLURL]</nolink> -(globale Koordinaten [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -Speicher: [MEMORY_MB] MB -Betriebssystem, Version: [OS_VERSION] -Grafikkarten-Hersteller: [GRAPHICS_CARD_VENDOR] -Grafikkarten: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Windows Grafiktreiber-Version: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - OpenGL Version: [OPENGL_VERSION] - -libcurl-Version: [LIBCURL_VERSION] -J2C-Decoderversion: [J2C_VERSION] -Audio-Treiberversion: [AUDIO_DRIVER_VERSION] -Qt Webkit-Version: [QT_WEBKIT_VERSION] -Voice-Serverversion: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (keiner) - </floater.string> - <floater.string name="AboutTraffic"> - Paketverlust: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Fehler beim Abrufen der URL für die Server-Versionshinweise. - </floater.string> <tab_container name="about_tab"> <panel label="Info" name="support_panel"> <button label="In Zwischenablage kopieren" name="copy_btn"/> </panel> <panel label="Danksagung" name="credits_panel"> - <text name="linden_intro"> - Second Life wird präsentiert von den Lindens: - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - mit Open-Source-Beiträgen von: - </text> - <text_editor name="contrib_names"> - Dummy-Name wird zur Laufzeit ersetzt - </text_editor> - <text name="trans_intro"> - mit Ãœbersetzungen von: - </text> - <text_editor name="trans_names"> - Dummy Name wird zur Laufzeit ersetzt - </text_editor> + <text name="linden_intro">Second Life wird präsentiert von den Lindens +mit Open-Source-Beiträgen von:</text> + <text_editor name="contrib_names">Dummy-Name wird zur Laufzeit ersetzt</text_editor> </panel> <panel label="Lizenzen" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion. + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion. APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg (daniel@haxx.se). @@ -95,8 +37,7 @@ Voice-Serverversion: [VOICE_VERSION] Alle Rechte vorbehalten. Details siehe licenses.txt. - Audiocodierung für Voice-Chat: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Audiocodierung für Voice-Chat: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_associate_listing.xml b/indra/newview/skins/default/xui/de/floater_associate_listing.xml new file mode 100644 index 0000000000..827b1b0aea --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="AUFLISTUNG VERKNÃœPFEN"> + <text name="message">Auflistungs-ID:</text> + <line_editor name="listing_id">ID hier eingeben</line_editor> + <button label="OK" name="OK"/> + <button label="Abbrechen" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/de/floater_edit_hover_height.xml new file mode 100644 index 0000000000..c26f7f367d --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="SCHWEBEHÖHE FESTLEGEN"> + <slider label="Höhe" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml index 7f48105460..92c038057f 100755 --- a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="EIGENSCHAFTEN: INVENTAROBJEKT"> - <floater.string name="unknown"> - (unbekannt) - </floater.string> - <floater.string name="public"> - (öffentlich) - </floater.string> - <floater.string name="you_can"> - Sie können: - </floater.string> - <floater.string name="owner_can"> - Eigentümer kann: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Name: - </text> - <text name="LabelItemDescTitle"> - Beschreibung: - </text> - <text name="LabelCreatorTitle"> - Ersteller: - </text> + <floater.string name="unknown">(unbekannt)</floater.string> + <floater.string name="public">(öffentlich)</floater.string> + <floater.string name="you_can">Sie können:</floater.string> + <floater.string name="owner_can">Eigentümer kann:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Name:</text> + <text name="LabelItemDescTitle">Beschreibung:</text> + <text name="LabelCreatorTitle">Ersteller:</text> <button label="Profil..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Eigentümer: - </text> + <text name="LabelOwnerTitle">Eigentümer:</text> <button label="Profil..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Erworben: - </text> - <text name="LabelAcquiredDate"> - Mittwoch, 24. Mai 2006, 12:50:46 - </text> - <text name="OwnerLabel"> - Sie: - </text> + <text name="LabelAcquiredTitle">Erworben:</text> + <text name="LabelAcquiredDate">Mittwoch, 24. Mai 2006, 12:50:46</text> + <text name="OwnerLabel">Sie:</text> <check_box label="Bearbeiten" name="CheckOwnerModify"/> <check_box label="Kopieren" left_delta="85" name="CheckOwnerCopy"/> <check_box label="Wiederverkaufen" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Jeder: - </text> + <text name="AnyoneLabel">Jeder:</text> <check_box label="Kopieren" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Gruppe: - </text> + <text name="GroupLabel">Gruppe:</text> <check_box label="Teilen" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="150"> - Nächster Eigentümer: - </text> + <text name="NextOwnerLabel" width="150">Nächster Eigentümer:</text> <check_box label="Bearbeiten" name="CheckNextOwnerModify"/> <check_box label="Kopieren" left_delta="55" name="CheckNextOwnerCopy"/> <check_box label="Wiederverkaufen" name="CheckNextOwnerTransfer"/> <check_box label="Zum Verkauf" name="CheckPurchase"/> - <combo_box name="combobox sale copy" left_pad="25"> - <combo_box.item label="Kopieren" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Kopie" name="Copy"/> + <combo_box.item label="Inhalt" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Preis:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_item_properties.xml b/indra/newview/skins/default/xui/de/floater_item_properties.xml new file mode 100644 index 0000000000..eb8314ad13 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="OBJEKTEIGENSCHAFTEN"/> diff --git a/indra/newview/skins/default/xui/de/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/de/floater_marketplace_listings.xml new file mode 100644 index 0000000000..fd6e2d904f --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="MARKTPLATZ-AUFLISTUNGEN"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Laden...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/de/floater_marketplace_validation.xml new file mode 100644 index 0000000000..4782b353b4 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Marketplace-Auflistungen prüfen"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_openobject.xml b/indra/newview/skins/default/xui/de/floater_openobject.xml index 5aa4477f2e..cd7796418c 100755 --- a/indra/newview/skins/default/xui/de/floater_openobject.xml +++ b/indra/newview/skins/default/xui/de/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="In Inventar kopieren" label_selected="In Inventar kopieren" name="copy_to_inventory_button" width="120"/> - <button label="Kopieren und zum Outfit hinzufügen" label_selected="Kopieren und zum Outfit hinzufügen" left_pad="6" name="copy_and_wear_button" width="136"/> + <text name="border_note"> + In Inventar kopieren und tragen + </text> + <button label="Zum Outfit hinzufügen" label_selected="Zum Outfit hinzufügen" left_pad="6" name="copy_and_wear_button" width="136"/> + <button label="Outfit ersetzen" label_selected="Outfit ersetzen" name="copy_and_replace_button"/> + <button label="Nur in Inventar kopieren" label_selected="Nur in Inventar kopieren" name="copy_to_inventory_button" width="120"/> + <button label="Abbrechen" label_selected="Abbrechen" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_pay.xml b/indra/newview/skins/default/xui/de/floater_pay.xml index a0a622ecbc..1882f5150b 100755 --- a/indra/newview/skins/default/xui/de/floater_pay.xml +++ b/indra/newview/skins/default/xui/de/floater_pay.xml @@ -1,25 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - Gruppe bezahlen - </string> - <string name="payee_resident"> - Einwohner bezahlen - </string> - <text name="payee_label" width="130"> - Bezahlen: - </text> - <icon name="icon_person" tool_tip="Person"/> - <text left="130" name="payee_name"> - Extrem langen Namen testen, um zu prüfen, ob er abgeschnitten wird - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text name="amount text"> - oder Betrag auswählen: - </text> - <button label="Bezahlen" label_selected="Bezahlen" name="pay btn"/> - <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn"/> + <string name="payee_group">Gruppe bezahlen</string> + <string name="payee_resident">Einwohner bezahlen</string> + <text name="paying_text">Sie zahlen:</text> + <text left="130" name="payee_name">Extrem langen Namen testen, um zu prüfen, ob er abgeschnitten wird</text> + <panel label="Suchen" name="PatternsPanel"> + <button label="L$ 1 zahlen" label_selected="L$ 1 zahlen" name="fastpay 1"/> + <button label="L$ 5 zahlen" label_selected="L$ 5 zahlen" name="fastpay 5"/> + <button label="L$ 10 zahlen" label_selected="L$ 10 zahlen" name="fastpay 10"/> + <button label="L$ 20 zahlen" label_selected="L$ 20 zahlen" name="fastpay 20"/> + </panel> + <panel label="Suchen" name="InputPanel"> + <text name="amount text">Anderer Betrag:</text> + <button label="Bezahlen" label_selected="Bezahlen" name="pay btn"/> + <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_pay_object.xml b/indra/newview/skins/default/xui/de/floater_pay_object.xml index 7159bbadb3..35f3ca032a 100755 --- a/indra/newview/skins/default/xui/de/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/de/floater_pay_object.xml @@ -1,29 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group" width="105"> - Gruppe bezahlen - </string> - <string name="payee_resident" width="118"> - Einwohner bezahlen - </string> - <icon name="icon_person" tool_tip="Person"/> - <text left="128" name="payee_name" width="168"> - Ericacita Moostopolison - </text> - <text halign="left" name="object_name_label"> - Ãœber Objekt: - </text> + <string name="payee_group" width="105">Gruppe bezahlen</string> + <string name="payee_resident" width="118">Einwohner bezahlen</string> + <text name="paying_text">Sie zahlen:</text> + <text left="128" name="payee_name" width="168">Ericacita Moostopolison</text> + <text halign="left" name="object_name_label">Ãœber Objekt:</text> <icon name="icon_object" tool_tip="Objekte"/> - <text left="105" name="object_name_text"> - ... - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text name="amount text"> - oder Betrag auswählen: - </text> - <button label="Bezahlen" label_selected="Bezahlen" name="pay btn"/> - <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn" width="76"/> + <text left="105" name="object_name_text">...</text> + <panel label="Suchen" name="PatternsPanel"> + <button label="L$ 1 zahlen" label_selected="L$ 1 zahlen" name="fastpay 1"/> + <button label="L$ 5 zahlen" label_selected="L$ 5 zahlen" name="fastpay 5"/> + <button label="L$ 10 zahlen" label_selected="L$ 10 zahlen" name="fastpay 10"/> + <button label="L$ 20 zahlen" label_selected="L$ 20 zahlen" name="fastpay 20"/> + </panel> + <panel label="Suchen" name="InputPanel"> + <text name="amount text">Anderer Betrag:</text> + <button label="Bezahlen" label_selected="Bezahlen" name="pay btn"/> + <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/de/menu_attachment_self.xml b/indra/newview/skins/default/xui/de/menu_attachment_self.xml index 7888c7b0a1..e0f37b28af 100755 --- a/indra/newview/skins/default/xui/de/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/de/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Mein Aussehen" name="Change Outfit"/> <menu_item_call label="Mein Outfit bearbeiten" name="Edit Outfit"/> <menu_item_call label="Meine Form bearbeiten" name="Edit My Shape"/> + <menu_item_call label="Schwebehöhe" name="Hover Height"/> <menu_item_call label="Meine Freunde" name="Friends..."/> <menu_item_call label="Meine Gruppen" name="Groups..."/> <menu_item_call label="Mein Profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/de/menu_avatar_self.xml b/indra/newview/skins/default/xui/de/menu_avatar_self.xml index 022cd8c3ca..b53f8cd6af 100755 --- a/indra/newview/skins/default/xui/de/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/de/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Mein Aussehen" name="Chenge Outfit"/> <menu_item_call label="Mein Outfit bearbeiten" name="Edit Outfit"/> <menu_item_call label="Meine Form bearbeiten" name="Edit My Shape"/> + <menu_item_call label="Schwebehöhe" name="Hover Height"/> <menu_item_call label="Meine Freunde" name="Friends..."/> <menu_item_call label="Meine Gruppen" name="Groups..."/> <menu_item_call label="Mein Profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml index d838f736f8..e1f545adfc 100755 --- a/indra/newview/skins/default/xui/de/menu_inventory.xml +++ b/indra/newview/skins/default/xui/de/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Auflistung erstellen" name="Marketplace Create Listing"/> + <menu_item_call label="Auflistung verknüpfen" name="Marketplace Associate Listing"/> + <menu_item_call label="Auflistung abrufen (aktualisieren)" name="Marketplace Get Listing"/> + <menu_item_call label="Auf Fehler prüfen" name="Marketplace Check Listing"/> + <menu_item_call label="Auflistung bearbeiten" name="Marketplace Edit Listing"/> + <menu_item_call label="Auflisten" name="Marketplace List"/> + <menu_item_call label="Entfernen" name="Marketplace Unlist"/> + <menu_item_call label="Aktivieren" name="Marketplace Activate"/> + <menu_item_call label="Deaktivieren" name="Marketplace Deactivate"/> <menu_item_call label="Teilen" name="Share"/> <menu_item_call label="Kaufen" name="Task Buy"/> <menu_item_call label="Öffnen" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Hinzufügen" name="Wearable Add"/> <menu_item_call label="Ausziehen" name="Take Off"/> <menu_item_call label="In Händler-Outbox kopieren" name="Merchant Copy"/> - <menu_item_call label="In Marktplatz übertragen" name="Marketplace Send"/> + <menu_item_call label="In Marktplatz-Auflistungen kopieren" name="Marketplace Copy"/> + <menu_item_call label="In Marktplatz-Auflistungen verschieben" name="Marketplace Move"/> <menu_item_call label="--keine Optionen--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/de/menu_marketplace_view.xml b/indra/newview/skins/default/xui/de/menu_marketplace_view.xml new file mode 100644 index 0000000000..41516a1e7c --- /dev/null +++ b/indra/newview/skins/default/xui/de/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Nach verfügbarer Menge sortieren (niedrig bis hoch)" name="sort_by_stock_amount"/> + <menu_item_check label="Nur Auflistungsordner anzeigen" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index a328ca39f8..956530c990 100755 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Fliegen" name="Fly"/> <menu_item_check label="Immer rennen" name="Always Run"/> <menu_item_call label="Animation meines Avatars stoppen" name="Stop Animating My Avatar"/> - <menu_item_call label="Gehen/Rennen/Fliegen..." name="Walk / run / fly"/> + <menu_item_call label="Gehen/Rennen/Fliegen..." name="WalkRunFly"/> </menu> <menu label="Status" name="Status"> <menu_item_check label="Abwesend" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="L$ kaufen..." name="Buy and Sell L$"/> <menu_item_call label="Händler-Outbox..." name="MerchantOutbox"/> + <menu_item_call label="Marktplatz-Auflistungen..." name="MarketplaceListings"/> <menu_item_call label="Kontoübersicht..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/> </menu_item_call> @@ -63,7 +64,7 @@ <menu_item_call label="Foto" name="Take Snapshot"/> <menu_item_call label="Ortsprofil" name="Place Profile"/> <menu_item_call label="Landinformationen" name="About Land"/> - <menu_item_call label="Region/Grundbesitz" name="Region/Estate"/> + <menu_item_call label="Region/Grundbesitz" name="RegionEstate"/> <menu_item_call label="Mein Landbesitz..." name="My Land"/> <menu_item_call label="Dieses Land kaufen" name="Buy Land"/> <menu label="Anzeigen" name="LandShow"> @@ -251,6 +252,7 @@ <menu_item_check label="Textur" name="Texture Console"/> <menu_item_check label="Fehler beseitigen" name="Debug Console"/> <menu_item_call label="Meldungen" name="Notifications"/> + <menu_item_check label="Regions-Debug-Konsole" name="Region Debug Console"/> <menu_item_check label="Schnelle Timer" name="Fast Timers"/> <menu_item_check label="Speicher" name="Memory"/> <menu_item_check label="Szenestatistiken" name="Scene Statistics"/> @@ -354,7 +356,7 @@ <menu_item_check label="Positionen der interpolierten Objekte anfragen" name="Ping Interpolate Object Positions"/> <menu_item_call label="Ein Paket fallenlassen" name="Drop a Packet"/> </menu> - <menu_item_call label="Geskriptete Kamera ausgeben" name="Dump Scripted Camera"/> + <menu_item_call label="Geskriptete Kamera ausgeben" name="Dump Scripted Camera"/> <menu label="Rekorder" name="Recorder"> <menu_item_call label="Wiedergabe starten" name="Start Playback"/> <menu_item_call label="Wiedergabe stoppen" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 09cba36e25..fa7db0a8a3 100755 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -129,6 +129,88 @@ Aufgrund eines System- oder Netzwerkfehlers wurden keine Ordner an den Marktplat Marktplatzinitialisierung aufgrund eines System- oder Netzwerkfehlers fehlgeschlagen. Versuchen Sie es später erneut. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Kopieren oder Verschieben in Bestandsordner fehlgeschlagen mit Fehler: + + „[ERROR_CODE]“ + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Kopieren oder Verschieben von Marktplatz-Auflistungen fehlgeschlagen mit Fehler: + + „[ERROR_CODE]“ + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + Marktplatztransaktion fehlgeschlagen mit Fehler: + + Grund: „[ERROR_REASON]“ + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Wir konnten dieses Produkt nicht auflisten bzw. den Versionsordner nicht aktivieren. Dies liegt meist an fehlenden Informationen im Formular zur Beschreibung der Auflistung, kann aber auch auf eine falsche Ordnerstruktur zurückzuführen sein. Bearbeiten Sie die Auflistung oder überprüfen Sie den Auflistungsordner auf Fehler. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Auflistung in Marktplatz fehlgeschlagen mit Fehler: + + „[ERROR_CODE]“ + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Aktivierung dieses Versionsordners fehlgeschlagen mit Fehler: + + „[ERROR_CODE]“ + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Diese Aktion ändert den aktiven Inhalt dieser Auflistung. Möchten Sie fortfahren? + <usetemplate ignoretext="Vor Ändern einer aktiven Auflistung im Marktplatz bestätigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Objekte, die ins Marktplatz-Auflistungsfenster gezogen werden, werden verschoben, nicht kopiert. Möchten Sie fortfahren? + <usetemplate ignoretext="Vor Verschieben eines Objekts aus dem Inventar in den Marktplatz bestätigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Wenn Sie einen Auflistungsordner verschieben oder löschen, wird Ihre Marktplatz-Auflistung gelöscht. Um die Marktplatz-Auflistung beizubehalten, verschieben oder löschen Sie den Inhalt des Versionsordners, den Sie ändern möchten. Möchten Sie fortfahren? + <usetemplate ignoretext="Bestätigen, bevor ich eine Auflistung aus dem Marktplatz entferne oder verschiebe" name="okcancelignore" notext="Abbrechen" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Sie haben keine Berechtigung, eines oder mehrere dieser Objekte in den Marktplatz zu kopieren. Sie können sie verschieben oder zurücklassen. + <usetemplate canceltext="Abbrechen" ignoretext="Vor Kopieren einer Auswahl mit kopiergeschützten Objekten in den Marktplatz bestätigen" name="yesnocancelbuttons" notext="Artikel nicht verschieben" yestext="Artikel verschieben"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Diese Aktion entfernt diese Auflistung. Möchten Sie fortfahren? + <usetemplate ignoretext="Vor Entfernen einer aktiven Auflistung aus dem Marktplatz bestätigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Diese Aktion deaktiviert den Versionsordner der aktuellen Auflistung. Möchten Sie fortfahren? + <usetemplate ignoretext="Vor Deaktivieren des Versionsordners einer Auflistung im Marktplatz bestätigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Diese Auflistung konnte nicht aktualisiert werden. +[[URL] Klicken Sie hier], um sie im Marktplatz zu bearbeiten. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Sie können keine Kleidung oder Körperteile tragen, die im Marktplatz-Auflistungsordner enthalten sind + </notification> + <notification name="AlertMerchantListingInvalidID"> + Auflistungs-ID ungültig. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + In dieser Auflistung gibt es mehrere oder keine Versionsordner. Sie müssen später einen auswählen und aktivieren. + <usetemplate ignoretext="Benachrichtung zur Versionsordneraktivierung, wenn ich eine Auflistung mit mehreren Versionsordnern erstelle" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Wir haben Bestandsobjekte unterschiedlicher Typen in separate Bestandsordner gelegt, damit wir Ihren Ordner auflisten können. + <usetemplate ignoretext="Benachrichtigen,wenn Bestandsordner vor dem Auflisten aufgeteilt wird" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Wir haben Ihre Auflistung entfernt, da der Bestandsordner leer ist. Um diese Auflistung wieder zu listen, müssen Sie weitere Einheiten zum Bestandsordner hinzufügen. + <usetemplate ignoretext="Benachrichtigen, wenn Auflistung aufgrund eines leeren Bestandsordners nicht aufgelistet wird" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> Der Text für ein Skript konnte aus folgendem Grund nicht hochgeladen werden: [REASON]. Bitte versuchen Sie es erneut. </notification> @@ -480,6 +562,10 @@ Hinweis: Der Cache wird dabei gelöscht/geleert. Änderungen speichern? <usetemplate canceltext="Abbrechen" name="yesnocancelbuttons" notext="Nicht speichern" yestext="Speichern"/> </notification> + <notification name="DeleteNotecard"> + Notizkarte löschen? + <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Speichern der Geste fehlgeschlagen. Die Geste besteht aus zu vielen Schritten. @@ -1882,6 +1968,9 @@ Tausende Regionen werden verändert und der Spaceserver wird dadurch stark belas Die Region, die Sie besuchen möchten, enthält Inhalte, die Ihre aktuellen Einstellungen überschreiten. Sie können Ihre Einstellungen unter „Ich“ > „Einstellungen“ > „Allgemein“ ändern. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> Die Region, die Sie besuchen möchten, enthält [REGIONMATURITY]-Inhalte, die nur für Erwachsene zugänglich sind. <url name="url"> @@ -2171,6 +2260,10 @@ Inventarobjekt(e) verschieben? <ignore name="ignore" text="Ich habe die Aktion „Objekt bezahlen" eingestellt, während ich ein Objekt gebaut habe, dass kein Geld()-Skript enthält."/> </form> </notification> + <notification name="PayConfirmation"> + Bestätigen Sie, dass Sie L$ [AMOUNT] an [TARGET] zahlen möchten. + <usetemplate ignoretext="Vor den Bezahlen bestätigen (Summen über L$ 200)" name="okcancelignore" notext="Abbrechen" yestext="Bezahlen"/> + </notification> <notification name="OpenObjectCannotCopy"> Sie haben keine Berechtigung zum Kopieren von Elementen in diesem Objekt. </notification> @@ -2709,9 +2802,6 @@ Versuchen Sie es in einigen Minuten erneut. <notification name="NoValidCircuit"> Kein gültiger Verbindungscode. </notification> - <notification name="NoValidTimestamp"> - Kein gültiger Zeitstempel. - </notification> <notification name="NoPendingConnection"> Verbindung kann nicht hergestellt werden. </notification> @@ -3855,9 +3945,11 @@ Warten Sie kurz und versuchen Sie es noch einmal. </notification> <notification name="TeleportedByAttachment"> Sie wurden von einem Anhang an [ITEM_ID] teleportiert + <usetemplate ignoretext="Teleport: Sie wurden von einem Anhang teleportiert" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Sie wurden von Objekt „[OBJECT_NAME]“ auf der Parzelle „[PARCEL_NAME]“ teleportiert + <usetemplate ignoretext="Teleport: Sie wurden von einem Objekt in einer Parzelle teleportiert" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Sie wurden von Objekt „[OBJECT_NAME]“, das [OWNER_ID] gehört, teleportiert @@ -4189,7 +4281,7 @@ Wählen Sie eine kleinere Landfläche aus. <usetemplate ignoretext="Dateien können nicht verschoben werden. Vorheriger Pfad wurde wiederhergestellt." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Die Standardberechtigungen konnten aus folgendem Grund nicht gespeichert werden: [REASON]. Versuchen Sie später, die Standardberechtigungen einzustellen. + Problem beim Speichern der standardmäßigen Objektberechtigungen: [REASON]. Versuchen Sie später, die Standardberechtigungen einzustellen. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/de/panel_login.xml b/indra/newview/skins/default/xui/de/panel_login.xml index 816f22178c..32c9598edf 100755 --- a/indra/newview/skins/default/xui/de/panel_login.xml +++ b/indra/newview/skins/default/xui/de/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=de - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=de</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Benutzername" name="username_combo" tool_tip="Bei der Registrierung gewählter Benutzername wie „berndschmidt12“ oder „Liebe Sonne“"/> <line_editor label="Kennwort" name="password_edit"/> - <check_box label="Details speichern" name="remember_check"/> - <text name="forgot_password_text"> - Kennwort vergessen - </text> - <button label="Anmelden" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - bei letztem Ort - </text> <combo_box label="Meine Lieblingsorte" name="start_location_combo"> + <combo_box.item label="Mein letzter Standort" name="MyLastLocation"/> <combo_box.item label="Mein Zuhause" name="MyHome"/> </combo_box> - <button label="Anmelden" name="connect_favorite_btn"/> - <line_editor label="Ort eingeben" name="location_edit"/> - <button label="Anmelden" name="connect_location_btn"/> + <button label="Anmelden" name="connect_btn"/> + <check_box label="Details speichern" name="remember_check"/> + <text name="forgot_password_text">Kennwort vergessen</text> <combo_box label="Grid auswählen" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/de/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/de/panel_marketplace_listings.xml new file mode 100644 index 0000000000..bc9065e185 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Marktplatz" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Anzeige-/Sortieroptionen"/> + <button name="add_btn" tool_tip="Neuen Auflistungsordner erstellen"/> + <button label="Auf Fehler prüfen" name="audit_btn" tool_tip="Marktplatz-Auflistungen überprüfen"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Marktplatz-Auflistungen filtern" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/de/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..becf79b0a2 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ALLE" name="All Items" tool_tip="Objekte zum Auflisten hier ablegen"/> diff --git a/indra/newview/skins/default/xui/de/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/de/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..63c4f34bad --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="AUFGELISTET" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/de/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/de/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..26908c3e25 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NICHT VERKNÃœPFT" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/de/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/de/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..00ea1e6fe7 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NICHT AUFGELISTET" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml index 3f5bbda724..3f5bbda724 100755..100644 --- a/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index 14ace0ac3a..d3d85de3c3 100755 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Paketverlust - </panel.string> - <panel.string name="bandwidth_tooltip"> - Bandbreite - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - [AMT] L$ - </panel.string> + <panel.string name="packet_loss_tooltip">Paketverlust</panel.string> + <panel.string name="bandwidth_tooltip">Bandbreite</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">[AMT] L$</panel.string> <panel left="-415" name="balance_bg" width="205"> - <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/> + <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="L$ ??"/> <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> <button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/> </panel> - <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)"> - 24:00 H PST - </text> + <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)">24:00 H PST</text> <button name="media_toggle_btn" tool_tip="Alle Medien starten/stoppen (Musik, Video, Webseiten)"/> <button name="volume_btn" tool_tip="Steuerung der Gesamtlautstärke"/> </panel> diff --git a/indra/newview/skins/default/xui/de/sidepanel_item_info.xml b/indra/newview/skins/default/xui/de/sidepanel_item_info.xml index d0bd23138d..f7dc265cf4 100755 --- a/indra/newview/skins/default/xui/de/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/de/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Ãœbertragen" name="CheckNextOwnerTransfer" tool_tip="Nächster Eigentümer kann dieses Objekt weitergeben oder -verkaufen"/> </panel> <check_box label="Zum Verkauf" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="Kopieren" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Kopie" name="Copy"/> + <combo_box.item label="Inhalt" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Preis: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/de/sidepanel_task_info.xml b/indra/newview/skins/default/xui/de/sidepanel_task_info.xml index 29239033fe..c30611c66c 100755 --- a/indra/newview/skins/default/xui/de/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/de/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Objektprofil"> - <panel.string name="text deed continued"> - Ãœbertragung - </panel.string> - <panel.string name="text deed"> - Ãœbertragung - </panel.string> - <panel.string name="text modify info 1"> - Sie können dieses Objekt bearbeiten. - </panel.string> - <panel.string name="text modify info 2"> - Sie können diese Objekte bearbeiten. - </panel.string> - <panel.string name="text modify info 3"> - Sie können dieses Objekt nicht bearbeiten. - </panel.string> - <panel.string name="text modify info 4"> - Sie können diese Objekte nicht bearbeiten. - </panel.string> - <panel.string name="text modify info 5"> - Dieses Objekt kann nicht über eine Regionsgrenze hinweg geändert werden - </panel.string> - <panel.string name="text modify info 6"> - Diese Objekte können nicht über eine Regionsgrenze hinweg geändert werden - </panel.string> - <panel.string name="text modify warning"> - Diese Objekt verfügt über verknüpfte Teile - </panel.string> - <panel.string name="Cost Default"> - Preis: L$ - </panel.string> - <panel.string name="Cost Total"> - Summe: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Stückpreis: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Mischpreis - </panel.string> - <panel.string name="Sale Mixed"> - Mischverkauf - </panel.string> + <panel.string name="text deed continued">Ãœbertragung</panel.string> + <panel.string name="text deed">Ãœbertragung</panel.string> + <panel.string name="text modify info 1">Sie können dieses Objekt bearbeiten.</panel.string> + <panel.string name="text modify info 2">Sie können diese Objekte bearbeiten.</panel.string> + <panel.string name="text modify info 3">Sie können dieses Objekt nicht bearbeiten.</panel.string> + <panel.string name="text modify info 4">Sie können diese Objekte nicht bearbeiten.</panel.string> + <panel.string name="text modify info 5">Dieses Objekt kann nicht über eine Regionsgrenze hinweg geändert werden</panel.string> + <panel.string name="text modify info 6">Diese Objekte können nicht über eine Regionsgrenze hinweg geändert werden</panel.string> + <panel.string name="text modify warning">Diese Objekt verfügt über verknüpfte Teile</panel.string> + <panel.string name="Cost Default">Preis: L$</panel.string> + <panel.string name="Cost Total">Summenpreis: L$</panel.string> + <panel.string name="Cost Per Unit">Stückpreis: L$</panel.string> + <panel.string name="Cost Mixed">Mischpreis</panel.string> + <panel.string name="Sale Mixed">Mischverkauf</panel.string> <text name="title" value="Objektprofil"/> <text name="where" value="(Inworld)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Name: - </text> - <text name="Description:"> - Beschreibung: - </text> - <text name="CreatorNameLabel"> - Ersteller: - </text> - <text name="Owner:"> - Eigentümer: - </text> - <text name="Group_label"> - Gruppe: - </text> + <text name="Name:">Name:</text> + <text name="Description:">Beschreibung:</text> + <text name="CreatorNameLabel">Ersteller:</text> + <text name="Owner:">Eigentümer:</text> + <text name="Group_label">Gruppe:</text> <button name="button set group" tool_tip="Eine Gruppe auswählen, um die Berechtigungen des Objekts zu teilen."/> <name_box initial_value="Wird geladen..." name="Group Name Proxy"/> <button label="Ãœbertragung" label_selected="Ãœbertragung" name="button deed" tool_tip="Eine Ãœbertragung bedeutet, dass das Objekt mit den Berechtigungen „Nächster Eigentümer“ weitergegeben wird. Mit der Gruppe geteilte Objekte können von einem Gruppen-Officer übertragen werden."/> - <text name="label click action"> - Bei Linksklick: - </text> + <text name="label click action">Bei Linksklick:</text> <combo_box name="clickaction"> <combo_box.item label="Berühren (Standard)" name="Touch/grab(default)"/> <combo_box.item label="Auf Objekt setzen" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Zoomen" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Sie können dieses Objekt bearbeiten. - </text> - <text name="Anyone can:"> - Jeder: - </text> + <text name="perm_modify">Sie können dieses Objekt bearbeiten.</text> + <text name="Anyone can:">Jeder:</text> <check_box label="Kopieren" name="checkbox allow everyone copy"/> <check_box label="Bewegen" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Gruppe: - </text> + <text name="GroupLabel">Gruppe:</text> <check_box label="Teilen" name="checkbox share with group" tool_tip="Mit allen Mitgliedern der zugeordneten Gruppe, Ihre Berechtigungen dieses Objekt zu ändern, teilen. Sie müssen Ãœbereignen, um Rollenbeschränkungen zu aktivieren."/> - <text name="NextOwnerLabel"> - Nächster Eigentümer: - </text> + <text name="NextOwnerLabel">Nächster Eigentümer:</text> <check_box label="Bearbeiten" name="checkbox next owner can modify"/> <check_box label="Kopieren" name="checkbox next owner can copy"/> <check_box label="Transferieren" name="checkbox next owner can transfer" tool_tip="Nächster Eigentümer kann dieses Objekt weitergeben oder -verkaufen"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Preis: L$" name="Edit Cost"/> <check_box label="In Suche anzeigen" name="search_check" tool_tip="Dieses Objekt in Suchergebnissen anzeigen"/> - <text name="pathfinding_attributes_label"> - Pathfinding-Attribute: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Pathfinding-Attribute:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Öffnen" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 7cb7b31886..35f5624c13 100755 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -454,28 +454,46 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. </string> <string name="TooltipPrice" value="[AMOUNT] L$"/> <string name="TooltipOutboxDragToWorld"> - Sie können Artikel nicht in Ihrer Händler-Outbox rezzen + Sie können keine Objekte aus dem Marktplatz-Auflistungsordner rezzen + </string> + <string name="TooltipOutboxWorn"> + Sie können Objekte, die Sie tragen, nicht in den Marktplatz-Auflistungsordner stellen + </string> + <string name="TooltipOutboxFolderLevels"> + Tiefe der verschachtelten Ordner überschreitet [AMOUNT]. Reduzieren Sie die Ordnertiefe. Verpacken Sie ggf. einige Artikel. + </string> + <string name="TooltipOutboxTooManyFolders"> + Anzahl von Unterordnern überschreitet [AMOUNT]. Reduzieren Sie die Anzahl von Ordnern in Ihrer Auflistung. Verpacken Sie ggf. einige Artikel. + </string> + <string name="TooltipOutboxTooManyObjects"> + Anzahl von Objekten überschreitet [AMOUNT]. Um mehr als [AMOUNT] Objekte in einer Auflistung verkaufen zu können, müssen Sie einige davon verpacken. + </string> + <string name="TooltipOutboxTooManyStockItems"> + Anzahl von Bestandsobjekten überschreitet [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Sie können Objekte oder Ordner nur in der Registerkarte „Alle“ ablegen. Wählen Sie diese Registerkarte aus und verschieben Sie Ihre Objekte bzw. Ordner noch einmal. </string> <string name="TooltipOutboxNoTransfer"> - Einer oder mehrere dieser Artikel können nicht verkauft oder übertragen werden. + Mindestens eines dieser Objekte kann nicht verkauft oder übertragen werden </string> <string name="TooltipOutboxNotInInventory"> - Nur Artikel direkt aus Ihrem Inventar können in Ihre Händler-Outbox gelegt werden + Sie können nur Objekte aus Ihrem Inventar in den Marktplatz einstellen </string> - <string name="TooltipOutboxWorn"> - Artikel, die Sie tragen, können nicht in Ihre Händler-Outbox gelegt werden. + <string name="TooltipOutboxLinked"> + Sie können keine verknüpften Objekte oder Ordner in den Marktplatz einstellen </string> <string name="TooltipOutboxCallingCard"> - Sie können keine Visitenkarten in Ihre Händler-Outbox legen + Sie können Visitenkarten nicht in den Marktplatz einstellen </string> - <string name="TooltipOutboxFolderLevels"> - Tiefe der verschachtelten Ordner überschreitet 3 + <string name="TooltipOutboxDragActive"> + Sie können keine gelistete Auflistung entfernen </string> - <string name="TooltipOutboxTooManyFolders"> - Anzahl von Unterordnern im obersten Ordner überschreitet 20 + <string name="TooltipOutboxCannotMoveRoot"> + Der Stammordner mit Marktplatz-Auflistungen kann nicht verschoben werden. </string> - <string name="TooltipOutboxTooManyObjects"> - Anzahl von Artikeln im obersten Ordner überschreitet 200 + <string name="TooltipOutboxMixedStock"> + Alle Objekte in einem Bestandsordner müssen vom gleichen Typ sein und die gleiche Berechtigung haben </string> <string name="TooltipDragOntoOwnChild"> Sie können einen Ordner nicht in einen seiner untergeordneten Ordner verschieben @@ -1063,7 +1081,7 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="AgentNameSubst"> (Sie) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Beim Verwalten von Grundbesitzzugangslisten Warnhinweise unterdrücken </string> @@ -1130,6 +1148,12 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="bitmap_image_files"> Bitmap-Bilder </string> + <string name="png_image_files"> + PNG-Bilder + </string> + <string name="save_texture_image_files"> + Targa- oder PNG-Bilder + </string> <string name="avi_movie_file"> AVI-Filmdatei </string> @@ -1379,6 +1403,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="FavoritesNoMatchingItems"> Landmarke hier hin ziehen, um diese hinzuzufügen. </string> + <string name="MarketplaceNoMatchingItems"> + Keine übereinstimmenden Objekte gefunden. Ãœberprüfen Sie die Schreibweise des Suchbegriffs und versuchen Sie es noch einmal. + </string> <string name="InventoryNoTexture"> Sie haben keine Kopie dieser Textur in Ihrem Inventar. </string> @@ -1426,29 +1453,95 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="InventoryOutboxError"> Der [[MARKETPLACE_CREATE_STORE_URL] Marktplatz-Laden] gibt Fehler zurück. </string> + <string name="InventoryMarketplaceError"> + Diese Funktion befindet sich in der Betaphase. Wenn Sie teilnehmen möchten, tragen Sie sich in dieses [http://goo.gl/forms/FCQ7UXkakz Google-Formular] ein. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Ihr Ordner mit Marktplatz-Auflistungen ist leer. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Ziehen Sie Ordner in diesen Bereich, um sie im [[MARKETPLACE_DASHBOARD_URL] Marktplatz] zum Verkauf anzubieten. + </string> + <string name="Marketplace Validation Warning Stock"> + Bestandsordner müssen in einem Versionsordner gespeichert sein + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Fehler: Alle Objekte in einem Bestandsordner müssen kopiergeschützt und vom gleichen Typ sein. + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Fehler: Bestandsordner kann keine Unterordner enthalten + </string> + <string name="Marketplace Validation Warning Empty"> + : Warnung: Ordner enthält keine Objekte + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Warnung: Bestandsordner wird erstellt + </string> + <string name="Marketplace Validation Warning Create Version"> + : Warnung: Versionsordner wird erstellt + </string> + <string name="Marketplace Validation Warning Move"> + : Warnung: Objekte werden verschoben + </string> + <string name="Marketplace Validation Warning Delete"> + : Warnung: Ordnerinhalte wurden in Bestandsordner übertragen; leerer Ordner wird entfernt + </string> + <string name="Marketplace Validation Error Stock Item"> + : Fehler: Kopiergeschützte Objekte müssen in einem Bestandsordner gespeichert sein + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Warnung: Objekte müssen in einem Versionsordner gespeichert sein + </string> + <string name="Marketplace Validation Error"> + : Fehler: + </string> + <string name="Marketplace Validation Warning"> + : Warnung: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Warnung: Versionsordner muss mindestens 1 Objekt enthalten + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Warnung: Bestandsordner muss mindestens 1 Objekt enthalten + </string> + <string name="Marketplace Validation No Error"> + Keine Fehler oder Warnungen + </string> <string name="Marketplace Error None"> Keine Fehler </string> + <string name="Marketplace Error Prefix"> + Fehler: + </string> <string name="Marketplace Error Not Merchant"> - Fehler: Bevor Sie Artikel in den Marktplatz übertragen können, müssen Sie sich als Händler registrieren (kostenlos). + Bevor Sie Artikel in den Marktplatz übertragen können, müssen Sie sich als Händler registrieren (kostenlos). + </string> + <string name="Marketplace Error Not Accepted"> + Objekt kann nicht in diesen Ordner verschoben werden. </string> - <string name="Marketplace Error Empty Folder"> - Fehler: Dieser Ordner ist leer. + <string name="Marketplace Error Unsellable Item"> + Dieses Objekt kann nicht im Marktplatz verkauft werden. </string> - <string name="Marketplace Error Unassociated Products"> - Fehler: Dieser Artikel konnte nicht hochgeladen werden, da in Ihrem Händlerkonto zu viele Artikel nicht mit Produkten verknüpft sind. Um diesen Fehler zu beheben, melden Sie sich auf der Marktplatz-Website an und reduzieren Sie die Anzahl von Artikeln, die nicht mit Produkten verknüpft sind. + <string name="MarketplaceNoID"> + keine Mkt-ID </string> - <string name="Marketplace Error Object Limit"> - Fehler: Dieser Artikel enthält zu viele Objekte. Beheben Sie diesen Fehler, indem Sie Objekte zusammen in Behältern verpacken, um die Objektanzahl auf unter 200 zu verringern. + <string name="MarketplaceLive"> + aufgelistet </string> - <string name="Marketplace Error Folder Depth"> - Fehler: Dieser Artikel enthält zu viele verschachtelte Ordnerebenen. Organisieren Sie ihn neu, sodass maximal drei verschachtelte Ordnerebenen vorhanden sind. + <string name="MarketplaceActive"> + aktiv </string> - <string name="Marketplace Error Unsellable Item"> - Fehler: Dieser Artikel kann nicht im Marktplatz verkauft werden. + <string name="MarketplaceMax"> + max. </string> - <string name="Marketplace Error Internal Import"> - Fehler: Bei diesem Artikel ist ein Problem aufgetreten. Versuchen Sie es später erneut. + <string name="MarketplaceStock"> + Bestand + </string> + <string name="MarketplaceNoStock"> + ausverkauft + </string> + <string name="MarketplaceUpdating"> + Aktualisierung läuft... </string> <string name="Open landmarks"> Landmarken öffnen @@ -1469,6 +1562,7 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. Keine Inhalte </string> <string name="WornOnAttachmentPoint" value=" (getragen am [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (aktiviert)"/> <string name="PermYes"> Ja @@ -1739,6 +1833,15 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="Invalid Attachment"> Ungültige Stelle für Anhang </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Fehler: fehlendes Objekt + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Fehler: Basisobjekt fehlt + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Fehler: Objekt ist im aktuellen Outfit, aber nicht angehängt + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] alt </string> @@ -1874,9 +1977,6 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="CompileQueueUnknownFailure"> Unbekannter Fehler beim Herunterladen </string> - <string name="CompileNoExperiencePerm"> - Skript „[SCRIPT]“ mit Erlebnis „[EXPERIENCE]“ wird übersprungen. - </string> <string name="CompileQueueTitle"> Rekompilierung </string> @@ -1910,6 +2010,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="SaveComplete"> Speichervorgang abgeschlossen. </string> + <string name="UploadFailed"> + Datei-Upload fehlgeschlagen: + </string> <string name="ObjectOutOfRange"> Skript (Objekt außerhalb des Bereichs) </string> @@ -1919,6 +2022,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="GroupsNone"> keine </string> + <string name="CompileNoExperiencePerm"> + Skript „[SCRIPT]“ mit Erlebnis „[EXPERIENCE]“ wird übersprungen. + </string> <string name="Group" value=" (Gruppe)"/> <string name="Unknown"> (unbekannt) @@ -5070,6 +5176,9 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="Command_Marketplace_Label"> Marktplatz </string> + <string name="Command_MarketplaceListings_Label"> + Marktplatz + </string> <string name="Command_MiniMap_Label"> Minikarte </string> @@ -5157,6 +5266,9 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="Command_Marketplace_Tooltip"> Einkaufen gehen </string> + <string name="Command_MarketplaceListings_Tooltip"> + Ihre Kreation verkaufen + </string> <string name="Command_MiniMap_Tooltip"> Leute in der Nähe anzeigen </string> @@ -5268,6 +5380,18 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="UserDictionary"> [Benutzer] </string> + <string name="logging_calls_disabled_log_empty"> + Unterhaltungen werden nicht protokolliert. Um ein Protokoll zu starten, wählen Sie „Speichern: nur Protokoll“ oder „Speichern: Protokoll und Transkripte“ unter „Einstellungen“ > „Chat“. + </string> + <string name="logging_calls_disabled_log_not_empty"> + Es werden keine Unterhaltungen mehr protokolliert. Um weiterhin ein Protokoll zu führen, wählen Sie „Speichern: nur Protokoll“ oder „Speichern: Protokoll und Transkripte“ unter „Einstellungen“ > „Chat“. + </string> + <string name="logging_calls_enabled_log_empty"> + Keine protokollierten Unterhaltungen verfügbar. Hier erscheint ein Protokolleintrag, wenn Sie eine Person kontaktieren oder von einer Person kontaktiert werden. + </string> + <string name="loading_chat_logs"> + Laden... + </string> <string name="experience_tools_experience"> Erlebnis </string> @@ -5349,16 +5473,4 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="ExperiencePermissionShort12"> Berechtigung </string> - <string name="logging_calls_disabled_log_empty"> - Unterhaltungen werden nicht protokolliert. Um ein Protokoll zu starten, wählen Sie „Speichern: nur Protokoll“ oder „Speichern: Protokoll und Transkripte“ unter „Einstellungen“ > „Chat“. - </string> - <string name="logging_calls_disabled_log_not_empty"> - Es werden keine Unterhaltungen mehr protokolliert. Um weiterhin ein Protokoll zu führen, wählen Sie „Speichern: nur Protokoll“ oder „Speichern: Protokoll und Transkripte“ unter „Einstellungen“ > „Chat“. - </string> - <string name="logging_calls_enabled_log_empty"> - Keine protokollierten Unterhaltungen verfügbar. Hier erscheint ein Protokolleintrag, wenn Sie eine Person kontaktieren oder von einer Person kontaktiert werden. - </string> - <string name="loading_chat_logs"> - Laden... - </string> </strings> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 60f36770bb..ec87b3684e 100755 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -43,6 +43,14 @@ top_pad="5" height="25" width="180" /> + <button + follows="left|top" + label="Check for updates" + name="update_btn" + left_pad="70" + top_delta="0" + height="25" + width="180" /> </panel> <panel border="true" 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 62ab8ed193..edf028bf60 100755 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -23,15 +23,15 @@ </floater.string> <floater.string name="Minutes"> - [MINUTES] minutes + [MINUTES] min. </floater.string> <floater.string name="Minute"> - minute + min. </floater.string> <floater.string name="Seconds"> - [SECONDS] seconds + [SECONDS] sec. </floater.string> <floater.string name="Remaining"> @@ -2013,7 +2013,7 @@ Only large parcels can be listed in search. name="AllowedText" top="0" width="230"> - Allowed Residents + Allowed Residents ([COUNT]) </text> <name_list column_padding="0" @@ -2062,7 +2062,7 @@ Only large parcels can be listed in search. name="BanCheck" top="0" width="200"> - Banned Residents + Banned Residents ([COUNT]) </text> <name_list column_padding="0" diff --git a/indra/newview/skins/default/xui/en/floater_associate_listing.xml b/indra/newview/skins/default/xui/en/floater_associate_listing.xml new file mode 100755 index 0000000000..e019ed58dd --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_associate_listing.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_minimize="false" + height="110" + layout="topleft" + name="associate listing" + help_topic="associate_listing" + title="ASSOCIATE LISTING" + width="375"> + <text + type="string" + length="1" + follows="top|left" + font="SansSerifLarge" + height="16" + layout="topleft" + left="10" + top="25" + name="message"> + Listing ID: + </text> + <line_editor + type="string" + length="1" + follows="top|right" + font="SansSerif" + height="20" + layout="topleft" + left_delta="0" + name="listing_id" + top_pad="5" + width="350"> + Type ID here + </line_editor> + <button + follows="bottom|left" + height="23" + label="OK" + layout="topleft" + left="155" + name="OK" + top_pad="10" + width="100" /> + <button + follows="bottom|right" + height="23" + label="Cancel" + layout="topleft" + left_pad="5" + name="Cancel" + width="100" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml index 1f2fe62b3c..126e3aac48 100755 --- a/indra/newview/skins/default/xui/en/floater_bumps.xml +++ b/indra/newview/skins/default/xui/en/floater_bumps.xml @@ -7,7 +7,7 @@ help_topic="floater_bumps" save_rect="true" title="BUMPS, PUSHES & HITS" - width="400"> + width="420"> <floater.string name="none_detected"> None detected @@ -34,7 +34,7 @@ </floater.string> <floater.string name="timeStr"> - [[hour,datetime,slt]:[min,datetime,slt]] + [[hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt]] </floater.string> <scroll_list draw_border="false" @@ -45,5 +45,5 @@ multi_select="true" name="bump_list" top="20" - width="388" /> + width="408" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_experiences.xml b/indra/newview/skins/default/xui/en/floater_experiences.xml index 70e7507907..442da887c5 100644 --- a/indra/newview/skins/default/xui/en/floater_experiences.xml +++ b/indra/newview/skins/default/xui/en/floater_experiences.xml @@ -12,7 +12,7 @@ name="floater_experiences" save_rect="true" single_instance="true" - reuse_instance="false" + bg_opaque_color="0 0.5 0 0.3" title="EXPERIENCES"> <tab_container diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 9deb0d2030..dcd6d98581 100755 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -191,8 +191,18 @@ label="OK" label_selected="OK" layout="topleft" - left="-102" + right="-105" name="OK" top="192" width="90" /> + <button + follows="right|bottom" + height="22" + label="Cancel" + label_selected="Cancel" + layout="topleft" + left_pad="5" + name="Cancel" + right="-10" + width="90" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_item_properties.xml b/indra/newview/skins/default/xui/en/floater_item_properties.xml new file mode 100755 index 0000000000..0fc54a9c8b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_item_properties.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="570" + layout="topleft" + name="Item Properties" + help_topic="item+properties" + title="ITEM PROPERTIES" + width="330"> + <panel + follows="all" + layout="topleft" + left="0" + class="sidepanel_item_info" + filename="sidepanel_item_info.xml" + name="item_panel" + top="20" + label="" + height="570" + visible="true" + width="330"> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml new file mode 100755 index 0000000000..0806a87288 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<floater + title="MARKETPLACE LISTINGS" + name="floater_marketplace_listings" + help_topic="floater_marketplace_listings" + positioning="cascading" + width="333" + height="445" + min_width="200" + min_height="300" + can_close="true" + can_resize="true" + save_rect="true" + save_visibility="false" + reuse_instance="true"> + <panel + name="marketplace_listings_panel" + follows="all" + layout="topleft" + left="0" + top="0" + height="440" + width="333"> + <panel + follows="all" + left="10" + height="440" + width="313" + top="0" + bg_opaque_color="InventoryBackgroundColor"> + <panel + name="marketplace_listings_inventory_placeholder_panel" + follows="all" + layout="topleft" + top="0" + left="0" + width="313" + height="440" + bg_opaque_color="InventoryBackgroundColor"> + <text + name="marketplace_listings_inventory_placeholder_title" + type="string" + follows="top|left|right" + layout="topleft" + top="10" + left="0" + width="313" + height="25" + wrap="true" + halign="center" + font="SansSerifBold"> + Loading... + </text> + <text + name="marketplace_listings_inventory_placeholder_text" + type="string" + follows="top|left|right" + layout="topleft" + top="35" + left="0" + width="313" + height="130" + wrap="true" + halign="left" /> + </panel> + <panel + name="panel_marketplace_listing" + filename="panel_marketplace_listings.xml" + class="llpanelmarketplacelistings" + top="0" + follows="all"/> + </panel> + <panel + name="marketplace_panel_status" + follows="bottom|left|right" + layout="topleft" + left="10" + width="313" + height="20"> + <text + name="marketplace_status" + type="string" + follows="bottom|left|right" + layout="topleft" + top="0" + left="5" + width="150" + height="20" + wrap="true" + halign="left" + valign="center" + font="SansSerif"/> + </panel> + <layout_stack name="initialization_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> + <layout_panel /> + <layout_panel height="24" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all"> + <layout_panel width="0" /> + <layout_panel width="24" auto_resize="false"> + <loading_indicator + height="24" + layout="topleft" + left="0" + top="0" + width="24" /> + </layout_panel> + <layout_panel width="0" /> + </layout_stack> + </layout_panel> + <layout_panel /> + </layout_stack> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/en/floater_marketplace_validation.xml new file mode 100755 index 0000000000..9035a7c161 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_marketplace_validation.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + title="Audit Marketplace Listings" + name="floater_marketplace_validation" + help_topic="floater_marketplace_validation" + layout="topleft" + positioning="cascading" + legacy_header_height="18" + width="600" + height="500" + min_width="400" + min_height="200" + can_close="true" + can_resize="true" + can_minimize="true" + save_rect="true" + reuse_instance="true" + save_visibility="false"> + <button + name="OK" + label="OK" + label_selected="OK" + layout="topleft" + follows="right|bottom" + top="465" + width="100" + height="20" + left="484"/> + <text_editor + name="validation_text" + type="string" + font="SansSerif" + length="1" + max_length="65536" + layout="topleft" + follows="all" + bg_readonly_color="TextBgReadOnlyColor" + text_readonly_color="TextFgReadOnlyColor" + top="25" + bottom="455" + left="20" + right="-20" + word_wrap="true"> + MARKETPLACE_VALIDATION_TEXT + </text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index a4acd1df78..7183b2f1f9 100755 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -31,6 +31,7 @@ <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> <string name="mesh_status_missing_lod">Missing required level of detail.</string> <string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string> + <string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string> <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" --> <string name="decomposing">Analyzing...</string> <string name="simplifying">Simplifying...</string> @@ -66,7 +67,7 @@ follows="top|left" layout="topleft" height="19" - max_length_bytes="64" + max_length_bytes="63" name="description_form" prevalidate_callback="ascii" top_pad="5" @@ -1027,19 +1028,19 @@ bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3" follows="left|top" - height="16" + height="19" layout="topleft" left="18" name="physics info" - top_pad="15" - width="589"> + top_pad="12" + width="319"> <text follows="top|left" height="15" layout="topleft" left="0" text_color="White" - top_pad="0" + top_pad="3" name="results_text" width="50"> Results: @@ -1077,6 +1078,33 @@ Hulls: [HULLS] </text> </panel> + <panel + bg_alpha_color="0 0 0 0" + bg_opaque_color="0 0 0 0.3" + follows="left|top" + height="19" + layout="topleft" + left_pad="5" + top_delta="0" + name="physics message" + width="270"> + <icon + follows="left|top" + height="16" + left="0" + layout="topleft" + name="physics_status_message_icon" + top_pad="0" + width="16" /> + <text + follows="left|top" + height="15" + layout="topleft" + left_pad="2" + name="physics_status_message_text" + width="252" + top_delta="3"/> + </panel> </panel> <!-- MODIFIERS PANEL --> <panel diff --git a/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml new file mode 100644 index 0000000000..afc609de52 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater + legacy_header_height="18" + bevel_style="in" + layout="topleft" + name="floater_notifications_tabbed" + help_topic="notification_chiclet" + save_rect="true" + title="NOTIFICATIONS" + width="350" + min_width="435" + height="550" + min_height="150" + can_minimize="false" + can_tear_off="false" + can_resize="true" + can_drag_on_left="false" + can_dock="true" + save_dock_state="true" + save_visibility="true" + single_instance="true" +> + <floater.string + name="system_tab_title"> + System ([COUNT]) + </floater.string> + <floater.string + name="transactions_tab_title"> + Transactions ([COUNT]) + </floater.string> + <floater.string + name="group_invitations_tab_title"> + Invitations ([COUNT]) + </floater.string> + <floater.string + name="group_notices_tab_title"> + Group ([COUNT]) + </floater.string> + + <string + name="title_notification_tabbed_window"> + NOTIFICATIONS + </string> + <layout_stack + width="336" + height="533" + enabled="true" + orientation="vertical" + name="TabButtonsStack" + follows="left|top|right|bottom" + top="17"> + <layout_panel + width="336" + height="530" + enabled="true" + name="TabButtonsLayoutPanel"> + <tab_container + follows="left|top|right|bottom" + halign="center" + layout="topleft" + tab_position="top" + left="7" + top="7" + width="336" + height="491" + mouse_opaque="true" + name="notifications_tab_container"> + <panel + border="true" + bevel_style="none" + follows="left|top|right|bottom" + label="System (0)" + layout="topleft" + name="system_notification_list_tab"> + <notification_list_view + color="FloaterDefaultBackgroundColor" + follows="all" + layout="topleft" + name="system_notification_list" + left="0" + top="5" + height="0" + width="330"/> + </panel> + <panel + border="true" + bevel_style="none" + follows="left|top|right|bottom" + label="Transactions (0)" + layout="topleft" + name="transaction_notifications_tab"> + <notification_list_view + color="FloaterDefaultBackgroundColor" + follows="all" + layout="topleft" + name="transaction_notification_list" + left="0" + top="5" + height="0" + width="328"/> + </panel> + <panel + border="true" + bevel_style="none" + follows="left|top|right|bottom" + label="Invitations (0)" + layout="topleft" + name="group_invite_notifications_tab"> + <notification_list_view + color="FloaterDefaultBackgroundColor" + follows="all" + layout="topleft" + name="group_invite_notification_list" + left="0" + top="5" + height="0" + width="328"/> + </panel> + <panel + border="true" + bevel_style="none" + follows="left|top|right|bottom" + label="Group (0)" + layout="topleft" + name="group_notice_notifications_tab"> + <notification_list_view + color="FloaterDefaultBackgroundColor" + follows="all" + layout="topleft" + name="group_notice_notification_list" + left="0" + top="5" + height="0" + width="328"/> + </panel> + </tab_container> + + <layout_stack width="336" height="26" enabled="true" orientation="horizontal" follows="left|right" name="ButtonsStack"> + <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="CondenseAllButtonPanel"> + <button width="93" height="21" left="2" label="Collapse all" name="collapse_all_button"> + </button> + </layout_panel> + <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="GapLayoutPanel"> + <panel width="90" height="21" left="2" label="Gap Panel" border="false" name="GapPanel"> + </panel> + </layout_panel> + <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="DeleteAllButtonPanel"> + <button width="93" height="21" left="2" label="Delete all" name="delete_all_button"> + </button> + </layout_panel> + </layout_stack> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml index ecedb27438..2c5176cf01 100755 --- a/indra/newview/skins/default/xui/en/floater_sys_well.xml +++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml @@ -23,10 +23,6 @@ name="title_im_well_window"> CONVERSATIONS </string> - <string - name="title_notification_well_window"> - NOTIFICATIONS - </string> <flat_list_view color="FloaterDefaultBackgroundColor" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 7099db63ab..61002bf1b5 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -4,6 +4,81 @@ layout="topleft" name="Popup" visible="false"> + <menu_item_call + label="Create listing" + layout="topleft" + name="Marketplace Create Listing"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_create_listing" /> + </menu_item_call> + <menu_item_call + label="Associate listing" + layout="topleft" + name="Marketplace Associate Listing"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_associate_listing" /> + </menu_item_call> + <menu_item_call + label="Get (Refresh) listing" + layout="topleft" + name="Marketplace Get Listing"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_get_listing" /> + </menu_item_call> + <menu_item_call + label="Check for errors" + layout="topleft" + name="Marketplace Check Listing"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_check_listing" /> + </menu_item_call> + <menu_item_call + label="Edit listing" + layout="topleft" + name="Marketplace Edit Listing"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_edit_listing" /> + </menu_item_call> + <menu_item_call + label="List" + layout="topleft" + name="Marketplace List"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_list" /> + </menu_item_call> + <menu_item_call + label="Unlist" + layout="topleft" + name="Marketplace Unlist"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_unlist" /> + </menu_item_call> + <menu_item_call + label="Activate" + layout="topleft" + name="Marketplace Activate"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_activate" /> + </menu_item_call> + <menu_item_call + label="Deactivate" + layout="topleft" + name="Marketplace Deactivate"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="marketplace_deactivate" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Marketplace Listings Separator" /> <menu_item_call label="Share" layout="topleft" @@ -490,14 +565,6 @@ <menu_item_call label="Delete" layout="topleft" - name="Remove Link"> - <menu_item_call.on_click - function="Inventory.DoToSelected" - parameter="delete" /> - </menu_item_call> - <menu_item_call - label="Delete" - layout="topleft" name="Delete"> <menu_item_call.on_click function="Inventory.DoToSelected" @@ -710,20 +777,20 @@ layout="topleft" name="Marketplace Separator" /> <menu_item_call - label="Copy to Merchant Outbox" - layout="topleft" - name="Merchant Copy"> + label="Copy to Marketplace Listings" + layout="topleft" + name="Marketplace Copy"> <menu_item_call.on_click - function="Inventory.DoToSelected" - parameter="copy_to_outbox" /> + function="Inventory.DoToSelected" + parameter="copy_to_marketplace_listings" /> </menu_item_call> <menu_item_call - label="Send to Marketplace" - layout="topleft" - name="Marketplace Send"> + label="Move to Marketplace Listings" + layout="topleft" + name="Marketplace Move"> <menu_item_call.on_click - function="Inventory.DoToSelected" - parameter="send_to_marketplace" /> + function="Inventory.DoToSelected" + parameter="move_to_marketplace_listings" /> </menu_item_call> <menu_item_call label="--no options--" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index e91eea04d1..73ca7c529d 100755 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -108,6 +108,12 @@ function="Floater.Show" parameter="sl_about" /> </menu_item_call> + <menu_item_call + label="Check for Updates" + name="Check for Updates"> + <menu_item_call.on_click + function="Advanced.CheckViewerUpdates"/> + </menu_item_call> </menu> <menu_item_check label="Show Debug Menu" diff --git a/indra/newview/skins/default/xui/en/menu_marketplace_view.xml b/indra/newview/skins/default/xui/en/menu_marketplace_view.xml new file mode 100755 index 0000000000..4b3bb8ee1c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_marketplace_view.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_marketplace_sort" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by name" + name="sort_by_name"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="sort_by_name" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="sort_by_name" /> + </menu_item_check> + <menu_item_check + label="Sort by most recent" + name="sort_by_recent"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="sort_by_recent" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="sort_by_recent" /> + </menu_item_check> + <menu_item_check + label="Sort by stock amount (low to high)" + name="sort_by_stock_amount"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="sort_by_stock_amount"/> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="sort_by_stock_amount"/> + </menu_item_check> + <menu_item_separator + layout="topleft" /> + <menu_item_check + label="Show only listing folders" + name="show_only_listing_folders"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="show_only_listing_folders"/> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="show_only_listing_folders"/> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_url_email.xml b/indra/newview/skins/default/xui/en/menu_url_email.xml new file mode 100644 index 0000000000..6467fe5c90 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_url_email.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Email Popup"> + <menu_item_call + label="Compose Email in an External client" + layout="topleft" + name="email_open_external"> + <menu_item_call.on_click + function="Url.OpenExternal" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Copy Email to clipboard" + layout="topleft" + name="email_copy"> + <menu_item_call.on_click + function="Url.CopyLabel" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 68ca55735a..3f557d0d0f 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -134,7 +134,7 @@ </menu_item_call> <menu_item_call label="Walk / run / fly..." - name="Walk / run / fly"> + name="WalkRunFly"> <menu_item_call.on_click function="Floater.ToggleOrBringToFront" parameter="moveview" /> @@ -180,6 +180,13 @@ function="Floater.ToggleOrBringToFront" parameter="outbox" /> </menu_item_call> + <menu_item_call + label="Marketplace listings..." + name="MarketplaceListings"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="marketplace_listings" /> + </menu_item_call> <menu_item_call label="Account dashboard..." name="Manage My Account"> @@ -502,7 +509,7 @@ </menu_item_call> <menu_item_call label="Region / Estate" - name="Region/Estate"> + name="RegionEstate"> <menu_item_call.on_click function="Floater.Show" parameter="region_info" /> @@ -1431,7 +1438,7 @@ function="Floater.Show" parameter="bumps" /> </menu_item_call> - <menu_item_separator/> + <menu_item_separator/> <menu_item_call label="About [APP_NAME]" name="About Second Life"> @@ -1439,6 +1446,12 @@ function="Floater.Show" parameter="sl_about" /> </menu_item_call> + <menu_item_call + label="Check for Updates" + name="Check for Updates"> + <menu_item_call.on_click + function="Advanced.CheckViewerUpdates"/> + </menu_item_call> </menu> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index cfe56e6a95..70ba4d5077 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -308,9 +308,251 @@ Initialization with the Marketplace failed because of a system or network error. name="okbutton" yestext="OK"/> </notification> + + <notification + icon="OutboxStatus_Error" + name="StockPasteFailed" + type="outbox"> + Copy or move to Stock Folder failed with error : + + '[ERROR_CODE]' + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="MerchantPasteFailed" + type="outbox"> + Copy or move to Marketplace Listings failed with error : + + '[ERROR_CODE]' + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="MerchantTransactionFailed" + type="outbox"> + The transaction with the Marketplace failed with the following error : + + Reason : '[ERROR_REASON]' + [ERROR_DESCRIPTION] + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="MerchantUnprocessableEntity" + type="outbox"> + We are unable to list this product or activate the version folder. Usually this is caused by missing information in the listing description form, but it may be due to errors in the folder structure. Either edit the listing or check the listing folder for errors. + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="MerchantListingFailed" + type="outbox"> + Listing to Marketplace failed with error : + + '[ERROR_CODE]' + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="MerchantFolderActivationFailed" + type="outbox"> + Activating this version folder failed with error : + + '[ERROR_CODE]' + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="MerchantForceValidateListing" + type="alertmodal"> + In order to create your listing, we fixed the hierarchy of your listing contents. + <tag>confirm</tag> + <usetemplate + ignoretext="Warn me that creating a listing fixes the hierarchy of the content" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ConfirmMerchantActiveChange" + type="alertmodal"> + This action will change the active content of this listing. Do you want to continue? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I change an active listing on the marketplace" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ConfirmMerchantMoveInventory" + type="alertmodal"> + Items dragged to the Marketplace Listings window are moved from their original locations, not copied. Do you want to continue? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I move an item from the inventory to the marketplace" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ConfirmListingCutOrDelete" + type="alertmodal"> + Moving or deleting a listing folder will delete your Marketplace listing. If you would like to keep the Marketplace listing, move or delete the contents of the version folder you would like to modify. Do you want to continue? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I move or delete a listing from the marketplace" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ConfirmCopyToMarketplace" + type="alertmodal"> + You don't have permission to copy one or more of these items to the Marketplace. You can move them or leave them behind. + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I try to copy a selection containing no copy items to the marketplace" + name="yesnocancelbuttons" + yestext="Move item(s)" + notext="Don't move item(s)" + canceltext="Cancel"/> + </notification> + <notification + icon="alertmodal.tga" + name="ConfirmMerchantUnlist" + type="alertmodal"> + This action will unlist this listing. Do you want to continue? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I unlist an active listing on the marketplace" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ConfirmMerchantClearVersion" + type="alertmodal"> + This action will deactivate the version folder of the current listing. Do you want to continue? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I deactivate the version folder of a listing on the marketplace" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantListingNotUpdated" + type="alertmodal"> +This listing could not be updated. +[[URL] Click here] to edit it on the Marketplace. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> <notification + icon="alertmodal.tga" + name="AlertMerchantListingCannotWear" + type="alertmodal"> + You cannot wear clothes or body parts that are in the Marketplace Listings folder. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantListingInvalidID" + type="alertmodal"> + Invalid listing ID. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantListingActivateRequired" + type="alertmodal"> + There are several or no version folders in this listing. You will need to select and activate one independently later. + <tag>confirm</tag> + <usetemplate + ignoretext="Alert about version folder activation when I create a listing with several version folders" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantStockFolderSplit" + type="alertmodal"> + We have separated stock items of different types into separate stock folders, so your folder is arranged in a way that we can list it. + <tag>confirm</tag> + <usetemplate + ignoretext="Alert when stock folder is being split before being listed" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantStockFolderEmpty" + type="alertmodal"> + We have unlisted your listing because the stock is empty. You need to add more units to the stock folder to list the listing again. + <tag>confirm</tag> + <usetemplate + ignoretext="Alert when a listing is unlisted because stock folder is empty" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="AlertMerchantVersionFolderEmpty" + type="alertmodal"> + We have unlisted your listing because the version folder is empty. You need to add items to the version folder to list the listing again. + <tag>confirm</tag> + <usetemplate + ignoretext="Alert when a listing is unlisted because version folder is empty" + name="okignore" + yestext="OK"/> + </notification> + + <notification icon="alertmodal.tga" name="CompileQueueSaveText" type="alertmodal"> @@ -577,6 +819,33 @@ If you no longer wish to have these abilities granted to this role, disable them notext="Cancel" yestext="Eject"/> </notification> + + <notification + icon="alertmodal.tga" + name="BanGroupMemberWarning" + type="alertmodal"> + You are about to ban [AVATAR_NAME] from the group. + <tag>group</tag> + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm banning a participant from group" + name="okcancelignore" + notext="Cancel" + yestext="Ban"/> + </notification> + <notification + icon="alertmodal.tga" + name="BanGroupMembersWarning" + type="alertmodal"> + You are about to ban [COUNT] members from group. + <tag>group</tag> + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm banning multiple members from group" + name="okcancelignore" + notext="Cancel" + yestext="Ban"/> + </notification> <notification icon="alertmodal.tga" @@ -783,7 +1052,7 @@ Objects: [N] icon="alertmodal.tga" name="ReturnAllTopObjects" type="alertmodal"> -Are you sure you want to return all listed objects back to their owner's inventory? +Are you sure you want to return all listed objects back to their owner's inventory? This will return ALL scripted objects in the region! <tag>confirm</tag> <usetemplate name="okcancelbuttons" @@ -3650,6 +3919,53 @@ see [[INFO_URL] Information about this update] name="okbutton" yestext="OK"/> </notification> + + <notification + icon="alertmodal.tga" + name="UpdateDownloadInProgress" + type="alertmodal"> +An update is available! +It's downloading in the background and we will prompt you to restart your viewer to finish installing it as soon as it's ready. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="UpdateDownloadComplete" + type="alertmodal"> +An update was downloaded. It will be installed during restart. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="UpdateCheckError" + type="alertmodal"> +An error occured while checking for update. +Please try again later. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="UpdateViewerUpToDate" + type="alertmodal"> +Your viewer is up to date! +If you can't wait to try out the latest features and fixes, check out the Alternate Viewers page. http://wiki.secondlife.com/wiki/Linden_Lab_Official:Alternate_Viewers. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> <notification icon="alertmodal.tga" @@ -3975,6 +4291,21 @@ You have reached your maximum number of groups. Please leave some group before j <notification icon="alert.tga" + name="GroupLimitInfo" + type="alert"> +The group limit for base accounts is [MAX_BASIC], and for [https://secondlife.com/premium/ premium] +accounts is [MAX_PREMIUM]. +If you downgraded your account, you will need to get below [MAX_BASIC] group limit before you can join more. + +[https://secondlife.com/my/account/membership.php Upgrade today!] + <tag>group</tag> + <usetemplate + name="okbutton" + yestext="Close"/> + </notification> + + <notification + icon="alert.tga" name="KickUser" type="alert"> <tag>win</tag> @@ -4587,6 +4918,13 @@ Are you sure you want to change the Estate Covenant? </notification> <notification + icon="alertmodal.tga" + name="SLM_UPDATE_FOLDER" + type="alertmodal"> + [MESSAGE] + </notification> + + <notification icon="alertmodal.tga" name="RegionEntryAccessBlocked_AdultsOnlyContent" type="alertmodal"> @@ -5460,16 +5798,19 @@ You cannot undo this action. notext="Cancel" yestext="OK"/> </notification> - + <notification - icon="alertmodal.tga" - name="HelpReportAbuseEmailLL" - type="alert"> + icon="alertmodal.tga" + name="ConfirmUnlink" + type="alertmodal"> <unique/> - -Use this tool to report violations of the [http://secondlife.com/corporate/tos.php Terms of Service] and [http://secondlife.com/corporate/cs.php Community Standards]. - -All reported abuses are investigated and resolved. + This is a large selection with linksets. If you unlink it, you may not be able to link it again. You may wish to take copies of linksets into your inventory as a precaution. + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm when unlinking a linkset" + name="okcancelignore" + notext="Cancel" + yestext="Unlink"/> </notification> <notification @@ -6777,15 +7118,6 @@ No valid circuit code. <notification icon="notify.tga" - name="NoValidTimestamp" - persist="true" - type="notify"> - <tag>fail</tag> -No valid timestamp. - </notification> - - <notification - icon="notify.tga" name="NoPendingConnection" persist="true" type="notify"> @@ -8015,9 +8347,8 @@ Select residents to share with. name="MeshUploadError" icon="alert.tga" type="alert"> - [LABEL] failed to upload: [MESSAGE] [IDENTIFIER] - -See the log file for details. + [LABEL] failed to upload: [MESSAGE] [IDENTIFIER] +[DETAILS]See SecondLife.log for details </notification> <notification @@ -8258,7 +8589,7 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran <notification icon="alertmodal.tga" name="ConfirmLeaveCall" - type="alert"> + type="alertmodal"> Are you sure you want to leave this call? <tag>confirm</tag> <tag>voice</tag> diff --git a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml index c76b958eda..c357f9e7d5 100644 --- a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml +++ b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml @@ -47,19 +47,19 @@ height="12" follows="top|left"> </text> - <scroll_list + <name_list draw_heading="false" left="3" width="225" height="75" follows="all" name="experience_list"> - <columns + <name_list.columns width="225" user_resize="false" name="experience_name" label="Name"/> - </scroll_list> + </name_list> <button layout="topleft" follows="top|right" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 0518688f45..0a85477bf4 100755 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -21,7 +21,7 @@ </panel.string> <panel.string name="ItemcountUnknown"> - + Fetched [ITEM_COUNT] Items [FILTER] </panel.string> <text type="string" diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml new file mode 100755 index 0000000000..2b17473a84 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + label="Marketplace" + name="Marketplace Panel" + follows="all" + layout="topleft" + width="308" + height="440"> + <panel + name="tool_panel" + follows="left|top|right" + layout="topleft" + height="30" + width="308" + top="0" + left="0"> + <menu_button + name="sort_btn" + tool_tip="View/sort options" + layout="topleft" + follows="top|left" + width="31" + height="25" + left="2" + menu_filename="menu_marketplace_view.xml" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + menu_position="bottomleft"/> + <button + name="add_btn" + tool_tip="Create a new listing folder" + layout="topleft" + follows="top|left" + width="31" + height="25" + left_pad="2" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_plus" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off"/> + <button + name="audit_btn" + label="Check for Errors" + tool_tip="Check your marketplace listings" + layout="topleft" + follows="top|right" + width="97" + height="26" + left_pad="143"/> + </panel> + <panel + name="tab_container_panel" + follows="all" + layout="topleft" + default_tab_group="1" + width="308" + height="350"> + <filter_editor + text_pad_left="10" + follows="left|top|right" + height="23" + label="Filter Marketplace Listings" + layout="topleft" + left="0" + max_length_chars="300" + name="filter_editor" + top="0" + width="308" /> + <tab_container + name="marketplace_filter_tabs" + follows="all" + layout="topleft" + top="30" + left="0" + top_pad="0" + width="308" + height="320" + halign="center" + tab_height="30" + tab_group="1" + tab_position="top" + tab_min_width="50"> + </tab_container> + </panel> + <panel + name="marketplace_drop_zone" + mouse_opaque="true" + follows="bottom|left|right" + left="2" + width="306" + height="40" + background_visible="true" + background_opaque="true" + bg_alpha_image="none" + bg_alpha_color="EmphasisColor_35" + bg_opaque_image="Marketplace_Dropzone_Background" + border="true" + bevel_style="in" + visible="true"> + <text + type="string" + follows="bottom|left|right" + layout="topleft" + top="13" + height="20" + left="2" + width="306" + halign="center" + font="SansSerifMedium" + font_shadow="hard" + valign="top"> + Drop folders here to create new listings + </text> + </panel> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings_inventory.xml new file mode 100755 index 0000000000..8d5fa265e2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings_inventory.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_panel + label="ALL" + name="All Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="370" + top="16" + left="0" + start_folder.name="Marketplace listings" + show_empty_message="true" + show_root_folder="false" + use_marketplace_folders="true" + start_folder.type="merchant" + tool_tip="Drag and drop items here to list them" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + <item allow_wear="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings_listed.xml new file mode 100755 index 0000000000..44f507ad84 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings_listed.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_panel + label="LISTED" + name="Active Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="370" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="true" + show_root_folder="false" + use_marketplace_folders="true" + allow_drop_on_root="false" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + <item allow_wear="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings_unassociated.xml new file mode 100755 index 0000000000..871e8773c4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_panel + label="UNASSOCIATED" + name="Unassociated Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="370" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="true" + show_root_folder="false" + use_marketplace_folders="true" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + <item allow_wear="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings_unlisted.xml new file mode 100755 index 0000000000..98bef04aa7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_panel + label="UNLISTED" + name="Inactive Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="370" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="true" + show_root_folder="false" + use_marketplace_folders="true" + allow_drop_on_root="false" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + <item allow_wear="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml new file mode 100644 index 0000000000..a909028f9f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- All our XML is utf-8 encoded. --> +<panel + translate="false" + name="main_panel" + title="panel_notification_list_item" + visible="true" + top="0" + left="0" + width="331" + height="202" + can_resize="true" + layout="topleft" + follows="left|top|right|bottom" > + <!-- background_opaque="false" --> + <!-- background_visible="true"> --> + <!-- bg_alpha_color="PanelNotificationListItem"> --> + <panel.string + name="sender_resident_text"> + Sender: "[SENDER_RESIDENT]" + </panel.string> + <panel.string + name="group_name_text"> + Group: "[GROUP_NAME]" + </panel.string> + <panel.string + name="group_fee_text"> + Fee: [GROUP_FEE] + </panel.string> + <panel.string + name="item_condensed_height"> + 50 + </panel.string> + <panel.string + name="item_expanded_height"> + 87 + </panel.string> + <panel.string + name="expanded_height_resize_for_attachment"> + 27 + </panel.string> + + <panel top="0" left="0" width="331" height="196" bevel_style="none" layout="topleft" follows="left|top|right|bottom" name="panel_total_view"> + <layout_stack top="0" left="0" width="331" height="196" orientation="vertical" follows="left|top|right|bottom" name="item_vertical_stack"> + <layout_panel top="0" left="0" height="30" follows="left|top|right|bottom" layout="topleft" name="layout_panel_condensed_view" visible="false" background_opaque="false" background_visible="true" bg_alpha_color="SysWellItemUnselected"> + <panel border="true" top="0" left="5" height="30" bevel_style="none" layout="topleft" follows="left|top|right|bottom" name="panel_condensed_view"> + <layout_stack top="0" left="0" width="325" height="50" orientation="horizontal" follows="left|top|right|bottom" name="horizontal_stack"> + <layout_panel width="30" height="39" orientation="horizontal" follows="left|top|right|bottom" name="layout_panel_right"> + <group_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="group_icon" tool_tip="Group" default_icon_name="Generic_Group" visible="true"/> + <avatar_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="avatar_icon" tool_tip="Avatar" default_icon_name="Generic_Person" visible="false"/> + <icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="system_notification_icon" tool_tip="Icon" image_name="System_Notification" visible="false"/> + </layout_panel> + <layout_panel width="260" height="50" orientation="horizontal" name="layout_panel_middle"> + <panel border="false" top="0" width="260" height="38" bevel_style="none" follows="left|top|right" layout="topleft" name="main_info_panel"> + <panel border="false" top="0" left="0" width="260" height="19" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="notification_title_panel"> + <text allow_scroll="false" font="SansSerifSmall" top="6" left="0" width="260" height="12" layout="topleft" follows="right|left" text_color="White" + use_ellipses="true" word_wrap="true" mouse_opaque="false" name="notification_title" > + Group Name:Notice Title N o t i c e T i t l e N o t i c e T i t l e N o t i c e T i t l e N oticeTitle + </text> + <icon top="1" left="242" width="21" height="21" image_name="Icon_Attachment_Small" follows="right" mouse_opaque="true" name="attachment_icon" tool_tip="Attachment" visible="false"/> + </panel> + <panel border="false" top="23" left="0" width="260" height="15" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="sender_time_panel"> + <text allow_scroll="false" font="SansSerifSmall" top="0" left="0" width="170" height="13" layout="topleft" follows="right|left" + use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box" visible="false"> + Sender: "Resident R e s i d e n t R e s i d e n t" + </text> + <text allow_scroll="false" font="SansSerifSmall" top="0" right="-5" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5" + name="notification_time" value="2014/12/24 23:30" /> + </panel> + </panel> + </layout_panel> + <layout_panel width="18" height="48" orientation="horizontal" follows="right|top|bottom" name="layout_panel_right"> + <panel top="0" left="0" width="17" height="39" follows="left|top|right|bottom" layout="topleft" name="close_expand_panel"> + <button top="0" left="0" width="17" height="17" layout="topleft" follows="top" name="close_btn" mouse_opaque="true" + tab_stop="false" image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" /> + <button bottom="-16" right="15" width="17" height="17" layout="topleft" follows="bottom" name="expand_btn" mouse_opaque="true" + tab_stop="false" image_unselected="Notification_Expand" image_selected="Notification_Expand" /> + </panel> + </layout_panel> + </layout_stack> + </panel> + </layout_panel> + <layout_panel top="0" left="0" height="196" follows="left|top|right|bottom" layout="topleft" name="layout_panel_expanded_view" visible="true" background_opaque="false" background_visible="true" bg_alpha_color="SysWellItemUnselected"> + <panel border="true" top="0" left="5" height="196" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="panel_expanded_view"> + <layout_stack top="0" left="0" width="325" height="196" orientation="horizontal" follows="left|top|right|bottom" name="horizontal_stack"> + <layout_panel width="30" height="170" orientation="horizontal" follows="left|top|bottom" name="layout_panel_right_exp"> + <group_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="group_icon_exp" tool_tip="Group" default_icon_name="Generic_Group" visible="true"/> + <avatar_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="avatar_icon_exp" tool_tip="Avatar" default_icon_name="Generic_Person" visible="false"/> + <icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="system_notification_icon_exp" tool_tip="Icon" image_name="System_Notification" visible="false"/> + <icon left="12" top="144" width="20" height="20" name="attachment_icon_exp" tool_tip="Attachment" image_name="Icon_Attachment_Large" follows="left" mouse_opaque="true" visible="false"/> + </layout_panel> + <layout_panel width="230" height="196" orientation="horizontal" follows="left|top|right|bottom" name="layout_panel_middle_exp"> + <panel border="false" top="0" width="230" height="196" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="main_info_panel_expanded"> + <panel border="false" top="0" left="0" width="230" height="30" bevel_style="none" follows="left|top|right" layout="topleft" name="notification_title_panel_exp" > + <text allow_scroll="false" font="SansSerif" top="6" left="0" width="233" height="10" layout="topleft" follows="right|left" text_color="White" + use_ellipses="true" word_wrap="false" mouse_opaque="false" name="notification_title_exp"> + Notice Title Notice Title N o t i c e T i t l e N o t i c e T i t l e + </text> + <text allow_scroll="false" font="SansSerif" left="0" width="233" height="10" layout="topleft" follows="right|left" text_color="White" + use_ellipses="true" word_wrap="false" mouse_opaque="false" name="group_name_exp" parse_urls="false" visible="false"> + Group Name Group Name Group Na m e e + </text> + </panel> + <panel border="false" left="0" width="230" height="15" bevel_style="none" follows="left|top|right" layout="topleft" name="sender_time_panel_exp"> + <text allow_scroll="false" font="SansSerifSmall" top="0" left="0" width="145" height="13" layout="topleft" follows="right|left" + use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box_exp" visible="false"> + Sender: "Resident R e s i d e n t R e s i d e n t" + </text> + <text allow_scroll="false" font="SansSerifSmall" top="0" right="-1" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5" + name="notification_time_exp" value="2014/12/24 23:30" /> + </panel> + <panel border="false" left="0" height="115" width="230" bevel_style="none" follows="all" layout="topleft" name="notification_text_panel_exp" visible="true"> + <chat_editor is_expandable="true" top="0" left="0" width="230" height="110" layout="topleft" follows="left|right" + word_wrap="true" max_length="65536" name="notification_text_exp" parse_urls="true"> + Notice text goes here b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla. bla bla bla bla bla bla bla bla bla bla bla bla bla . + </chat_editor> + </panel> + <panel border="false" left="1" bottom="-5" width="230" height="22" bevel_style="none" follows="left|right|bottom" layout="topleft" name="attachment_panel" visible="false"> + <text allow_scroll="false" font="SansSerifSmall" top="4" left="5" width="220" height="12" layout="topleft" follows="left|top|right|bottom" + use_ellipses="true" word_wrap="true" max_length="96" name="attachment_text"> + Attachment goes here b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla. bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla . + </text> + </panel> + <panel border="false" left="1" bottom="-5" height="55" bevel_style="none" follows="left|right|bottom" layout="topleft" name="button_panel" visible="false"> + <button top="2" left="0" width="65" height="23" layout="topleft" follows="left|top|bottom" name="join_btn" mouse_opaque="true" tab_stop="false" label = "Join"/> + <button top="2" left_pad="12" width="65" height="23" layout="topleft" follows="left|top|bottom" name="decline_btn" mouse_opaque="true" tab_stop="false" label = "Decline"/> + <button top="2" left_pad="12" width="65" height="23" layout="topleft" follows="left|top|bottom" name="info_btn" mouse_opaque="true" tab_stop="false" label = "Info"/> + </panel> + </panel> + </layout_panel> + <layout_panel width="18" orientation="horizontal" follows="right|top|bottom" name="layout_panel_left_exp"> + <panel top="0" left="0" width="17" follows="left|top|right|bottom" layout="topleft" name="close_expand_panel_exp"> + <button top="0" left="2" width="17" height="17" layout="topleft" follows="top" name="close_expanded_btn" mouse_opaque="true" + tab_stop="false" image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" /> + <button bottom="5" left="0" width="17" height="17" layout="topleft" follows="bottom" name="condense_btn" mouse_opaque="true" + tab_stop="false" image_unselected="Notification_Condense" image_selected="Notification_Condense" /> + </panel> + </layout_panel> + </layout_stack> + </panel> + </layout_panel> + </layout_stack> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index c80e5b168a..b2d8bb874b 100755 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -3,7 +3,6 @@ name="inventory_outbox" start_folder.name="Outbox" show_empty_message="false" - show_load_status="false" start_folder.type="outbox" follows="all" layout="topleft" top="0" left="0" height="165" width="308" @@ -28,5 +27,5 @@ text_pad_right="4" arrow_size="12" max_folder_item_overlap="2"/> - <item allow_open="false"/> + <item allow_wear="false"/> </inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 2d4665c128..4fb8b9a67f 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -506,7 +506,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left="3" use_ellipses="true" name="groupcount"> - You belong to [COUNT] groups, and can join [REMAINING] more. + You belong to [COUNT] groups, and can join [REMAINING] more. [secondlife:/// Want more?] </text> <group_list allow_select="true" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 2e778014c5..3e96160834 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -216,7 +216,7 @@ control_name="QAMode" follows="top|left" height="15" - label="Show Developer Menu" + label="Show Develop Menu" layout="topleft" left="30" name="show_develop_menu_check" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 1e9a1aa27c..b201e071ef 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -270,7 +270,7 @@ value="1" /> --> <combo_box.item - label="Download and install updates manually" + label="I will download and install updates manually" name="Install_manual" value="0" /> </combo_box> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml index ea579c6dae..d019a0a310 100755 --- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -60,6 +60,10 @@ name="Large(512x512)" value="[i512,i512]" /> <combo_box.item + label="Current Window(512x512)" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item label="Custom" name="Custom" value="[i-1,i-1]" /> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml index 975b08be05..975b08be05 100755..100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ca38a9bc3f..4eb6e2462d 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -96,7 +96,10 @@ Voice Server Version: [VOICE_VERSION] <string name="LoginFailed">Login failed.</string> <string name="Quit">Quit</string> <string name="create_account_url">http://join.secondlife.com/?sourceid=[sourceid]</string> - + + <string name="AgniGridLabel">Second Life Main Grid (Agni)</string> + <string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string> + <string name="ViewerDownloadURL">http://secondlife.com/download</string> <string name="LoginFailedViewerNotPermitted"> The viewer you are using can no longer access Second Life. Please visit the following page to download a new viewer: @@ -235,15 +238,22 @@ Please try logging in again in a minute.</string> <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> <string name="TooltipTooManyWearables">You can't wear a folder containing more than [AMOUNT] items. You can change this limit in Advanced > Show Debug Settings > WearFolderLimit.</string> <string name="TooltipPrice" value="L$[AMOUNT]: "/> - - <string name="TooltipOutboxDragToWorld">You can not rez items in your merchant outbox</string> - <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string> - <string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string> - <string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string> - <string name="TooltipOutboxCallingCard">You can not put calling cards into your merchant outbox</string> - <string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds 3</string> - <string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string> - <string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string> + <string name="TooltipSLIcon">This links to a page on the official SecondLife.com or LindenLab.com domain.</string> + + <string name="TooltipOutboxDragToWorld">You can't rez items from the Marketplace Listings folder</string> + <string name="TooltipOutboxWorn">You can't put items you are wearing in the Marketplace Listings folder</string> + <string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds [AMOUNT]. Decrease the depth of folders-within-folders; box items if necessary.</string> + <string name="TooltipOutboxTooManyFolders">Subfolder count exceeds [AMOUNT]. Decrease the number of folders in your listing; box items if necessary.</string> + <string name="TooltipOutboxTooManyObjects">Item count exceeds [AMOUNT]. In order to sell more than [AMOUNT] items in one listing, you must box some of them.</string> + <string name="TooltipOutboxTooManyStockItems">Stock items count exceeds [AMOUNT].</string> + <string name="TooltipOutboxCannotDropOnRoot">You can only drop items or folders in the ALL or UNASSOCIATED tabs. Please select one of those tabs and move your item(s) or folder(s) again.</string> + <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred</string> + <string name="TooltipOutboxNotInInventory">You can only put items from your inventory on the marketplace</string> + <string name="TooltipOutboxLinked">You can't put linked items or folders on the marketplace</string> + <string name="TooltipOutboxCallingCard">You can't put calling cards on the marketplace</string> + <string name="TooltipOutboxDragActive">You can't move a listed listing</string> + <string name="TooltipOutboxCannotMoveRoot">You can't move the marketplace listings root folder</string> + <string name="TooltipOutboxMixedStock">All items in a stock folder must have the same type and permission</string> <string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string> <string name="TooltipDragOntoSelf">You can't move a folder into itself</string> @@ -268,6 +278,7 @@ Please try logging in again in a minute.</string> <string name="TooltipMapUrl">Click to view this location on a map</string> <string name="TooltipSLAPP">Click to run the secondlife:// command</string> <string name="CurrentURL" value=" CurrentURL: [CurrentURL]" /> + <string name="TooltipEmail">Click to compose an email</string> <!-- text for SLURL labels --> <string name="SLurlLabelTeleport">Teleport to</string> @@ -489,7 +500,7 @@ Please try logging in again in a minute.</string> <string name="NotConnected">Not Connected</string> <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> - <string name="JoinAnExperience"></string> <!-- intentionally left blank --> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess">Suppress alerts when managing estate access lists</string> <string name="OverrideYourAnimations">Replace your default animations</string> <string name="ScriptReturnObjects">Return objects on your behalf</string> @@ -520,6 +531,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> @@ -2254,6 +2267,7 @@ For AI Character: Get the closest navigable point to the point provided. <string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string> <string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string> <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> + <string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string> <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> @@ -2281,16 +2295,45 @@ We are accessing your account on the [[MARKETPLACE_CREATE_STORE_URL] Marketplace <string name="InventoryOutboxError"> The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. </string> - + <string name="InventoryMarketplaceError"> +This feature is currently in Beta. Please add your name to this [http://goo.gl/forms/FCQ7UXkakz Google form] if you would like to participate. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle">Your Marketplace Listings folder is empty.</string> + <string name="InventoryMarketplaceListingsNoItemsTooltip"></string> + <string name="InventoryMarketplaceListingsNoItems"> + Drag folders to this area to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> + + <string name="Marketplace Validation Log"></string> + <string name="Marketplace Validation Warning Stock">stock folder must be contained by a version folder</string> + <string name="Marketplace Validation Error Mixed Stock">: Error: all items in a stock folder must be no-copy and of the same type</string> + <string name="Marketplace Validation Error Subfolder In Stock">: Error: stock folder cannot contain subfolders</string> + <string name="Marketplace Validation Warning Empty">: Warning: folder doesn't contain any items</string> + <string name="Marketplace Validation Warning Create Stock">: Warning: creating stock folder</string> + <string name="Marketplace Validation Warning Create Version">: Warning: creating version folder</string> + <string name="Marketplace Validation Warning Move">: Warning : moving items</string> + <string name="Marketplace Validation Warning Delete">: Warning: folder content transfered to stock folder, removing empty folder</string> + <string name="Marketplace Validation Error Stock Item">: Error: no-copy items must be contained by a stock folder</string> + <string name="Marketplace Validation Warning Unwrapped Item">: Warning: items must be contained by a version folder</string> + <string name="Marketplace Validation Error">: Error: </string> + <string name="Marketplace Validation Warning">: Warning: </string> + <string name="Marketplace Validation Error Empty Version">: Warning: version folder must contain at least 1 item</string> + <string name="Marketplace Validation Error Empty Stock">: Warning: stock folder must contain at least 1 item</string> + + <string name="Marketplace Validation No Error">No errors or warnings to report</string> <string name="Marketplace Error None">No errors</string> - <string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> - <string name="Marketplace Error Empty Folder">Error: This folder has no contents.</string> - <string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, log in to the marketplace website and reduce your unassociated item count.</string> - - <string name="Marketplace Error Object Limit">Error: This item contains too many objects. Fix this error by placing objects together in boxes to reduce the total count to less than 200.</string> - <string name="Marketplace Error Folder Depth">Error: This item contains too many levels of nested folders. Reorganize it to a maximum of 3 levels of nested folders.</string> - <string name="Marketplace Error Unsellable Item">Error: This item can not be sold on the marketplace.</string> - <string name="Marketplace Error Internal Import">Error: There was a problem with this item. Try again later.</string> + <string name="Marketplace Error Prefix">Error: </string> + <string name="Marketplace Error Not Merchant">Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> + <string name="Marketplace Error Not Accepted">Cannot move item in that folder.</string> + <string name="Marketplace Error Unsellable Item">This item cannot be sold on the Marketplace.</string> + + <string name="MarketplaceNoID">no Mkt ID</string> + <string name="MarketplaceLive">listed</string> + <string name="MarketplaceActive">active</string> + <string name="MarketplaceMax">max</string> + <string name="MarketplaceStock">stock</string> + <string name="MarketplaceNoStock">out of stock</string> + <string name="MarketplaceUpdating">updating...</string> <string name="Open landmarks">Open landmarks</string> <string name="Unconstrained">Unconstrained</string> @@ -2497,8 +2540,8 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. <string name="CompileQueueProblemDownloading">Problem downloading</string> <string name="CompileQueueInsufficientPermDownload">Insufficient permissions to download a script.</string> <string name="CompileQueueInsufficientPermFor">Insufficient permissions for</string> - <string name="CompileQueueUnknownFailure">Unknown failure to download</string> - <string name="CompileNoExperiencePerm">Skipping script [SCRIPT] with Experience [EXPERIENCE].</string> + <string name="CompileQueueUnknownFailure">Unknown failure to download</string> + <string name="CompileNoExperiencePerm">Skipping script [SCRIPT] with Experience [EXPERIENCE].</string> <string name="CompileQueueTitle">Recompilation Progress</string> <string name="CompileQueueStart">recompile</string> <string name="ResetQueueTitle">Reset Progress</string> @@ -3954,6 +3997,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Inventory_Label">Inventory</string> <string name="Command_Map_Label">Map</string> <string name="Command_Marketplace_Label">Marketplace</string> + <string name="Command_MarketplaceListings_Label">Marketplace</string> <string name="Command_MiniMap_Label">Mini-map</string> <string name="Command_Move_Label">Walk / run / fly</string> <string name="Command_Outbox_Label">Merchant outbox</string> @@ -3984,6 +4028,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Inventory_Tooltip">View and use your belongings</string> <string name="Command_Map_Tooltip">Map of the world</string> <string name="Command_Marketplace_Tooltip">Go shopping</string> + <string name="Command_MarketplaceListings_Tooltip">Sell your creation</string> <string name="Command_MiniMap_Tooltip">Show nearby people</string> <string name="Command_Move_Tooltip">Moving your avatar</string> <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string> @@ -4075,5 +4120,17 @@ Try enclosing path to the editor with double quotes. <string name="loading_chat_logs"> Loading... </string> - - </strings> + + <string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES"> + The physics shape contains triangles which are too small. Try simplifying the physics model. + </string> + + <string name="Mav_Details_MAV_CONFIRMATION_DATA_MISMATCH"> + The physics shape contains bad confirmation data. Try to correct the physics model. + </string> + + <string name="Mav_Details_MAV_UNKNOWN_VERSION"> + The physics shape does not have correct version. Set the correct version for the physics model. + </string> + +</strings> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml index d5b10e7f51..92f815d4bf 100755 --- a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml @@ -1,3 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<inbox_inventory_panel show_load_status="false" - start_folder.type="inbox"/> +<inbox_inventory_panel start_folder.type="inbox"/> diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml index eaf148c5e4..d5efd723c4 100755 --- a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml @@ -3,7 +3,6 @@ bg_opaque_color="InventoryBackgroundColor" background_visible="true" background_opaque="true" - show_load_status="true" accepts_drag_and_drop="true" > <scroll diff --git a/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml b/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml new file mode 100644 index 0000000000..150225af27 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<notification_list_view + allow_select="false" + color="PanelFocusBackgroundColor" + item_pad="0" + keep_one_selected="false" + multi_select="false" + opaque="true"> + <flat_list_view + color="FloaterDefaultBackgroundColor" + follows="all" + layout="topleft" + name="notification_list" + left="1" + top="20" + height="0" + width="318"/> +</notification_list_view>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index e0a2375067..9bf485ce40 100755 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -1,82 +1,24 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="ACERCA DE [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - Compilado con [COMPILER], versión [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL: <nolink>[SLURL]</nolink> -(coordenadas globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -Memoria: [MEMORY_MB] MB -Versión del Sistema Operativo: [OS_VERSION] -Fabricante de la tarjeta gráfica: [GRAPHICS_CARD_VENDOR] -Tarjeta gráfica: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Versión de Windows Graphics Driver: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - Versión de OpenGL: [OPENGL_VERSION] - -Versión de libcurl: [LIBCURL_VERSION] -Versión de J2C Decoder: [J2C_VERSION] -Versión de Audio Driver: [AUDIO_DRIVER_VERSION] -Versión de Qt Webkit: [QT_WEBKIT_VERSION] -Versión del servidor de voz: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (no hay) - </floater.string> - <floater.string name="AboutTraffic"> - Paquetes perdidos: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Error al obtener la URL de las notas de la versión del servidor. - </floater.string> <tab_container name="about_tab"> <panel label="Información" name="support_panel"> <button label="Copiar al portapapeles" name="copy_btn" width="165"/> </panel> <panel label="Créditos" name="credits_panel"> - <text name="linden_intro"> - Second Life ofrecido por los Lindens: - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - con contribuciones de código abierto de: - </text> - <text_editor name="contrib_names"> - Dummy Name sustituido durante la ejecución - </text_editor> - <text name="trans_intro"> - y traducido por: - </text> - <text_editor name="trans_names"> - Dummy Name sustituido durante la ejecución - </text_editor> + <text name="linden_intro">Second Life ofrecido por los Lindens, +con contribuciones de código abierto de:</text> + <text_editor name="contrib_names">Dummy Name sustituido durante la ejecución</text_editor> </panel> <panel label="Licencias" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. + FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm y Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. + GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University y David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) @@ -87,7 +29,7 @@ Versión del servidor de voz: [VOICE_VERSION] SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. + zlib Copyright (C) 1995-2012 Jean-loup Gailly y Mark Adler. El visor de Second Life usa Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (y sus licenciadores). Reservados todos los derechos. Vea los detalles en www.havok.com. @@ -95,8 +37,7 @@ Versión del servidor de voz: [VOICE_VERSION] Reservados todos los derechos. Consulte los detalles en licenses.txt. - Codificación del audio del chat de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Codificación del audio del chat de voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_associate_listing.xml b/indra/newview/skins/default/xui/es/floater_associate_listing.xml new file mode 100644 index 0000000000..128382b277 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="ASOCIAR ARTÃCULOS"> + <text name="message">Id. de artÃculos:</text> + <line_editor name="listing_id">Escribe aquà el Id.</line_editor> + <button label="OK" name="OK"/> + <button label="Cancelar" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/es/floater_edit_hover_height.xml new file mode 100644 index 0000000000..d2130228bc --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="CONFIGURAR ALTURA DEL AVATAR"> + <slider label="Altura" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml index bf84c3d808..a8a3ad08f8 100755 --- a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="PROPIEDADES DEL ÃTEM DEL INVENTARIO"> - <floater.string name="unknown"> - (desconocido) - </floater.string> - <floater.string name="public"> - (público) - </floater.string> - <floater.string name="you_can"> - Usted puede: - </floater.string> - <floater.string name="owner_can"> - El propietario puede: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local][day,datetime,local] [mth,datetime,local] [year,datetime,local][hour,datetime,local]:[min,datetime,local]:[second,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Nombre: - </text> - <text name="LabelItemDescTitle"> - Descripción: - </text> - <text name="LabelCreatorTitle"> - Creador: - </text> + <floater.string name="unknown">(desconocido)</floater.string> + <floater.string name="public">(público)</floater.string> + <floater.string name="you_can">Usted puede:</floater.string> + <floater.string name="owner_can">El propietario puede:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local][day,datetime,local] [mth,datetime,local] [year,datetime,local][hour,datetime,local]:[min,datetime,local]:[second,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Nombre:</text> + <text name="LabelItemDescTitle">Descripción:</text> + <text name="LabelCreatorTitle">Creador:</text> <button label="Perfil..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Propietario: - </text> + <text name="LabelOwnerTitle">Propietario:</text> <button label="Perfil..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Adquirido: - </text> - <text name="LabelAcquiredDate"> - May Mié 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Tú: - </text> + <text name="LabelAcquiredTitle">Adquirido:</text> + <text name="LabelAcquiredDate">May Mié 24 12:50:46 2006</text> + <text name="OwnerLabel">Tú:</text> <check_box label="Editar" name="CheckOwnerModify"/> <check_box label="Copiarlo" left_delta="88" name="CheckOwnerCopy"/> <check_box label="Revender" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Cualquiera: - </text> + <text name="AnyoneLabel">Cualquiera:</text> <check_box label="Copiar" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Grupo: - </text> + <text name="GroupLabel">Grupo:</text> <check_box label="Compartir" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="230"> - Próximo propietario: - </text> + <text name="NextOwnerLabel" width="230">Próximo propietario:</text> <check_box label="Editar" name="CheckNextOwnerModify"/> <check_box label="Copiarlo" left_delta="88" name="CheckNextOwnerCopy"/> <check_box label="Revender" name="CheckNextOwnerTransfer"/> <check_box label="En venta" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="Copia" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Copiar" name="Copy"/> + <combo_box.item label="Contenidos" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Precio:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_item_properties.xml b/indra/newview/skins/default/xui/es/floater_item_properties.xml new file mode 100644 index 0000000000..b5fd595c24 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="PROPIEDADES DEL ARTÃCULO"/> diff --git a/indra/newview/skins/default/xui/es/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/es/floater_marketplace_listings.xml new file mode 100644 index 0000000000..2869af87f3 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="ARTÃCULOS DEL MERCADO"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Cargando...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/es/floater_marketplace_validation.xml new file mode 100644 index 0000000000..aab4b223dc --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Auditar artÃculos del Mercado"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_openobject.xml b/indra/newview/skins/default/xui/es/floater_openobject.xml index e350479e01..ab5bec3301 100755 --- a/indra/newview/skins/default/xui/es/floater_openobject.xml +++ b/indra/newview/skins/default/xui/es/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Copiar en el inventario" label_selected="Copiar en el inventario" name="copy_to_inventory_button"/> - <button label="Copiar y añadir al vestuario" label_selected="Copiar y añadir al vestuario" name="copy_and_wear_button"/> + <text name="border_note"> + Copiar en el inventario y vestir + </text> + <button label="Añadir a vestuario" label_selected="Añadir a vestuario" name="copy_and_wear_button"/> + <button label="Reemplazar vestuario" label_selected="Reemplazar vestuario" name="copy_and_replace_button"/> + <button label="Solo copiar en el inventario" label_selected="Solo copiar en el inventario" name="copy_to_inventory_button"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_pay.xml b/indra/newview/skins/default/xui/es/floater_pay.xml index ad9a43ad71..567f980446 100755 --- a/indra/newview/skins/default/xui/es/floater_pay.xml +++ b/indra/newview/skins/default/xui/es/floater_pay.xml @@ -1,26 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - Pagar al grupo - </string> - <string name="payee_resident"> - Pagar al residente - </string> - <text left="5" name="payee_label" width="105"> - Pagar: - </text> - <icon name="icon_person" tool_tip="Persona"/> - <text left="115" name="payee_name"> - Nombre de prueba demasiado largo para comprobar la función de recorte - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text left="4" name="amount text"> - O elige cuánto: - </text> - <line_editor left="60" name="amount" width="55"/> - <button label="Pagar" label_selected="Pagar" name="pay btn"/> - <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + <string name="payee_group">Pagar al grupo</string> + <string name="payee_resident">Pagar al residente</string> + <text name="paying_text">Vas a pagar:</text> + <text left="115" name="payee_name">Nombre de prueba demasiado largo para comprobar la función de recorte</text> + <panel label="Buscar" name="PatternsPanel"> + <button label="Pagar 1 L$" label_selected="Pagar 1 L$" name="fastpay 1"/> + <button label="Pagar 5 L$" label_selected="Pagar 5 L$" name="fastpay 5"/> + <button label="Pagar 10 L$" label_selected="Pagar 10 L$" name="fastpay 10"/> + <button label="Pagar 20 L$" label_selected="Pagar 20 L$" name="fastpay 20"/> + </panel> + <panel label="Buscar" name="InputPanel"> + <text name="amount text">Otra cantidad:</text> + <button label="Pagar" label_selected="Pagar" name="pay btn"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_pay_object.xml b/indra/newview/skins/default/xui/es/floater_pay_object.xml index 4767f4dfa0..8a5b028927 100755 --- a/indra/newview/skins/default/xui/es/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/es/floater_pay_object.xml @@ -1,29 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string left="5" name="payee_group" width="110"> - Pagar al grupo - </string> - <string left="5" name="payee_resident" width="110"> - Pagar al residente - </string> - <icon name="icon_person" tool_tip="Persona"/> - <text left="120" name="payee_name" width="180"> - Ericacita Moostopolison - </text> - <text left="5" name="object_name_label" width="110"> - A través del objeto: - </text> + <string left="5" name="payee_group" width="110">Pagar al grupo</string> + <string left="5" name="payee_resident" width="110">Pagar al residente</string> + <text name="paying_text">Vas a pagar:</text> + <text left="120" name="payee_name" width="180">Ericacita Moostopolison</text> + <text left="5" name="object_name_label" width="110">A través del objeto:</text> <icon name="icon_object" tool_tip="Objetos"/> - <text left="120" name="object_name_text" width="180"> - El muy largo nombre de mi objeto - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text name="amount text"> - O elige cuánto: - </text> - <button label="Pagar" label_selected="Pagar" name="pay btn"/> - <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + <text left="120" name="object_name_text" width="180">El muy largo nombre de mi objeto</text> + <panel label="Buscar" name="PatternsPanel"> + <button label="Pagar 1 L$" label_selected="Pagar 1 L$" name="fastpay 1"/> + <button label="Pagar 5 L$" label_selected="Pagar 5 L$" name="fastpay 5"/> + <button label="Pagar 10 L$" label_selected="Pagar 10 L$" name="fastpay 10"/> + <button label="Pagar 20 L$" label_selected="Pagar 20 L$" name="fastpay 20"/> + </panel> + <panel label="Buscar" name="InputPanel"> + <text name="amount text">Otra cantidad:</text> + <button label="Pagar" label_selected="Pagar" name="pay btn"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/es/menu_attachment_self.xml b/indra/newview/skins/default/xui/es/menu_attachment_self.xml index 5acd0c327a..02819e6816 100755 --- a/indra/newview/skins/default/xui/es/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/es/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Mi apariencia" name="Change Outfit"/> <menu_item_call label="Editar mi vestuario" name="Edit Outfit"/> <menu_item_call label="Editar mi anatomÃa" name="Edit My Shape"/> + <menu_item_call label="Altura del avatar" name="Hover Height"/> <menu_item_call label="Mis amigos" name="Friends..."/> <menu_item_call label="Mis grupos" name="Groups..."/> <menu_item_call label="Mi perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/es/menu_avatar_self.xml b/indra/newview/skins/default/xui/es/menu_avatar_self.xml index 717b46ac74..d60a3434cf 100755 --- a/indra/newview/skins/default/xui/es/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/es/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Mi apariencia" name="Chenge Outfit"/> <menu_item_call label="Editar mi vestuario" name="Edit Outfit"/> <menu_item_call label="Editar mi anatomÃa" name="Edit My Shape"/> + <menu_item_call label="Altura del avatar" name="Hover Height"/> <menu_item_call label="Mis amigos" name="Friends..."/> <menu_item_call label="Mis grupos" name="Groups..."/> <menu_item_call label="Mi perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml index cd5bc7917d..5d108abf67 100755 --- a/indra/newview/skins/default/xui/es/menu_inventory.xml +++ b/indra/newview/skins/default/xui/es/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Crear artÃculos" name="Marketplace Create Listing"/> + <menu_item_call label="Asociar artÃculos" name="Marketplace Associate Listing"/> + <menu_item_call label="Obtener (actualizar) artÃculos" name="Marketplace Get Listing"/> + <menu_item_call label="Comprobar errores" name="Marketplace Check Listing"/> + <menu_item_call label="Editar artÃculos" name="Marketplace Edit Listing"/> + <menu_item_call label="Incluir en la lista" name="Marketplace List"/> + <menu_item_call label="Retirar de la lista" name="Marketplace Unlist"/> + <menu_item_call label="Activar" name="Marketplace Activate"/> + <menu_item_call label="Desactivar" name="Marketplace Deactivate"/> <menu_item_call label="Compartir" name="Share"/> <menu_item_call label="Comprar" name="Task Buy"/> <menu_item_call label="Abrir" name="Task Open"/> @@ -86,6 +95,7 @@ <menu_item_call label="Añadir" name="Wearable Add"/> <menu_item_call label="Quitarse" name="Take Off"/> <menu_item_call label="Copiar al Buzón de salida de comerciante" name="Merchant Copy"/> - <menu_item_call label="Enviar al Mercado" name="Marketplace Send"/> + <menu_item_call label="Copiar en artÃculos del Mercado" name="Marketplace Copy"/> + <menu_item_call label="Mover a artÃculos del Mercado" name="Marketplace Move"/> <menu_item_call label="--sin opciones--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/es/menu_marketplace_view.xml b/indra/newview/skins/default/xui/es/menu_marketplace_view.xml new file mode 100644 index 0000000000..c46a9f490e --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Ordenar por cantidad en stock (de baja a alta)" name="sort_by_stock_amount"/> + <menu_item_check label="Mostrar solamente las carpetas de artÃculos" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 797cf30387..f6ebb498ec 100755 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -15,13 +15,14 @@ <menu_item_check label="Volar" name="Fly"/> <menu_item_check label="Correr siempre" name="Always Run"/> <menu_item_call label="Parar mis animaciones" name="Stop Animating My Avatar"/> - <menu_item_call label="Caminar / Correr / Volar..." name="Walk / run / fly"/> + <menu_item_call label="Caminar / Correr / Volar..." name="WalkRunFly"/> </menu> <menu label="Estado" name="Status"> <menu_item_check label="Ausente" name="Away"/> <menu_item_check label="No molestar" name="Do Not Disturb"/> </menu> <menu_item_call label="Comprar L$..." name="Buy and Sell L$"/> + <menu_item_call label="ArtÃculos del Mercado..." name="MarketplaceListings"/> <menu_item_call label="Panel de control de la cuenta..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es"/> </menu_item_call> @@ -62,7 +63,7 @@ <menu_item_call label="Foto" name="Take Snapshot"/> <menu_item_call label="Perfil del lugar" name="Place Profile"/> <menu_item_call label="Acerca del terreno" name="About Land"/> - <menu_item_call label="Región/Estado" name="Region/Estate"/> + <menu_item_call label="Región/Estado" name="RegionEstate"/> <menu_item_call label="Mis terrenos..." name="My Land"/> <menu_item_call label="Comprar este terreno" name="Buy Land"/> <menu label="Mostrar" name="LandShow"> @@ -249,6 +250,7 @@ <menu_item_check label="Texture Console" name="Texture Console"/> <menu_item_check label="Debug Console" name="Debug Console"/> <menu_item_call label="Notifications Console" name="Notifications"/> + <menu_item_check label="Consola de depuración de región" name="Region Debug Console"/> <menu_item_check label="Fast Timers" name="Fast Timers"/> <menu_item_check label="Memory" name="Memory"/> <menu_item_check label="Datos de la escena" name="Scene Statistics"/> @@ -324,7 +326,7 @@ <menu label="Red" name="Network"> <menu_item_check label="Pause Avatar" name="AgentPause"/> <menu_item_call label="Drop a Packet" name="Drop a Packet"/> - </menu> + </menu> <menu label="Mundo virtual" name="DevelopWorld"> <menu_item_check label="Anular el sol del Sim" name="Sim Sun Override"/> <menu_item_check label="MeteorologÃa fija" name="Fixed Weather"/> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index cc0d46bfe0..1e367b33fc 100755 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -129,6 +129,88 @@ No se han enviado carpetas al Mercado a causa de un error del sistema o de la re La inicialización del mercado ha fallado por un error del sistema o de la red. Vuelve a intentarlo más tarde. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Ha ocurrido el siguiente error al copiar o mover a la carpeta de stock: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Ha ocurrido el siguiente error al copiar o mover a artÃculos del Mercado: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + La transacción con el Mercado ha fallado por el siguiente error: + + Motivo: '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + No hemos podido incluir este producto en tus artÃculos o activar la carpeta de versión. Normalmente esto ocurre porque falta información en el formulario de descripción de los artÃculos, aunque también puede deberse a errores en la estructura de carpetas. Puedes editar los artÃculos o comprobar si la carpeta de artÃculos tiene algún error. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Ha ocurrido el siguiente error en la lista de artÃculos del Mercado: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Ha ocurrido el siguiente error al activar esta carpeta de versión: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Esta acción cambiará el contenido activo de esta lista de artÃculos. ¿Quieres continuar? + <usetemplate ignoretext="Confirmar antes de que cambie una lista de artÃculos activa en el Mercado" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Los artÃculos arrastrados a la ventana ArtÃculos del mercado se mueven desde sus ubicaciones originales, no se copian. ¿Quieres continuar? + <usetemplate ignoretext="Confirmar antes de mover un artÃculo desde el inventario al Mercado" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Al mover o eliminar una carpeta de artÃculos, se eliminarán tus artÃculos del Mercado. Si deseas conservar los artÃculos del Mercado, mueve o elimina el contenido de la carpeta de versión que desees modificar. ¿Quieres continuar? + <usetemplate ignoretext="Confirmar antes de que mueva o elimine una lista de artÃculos del Mercado" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + No tienes permiso para copiar uno o varios de estos artÃculos en el Mercado. Puedes moverlos o dejártelos. + <usetemplate canceltext="Cancelar" ignoretext="Confirmar cuando intente copiar una selección que contiene artÃculos que no se pueden copiar en el Mercado" name="yesnocancelbuttons" notext="No mover objeto(s)" yestext="Mover objeto(s)"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Esta acción retirará esta lista de artÃculos. ¿Quieres continuar? + <usetemplate ignoretext="Confirmar antes de que retire una lista de artÃculos activa en el Mercado" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Esta acción desactivará la carpeta de versión de la lista de artÃculos actual. ¿Quieres continuar? + <usetemplate ignoretext="Confirmar antes de que desactive la carpeta de versión de una lista de artÃculos del Mercado" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + No se ha podido actualizar esta lista de artÃculos. +[[URL] Haz clic aquÃ] para editarla en el Mercado. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + No puedes ponerte prendas ni partes del cuerpo que se encuentren en la carpeta ArtÃculos del mercado. + </notification> + <notification name="AlertMerchantListingInvalidID"> + Id. de lista de artÃculos no válida + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Esta lista de artÃculos contiene varias carpetas de versión o ninguna. Tendrás que seleccionar y activar una por tu cuenta más tarde. + <usetemplate ignoretext="Mostrar una alerta de la activación de la carpeta de versión cuando cree una lista de artÃculos con varias carpetas de versión" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Hemos separado los artÃculos en stock de diferentes tipos en carpetas distintas, para que tu carpeta esté organizada de tal forma que podamos incluirla en el Mercado. + <usetemplate ignoretext="Mostrar alerta cuando la carpeta de stock se divida antes de incluirla en la lista" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Hemos retirado tu lista de artÃculos porque el stock está vacÃo. Para volver a publicar tus artÃculos, añade más unidades a la carpeta de stock. + <usetemplate ignoretext="Mostrar alerta cuando una lista de artÃculos se retire porque la carpeta de stock está vacÃa" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> Hubo un problema al subir el texto de un script por la siguiente razón: [REASON]. Por favor, inténtalo más tarde. </notification> @@ -468,6 +550,10 @@ o hacer una puja? ¿Guardar los cambios? <usetemplate canceltext="Cancelar" name="yesnocancelbuttons" notext="No guardar" yestext="Guardar"/> </notification> + <notification name="DeleteNotecard"> + ¿Deseas borrar la nota? + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Fallo al guardar el gesto. Este gesto tiene demasiados pasos. @@ -1877,6 +1963,9 @@ Se cambiarán miles de regiones, y se provocará un colapso en el espacio del se Tus preferencias de contenido actuales te impiden visitar la región que has seleccionado. Puedes cambiar las preferencias en Yo > Preferencias > General. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> La región que intentas visitar tiene un contenido [REGIONMATURITY], que solo es accesible para los adultos. <url name="url"> @@ -2165,6 +2254,10 @@ Dado que estos objetos tienen scripts, moverlos a tu inventario puede provocar u <ignore name="ignore" text="He establecido la acción 'Pagar al objeto' cuando construyo uno sin un script money()"/> </form> </notification> + <notification name="PayConfirmation"> + Confirma que deseas pagar L$[AMOUNT] a [TARGET]. + <usetemplate ignoretext="Confirmar antes de pagar (sumas mayores de 200 L$)" name="okcancelignore" notext="Cancelar" yestext="Pagar"/> + </notification> <notification name="OpenObjectCannotCopy"> En este objeto, no hay Ãtems que estés autorizado a copiar. </notification> @@ -2703,9 +2796,6 @@ Por favor, vuelve a intentarlo en unos momentos. <notification name="NoValidCircuit"> Circuito de código inválido. </notification> - <notification name="NoValidTimestamp"> - Fecha inválida. - </notification> <notification name="NoPendingConnection"> No se puede crear la conexión. </notification> @@ -3840,9 +3930,11 @@ Prueba otra vez dentro de un minuto. </notification> <notification name="TeleportedByAttachment"> Has sido teleportado por un anexo de [ITEM_ID] + <usetemplate ignoretext="Teleportarme: has sido teleportado por un anexo" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Has sido teleportado por el objeto '[OBJECT_NAME]' de la parcela '[PARCEL_NAME]' + <usetemplate ignoretext="Teleportarme: has sido teleportado por un objeto de una parcela" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Has sido teleportado por el objeto '[OBJECT_NAME]' que es propiedad de [OWNER_ID] @@ -4174,7 +4266,7 @@ Prueba a seleccionar un terreno más pequeño. <usetemplate ignoretext="No se pueden mover los archivos. Ruta anterior restaurada." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Ha ocurrido un problema al guardar los permisos predeterminados por el siguiente motivo: [REASON]. Intenta configurar los permisos predeterminados más adelante. + Ha ocurrido un problema al guardar los permisos de objeto predeterminados: [REASON]. Intenta configurar los permisos predeterminados más adelante. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/es/panel_login.xml b/indra/newview/skins/default/xui/es/panel_login.xml index 253d0800e1..5300fce153 100755 --- a/indra/newview/skins/default/xui/es/panel_login.xml +++ b/indra/newview/skins/default/xui/es/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=es - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=es</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Nombre de usuario" name="username_combo" tool_tip="El nombre de usuario que elegiste al registrarte, como bobsmith12 o Steller Sunshine"/> <line_editor label="Contraseña" name="password_edit"/> - <check_box label="Recordarme" name="remember_check"/> - <text name="forgot_password_text"> - Contraseña olvidada - </text> - <button label="Iniciar sesión" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - en mi última posición - </text> <combo_box label="Mis lugares favoritos" name="start_location_combo"> + <combo_box.item label="Mi última posición" name="MyLastLocation"/> <combo_box.item label="Mi Base" name="MyHome"/> </combo_box> - <button label="Iniciar sesión" name="connect_favorite_btn"/> - <line_editor label="Especifica una ubicación" name="location_edit"/> - <button label="Iniciar sesión" name="connect_location_btn"/> + <button label="Iniciar sesión" name="connect_btn"/> + <check_box label="Recordarme" name="remember_check"/> + <text name="forgot_password_text">Contraseña olvidada</text> <combo_box label="Seleccionar cuadrÃcula" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/es/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/es/panel_marketplace_listings.xml new file mode 100644 index 0000000000..d9cd93b349 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Mercado" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Opciones de vista/orden"/> + <button name="add_btn" tool_tip="Crear una carpeta de artÃculos nueva"/> + <button label="Comprobar errores" name="audit_btn" tool_tip="Comprobar tus artÃculos del Mercado"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Filtrar artÃculos del Mercado" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/es/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..77540aee39 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="TODOS" name="All Items" tool_tip="Arrastra y suelta aquà los artÃculos para incluirlos en la lista de artÃculos"/> diff --git a/indra/newview/skins/default/xui/es/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/es/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..ca8ff6aea9 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="INCLUIDOS EN LA LISTA" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/es/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/es/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..2606e035cd --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="SIN ASOCIAR" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/es/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/es/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..ea568cab8a --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="RETIRADOS DE LA LISTA" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml index 357b432c4c..357b432c4c 100755..100644 --- a/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml index 7eead3bc18..8ea56c5262 100755 --- a/indra/newview/skins/default/xui/es/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Pérdida de paquetes - </panel.string> - <panel.string name="bandwidth_tooltip"> - Ancho de banda - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - [AMT] L$ - </panel.string> + <panel.string name="packet_loss_tooltip">Pérdida de paquetes</panel.string> + <panel.string name="bandwidth_tooltip">Ancho de banda</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">[AMT] L$</panel.string> <panel left="-410" name="balance_bg" width="200"> - <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/> + <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="L$??"/> <button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/> </panel> - <text name="TimeText" tool_tip="Hora actual (PacÃfico)"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="Hora actual (PacÃfico)">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="Iniciar/Parar todos los media (música, vÃdeo, páginas web)"/> <button name="volume_btn" tool_tip="Control general del volumen"/> </panel> diff --git a/indra/newview/skins/default/xui/es/sidepanel_item_info.xml b/indra/newview/skins/default/xui/es/sidepanel_item_info.xml index 94c8011768..8132bbdb1b 100755 --- a/indra/newview/skins/default/xui/es/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/es/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Transferir" name="CheckNextOwnerTransfer" tool_tip="El próximo propietario puede dar o revender este objeto"/> </panel> <check_box label="En venta" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Copiar" name="Copy"/> + <combo_box.item label="Contenidos" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Precio: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/es/sidepanel_task_info.xml b/indra/newview/skins/default/xui/es/sidepanel_task_info.xml index cb061796e7..b9c8139f16 100755 --- a/indra/newview/skins/default/xui/es/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/es/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Perfil del objeto"> - <panel.string name="text deed continued"> - Transferir - </panel.string> - <panel.string name="text deed"> - Transferir - </panel.string> - <panel.string name="text modify info 1"> - Puedes modificar este objeto - </panel.string> - <panel.string name="text modify info 2"> - Puedes modificar estos objetos - </panel.string> - <panel.string name="text modify info 3"> - No puedes modificar este objeto - </panel.string> - <panel.string name="text modify info 4"> - No puedes modificar estos objetos - </panel.string> - <panel.string name="text modify info 5"> - No se puede modificar este objeto a través del lÃmite de una región - </panel.string> - <panel.string name="text modify info 6"> - No se pueden modificar estos objetos a través del lÃmite de una región - </panel.string> - <panel.string name="text modify warning"> - Este objeto tiene partes enlazadas - </panel.string> - <panel.string name="Cost Default"> - Precio: L$ - </panel.string> - <panel.string name="Cost Total"> - Precio total: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Price Per: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Mixed Price - </panel.string> - <panel.string name="Sale Mixed"> - Mixed Sale - </panel.string> + <panel.string name="text deed continued">Transferir</panel.string> + <panel.string name="text deed">Transferir</panel.string> + <panel.string name="text modify info 1">Puedes modificar este objeto</panel.string> + <panel.string name="text modify info 2">Puedes modificar estos objetos</panel.string> + <panel.string name="text modify info 3">No puedes modificar este objeto</panel.string> + <panel.string name="text modify info 4">No puedes modificar estos objetos</panel.string> + <panel.string name="text modify info 5">No se puede modificar este objeto a través del lÃmite de una región</panel.string> + <panel.string name="text modify info 6">No se pueden modificar estos objetos a través del lÃmite de una región</panel.string> + <panel.string name="text modify warning">Este objeto tiene partes enlazadas</panel.string> + <panel.string name="Cost Default">Precio: L$</panel.string> + <panel.string name="Cost Total">Precio total: L$</panel.string> + <panel.string name="Cost Per Unit">Price Per: L$</panel.string> + <panel.string name="Cost Mixed">Mixed Price</panel.string> + <panel.string name="Sale Mixed">Mixed Sale</panel.string> <text name="title" value="Perfil del objeto"/> <text name="where" value="(En el mundo)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Nombre: - </text> - <text name="Description:"> - Descripción: - </text> - <text name="CreatorNameLabel"> - Creador: - </text> - <text name="Owner:"> - Propietario: - </text> - <text name="Group_label"> - Grupo: - </text> + <text name="Name:">Nombre:</text> + <text name="Description:">Descripción:</text> + <text name="CreatorNameLabel">Creador:</text> + <text name="Owner:">Propietario:</text> + <text name="Group_label">Grupo:</text> <button name="button set group" tool_tip="Elige un grupo con el que compartir los permisos de este objeto"/> <name_box initial_value="Cargando..." name="Group Name Proxy"/> <button label="Transferir" label_selected="Transferir" name="button deed" tool_tip="La transferencia entrega este objeto con los permisos del próximo propietario. Los objetos compartidos por el grupo pueden ser transferidos por un oficial del grupo."/> - <text name="label click action"> - Pulsa para: - </text> + <text name="label click action">Pulsa para:</text> <combo_box name="clickaction"> <combo_box.item label="Tocarlo (por defecto)" name="Touch/grab(default)"/> <combo_box.item label="Sentarme en el objeto" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Zoom" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Puedes modificar este objeto - </text> - <text name="Anyone can:"> - Cualquiera: - </text> + <text name="perm_modify">Puedes modificar este objeto</text> + <text name="Anyone can:">Cualquiera:</text> <check_box label="Copiar" name="checkbox allow everyone copy"/> <check_box label="Mover" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Grupo: - </text> + <text name="GroupLabel">Grupo:</text> <check_box label="Compartir" name="checkbox share with group" tool_tip="Permite que todos los miembros del grupo compartan tus permisos de modificación de este objeto. Debes transferirlo para activar las restricciones según los roles."/> - <text name="NextOwnerLabel"> - Próximo propietario: - </text> + <text name="NextOwnerLabel">Próximo propietario:</text> <check_box label="Modificar" name="checkbox next owner can modify"/> <check_box label="Copiar" name="checkbox next owner can copy"/> <check_box label="Transferir" name="checkbox next owner can transfer" tool_tip="El próximo propietario puede dar o revender este objeto"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Precio: L$" name="Edit Cost"/> <check_box label="Mostrar en la búsqueda" name="search_check" tool_tip="Permitir que la gente vea este objeto en los resultados de la búsqueda"/> - <text name="pathfinding_attributes_label"> - Atributos de pathfinding: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Atributos de pathfinding:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Abrir" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index cabb5ee67b..404aa1e60e 100755 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -445,28 +445,46 @@ Intenta iniciar sesión de nuevo en unos instantes. </string> <string name="TooltipPrice" value="[AMOUNT] L$:"/> <string name="TooltipOutboxDragToWorld"> - No puedes colocar objetos en tu buzón de salida de comerciante + No se pueden mostrar artÃculos desde la carpeta ArtÃculos del mercado + </string> + <string name="TooltipOutboxWorn"> + Los artÃculos que tienes puestos no se pueden colocar en la carpeta ArtÃculos del mercado + </string> + <string name="TooltipOutboxFolderLevels"> + La profundidad de carpetas anidadas excede de [AMOUNT]. Disminuye la profundidad de las carpetas anidadas; si es necesario, agrupa los artÃculos. + </string> + <string name="TooltipOutboxTooManyFolders"> + La cantidad de subcarpetas excede de [AMOUNT]. Disminuye la cantidad de carpetas de tu lista de artÃculos; si es necesario, agrupa los artÃculos. + </string> + <string name="TooltipOutboxTooManyObjects"> + La cantidad de artÃculos excede de [AMOUNT]. Para vender más de [AMOUNT] artÃculos en la misma lista, debes agrupar algunos. + </string> + <string name="TooltipOutboxTooManyStockItems"> + La cantidad de artÃculos en stock excede de [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Solo se pueden soltar artÃculos o carpetas en la pestaña TODOS. Selecciona esta pestaña y mueve otra vez los artÃculos o carpetas. </string> <string name="TooltipOutboxNoTransfer"> - Uno o varios de estos objetos no se pueden vender o transferir. + Uno o varios de estos objetos no se pueden vender o transferir </string> <string name="TooltipOutboxNotInInventory"> - Tu buzón de salida de comerciante sólo puede aceptar objetos procedentes directamente de tu inventario + Solo puedes colocar en el mercado artÃculos de tu inventario </string> - <string name="TooltipOutboxWorn"> - No puedes poner artÃculos que llevas puestos en el buzón de salida de comerciante + <string name="TooltipOutboxLinked"> + No puedes poner carpetas o artÃculos vinculados en el Mercado </string> <string name="TooltipOutboxCallingCard"> - No puedes poner tarjetas de visita en tu buzón de salida de comerciante + No puedes colocar tarjetas de visita en el Mercado </string> - <string name="TooltipOutboxFolderLevels"> - La profundidad de carpetas anidadas excede de 3 + <string name="TooltipOutboxDragActive"> + No se puede mover una lista de artÃculos publicada </string> - <string name="TooltipOutboxTooManyFolders"> - El número de subcarpetas de la carpeta de nivel superior excede de 20 + <string name="TooltipOutboxCannotMoveRoot"> + No se puede mover la carpeta raÃz de artÃculos del Mercado </string> - <string name="TooltipOutboxTooManyObjects"> - El número de elementos de la carpeta de nivel superior excede de 200 + <string name="TooltipOutboxMixedStock"> + Todos los artÃculos de una carpeta de stock deben tener el mismo tipo y permiso </string> <string name="TooltipDragOntoOwnChild"> No puedes mover una carpeta a su carpeta secundaria @@ -1045,7 +1063,7 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="AgentNameSubst"> (Tú) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Suprimir alertas al gestionar las listas de acceso a un estado </string> @@ -1112,6 +1130,12 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="bitmap_image_files"> Imágenes de mapa de bits </string> + <string name="png_image_files"> + Imágenes PNG + </string> + <string name="save_texture_image_files"> + Imágenes Targa o PNG + </string> <string name="avi_movie_file"> Archivo de pelÃcula AVI </string> @@ -1361,6 +1385,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="FavoritesNoMatchingItems"> Arrastra aquà un hito para tenerlo en tus favoritos. </string> + <string name="MarketplaceNoMatchingItems"> + No se han encontrado artÃculos. Comprueba si has escrito correctamente la cadena de búsqueda y vuelve a intentarlo. + </string> <string name="InventoryNoTexture"> No tienes en tu inventario una copia de esta textura </string> @@ -1408,29 +1435,95 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="InventoryOutboxError"> La [[MARKETPLACE_CREATE_STORE_URL] tienda del Mercado] devuelve errores. </string> + <string name="InventoryMarketplaceError"> + Esta función está actualmente en versión beta. Si quieres participar, añade tu nombre a este [http://goo.gl/forms/FCQ7UXkakz Formulario de Google]. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Tu carpeta ArtÃculos del mercado está vacÃa. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Arrastra carpetas a esta sección para incluirlas en la lista de venta del [[MARKETPLACE_DASHBOARD_URL] Mercado]. + </string> + <string name="Marketplace Validation Warning Stock"> + La carpeta de stock debe estar contenida en una carpeta de versión + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Error: todos los artÃculos de una carpeta de stock deben ser del mismo tipo y que no se puedan copiar + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Error: la carpeta de stock no puede contener subcarpetas + </string> + <string name="Marketplace Validation Warning Empty"> + : Atención: la carpeta no contiene ningún artÃculo + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Atención: creando carpeta de stock + </string> + <string name="Marketplace Validation Warning Create Version"> + : Atención: creando la carpeta de versión + </string> + <string name="Marketplace Validation Warning Move"> + : Atención: moviendo artÃculos + </string> + <string name="Marketplace Validation Warning Delete"> + : Atención: se ha transferido el contenido de la carpeta a la carpeta de stock, y se eliminará la carpeta vacÃa + </string> + <string name="Marketplace Validation Error Stock Item"> + : Error: los artÃculos que no se pueden copiar deben estar contenidos en una carpeta de stock + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Atención: los artÃculos deben estar contenidos en una carpeta de versión + </string> + <string name="Marketplace Validation Error"> + : Error: + </string> + <string name="Marketplace Validation Warning"> + : Atención: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Atención: la carpeta de versión debe contener al menos un artÃculo + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Atención: la carpeta de stock debe contener al menos un artÃculo + </string> + <string name="Marketplace Validation No Error"> + No se han producido errores ni advertencias + </string> <string name="Marketplace Error None"> Sin errores </string> + <string name="Marketplace Error Prefix"> + Error: + </string> <string name="Marketplace Error Not Merchant"> - Error: Para poder enviar objetos al mercado, debes registrarte como comerciante (es gratis). + Para poder enviar objetos al mercado, debes registrarte como comerciante (es gratis). + </string> + <string name="Marketplace Error Not Accepted"> + No se puede mover el artÃculo a esa carpeta. </string> - <string name="Marketplace Error Empty Folder"> - Error: Esta carpeta está vacÃa. + <string name="Marketplace Error Unsellable Item"> + Este artÃculo no se puede vender en el Mercado. </string> - <string name="Marketplace Error Unassociated Products"> - Error: Este objeto no se pudo subir porque tu cuenta de comerciante tiene demasiados objetos que no están asociados a productos. Para corregirlo, inicia sesión en la página web del mercado y asocia más objetos. + <string name="MarketplaceNoID"> + no Mkt ID </string> - <string name="Marketplace Error Object Limit"> - Error: Este elemento contiene demasiados objetos. Para corregir el error, guarda objetos en cajas de forma que el total de objetos sea menor que 200. + <string name="MarketplaceLive"> + en la lista </string> - <string name="Marketplace Error Folder Depth"> - Error: Este objeto contiene demasiados niveles de carpetas anidadas. ReorganÃzalo de forma que tenga como máximo 3 niveles de carpetas anidadas. + <string name="MarketplaceActive"> + activa </string> - <string name="Marketplace Error Unsellable Item"> - Error: Este objeto no se puede vender en el mercado. + <string name="MarketplaceMax"> + máx. </string> - <string name="Marketplace Error Internal Import"> - Error: Este objeto tiene un problema. Vuelve a intentarlo más tarde. + <string name="MarketplaceStock"> + stock + </string> + <string name="MarketplaceNoStock"> + existencias agotadas + </string> + <string name="MarketplaceUpdating"> + actualizando... </string> <string name="Open landmarks"> Abrir hitos @@ -1451,6 +1544,7 @@ Intenta iniciar sesión de nuevo en unos instantes. No hay contenido </string> <string name="WornOnAttachmentPoint" value="(lo llevas en: [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (activo)"/> <string name="Chat Message" value="Chat:"/> <string name="Sound" value="Sonido :"/> @@ -1715,6 +1809,15 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="Invalid Attachment"> Punto de colocación no válido </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Error: falta un artÃculo + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Error: falta el artÃculo de base + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Error: el objeto se encuentra en el vestuario actual, pero no está anexado + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] de edad </string> @@ -1850,9 +1953,6 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="CompileQueueUnknownFailure"> Fallo desconocido en la descarga </string> - <string name="CompileNoExperiencePerm"> - Omitiendo el script [SCRIPT] con la experiencia [EXPERIENCE]. - </string> <string name="CompileQueueTitle"> Recompilando </string> @@ -1886,6 +1986,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="SaveComplete"> Guardado. </string> + <string name="UploadFailed"> + Error al subir el archivo: + </string> <string name="ObjectOutOfRange"> Script (objeto fuera de rango) </string> @@ -1895,6 +1998,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="GroupsNone"> ninguno </string> + <string name="CompileNoExperiencePerm"> + Omitiendo el script [SCRIPT] con la experiencia [EXPERIENCE]. + </string> <string name="Group" value="(grupo)"/> <string name="Unknown"> (Desconocido) @@ -4980,6 +5086,9 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="Command_Marketplace_Label"> Mercado </string> + <string name="Command_MarketplaceListings_Label"> + Mercado + </string> <string name="Command_MiniMap_Label"> Minimapa </string> @@ -5067,6 +5176,9 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="Command_Marketplace_Tooltip"> Ir de compras </string> + <string name="Command_MarketplaceListings_Tooltip"> + Vende tu creación + </string> <string name="Command_MiniMap_Tooltip"> Mostrar la gente que está cerca </string> @@ -5178,6 +5290,18 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="UserDictionary"> [Usuario] </string> + <string name="logging_calls_disabled_log_empty"> + No se están registrando las conversaciones. Para empezar a grabar un registro, elige "Guardar: Solo registro" o "Guardar: Registro y transcripciones" en Preferencias > Chat. + </string> + <string name="logging_calls_disabled_log_not_empty"> + No se registrarán más conversaciones. Para reanudar la grabación de un registro, elige "Guardar: Solo registro" o "Guardar: Registro y transcripciones" en Preferencias > Chat. + </string> + <string name="logging_calls_enabled_log_empty"> + No hay conversaciones grabadas. Después de contactar con una persona, o de que alguien contacte contigo, aquà se mostrará una entrada de registro. + </string> + <string name="loading_chat_logs"> + Cargando... + </string> <string name="experience_tools_experience"> Experiencia </string> @@ -5259,16 +5383,4 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="ExperiencePermissionShort12"> Otorgar permisos </string> - <string name="logging_calls_disabled_log_empty"> - No se están registrando las conversaciones. Para empezar a grabar un registro, elige "Guardar: Solo registro" o "Guardar: Registro y transcripciones" en Preferencias > Chat. - </string> - <string name="logging_calls_disabled_log_not_empty"> - No se registrarán más conversaciones. Para reanudar la grabación de un registro, elige "Guardar: Solo registro" o "Guardar: Registro y transcripciones" en Preferencias > Chat. - </string> - <string name="logging_calls_enabled_log_empty"> - No hay conversaciones grabadas. Después de contactar con una persona, o de que alguien contacte contigo, aquà se mostrará una entrada de registro. - </string> - <string name="loading_chat_logs"> - Cargando... - </string> </strings> diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index 384966354e..08f26e60b4 100755 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -1,74 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="À PROPOS DE [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - Compilé avec [COMPILER] version [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL : <nolink>[SLURL]</nolink> -(coordonnées globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU : [CPU] -Mémoire : [MEMORY_MB] Mo -Version OS : [OS_VERSION] -Distributeur de cartes graphiques : [GRAPHICS_CARD_VENDOR] -Cartes graphiques : [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Version Windows Graphics Driver : [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - Version OpenGL : [OPENGL_VERSION] - -Version libcurl : [LIBCURL_VERSION] -Version J2C Decoder : [J2C_VERSION] -Version Audio Driver : [AUDIO_DRIVER_VERSION] -Version Qt Webkit : [QT_WEBKIT_VERSION] -Version serveur vocal : [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (aucun) - </floater.string> - <floater.string name="AboutTraffic"> - Paquets perdus : [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Erreur lors de la récupération de l'URL des notes de version du serveur. - </floater.string> <tab_container name="about_tab"> <panel label="Infos" name="support_panel"> <button label="Copier dans le presse-papiers" name="copy_btn"/> </panel> <panel label="Remerciements" name="credits_panel"> - <text name="linden_intro"> - Second Life vous est proposé par les Linden : - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - Contributions Open Source : - </text> - <text_editor name="contrib_names"> - Dummy Name remplacé au moment de l'exécution - </text_editor> - <text name="trans_intro"> - Participation aux traductions : - </text> - <text_editor name="trans_names"> - Dummy Name remplacé au moment de l'exécution - </text_editor> + <text name="linden_intro">Second Life vous est proposé par les Linden, +avec les contributions Open Source de :</text> + <text_editor name="contrib_names">Dummy Name remplacé au moment de l'exécution</text_editor> </panel> <panel label="Licences" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -95,8 +37,7 @@ Version serveur vocal : [VOICE_VERSION] Tous droits réservés. Voir licenses.txt pour plus d'informations. - Codage audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Codage audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_associate_listing.xml b/indra/newview/skins/default/xui/fr/floater_associate_listing.xml new file mode 100644 index 0000000000..3c61cfe4ca --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="ASSOCIER L'ANNONCE"> + <text name="message">ID d'annonce :</text> + <line_editor name="listing_id">Saisir l'ID ici</line_editor> + <button label="OK" name="OK"/> + <button label="Annuler" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/fr/floater_edit_hover_height.xml new file mode 100644 index 0000000000..28e7e87193 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="DÉFINIR LA HAUTEUR DE SUSTENTATION"> + <slider label="Hauteur" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml index f2eb3cb6bc..1d4e7c818f 100755 --- a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="PROPRIÉTÉS DES ARTICLES DE L'INVENTAIRE"> - <floater.string name="unknown"> - (inconnu) - </floater.string> - <floater.string name="public"> - (public) - </floater.string> - <floater.string name="you_can"> - Vous pouvez : - </floater.string> - <floater.string name="owner_can"> - Le propriétaire peut : - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Nom : - </text> - <text name="LabelItemDescTitle"> - Description : - </text> - <text name="LabelCreatorTitle"> - Créateur : - </text> + <floater.string name="unknown">(inconnu)</floater.string> + <floater.string name="public">(public)</floater.string> + <floater.string name="you_can">Vous pouvez :</floater.string> + <floater.string name="owner_can">Le propriétaire peut :</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Nom :</text> + <text name="LabelItemDescTitle">Description :</text> + <text name="LabelCreatorTitle">Créateur :</text> <button label="Profil..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Propriétaire : - </text> + <text name="LabelOwnerTitle">Propriétaire :</text> <button label="Profil..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Acquis : - </text> - <text name="LabelAcquiredDate"> - Wed May 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Vous : - </text> + <text name="LabelAcquiredTitle">Acquis :</text> + <text name="LabelAcquiredDate">Wed May 24 12:50:46 2006</text> + <text name="OwnerLabel">Vous :</text> <check_box label="Modifier" name="CheckOwnerModify"/> <check_box label="Copier" name="CheckOwnerCopy"/> <check_box label="Revendre" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel" width="80"> - N'importe qui : - </text> + <text name="AnyoneLabel" width="80">N'importe qui :</text> <check_box label="Copier" name="CheckEveryoneCopy"/> - <text name="GroupLabel" width="80"> - Groupe : - </text> + <text name="GroupLabel" width="80">Groupe :</text> <check_box label="Partager" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="192"> - Le prochain propriétaire : - </text> + <text name="NextOwnerLabel" width="192">Le prochain propriétaire :</text> <check_box label="Modifier" name="CheckNextOwnerModify"/> <check_box label="Copier" name="CheckNextOwnerCopy"/> <check_box label="Revendre" name="CheckNextOwnerTransfer"/> <check_box label="À vendre" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Copier" name="Copy"/> + <combo_box.item label="Contenu" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Prix :" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_item_properties.xml b/indra/newview/skins/default/xui/fr/floater_item_properties.xml new file mode 100644 index 0000000000..5301e759ee --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="PROPRIÉTÉS DE L'ARTICLE"/> diff --git a/indra/newview/skins/default/xui/fr/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/fr/floater_marketplace_listings.xml new file mode 100644 index 0000000000..8488d17d00 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="ANNONCES DE LA PLACE DU MARCHÉ"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Chargement…</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/fr/floater_marketplace_validation.xml new file mode 100644 index 0000000000..01527800ac --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Auditer les annonces de la Place du marché"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_openobject.xml b/indra/newview/skins/default/xui/fr/floater_openobject.xml index ee969169d2..54edf92379 100755 --- a/indra/newview/skins/default/xui/fr/floater_openobject.xml +++ b/indra/newview/skins/default/xui/fr/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Copier dans l'inventaire" label_selected="Copier dans l'inventaire" name="copy_to_inventory_button" width="132"/> - <button label="Copier et ajouter à la tenue" label_selected="Copier et ajouter à la tenue" left="152" name="copy_and_wear_button"/> + <text name="border_note"> + Copier dans l'inventaire et porter + </text> + <button label="Ajouter à la tenue" label_selected="Ajouter à la tenue" left="152" name="copy_and_wear_button"/> + <button label="Remplacer la tenue" label_selected="Remplacer la tenue" name="copy_and_replace_button"/> + <button label="Copier uniquement dans l'inventaire" label_selected="Copier uniquement dans l'inventaire" name="copy_to_inventory_button" width="132"/> + <button label="Annuler" label_selected="Annuler" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_pay.xml b/indra/newview/skins/default/xui/fr/floater_pay.xml index 397436876d..bbd20e868c 100755 --- a/indra/newview/skins/default/xui/fr/floater_pay.xml +++ b/indra/newview/skins/default/xui/fr/floater_pay.xml @@ -1,26 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - Payer le groupe - </string> - <string name="payee_resident"> - Payer le résident - </string> - <text left="5" name="payee_label"> - Payer : - </text> - <icon name="icon_person" tool_tip="Résident"/> - <text name="payee_name"> - Test Name That Is Extremely Long To Check Clipping - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text left="4" name="amount text"> - Ou choisir un montant : - </text> - <line_editor left="60" name="amount" width="55"/> - <button label="Payer" label_selected="Payer" name="pay btn"/> - <button label="Annuler" label_selected="Annuler" name="cancel btn"/> + <string name="payee_group">Payer le groupe</string> + <string name="payee_resident">Payer le résident</string> + <text name="paying_text">Vous payez :</text> + <text name="payee_name">Test Name That Is Extremely Long To Check Clipping</text> + <panel label="Rechercher" name="PatternsPanel"> + <button label="Payer 1 L$" label_selected="Payer 1 L$" name="fastpay 1"/> + <button label="Payer 5 L$" label_selected="Payer 5 L$" name="fastpay 5"/> + <button label="Payer 10 L$" label_selected="Payer 10 L$" name="fastpay 10"/> + <button label="Payer 20 L$" label_selected="Payer 20 L$" name="fastpay 20"/> + </panel> + <panel label="Rechercher" name="InputPanel"> + <text name="amount text">Autre montant :</text> + <button label="Payer" label_selected="Payer" name="pay btn"/> + <button label="Annuler" label_selected="Annuler" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_pay_object.xml b/indra/newview/skins/default/xui/fr/floater_pay_object.xml index 966fa3b8a6..c98d2f7c0c 100755 --- a/indra/newview/skins/default/xui/fr/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/fr/floater_pay_object.xml @@ -1,30 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group" width="95"> - Payer le groupe - </string> - <string halign="left" name="payee_resident" width="100"> - Payer le résident - </string> - <icon name="icon_person" tool_tip="Résident"/> - <text left="105" name="payee_name"> - Ericacita Moostopolison - </text> - <text left="25" name="object_name_label"> - Via un objet : - </text> + <string name="payee_group" width="95">Payer le groupe</string> + <string halign="left" name="payee_resident" width="100">Payer le résident</string> + <text name="paying_text">Vous payez :</text> + <text left="105" name="payee_name">Ericacita Moostopolison</text> + <text left="25" name="object_name_label">Via un objet :</text> <icon name="icon_object" tool_tip="Objets"/> - <text left="105" name="object_name_text"> - ... - </text> - <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> - <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" name="fastpay 10"/> - <button label="20 L$" label_selected="20 L$" name="fastpay 20"/> - <text halign="left" left="5" name="amount text"> - Ou choisir un montant : - </text> - <line_editor left="65" name="amount" width="50"/> - <button label="Payer" label_selected="Payer" name="pay btn"/> - <button label="Annuler" label_selected="Annuler" name="cancel btn"/> + <text left="105" name="object_name_text">...</text> + <panel label="Rechercher" name="PatternsPanel"> + <button label="Payer 1 L$" label_selected="Payer 1 L$" name="fastpay 1"/> + <button label="Payer 5 L$" label_selected="Payer 5 L$" name="fastpay 5"/> + <button label="Payer 10 L$" label_selected="Payer 10 L$" name="fastpay 10"/> + <button label="Payer 20 L$" label_selected="Payer 20 L$" name="fastpay 20"/> + </panel> + <panel label="Rechercher" name="InputPanel"> + <text name="amount text">Autre montant :</text> + <button label="Payer" label_selected="Payer" name="pay btn"/> + <button label="Annuler" label_selected="Annuler" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/fr/menu_attachment_self.xml b/indra/newview/skins/default/xui/fr/menu_attachment_self.xml index f2e7928c24..1ccba08099 100755 --- a/indra/newview/skins/default/xui/fr/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/fr/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Mon apparence" name="Change Outfit"/> <menu_item_call label="Modifier ma tenue" name="Edit Outfit"/> <menu_item_call label="Modifier ma silhouette" name="Edit My Shape"/> + <menu_item_call label="Hauteur de sustentation" name="Hover Height"/> <menu_item_call label="Mes amis" name="Friends..."/> <menu_item_call label="Mes groupes" name="Groups..."/> <menu_item_call label="Mon profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/fr/menu_avatar_self.xml b/indra/newview/skins/default/xui/fr/menu_avatar_self.xml index 4815ad0676..1c768a078c 100755 --- a/indra/newview/skins/default/xui/fr/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/fr/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Mon apparence" name="Chenge Outfit"/> <menu_item_call label="Modifier ma tenue" name="Edit Outfit"/> <menu_item_call label="Modifier ma silhouette" name="Edit My Shape"/> + <menu_item_call label="Hauteur de sustentation" name="Hover Height"/> <menu_item_call label="Mes amis" name="Friends..."/> <menu_item_call label="Mes groupes" name="Groups..."/> <menu_item_call label="Mon profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml index 87b11bdaa5..c0808f1139 100755 --- a/indra/newview/skins/default/xui/fr/menu_inventory.xml +++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Créer une annonce" name="Marketplace Create Listing"/> + <menu_item_call label="Associer l'annonce" name="Marketplace Associate Listing"/> + <menu_item_call label="Obtenir (actualiser) l'annonce" name="Marketplace Get Listing"/> + <menu_item_call label="Consultez les erreurs" name="Marketplace Check Listing"/> + <menu_item_call label="Modifier l'annonce" name="Marketplace Edit Listing"/> + <menu_item_call label="Publier" name="Marketplace List"/> + <menu_item_call label="Ne plus publier" name="Marketplace Unlist"/> + <menu_item_call label="Activer" name="Marketplace Activate"/> + <menu_item_call label="Désactiver" name="Marketplace Deactivate"/> <menu_item_call label="Partager" name="Share"/> <menu_item_call label="Acheter" name="Task Buy"/> <menu_item_call label="Ouvrir" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Ajouter" name="Wearable Add"/> <menu_item_call label="Enlever" name="Take Off"/> <menu_item_call label="Copier vers la boîte d'envoi vendeur" name="Merchant Copy"/> - <menu_item_call label="Envoyer vers la Place du marché" name="Marketplace Send"/> + <menu_item_call label="Copier dans les annonces Place du marché" name="Marketplace Copy"/> + <menu_item_call label="Déplacer dans les annonces Place du marché" name="Marketplace Move"/> <menu_item_call label="--aucune option--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/fr/menu_marketplace_view.xml b/indra/newview/skins/default/xui/fr/menu_marketplace_view.xml new file mode 100644 index 0000000000..a63e2082b7 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Trier par volume de stock (de bas à élevé)" name="sort_by_stock_amount"/> + <menu_item_check label="Afficher uniquement les dossiers d'annonces" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 9a4d721bc3..788cdbf856 100755 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Voler" name="Fly"/> <menu_item_check label="Toujours courir" name="Always Run"/> <menu_item_call label="Arrêter mon animation" name="Stop Animating My Avatar"/> - <menu_item_call label="Marcher / Courir / Voler..." name="Walk / run / fly"/> + <menu_item_call label="Marcher / Courir / Voler..." name="WalkRunFly"/> </menu> <menu label="Statut" name="Status"> <menu_item_check label="Absent" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="Acheter des L$..." name="Buy and Sell L$"/> <menu_item_call label="Boîte d'envoi vendeur..." name="MerchantOutbox"/> + <menu_item_call label="Annonces de Place du marché..." name="MarketplaceListings"/> <menu_item_call label="Page d'accueil du compte..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/> </menu_item_call> @@ -63,7 +64,7 @@ <menu_item_call label="Photo" name="Take Snapshot"/> <menu_item_call label="Profil du lieu" name="Place Profile"/> <menu_item_call label="À propos du terrain" name="About Land"/> - <menu_item_call label="Région/Domaine" name="Region/Estate"/> + <menu_item_call label="Région/Domaine" name="RegionEstate"/> <menu_item_call label="Mes terrains..." name="My Land"/> <menu_item_call label="Acheter ce terrain" name="Buy Land"/> <menu label="Afficher" name="LandShow"> @@ -251,6 +252,7 @@ <menu_item_check label="Console de textures" name="Texture Console"/> <menu_item_check label="Console de débogage" name="Debug Console"/> <menu_item_call label="Console de notifications" name="Notifications"/> + <menu_item_check label="Console de débogage de région" name="Region Debug Console"/> <menu_item_check label="Chronos" name="Fast Timers"/> <menu_item_check label="Mémoire" name="Memory"/> <menu_item_check label="Statistiques de la scène" name="Scene Statistics"/> @@ -354,7 +356,7 @@ <menu_item_check label="Interpolation ping des positions des objets" name="Ping Interpolate Object Positions"/> <menu_item_call label="Abandonner un paquet" name="Drop a Packet"/> </menu> - <menu_item_call label="Dump caméra scriptée" name="Dump Scripted Camera"/> + <menu_item_call label="Dump caméra scriptée" name="Dump Scripted Camera"/> <menu label="Enregistreur" name="Recorder"> <menu_item_call label="Commencer la lecture" name="Start Playback"/> <menu_item_call label="Arrêter la lecture" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 28689a93d6..29e6fe1979 100755 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -129,6 +129,88 @@ Aucun dossier n'a été envoyé vers la Place du marché en raison d'u L'initialisation de la Place du marché a échoué en raison d'une erreur système ou réseau. Réessayez ultérieurement. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Échec de la copie ou du déplacement vers le dossier de stock. Erreur : + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Échec de la copie ou du déplacement vers les annonces Place du marché. Erreur : + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + La transaction avec la Place du marché a échoué en raison de l'erreur suivante : + + Motif : '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Nous ne pouvons pas publier ce produit ni activer le dossier de version. Cela est en général dû à des informations manquantes dans le formulaire de description de l'annonce, mais parfois à cause d'erreurs dans la structure du dossier. Modifiez l'annonce ou consultez les erreurs du dossier de l'annonce. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Échec de la publication d'une annonce sur la Place du marché. Erreur : + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Échec de l'activation de ce dossier de version. Erreur : + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Cette action va modifier le contenu actif de cette annonce. Voulez-vous continuer ? + <usetemplate ignoretext="Confirmer avant que je ne modifie une annonce active sur la Place du marché" name="okcancelignore" notext="Annuler" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Les articles glissés vers la fenêtre Annonces de la Place du marché sont déplacés de leur emplacement d'origine, et non copiés. Voulez-vous continuer ? + <usetemplate ignoretext="Confirmer avant que je ne déplace un article de l'inventaire vers la Place du marché" name="okcancelignore" notext="Annuler" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Le déplacement ou la suppression d'un dossier d'annonces supprimera votre annonce de la Place du marché. Si vous souhaitez conserver l'annonce de la Place du marché, déplacez ou supprimez le contenu du dossier de version que vous souhaitez modifier. Voulez-vous continuer ? + <usetemplate ignoretext="Confirmer avant que je déplace ou supprime une annonce de la Place du marché" name="okcancelignore" notext="Annuler" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Vous n'êtes pas autorisé à copier un ou plusieurs de ces articles vers la Place du marché. Vous pouvez les déplacer ou les laisser. + <usetemplate canceltext="Annuler" ignoretext="Confirmer avant que je ne copie une sélection contenant des articles non reproductibles vers la Place du marché" name="yesnocancelbuttons" notext="Ne pas déplacer les articles" yestext="Déplacer les articles"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Cette action va annuler cette annonce. Voulez-vous continuer ? + <usetemplate ignoretext="Confirmer avant que j'annule une annonce active sur la Place du marché" name="okcancelignore" notext="Annuler" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Cette action va désactiver le dossier de version de l'annonce active. Voulez-vous continuer ? + <usetemplate ignoretext="Confirmer avant que je ne désactive le dossier de version d'une annonce de la Place du marché" name="okcancelignore" notext="Annuler" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Impossible de mettre à jour cette annonce. +[[URL] Cliquez ici] pour la modifier sur la Place du marché. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Vous ne pouvez pas porter de vêtements ou des parties du corps se trouvant dans le dossier Annonces de la Place du marché. + </notification> + <notification name="AlertMerchantListingInvalidID"> + ID d'annonce non valide. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Il y a plusieurs dossiers de version (ou aucun) dans cette liste. Vous devrez en sélectionner et activer un indépendamment plus tard. + <usetemplate ignoretext="Alerter en cas d'activation du dossier de version lorsque je crée une annonce avec plusieurs dossiers de version" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Nous avons classé les articles du stock de types différents dans des dossiers de stocks distincts ; votre dossier est organisé de telle façon que nous pouvons le répertorier. + <usetemplate ignoretext="Alerter lorsque le dossier de stock est divisé avant publication" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Nous avons retiré votre annonce car le stock est vide. Vous devez ajouter plus d'unités au dossier de stock pour publier à nouveau l'annonce. + <usetemplate ignoretext="Alerter lorsqu'une annonce n'est pas publiée parce que le dossier de stock est vide" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> Une erreur est survenue lors du chargement du texte pour un script, suite au problème suivant : [REASON]. Veuillez réessayer ultérieurement. </notification> @@ -472,6 +554,10 @@ Remarque : cela videra le cache. Enregistrer les changements ? <usetemplate canceltext="Annuler" name="yesnocancelbuttons" notext="Ne pas enregistrer" yestext="Enregistrer"/> </notification> + <notification name="DeleteNotecard"> + Supprimer la note ? + <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> L'enregistrement du geste a échoué. Il y a trop d'étapes dans ce geste. @@ -1867,6 +1953,9 @@ Cette action modifiera des milliers de régions et sera difficile à digérer po La région que vous essayez de visiter comporte du contenu dont le niveau dépasse celui de vos préférences actuelles. Vous pouvez modifier vos préférences en accédant à Moi > Préférences > Général. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> La région que vous essayez de visiter comporte du contenu [REGIONMATURITY] uniquement accessible aux adultes. <url name="url"> @@ -2155,6 +2244,10 @@ Déplacer les objets de l'inventaire ? <ignore name="ignore" text="Je définis l'action du clic Payer l'objet lorsque je construis un objet sans le script money()"/> </form> </notification> + <notification name="PayConfirmation"> + Confirmez que vous voulez payer [AMOUNT] L$ à [TARGET]. + <usetemplate ignoretext="Confirmez avant de payer (sommes supérieures à 200 L$)" name="okcancelignore" notext="Annuler" yestext="Payer"/> + </notification> <notification name="OpenObjectCannotCopy"> Vous n'êtes autorisé à copier aucun élément dans cet objet. </notification> @@ -2695,9 +2788,6 @@ Veuillez réessayer dans quelques minutes. <notification name="NoValidCircuit"> Aucun code de circuit valide. </notification> - <notification name="NoValidTimestamp"> - Timestamp non valide. - </notification> <notification name="NoPendingConnection"> Impossible de créer la connexion en attente. </notification> @@ -3841,9 +3931,11 @@ Veuillez réessayer dans une minute. </notification> <notification name="TeleportedByAttachment"> Vous avez été téléporté par un élément sur [ITEM_ID] + <usetemplate ignoretext="Téléportation : vous avez été téléporté par un attachement." name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Vous avez été téléporté par l'objet [OBJECT_NAME] sur la parcelle [PARCEL_NAME]. + <usetemplate ignoretext="Téléportation : vous avez été téléporté par un objet sur une parcelle" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Vous avez été téléporté par l'objet [OBJECT_NAME] appartenant à [OWNER_ID]. @@ -4175,7 +4267,7 @@ Veuillez sélectionner un terrain plus petit. <usetemplate ignoretext="Impossible de déplacer les fichiers. Chemin précédent rétabli." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Une erreur est survenue lors de l'enregistrement des droits par défaut, suite au problème suivant : [REASON]. Réessayez de définir les droits par défaut ultérieurement. + Problème lors de l'enregistrement des droits d'objet par défaut : [REASON]. Réessayez de définir les droits par défaut ultérieurement. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/fr/panel_login.xml b/indra/newview/skins/default/xui/fr/panel_login.xml index b39920fe13..2b8249c8a9 100755 --- a/indra/newview/skins/default/xui/fr/panel_login.xml +++ b/indra/newview/skins/default/xui/fr/panel_login.xml @@ -1,27 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=fr - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=fr</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Nom d'utilisateur" name="username_combo" tool_tip="Nom d'utilisateur que vous avez choisi lors de votre inscription (par exemple, bobsmith12 ou Steller Sunshine)."/> <line_editor label="Mot de passe" name="password_edit"/> - <check_box label="Mémoriser mes informations" name="remember_check"/> - <text name="forgot_password_text"> - Mot de passe oublié - </text> - <button label="Connexion" name="connect_btn"/> - <text name="At_My_Last_Location_Label" font="SansSerifSmall" width="140"> - au dernier emplacement - </text> <combo_box label="Mes lieux préférés" name="start_location_combo"> + <combo_box.item label="Dernier emplacement" name="MyLastLocation"/> <combo_box.item label="Domicile" name="MyHome"/> </combo_box> - <button label="Connexion" name="connect_favorite_btn"/> - <line_editor label="Tapez un emplacement" name="location_edit"/> - <button label="Connexion" name="connect_location_btn"/> - <combo_box label="Sélectionner la grille" name="server_combo"/> + <button label="Connexion" name="connect_btn"/> + <check_box label="Mémoriser mes informations" name="remember_check"/> + <text name="forgot_password_text">Mot de passe oublié</text> + <combo_box label="Sélectionner la grille" name="server_combo" left_pad="20"/> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/fr/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/fr/panel_marketplace_listings.xml new file mode 100644 index 0000000000..46578182da --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Place du marché" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Options d'affichage/de tri"/> + <button name="add_btn" tool_tip="Créer un nouveau dossier d'annonces"/> + <button label="Consulter les erreurs" name="audit_btn" tool_tip="Consulter vos annonces de Place du marché"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Filtrer les annonces de Place du marché" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..fdee447a29 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="TOUT" name="All Items" tool_tip="Faire glisser les objets et les déposer ici pour les publier"/> diff --git a/indra/newview/skins/default/xui/fr/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..d3d476af6e --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="PUBLIÉS" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..95018e339f --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="DÉSASSOCIÉE" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..5d811af914 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NON PUBLIÉS" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml index 067fa091d8..067fa091d8 100755..100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml index ba36a7d299..e2f05a525e 100755 --- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Perte de paquets - </panel.string> - <panel.string name="bandwidth_tooltip"> - Bande passante - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - [AMT] L$ - </panel.string> + <panel.string name="packet_loss_tooltip">Perte de paquets</panel.string> + <panel.string name="bandwidth_tooltip">Bande passante</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">[AMT] L$</panel.string> <panel left="-405" name="balance_bg" width="195"> - <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/> + <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="L$ ??"/> <button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/> <button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/> </panel> - <text name="TimeText" tool_tip="Heure actuelle (Pacifique)"> - 00h00 PST - </text> + <text name="TimeText" tool_tip="Heure actuelle (Pacifique)">00h00 PST</text> <button name="media_toggle_btn" tool_tip="Arrêter tous les médias (musique, vidéo, pages web)."/> <button name="volume_btn" tool_tip="Régler le volume global."/> </panel> diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml index 502dc919b1..ede5ec08af 100755 --- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Transférer" name="CheckNextOwnerTransfer" tool_tip="Le prochain propriétaire peut donner ou revendre cet objet."/> </panel> <check_box label="À vendre" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Copier" name="Copy"/> + <combo_box.item label="Contenu" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Prix : L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml index 896dd932e3..f6b4f28046 100755 --- a/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Profil de l'objet"> - <panel.string name="text deed continued"> - Céder - </panel.string> - <panel.string name="text deed"> - Céder - </panel.string> - <panel.string name="text modify info 1"> - Vous pouvez modifier cet objet - </panel.string> - <panel.string name="text modify info 2"> - Vous pouvez modifier ces objets - </panel.string> - <panel.string name="text modify info 3"> - Vous ne pouvez pas modifier cet objet - </panel.string> - <panel.string name="text modify info 4"> - Vous ne pouvez pas modifier ces objets - </panel.string> - <panel.string name="text modify info 5"> - Impossible de modifier cet objet au-delà de la frontière d'une région - </panel.string> - <panel.string name="text modify info 6"> - Impossible de modifier ces objets au-delà de la frontière d'une région - </panel.string> - <panel.string name="text modify warning"> - Cet objet comprend des parties liées - </panel.string> - <panel.string name="Cost Default"> - Prix : L$ - </panel.string> - <panel.string name="Cost Total"> - Prix total : L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Prix par : L$ - </panel.string> - <panel.string name="Cost Mixed"> - Prix mixte - </panel.string> - <panel.string name="Sale Mixed"> - Vente mixte - </panel.string> + <panel.string name="text deed continued">Céder</panel.string> + <panel.string name="text deed">Céder</panel.string> + <panel.string name="text modify info 1">Vous pouvez modifier cet objet</panel.string> + <panel.string name="text modify info 2">Vous pouvez modifier ces objets</panel.string> + <panel.string name="text modify info 3">Vous ne pouvez pas modifier cet objet</panel.string> + <panel.string name="text modify info 4">Vous ne pouvez pas modifier ces objets</panel.string> + <panel.string name="text modify info 5">Impossible de modifier cet objet au-delà de la frontière d'une région</panel.string> + <panel.string name="text modify info 6">Impossible de modifier ces objets au-delà de la frontière d'une région</panel.string> + <panel.string name="text modify warning">Cet objet comprend des parties liées</panel.string> + <panel.string name="Cost Default">Prix : L$</panel.string> + <panel.string name="Cost Total">Prix total : L$</panel.string> + <panel.string name="Cost Per Unit">Prix par : L$</panel.string> + <panel.string name="Cost Mixed">Prix mixte</panel.string> + <panel.string name="Sale Mixed">Vente mixte</panel.string> <text name="title" value="Profil de l'objet"/> <text name="where" value="(dans Second Life)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Nom : - </text> - <text name="Description:"> - Description : - </text> - <text name="CreatorNameLabel"> - Créateur : - </text> - <text name="Owner:"> - Propriétaire : - </text> - <text name="Group_label"> - Groupe : - </text> + <text name="Name:">Nom :</text> + <text name="Description:">Description :</text> + <text name="CreatorNameLabel">Créateur :</text> + <text name="Owner:">Propriétaire :</text> + <text name="Group_label">Groupe :</text> <button name="button set group" tool_tip="Choisir un groupe pour partager les droits relatifs à cet objet"/> <name_box initial_value="Chargement…" name="Group Name Proxy"/> <button label="Céder" label_selected="Céder" name="button deed" tool_tip="En cédant un objet, vous donnez aussi les droits au prochain propriétaire. Seul un officier peut céder les objets partagés d'un groupe."/> - <text name="label click action"> - Cliquer pour : - </text> + <text name="label click action">Cliquer pour :</text> <combo_box name="clickaction"> <combo_box.item label="Toucher (défaut)" name="Touch/grab(default)"/> <combo_box.item label="S'asseoir sur l'objet" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Zoom" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Vous pouvez modifier cet objet - </text> - <text name="Anyone can:"> - N'importe qui : - </text> + <text name="perm_modify">Vous pouvez modifier cet objet</text> + <text name="Anyone can:">N'importe qui :</text> <check_box label="Copier" name="checkbox allow everyone copy"/> <check_box label="Bouger" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Groupe : - </text> + <text name="GroupLabel">Groupe :</text> <check_box label="Partager" name="checkbox share with group" tool_tip="Autoriser tous les membres du groupe choisi à partager vos droits de modification pour cet objet. Pour activer les restrictions de rôles, vous devez d'abord cliquer sur Céder."/> - <text name="NextOwnerLabel"> - Le prochain propriétaire : - </text> + <text name="NextOwnerLabel">Le prochain propriétaire :</text> <check_box label="Modifier" name="checkbox next owner can modify"/> <check_box label="Copier" name="checkbox next owner can copy"/> <check_box label="Transférer" name="checkbox next owner can transfer" tool_tip="Le prochain propriétaire peut donner ou revendre cet objet"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Prix : L$" name="Edit Cost"/> <check_box label="Afficher avec la recherche" name="search_check" tool_tip="Permettre aux autres résidents de voir cet objet dans les résultats de recherche"/> - <text name="pathfinding_attributes_label"> - Attributs de recherche de chemin : - </text> - <text name="B:"> - B : - </text> - <text name="O:"> - O : - </text> - <text name="G:"> - G : - </text> - <text name="E:"> - E : - </text> - <text name="N:"> - N : - </text> - <text name="F:"> - F : - </text> + <text name="pathfinding_attributes_label">Attributs de recherche de chemin :</text> + <text name="B:">B :</text> + <text name="O:">O :</text> + <text name="G:">G :</text> + <text name="E:">E :</text> + <text name="N:">N :</text> + <text name="F:">F :</text> </panel> <panel name="button_panel"> <button label="Ouvrir" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 8df13b2661..e462b805e3 100755 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -454,28 +454,46 @@ Veuillez réessayer de vous connecter dans une minute. </string> <string name="TooltipPrice" value="[AMOUNT] L$ :"/> <string name="TooltipOutboxDragToWorld"> - Impossible de rezzer des articles dans la boîte d'envoi vendeur + Vous ne pouvez pas rezzer (charger) des articles du dossier Annonces de la Place de marché + </string> + <string name="TooltipOutboxWorn"> + Vous ne pouvez pas mettre d'articles que vous portez dans le dossier Annonces de la Place du marché + </string> + <string name="TooltipOutboxFolderLevels"> + Le niveau de dossiers imbriqués dépasse [AMOUNT]. Diminuez le nombre de niveaux de dossiers imbriqués dans d'autres dossiers. Si nécessaire, placez certains articles dans une boîte. + </string> + <string name="TooltipOutboxTooManyFolders"> + Le nombre de sous-dossiers dépasse [AMOUNT]. Diminuez le nombre de sous-dossiers dans votre annonce. Si nécessaire, placez certains articles dans une boîte. + </string> + <string name="TooltipOutboxTooManyObjects"> + Le nombre d'articles dépasse [AMOUNT]. Pour pouvoir vendre plus de [AMOUNT] articles au sein d'une même annonce, vous devez placer certains de ces articles dans une boîte. + </string> + <string name="TooltipOutboxTooManyStockItems"> + Le nombre d'articles de stock dépasse [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Vous ne pouvez déposer des articles ou des dossiers que dans l'onglet TOUT. Veuillez activer cet onglet et déplacer à nouveau article(s) et dossier(s). </string> <string name="TooltipOutboxNoTransfer"> - Impossible de vendre ou de transférer un ou plusieurs de ces objets. + Impossible de vendre ou de transférer un ou plusieurs de ces objets </string> <string name="TooltipOutboxNotInInventory"> - La boîte d'envoi vendeur n'accepte que les articles directement issus de votre inventaire. + Vous ne pouvez mettre sur la Place du marché que des articles de votre inventaire </string> - <string name="TooltipOutboxWorn"> - Impossible de placer des articles que vous portez dans votre boîte d'envoi vendeur + <string name="TooltipOutboxLinked"> + Vous ne pouvez pas mettre des articles ou dossiers liés sur la Place du marché </string> <string name="TooltipOutboxCallingCard"> - Impossible de placer des cartes de visite dans votre boîte d'envoi vendeur + Vous ne pouvez pas mettre des cartes de visite sur la Place du marché </string> - <string name="TooltipOutboxFolderLevels"> - Il existe plus de 3 niveaux de dossiers imbriqués. + <string name="TooltipOutboxDragActive"> + vous ne pouvez pas déplacer une annonce publiée </string> - <string name="TooltipOutboxTooManyFolders"> - Le dossier de niveau supérieur contient plus de 20 sous-dossiers. + <string name="TooltipOutboxCannotMoveRoot"> + Vous ne pouvez pas déplacer le dossier racine des annonces de la Place du marché </string> - <string name="TooltipOutboxTooManyObjects"> - Le dossier de niveau supérieur contient plus de 200 articles. + <string name="TooltipOutboxMixedStock"> + tous les articles d'un dossier de stock doivent avoir le même type et droit </string> <string name="TooltipDragOntoOwnChild"> Impossible de déplacer un dossier vers son enfant @@ -1063,7 +1081,7 @@ Veuillez réessayer de vous connecter dans une minute. <string name="AgentNameSubst"> (Vous) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Supprimer les alertes lors de la gestion des listes d'accès aux domaines </string> @@ -1130,6 +1148,12 @@ Veuillez réessayer de vous connecter dans une minute. <string name="bitmap_image_files"> Images Bitmap </string> + <string name="png_image_files"> + Images PNG + </string> + <string name="save_texture_image_files"> + Images Targa ou PNG + </string> <string name="avi_movie_file"> Fichier de film AVI </string> @@ -1379,6 +1403,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="FavoritesNoMatchingItems"> Faites glisser un repère ici pour l'ajouter à vos Favoris. </string> + <string name="MarketplaceNoMatchingItems"> + Aucun article trouvé. Vérifiez l'orthographe de votre chaîne de recherche et réessayez. + </string> <string name="InventoryNoTexture"> Vous n'avez pas de copie de cette texture dans votre inventaire </string> @@ -1426,29 +1453,95 @@ Veuillez réessayer de vous connecter dans une minute. <string name="InventoryOutboxError"> La [[MARKETPLACE_CREATE_STORE_URL] boutique de la Place du marché] renvoie des erreurs. </string> + <string name="InventoryMarketplaceError"> + Cette fonctionnalité est en version bêta. Veuillez ajouter votre nom à ce [http://goo.gl/forms/FCQ7UXkakz formulaire Google] si vous souhaitez participer. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Votre dossier Annonces de la Place du marché est vide. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Pour mettre des dossiers en vente sur la [[MARKETPLACE_DASHBOARD_URL] Place du marché], faites-les glisser vers cette zone. + </string> + <string name="Marketplace Validation Warning Stock"> + le dossier de stock doit être contenu dans un dossier de version + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Erreur : tous les articles d'un dossier de stock doivent être non reproductibles et de même type + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Erreur : un dossier de stock ne peut pas contenir de sous-dossiers + </string> + <string name="Marketplace Validation Warning Empty"> + : Avertissement : le dossier ne contient aucun article + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Avertissement : création du dossier de stock + </string> + <string name="Marketplace Validation Warning Create Version"> + : Avertissement : création du dossier de version + </string> + <string name="Marketplace Validation Warning Move"> + : Avertissement : déplacement d'articles + </string> + <string name="Marketplace Validation Warning Delete"> + : Avertissement : contenu du dossier transféré vers le dossier de stock, suppression du dossier vide + </string> + <string name="Marketplace Validation Error Stock Item"> + : Erreur : les articles non reproductibles doivent être contenus dans un dossier de stock + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Avertissement : les articles doivent être contenus dans un dossier de version + </string> + <string name="Marketplace Validation Error"> + : Erreur : + </string> + <string name="Marketplace Validation Warning"> + : Avertissement : + </string> + <string name="Marketplace Validation Error Empty Version"> + : Avertissement : le dossier de version doit contenir au moins 1 article + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Avertissement : le dossier de stock doit contenir au moins 1 article + </string> + <string name="Marketplace Validation No Error"> + Pas d'erreur ni d'avertissement à signaler + </string> <string name="Marketplace Error None"> Aucune erreur </string> + <string name="Marketplace Error Prefix"> + Erreur : + </string> <string name="Marketplace Error Not Merchant"> - Erreur : avant d'envoyer des articles vers la Place du marché, vous devez vous configurer comme vendeur (gratuit). + Avant d'envoyer des articles vers la Place du marché, vous devez vous configurer comme vendeur (gratuit). + </string> + <string name="Marketplace Error Not Accepted"> + Impossible de déplacer l'article dans ce dossier. </string> - <string name="Marketplace Error Empty Folder"> - Erreur : ce dossier est vide. + <string name="Marketplace Error Unsellable Item"> + Cet article ne peut pas être vendu sur la Place du marché. </string> - <string name="Marketplace Error Unassociated Products"> - Erreur : le chargement de cet article a échoué en raison d'un nombre trop important d'articles non associés à des produits au niveau de votre compte de vendeur. Pour résoudre ce problème, connectez-vous au site Web de la Place du marché et réduisez le nombre d'articles non associés. + <string name="MarketplaceNoID"> + no Mkt ID </string> - <string name="Marketplace Error Object Limit"> - Erreur : cet article contient trop d'objets. Pour résoudre le problème, regroupez des objets dans des paquets afin de réduire le nombre total à moins de 200. + <string name="MarketplaceLive"> + publié </string> - <string name="Marketplace Error Folder Depth"> - Erreur : trop de niveaux de dossiers imbriqués concernant cet article. Réorganisez le tout afin qu'un maximum de 3 niveaux soit utilisé. + <string name="MarketplaceActive"> + actif </string> - <string name="Marketplace Error Unsellable Item"> - Erreur : cet article ne peut pas être vendu sur la Place du marché. + <string name="MarketplaceMax"> + max. </string> - <string name="Marketplace Error Internal Import"> - Erreur : un problème est survenu concernant cet article. Veuillez réessayer ultérieurement. + <string name="MarketplaceStock"> + stock + </string> + <string name="MarketplaceNoStock"> + rupture de stock + </string> + <string name="MarketplaceUpdating"> + mise à jour... </string> <string name="Open landmarks"> Ouvrir les repères @@ -1469,6 +1562,7 @@ Veuillez réessayer de vous connecter dans une minute. Aucun contenu </string> <string name="WornOnAttachmentPoint" value=" (porté sur [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (actif)"/> <string name="PermYes"> Oui @@ -1739,6 +1833,15 @@ Veuillez réessayer de vous connecter dans une minute. <string name="Invalid Attachment"> Point d'attache non valide </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Erreur : article manquant + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Erreur : article de base manquant + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Erreur : l'objet est dans une tenue actuelle, mais il n'est pas attaché + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] </string> @@ -1874,9 +1977,6 @@ Veuillez réessayer de vous connecter dans une minute. <string name="CompileQueueUnknownFailure"> Échec du téléchargement, erreur inconnue </string> - <string name="CompileNoExperiencePerm"> - En train d'ignorer le script [SCRIPT] avec l'expérience [EXPERIENCE]. - </string> <string name="CompileQueueTitle"> Recompilation - progrès </string> @@ -1910,6 +2010,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="SaveComplete"> Enregistrement terminé. </string> + <string name="UploadFailed"> + Échec du chargement de fichier : + </string> <string name="ObjectOutOfRange"> Script (objet hors de portée) </string> @@ -1919,6 +2022,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="GroupsNone"> aucun </string> + <string name="CompileNoExperiencePerm"> + En train d'ignorer le script [SCRIPT] avec l'expérience [EXPERIENCE]. + </string> <string name="Group" value=" (groupe)"/> <string name="Unknown"> (Inconnu) @@ -5070,6 +5176,9 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="Command_Marketplace_Label"> Place du marché </string> + <string name="Command_MarketplaceListings_Label"> + Place du marché + </string> <string name="Command_MiniMap_Label"> Mini-carte </string> @@ -5157,6 +5266,9 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="Command_Marketplace_Tooltip"> Faire du shopping </string> + <string name="Command_MarketplaceListings_Tooltip"> + Vendez votre création + </string> <string name="Command_MiniMap_Tooltip"> Afficher les personnes près de vous </string> @@ -5268,6 +5380,18 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="UserDictionary"> [User] </string> + <string name="logging_calls_disabled_log_empty"> + Les conversations ne sont pas archivées. Pour commencer à tenir un journal, choisissez Enregistrer : Journal seul ou Enregistrer : Journal et transcriptions sous Préférences > Chat. + </string> + <string name="logging_calls_disabled_log_not_empty"> + Aucune conversation ne sera plus enregistrée. Pour recommencer à tenir un journal, choisissez Enregistrer : Journal seul ou Enregistrer : Journal et transcriptions sous Préférences > Chat. + </string> + <string name="logging_calls_enabled_log_empty"> + Il n'y a aucune conversation enregistrée. Quand quelqu'un vous contacte ou quand vous contactez quelqu'un, une entrée de journal s'affiche ici. + </string> + <string name="loading_chat_logs"> + Chargement... + </string> <string name="experience_tools_experience"> Expérience </string> @@ -5349,16 +5473,4 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="ExperiencePermissionShort12"> Permission </string> - <string name="logging_calls_disabled_log_empty"> - Les conversations ne sont pas archivées. Pour commencer à tenir un journal, choisissez Enregistrer : Journal seul ou Enregistrer : Journal et transcriptions sous Préférences > Chat. - </string> - <string name="logging_calls_disabled_log_not_empty"> - Aucune conversation ne sera plus enregistrée. Pour recommencer à tenir un journal, choisissez Enregistrer : Journal seul ou Enregistrer : Journal et transcriptions sous Préférences > Chat. - </string> - <string name="logging_calls_enabled_log_empty"> - Il n'y a aucune conversation enregistrée. Quand quelqu'un vous contacte ou quand vous contactez quelqu'un, une entrée de journal s'affiche ici. - </string> - <string name="loading_chat_logs"> - Chargement... - </string> </strings> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 6f09eca90c..f3b7effdaa 100755 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -1,82 +1,24 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="INFO [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - Generato con [COMPILER] versione [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Tu sei a [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL: <nolink>[SLURL]</nolink> -(coordinate globali [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -Memoria: [MEMORY_MB] MB -Versione sistema operativo: [OS_VERSION] -Venditore scheda grafica: [GRAPHICS_CARD_VENDOR] -Scheda grafica: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Versione driver Windows per grafica: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - Versione OpenGL: [OPENGL_VERSION] - -Versione libcurl: [LIBCURL_VERSION] -Versione J2C Decoder: [J2C_VERSION] -Versione Driver audio: [AUDIO_DRIVER_VERSION] -Versione Qt Webkit: [QT_WEBKIT_VERSION] -Versione Server voice: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (nessuno) - </floater.string> - <floater.string name="AboutTraffic"> - Pacchetti perduti: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) Informazioni - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Errore nel recupero URL note rilascio versione - </floater.string> <tab_container name="about_tab"> <panel label="Informazioni" name="support_panel"> <button label="Copia negli appunti" name="copy_btn"/> </panel> <panel label="Ringraziamenti" name="credits_panel"> - <text name="linden_intro"> - Second Life vi è offerto dai Linden: - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - con contributi open source da: - </text> - <text_editor name="contrib_names"> - Dummy Name sostituito all'avvio - </text_editor> - <text name="trans_intro"> - e le traduzioni da: - </text> - <text_editor name="trans_names"> - Dummy Name sostituito all'avvio - </text_editor> + <text name="linden_intro">Second Life vi è offerto dai Linden, +con contributi open source da:</text> + <text_editor name="contrib_names">Dummy Name sostituito all'avvio</text_editor> </panel> <panel label="Licenze" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. + FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm e Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. + GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University e David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) @@ -87,7 +29,7 @@ Versione Server voice: [VOICE_VERSION] SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. + zlib Copyright (C) 1995-2012 Jean-loup Gailly e Mark Adler. Il Viewer Second Life utilizza Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (e licenziatari). Tutti i diritti riservati. Per informazioni dettagliate, vedere www.havok.com. @@ -95,8 +37,7 @@ Versione Server voice: [VOICE_VERSION] Tutti i diritti riservati. Per informazioni dettagliate, vedere licenses.txt. - Codifica audio chat vocale: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Codifica audio chat vocale: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_associate_listing.xml b/indra/newview/skins/default/xui/it/floater_associate_listing.xml new file mode 100644 index 0000000000..2d7e1f9d3b --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="ASSOCIA ANNUNCIO"> + <text name="message">ID annuncio:</text> + <line_editor name="listing_id">Digita qui l'ID</line_editor> + <button label="OK" name="OK"/> + <button label="Annulla" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/it/floater_edit_hover_height.xml new file mode 100644 index 0000000000..a395b247ed --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="IMPOSTA ALTEZZA DI VOLO"> + <slider label="Altezza" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml index 7ed3486b9b..8cf680b3f0 100755 --- a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="CARATTERISTICHE DELL'ARTICOLO IN INVENTARIO"> - <floater.string name="unknown"> - (sconosciuto) - </floater.string> - <floater.string name="public"> - (pubblico) - </floater.string> - <floater.string name="you_can"> - Tu puoi: - </floater.string> - <floater.string name="owner_can"> - Il proprietario può: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Nome: - </text> - <text name="LabelItemDescTitle"> - Descrizione: - </text> - <text name="LabelCreatorTitle"> - Creatore: - </text> + <floater.string name="unknown">(sconosciuto)</floater.string> + <floater.string name="public">(pubblico)</floater.string> + <floater.string name="you_can">Tu puoi:</floater.string> + <floater.string name="owner_can">Il proprietario può:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Nome:</text> + <text name="LabelItemDescTitle">Descrizione:</text> + <text name="LabelCreatorTitle">Creatore:</text> <button label="Profilo..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - proprietario: - </text> + <text name="LabelOwnerTitle">proprietario:</text> <button label="Profilo..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Acquisito: - </text> - <text name="LabelAcquiredDate"> - Wed May 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Tu: - </text> + <text name="LabelAcquiredTitle">Acquisito:</text> + <text name="LabelAcquiredDate">Wed May 24 12:50:46 2006</text> + <text name="OwnerLabel">Tu:</text> <check_box label="Modifica" name="CheckOwnerModify"/> <check_box label="Copiare" left_delta="88" name="CheckOwnerCopy"/> <check_box label="Rivendi" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Chiunque: - </text> + <text name="AnyoneLabel">Chiunque:</text> <check_box label="Copia" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Gruppo: - </text> + <text name="GroupLabel">Gruppo:</text> <check_box label="Condividi" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="230"> - Proprietario successivo: - </text> + <text name="NextOwnerLabel" width="230">Proprietario successivo:</text> <check_box label="Modifica" name="CheckNextOwnerModify"/> <check_box label="Copiare" left_delta="88" name="CheckNextOwnerCopy"/> <check_box label="Rivendi" name="CheckNextOwnerTransfer"/> <check_box label="In vendita" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Copia" name="Copy"/> + <combo_box.item label="Contenuti" name="Contents"/> <combo_box.item label="Originale" name="Original"/> </combo_box> <spinner label="Prezzo:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_item_properties.xml b/indra/newview/skins/default/xui/it/floater_item_properties.xml new file mode 100644 index 0000000000..ba57e27b45 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="CARATTERISTICHE DELL'ARTICOLO"/> diff --git a/indra/newview/skins/default/xui/it/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/it/floater_marketplace_listings.xml new file mode 100644 index 0000000000..bff5189ea4 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="ANNUNCI NEL MARKETPLACE"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Caricamento in corso...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/it/floater_marketplace_validation.xml new file mode 100644 index 0000000000..45805a3232 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Verifica annunci Marketplace"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_openobject.xml b/indra/newview/skins/default/xui/it/floater_openobject.xml index 9b04c230c8..0d313602b5 100755 --- a/indra/newview/skins/default/xui/it/floater_openobject.xml +++ b/indra/newview/skins/default/xui/it/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Copia nell'Inventario" label_selected="Copia nell'Inventario" name="copy_to_inventory_button"/> - <button label="Copia e aggiungi al vestiario" label_selected="Copia e aggiungi al vestiario" name="copy_and_wear_button"/> + <text name="border_note"> + Copia nell'inventario e indossa + </text> + <button label="Aggiungi al vestiario" label_selected="Aggiungi al vestiario" name="copy_and_wear_button"/> + <button label="Sostituisci vestiario" label_selected="Sostituisci vestiario" name="copy_and_replace_button"/> + <button label="Crea solo la copia nell'inventario" label_selected="Crea solo la copia nell'inventario" name="copy_to_inventory_button"/> + <button label="Annulla" label_selected="Annulla" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_pay.xml b/indra/newview/skins/default/xui/it/floater_pay.xml index 5753c8c765..ef24fc850d 100755 --- a/indra/newview/skins/default/xui/it/floater_pay.xml +++ b/indra/newview/skins/default/xui/it/floater_pay.xml @@ -1,26 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - Paga gruppo - </string> - <string name="payee_resident"> - Paga residente - </string> - <text left="5" name="payee_label" width="105"> - Paga: - </text> - <icon name="icon_person" tool_tip="Persona"/> - <text left="115" name="payee_name"> - Nome di test che è troppo lungo per controllare il taglio - </text> - <button label="1 L$" label_selected="1 L$" left="118" name="fastpay 1" width="80"/> - <button label="5 L$" label_selected="5 L$" left="210" name="fastpay 5"/> - <button label="10 L$" label_selected="10 L$" left="118" name="fastpay 10" width="80"/> - <button label="20 L$" label_selected="20 L$" left="210" name="fastpay 20"/> - <text left="4" name="amount text"> - Oppure, scegli importo: - </text> - <line_editor left="70" name="amount" width="49"/> - <button label="Paga" label_selected="Paga" left="127" name="pay btn"/> - <button label="Annulla" label_selected="Annulla" left="210" name="cancel btn"/> + <string name="payee_group">Paga gruppo</string> + <string name="payee_resident">Paga residente</string> + <text name="paying_text">Stai pagando:</text> + <text left="115" name="payee_name">Nome di test che è troppo lungo per controllare il taglio</text> + <panel label="Cerca" name="PatternsPanel"> + <button label="Paga 1 L$" label_selected="Paga 1 L$" name="fastpay 1"/> + <button label="Paga 5 L$" label_selected="Paga 5 L$" name="fastpay 5"/> + <button label="Paga 10 L$" label_selected="Paga 10 L$" name="fastpay 10"/> + <button label="Paga 20 L$" label_selected="Paga 20 L$" name="fastpay 20"/> + </panel> + <panel label="Cerca" name="InputPanel"> + <text name="amount text">Altro importo:</text> + <button label="Paga" label_selected="Paga" name="pay btn"/> + <button label="Annulla" label_selected="Annulla" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_pay_object.xml b/indra/newview/skins/default/xui/it/floater_pay_object.xml index 8805f3208e..8e6fd37c2d 100755 --- a/indra/newview/skins/default/xui/it/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/it/floater_pay_object.xml @@ -1,30 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string halign="left" name="payee_group" width="100"> - Paga gruppo - </string> - <string halign="left" name="payee_resident" width="120"> - Paga residente - </string> - <icon name="icon_person" tool_tip="Persona"/> - <text left="120" name="payee_name"> - Ericacita Moostopolison - </text> - <text halign="left" left="5" name="object_name_label" width="110"> - Mediante l'oggetto: - </text> + <string halign="left" name="payee_group" width="100">Paga gruppo</string> + <string halign="left" name="payee_resident" width="120">Paga residente</string> + <text name="paying_text">Stai pagando:</text> + <text left="120" name="payee_name">Ericacita Moostopolison</text> + <text halign="left" left="5" name="object_name_label" width="110">Mediante l'oggetto:</text> <icon name="icon_object" tool_tip="Oggetti"/> - <text left="120" name="object_name_text"> - Il mio oggetto con un nome veramente lungo - </text> - <button label="1 L$" label_selected="1 L$" left="125" name="fastpay 1" width="70"/> - <button label="5 L$" label_selected="5 L$" left="200" name="fastpay 5" width="70"/> - <button label="10 L$" label_selected="10 L$" left="125" name="fastpay 10" width="70"/> - <button label="20 L$" label_selected="20 L$" left="200" name="fastpay 20" width="70"/> - <text halign="left" left="5" name="amount text"> - Oppure, scegli importo: - </text> - <line_editor left="74" name="amount" width="50"/> - <button label="Paga" label_selected="Paga" name="pay btn"/> - <button label="Cancella" label_selected="Cancella" name="cancel btn"/> + <text left="120" name="object_name_text">Il mio oggetto con un nome veramente lungo</text> + <panel label="Cerca" name="PatternsPanel"> + <button label="Paga 1 L$" label_selected="Paga 1 L$" name="fastpay 1"/> + <button label="Paga 5 L$" label_selected="Paga 5 L$" name="fastpay 5"/> + <button label="Paga 10 L$" label_selected="Paga 10 L$" name="fastpay 10"/> + <button label="Paga 20 L$" label_selected="Paga 20 L$" name="fastpay 20"/> + </panel> + <panel label="Cerca" name="InputPanel"> + <text name="amount text">Altro importo:</text> + <button label="Paga" label_selected="Paga" name="pay btn"/> + <button label="Annulla" label_selected="Annulla" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/it/menu_attachment_self.xml b/indra/newview/skins/default/xui/it/menu_attachment_self.xml index b28137262f..1539fbafa1 100755 --- a/indra/newview/skins/default/xui/it/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/it/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Il mio aspetto" name="Change Outfit"/> <menu_item_call label="Modifica il mio vestiario" name="Edit Outfit"/> <menu_item_call label="Modifica la figura corporea" name="Edit My Shape"/> + <menu_item_call label="Altezza di volo" name="Hover Height"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_avatar_self.xml b/indra/newview/skins/default/xui/it/menu_avatar_self.xml index 3666571065..0c9663fd4c 100755 --- a/indra/newview/skins/default/xui/it/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/it/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Il mio aspetto" name="Chenge Outfit"/> <menu_item_call label="Modifica il mio vestiario" name="Edit Outfit"/> <menu_item_call label="Modifica la figura corporea" name="Edit My Shape"/> + <menu_item_call label="Altezza di volo" name="Hover Height"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml index c8042f4253..2cd0d2c078 100755 --- a/indra/newview/skins/default/xui/it/menu_inventory.xml +++ b/indra/newview/skins/default/xui/it/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Crea annuncio" name="Marketplace Create Listing"/> + <menu_item_call label="Associa annuncio" name="Marketplace Associate Listing"/> + <menu_item_call label="Visualizza (aggiorna) annuncio" name="Marketplace Get Listing"/> + <menu_item_call label="Controlla che non ci siano errori" name="Marketplace Check Listing"/> + <menu_item_call label="Modifica annuncio" name="Marketplace Edit Listing"/> + <menu_item_call label="Elenca" name="Marketplace List"/> + <menu_item_call label="Rimuovi annuncio" name="Marketplace Unlist"/> + <menu_item_call label="Attiva" name="Marketplace Activate"/> + <menu_item_call label="Disattiva" name="Marketplace Deactivate"/> <menu_item_call label="Condividi" name="Share"/> <menu_item_call label="Compra" name="Task Buy"/> <menu_item_call label="Apri" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Aggiungi" name="Wearable Add"/> <menu_item_call label="Togli" name="Take Off"/> <menu_item_call label="Copia nella casella venditore in uscita" name="Merchant Copy"/> - <menu_item_call label="Invia a Marketplace" name="Marketplace Send"/> + <menu_item_call label="Copia negli annunci Marketplace" name="Marketplace Copy"/> + <menu_item_call label="Sposta negli annunci Marketplace" name="Marketplace Move"/> <menu_item_call label="--nessuna opzione--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/it/menu_marketplace_view.xml b/indra/newview/skins/default/xui/it/menu_marketplace_view.xml new file mode 100644 index 0000000000..63f0b7fc50 --- /dev/null +++ b/indra/newview/skins/default/xui/it/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Ordina per quantità in magazzino (da bassa ad alta)" name="sort_by_stock_amount"/> + <menu_item_check label="Mostra solo cartelle annunci" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index 275315b455..18ddad5ee8 100755 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Vola" name="Fly"/> <menu_item_check label="Corri sempre" name="Always Run"/> <menu_item_call label="Ferma animazione" name="Stop Animating My Avatar"/> - <menu_item_call label="Cammina / corri / vola..." name="Walk / run / fly"/> + <menu_item_call label="Cammina / corri / vola..." name="WalkRunFly"/> </menu> <menu label="Stato" name="Status"> <menu_item_check label="Assente" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="Acquista L$..." name="Buy and Sell L$"/> <menu_item_call label="Casella venditore in uscita..." name="MerchantOutbox"/> + <menu_item_call label="Annunci Marketplace..." name="MarketplaceListings"/> <menu_item_call label="Dashboard dell'account..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=it"/> </menu_item_call> @@ -63,7 +64,7 @@ <menu_item_call label="Istantanea" name="Take Snapshot"/> <menu_item_call label="Profilo del luogo" name="Place Profile"/> <menu_item_call label="Informazioni sul terreno" name="About Land"/> - <menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/> + <menu_item_call label="Regione/proprietà immobiliare" name="RegionEstate"/> <menu_item_call label="Terreni posseduti..." name="My Land"/> <menu_item_call label="Acquista questo terreno" name="Buy Land"/> <menu label="Mostra" name="LandShow"> @@ -250,6 +251,7 @@ <menu_item_check label="Console texture" name="Texture Console"/> <menu_item_check label="Console di Debug" name="Debug Console"/> <menu_item_call label="Console notifiche" name="Notifications"/> + <menu_item_check label="Console di debug regione" name="Region Debug Console"/> <menu_item_check label="Timer veloci" name="Fast Timers"/> <menu_item_check label="Memoria" name="Memory"/> <menu_item_check label="Statistiche scena" name="Scene Statistics"/> @@ -325,7 +327,7 @@ <menu label="Rete" name="Network"> <menu_item_check label="Metti in pausa" name="AgentPause"/> <menu_item_call label="Lascia un pacchetto" name="Drop a Packet"/> - </menu> + </menu> <menu label="Mondo" name="DevelopWorld"> <menu_item_check label="Esclusione al sole della simulazione" name="Sim Sun Override"/> <menu_item_check label="Clima fisso" name="Fixed Weather"/> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index fe53dd18dd..61131b09c3 100755 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -129,6 +129,88 @@ Nessuna cartella è stata inviata a Marketplace, a causa di un errore di sistema L'inizializzazione con il Marketplace non ha avuto successo a causa di un errore di sistema o di rete. Riprova più tardi. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Impossibile copiare o spostare la cartella di magazzino a causa dell'errore seguente: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Impossibile copiare o spostare gli annunci Marketplace a causa dell'errore seguente: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + La transazione in Marketplace non è riuscita a causa dell'errore seguente: + + Motivo: '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Non siamo in grado di creare un annuncio per questo prodotto o di attivare la cartella di versione. Di solito la causa è la mancanza di informazioni nel modulo di descrizione dell'annuncio, ma potrebbero esserci errori nella struttura delle cartelle. Modifica l'annuncio oppure verifica che non ci siano problemi legati alla cartella dell'annuncio. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Aggiunta annuncio a Marketplace non riuscita a causa dell'errore seguente: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + L'attivazione di questa cartella di versione non è riuscita a causa dell'errore: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Questa azione cambierà il contenuto attivo di questo annuncio. Vuoi continuare? + <usetemplate ignoretext="Conferma prima di modificare un annuncio attivo su Marketplace" name="okcancelignore" notext="Annulla" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Gli articoli trascinati nella finestra degli annunci di Marketplace vengono spostati dalle posizioni iniziali e non vengono copiati. Vuoi continuare? + <usetemplate ignoretext="Conferma prima di spostare un articolo dall'inventario a Marketplace" name="okcancelignore" notext="Annulla" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Se sposti o elimini la cartella dell'annuncio, l'annuncio su Marketplace verrà eliminato. Per mantenere l'annuncio su Marketplace, sposta o elimina i contenuti della cartella di versione da modificare. Vuoi continuare? + <usetemplate ignoretext="Conferma prima di spostare o eliminare un annuncio da Marketplace" name="okcancelignore" notext="Annulla" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Non hai l'autorizzazione necessaria per copiare uno o più di questi articoli su Marketplace. Puoi spostarli o lasciarli dove si trovano. + <usetemplate canceltext="Annulla" ignoretext="Conferma prima di copiare nel Marketplace una selezione che contiene articoli per i quali non è consentita la copia" name="yesnocancelbuttons" notext="Non spostare gli articoli" yestext="Sposta articoli"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Questa azione causa la rimozione dell'annuncio. Vuoi continuare? + <usetemplate ignoretext="Conferma prima di rimuovere un annuncio attivo da Marketplace" name="okcancelignore" notext="Annulla" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Questa azione disattiverà la cartella di versione per l'annuncio corrente. Vuoi continuare? + <usetemplate ignoretext="Conferma prima di disattivare la cartella di versione di un annuncio su Marketplace" name="okcancelignore" notext="Annulla" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Impossibile aggiornare l'annuncio. +[[URL] Fai clic qui] per modificarlo in Marketplace. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Non puoi indossare vestiario o parti del corpo che sono nella cartella degli annunci di Marketplace. + </notification> + <notification name="AlertMerchantListingInvalidID"> + ID annuncio non valido. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Ci sono svariate cartelle di versione oppure nessuna cartella di versione in questo annuncio. In seguito dovrai selezionarne e attivarne una separatamente. + <usetemplate ignoretext="Avvisa riguardo all'attivazione della cartella di versione quando creo un annuncio con varie cartelle di versione" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Abbiamo diviso gli articoli in magazzino di tipo diverso in cartelle di magazzino separate. In questo modo la tua cartella è ordinata per la pubblicazione nell'annuncio. + <usetemplate ignoretext="Avverti quando la cartella di magazzino viene suddivisa prima della pubblicazione dell'annuncio" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + L'annuncio è stato rimosso perché il magazzino è esaurito. Aggiungi altre unità alla cartella di magazzino prima di pubblicare nuovamente l'annuncio. + <usetemplate ignoretext="Avverti quando un annuncio viene rimosso perché la cartella di magazzino è vuota" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> C'è stato un problema importando il testo di uno script per la seguente ragione: [REASON]. Riprova più tardi. </notification> @@ -470,6 +552,10 @@ Nota: questa operazione cancellerà la cache. Salva le modifiche? <usetemplate canceltext="Annulla" name="yesnocancelbuttons" notext="Non salvare" yestext="Salva"/> </notification> + <notification name="DeleteNotecard"> + Vuoi eliminare il biglietto? + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Il salvataggio della Gesture è fallito. La gesture ha troppi passi. @@ -1872,6 +1958,9 @@ Cambierà migliaia di regioni e produrrà seri problemi ai vari server. La regione che cerchi di visitare include contenuti che non corripondono al livello selezionato nelle preferenze. Per cambiare le preferenze seleziona Io > Preferenze > Generale. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> La regione che cerchi di visitare include contenuti [REGIONMATURITY] accessibili solo ad adulti. <url name="url"> @@ -2161,6 +2250,10 @@ Trasferisci gli elementi nell'inventario? <ignore name="ignore" text="Ho impostato l'azione Paga oggetto costruendo un oggetto senza uno script money()"/> </form> </notification> + <notification name="PayConfirmation"> + Conferma che desideri pagare [AMOUNT] L$ a [TARGET]. + <usetemplate ignoretext="Conferma prima di pagare (somme superiori a 200 L$)" name="okcancelignore" notext="Annulla" yestext="Paga"/> + </notification> <notification name="OpenObjectCannotCopy"> Non ci sono elementi in questo oggetto che tu possa copiare. </notification> @@ -2700,9 +2793,6 @@ Riprova tra qualche istante. <notification name="NoValidCircuit"> Nessun codice circuito valido. </notification> - <notification name="NoValidTimestamp"> - Nessuna data/timestamp valido. - </notification> <notification name="NoPendingConnection"> Impossibile creare la connessione in sospeso. </notification> @@ -3847,9 +3937,11 @@ Riprova tra un minuto. </notification> <notification name="TeleportedByAttachment"> Sei stato teletrasportato da un elemento collegato a [ITEM_ID] + <usetemplate ignoretext="Teleport: sei stato teleportato da un elemento accessorio" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Sei stato teleportato dall'oggetto '[OBJECT_NAME]' sul lotto '[PARCEL_NAME]' + <usetemplate ignoretext="Teleport: sei stato teleportato su un lotto da un oggetto" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Sei stato teleportato dall'oggetto '[OBJECT_NAME]' di proprietà di [OWNER_ID] @@ -4181,7 +4273,7 @@ Prova a selezionare un pezzo di terreno più piccolo. <usetemplate ignoretext="Impossibile spostare i file. Il percorso precedente è stato ripristinato." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Si è verificato un problema nel salvare i diritti predefiniti per il motivo seguente: [REASON]. Riprova più tardi. + Si è verificato un problema nel salvare le autorizzazioni predefinite dell'oggetto: [REASON]. Riprova più tardi. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/it/panel_login.xml b/indra/newview/skins/default/xui/it/panel_login.xml index 1ce38ac40c..6c1777163c 100755 --- a/indra/newview/skins/default/xui/it/panel_login.xml +++ b/indra/newview/skins/default/xui/it/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=it - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=it</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Nome utente" name="username_combo" tool_tip="Il nome utente che hai scelto durante la registrazione, come roby12 o Stella Solare"/> <line_editor label="Password" name="password_edit"/> - <check_box label="Ricordami" name="remember_check"/> - <text name="forgot_password_text"> - Password dimenticata - </text> - <button label="Accedi" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - all'ultima ubicazione - </text> <combo_box label="I miei luoghi preferiti" name="start_location_combo"> + <combo_box.item label="La mia ultima ubicazione" name="MyLastLocation"/> <combo_box.item label="Casa mia" name="MyHome"/> </combo_box> - <button label="Accedi" name="connect_favorite_btn"/> - <line_editor label="Digita un'ubicazione" name="location_edit"/> - <button label="Accedi" name="connect_location_btn"/> + <button label="Accedi" name="connect_btn"/> + <check_box label="Ricordami" name="remember_check"/> + <text name="forgot_password_text">Password dimenticata</text> <combo_box label="Seleziona griglia" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/it/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/it/panel_marketplace_listings.xml new file mode 100644 index 0000000000..d28dfadf45 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Marketplace" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Visualizza/ordina opzioni"/> + <button name="add_btn" tool_tip="Crea una nuova cartella annunci"/> + <button label="Controlla che non ci siano errori" name="audit_btn" tool_tip="Controlla i tuoi annunci su Marketplace"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Filtra annunci Marketplace" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/it/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..4902442d2b --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="TUTTO" name="All Items" tool_tip="Trascina e rilascia qui gli articoli da elencare"/> diff --git a/indra/newview/skins/default/xui/it/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/it/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..3fb0d5645c --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="IN ELENCO" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/it/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/it/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..ac6b2952fc --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NON ASSOCIATO" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/it/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/it/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..6c9fae7ddc --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="RIMOSSI" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml index be7d8763b6..be7d8763b6 100755..100644 --- a/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml index 0aaf89d8c8..83d2ae5bab 100755 --- a/indra/newview/skins/default/xui/it/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Perdita di pacchetti - </panel.string> - <panel.string name="bandwidth_tooltip"> - Larghezza di banda - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">Perdita di pacchetti</panel.string> + <panel.string name="bandwidth_tooltip">Larghezza di banda</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel left="-405" name="balance_bg" width="195"> - <text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ 20"/> + <text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ ??"/> <button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/> <button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/> </panel> - <text name="TimeText" tool_tip="Orario attuale (Pacifico)"> - 24:00, ora del Pacifico - </text> + <text name="TimeText" tool_tip="Orario attuale (Pacifico)">24:00, ora del Pacifico</text> <button name="media_toggle_btn" tool_tip="Attiva/ferma tutti i media (musica, video, pagine Web)"/> <button name="volume_btn" tool_tip="Regolazione del volume globale"/> </panel> diff --git a/indra/newview/skins/default/xui/it/sidepanel_item_info.xml b/indra/newview/skins/default/xui/it/sidepanel_item_info.xml index 422f15e3cf..14c1c43816 100755 --- a/indra/newview/skins/default/xui/it/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Trasferisci" name="CheckNextOwnerTransfer" tool_tip="Il prossimo proprietario può regalare o rivendere questo oggetto"/> </panel> <check_box label="In vendita" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Copia" name="Copy"/> + <combo_box.item label="Contenuti" name="Contents"/> <combo_box.item label="Originale" name="Original"/> </combo_box> <spinner label="Prezzo: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/it/sidepanel_task_info.xml b/indra/newview/skins/default/xui/it/sidepanel_task_info.xml index 5f912dd126..aabefd7d3c 100755 --- a/indra/newview/skins/default/xui/it/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Profilo dell'oggetto"> - <panel.string name="text deed continued"> - Cessione - </panel.string> - <panel.string name="text deed"> - Cessione - </panel.string> - <panel.string name="text modify info 1"> - Tu puoi modificare questo oggetto - </panel.string> - <panel.string name="text modify info 2"> - Tu puoi modificare questi oggetti - </panel.string> - <panel.string name="text modify info 3"> - Non puoi modificare questo oggetto - </panel.string> - <panel.string name="text modify info 4"> - Non puoi modificare questi oggetti - </panel.string> - <panel.string name="text modify info 5"> - Questo oggetto non può essere modificato attraverso il confine di una regione - </panel.string> - <panel.string name="text modify info 6"> - Questi oggetti non possono essere modificati attraverso il confine di una regione - </panel.string> - <panel.string name="text modify warning"> - Questo oggetto ha parti collegate - </panel.string> - <panel.string name="Cost Default"> - Prezzo: L$ - </panel.string> - <panel.string name="Cost Total"> - Prezzo totale: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Prezzo per: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Prezzo misto - </panel.string> - <panel.string name="Sale Mixed"> - Vendita mista - </panel.string> + <panel.string name="text deed continued">Cessione</panel.string> + <panel.string name="text deed">Cessione</panel.string> + <panel.string name="text modify info 1">Tu puoi modificare questo oggetto</panel.string> + <panel.string name="text modify info 2">Tu puoi modificare questi oggetti</panel.string> + <panel.string name="text modify info 3">Non puoi modificare questo oggetto</panel.string> + <panel.string name="text modify info 4">Non puoi modificare questi oggetti</panel.string> + <panel.string name="text modify info 5">Questo oggetto non può essere modificato attraverso il confine di una regione</panel.string> + <panel.string name="text modify info 6">Questi oggetti non possono essere modificati attraverso il confine di una regione</panel.string> + <panel.string name="text modify warning">Questo oggetto ha parti collegate</panel.string> + <panel.string name="Cost Default">Prezzo: L$</panel.string> + <panel.string name="Cost Total">Prezzo totale: L$</panel.string> + <panel.string name="Cost Per Unit">Prezzo per: L$</panel.string> + <panel.string name="Cost Mixed">Prezzo misto</panel.string> + <panel.string name="Sale Mixed">Vendita mista</panel.string> <text name="title" value="Profilo dell'oggetto"/> <text name="where" value="(in Second Life)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Nome: - </text> - <text name="Description:"> - Descrizione: - </text> - <text name="CreatorNameLabel"> - Ideatore: - </text> - <text name="Owner:"> - Proprietario: - </text> - <text name="Group_label"> - Gruppo: - </text> + <text name="Name:">Nome:</text> + <text name="Description:">Descrizione:</text> + <text name="CreatorNameLabel">Ideatore:</text> + <text name="Owner:">Proprietario:</text> + <text name="Group_label">Gruppo:</text> <button name="button set group" tool_tip="Scegli un gruppo con cui condividere i diritti relativi all'oggetto"/> <name_box initial_value="Caricamento in corso..." name="Group Name Proxy"/> <button label="Cessione" label_selected="Cessione" name="button deed" tool_tip="Con una cessione si trasferisce il bene con i diritti al proprietario successivo Gli oggetti in proprietà condivisa di gruppo possono essere ceduti soltanto da un funzionario del gruppo."/> - <text name="label click action"> - Fai clic per: - </text> + <text name="label click action">Fai clic per:</text> <combo_box name="clickaction"> <combo_box.item label="Tocca (predefinito)" name="Touch/grab(default)"/> <combo_box.item label="Siediti sull'oggetto" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Ingrandisci" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Tu puoi modificare questo oggetto - </text> - <text name="Anyone can:"> - Chiunque: - </text> + <text name="perm_modify">Tu puoi modificare questo oggetto</text> + <text name="Anyone can:">Chiunque:</text> <check_box label="Copia" name="checkbox allow everyone copy"/> <check_box label="Sposta" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Gruppo: - </text> + <text name="GroupLabel">Gruppo:</text> <check_box label="Condividi" name="checkbox share with group" tool_tip="Consenti a tutti i membri del gruppo selezionato di condividere i tuoi diritti di modifica di questo oggetto. Per attivare le restrizioni per ruolo devi prima effettuare la cessione."/> - <text name="NextOwnerLabel"> - Proprietario successivo: - </text> + <text name="NextOwnerLabel">Proprietario successivo:</text> <check_box label="Modifica" name="checkbox next owner can modify"/> <check_box label="Copia" name="checkbox next owner can copy"/> <check_box label="Trasferisci" name="checkbox next owner can transfer" tool_tip="Il prossimo proprietario può regalare o rivendere questo oggetto"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Prezzo: L$" name="Edit Cost"/> <check_box label="Mostra nella ricerca" name="search_check" tool_tip="Permetti alle persone di vedere questo oggetto nei risultati della ricerca"/> - <text name="pathfinding_attributes_label"> - Attributi pathfinding: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Attributi pathfinding:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Apri" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 25c784975e..b9a87a1527 100755 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -451,28 +451,46 @@ Prova ad accedere nuovamente tra un minuto. </string> <string name="TooltipPrice" value="L$ [AMOUNT]:"/> <string name="TooltipOutboxDragToWorld"> - Non puoi rezzare elementi nella tua casella in uscita del rivenditore + Non puoi rezzare articoli dalla cartella degli annunci di Marketplace + </string> + <string name="TooltipOutboxWorn"> + Non puoi inserire nella cartella degli annunci in Marketplace gli articoli che indossi + </string> + <string name="TooltipOutboxFolderLevels"> + La profondità delle caselle nidificate è maggiore di [AMOUNT]. Diminuisci la profondità delle cartelle nidificate; se necessario, raggruppa gli articoli. + </string> + <string name="TooltipOutboxTooManyFolders"> + Il numero di sottocartelle è maggiore di [AMOUNT]. Diminuisci il numero delle cartelle nel tuo annuncio; se necessario, raggruppa gli articoli. + </string> + <string name="TooltipOutboxTooManyObjects"> + Il numero di articoli è maggiore di [AMOUNT]. Per vendere più di [AMOUNT] articoli in un annuncio, devi raggruppare alcuni di essi. + </string> + <string name="TooltipOutboxTooManyStockItems"> + Il numero di articoli in magazzino è maggiore di [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Puoi trascinare articoli o cartelle solo nella scheda TUTTI. Seleziona la scheda e sposta nuovamente gli articoli o le cartelle. </string> <string name="TooltipOutboxNoTransfer"> - Almeno uno di questi oggetti non può essere venduto o trasferito. + Almeno uno di questi oggetti non può essere venduto o trasferito </string> <string name="TooltipOutboxNotInInventory"> - La tua casella in uscita del rivenditore può accettare solo elementi provenienti dal tuo inventario + Puoi aggiungere a Marketplace solo gli articoli nel tuo inventario </string> - <string name="TooltipOutboxWorn"> - Non puoi mettere gli elementi che indossi nella casella in uscita del rivenditore + <string name="TooltipOutboxLinked"> + Non puoi inserire cartelle o articoli collegati tramite link nel Marketplace </string> <string name="TooltipOutboxCallingCard"> - Non puoi inserire il tuo biglietto da visita nella tua casella in uscita del rivenditore + Non puoi inserire biglietti da visita in Marketplace </string> - <string name="TooltipOutboxFolderLevels"> - La profondità delle caselle nidificate è maggiore di 3 + <string name="TooltipOutboxDragActive"> + non puoi muovere un annuncio attivo </string> - <string name="TooltipOutboxTooManyFolders"> - Il numero di sottocartelle nella cartella al livello più alto è maggiore di 20 + <string name="TooltipOutboxCannotMoveRoot"> + Non puoi spostare la cartella principale degli annunci di Marketplace </string> - <string name="TooltipOutboxTooManyObjects"> - Il numero di elementi nella cartella al livello più alto è maggiore di 200 + <string name="TooltipOutboxMixedStock"> + Tutti gli articoli in una cartella di magazzino devono essere dello stesso tipo e con le stesse autorizzazioni </string> <string name="TooltipDragOntoOwnChild"> Non puoi spostare una cartella nella relativa cartella secondaria @@ -1054,7 +1072,7 @@ Prova ad accedere nuovamente tra un minuto. <string name="AgentNameSubst"> (Tu) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Omette gli avvisi durante la gestione degli elenchi di accesso alle proprietà immobiliari </string> @@ -1121,6 +1139,12 @@ Prova ad accedere nuovamente tra un minuto. <string name="bitmap_image_files"> Immagini Bitmap </string> + <string name="png_image_files"> + Immagini PNG + </string> + <string name="save_texture_image_files"> + Immagini Targa o PNG + </string> <string name="avi_movie_file"> File video AVI </string> @@ -1370,6 +1394,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="FavoritesNoMatchingItems"> Trascina qui un punto di riferimento per aggiungerlo ai Preferiti. </string> + <string name="MarketplaceNoMatchingItems"> + Nessun articolo trovato. Controlla di aver digitato la stringa di ricerca correttamente e riprova. + </string> <string name="InventoryNoTexture"> Non hai una copia di questa texture nel tuo inventario </string> @@ -1417,29 +1444,95 @@ Prova ad accedere nuovamente tra un minuto. <string name="InventoryOutboxError"> Il [[MARKETPLACE_CREATE_STORE_URL] negozio nel Marketplace] ha riportato errori. </string> + <string name="InventoryMarketplaceError"> + Questa funzione è al momento in versione beta. Per partecipare, aggiungi il tuo nome a questo [http://goo.gl/forms/FCQ7UXkakz modulo Google]. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + La cartella degli annunci di Marketplace è vuota. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Trascina le cartelle in questa area per metterle in vendita su [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> + <string name="Marketplace Validation Warning Stock"> + la cartella di magazzino deve essere inclusa in una cartella di versione + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Errore: tutti gli articoli un una cartella di magazzino devono essere non copiabili e dello stesso tipo + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Errore: la cartella di magazzino non può contenere sottocartelle + </string> + <string name="Marketplace Validation Warning Empty"> + : Avviso: la cartella non contiene alcun articolo + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Avviso: creazione cartella di magazzino in corso + </string> + <string name="Marketplace Validation Warning Create Version"> + : Avviso: creazione cartella di versione in corso + </string> + <string name="Marketplace Validation Warning Move"> + : Avviso: spostamento articoli in corso + </string> + <string name="Marketplace Validation Warning Delete"> + : Avviso: il contenuto della cartella è stato trasferito alla cartella di magazzino e la cartella vuota sta per essere rimossa + </string> + <string name="Marketplace Validation Error Stock Item"> + : Errore: gli articoli di cui non è permessa la copia devono essere all'interno di una cartella di magazzino + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Avviso: gli articoli devono essere inclusi in una cartella di versione + </string> + <string name="Marketplace Validation Error"> + : Errore: + </string> + <string name="Marketplace Validation Warning"> + : Avviso: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Avviso: la cartella di versione deve contenere almeno 1 articolo + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Avviso: la cartella di magazzino deve contenere almeno 1 articolo + </string> + <string name="Marketplace Validation No Error"> + Nessun errore o avviso da segnalare + </string> <string name="Marketplace Error None"> Nessun errore </string> + <string name="Marketplace Error Prefix"> + Errore: + </string> <string name="Marketplace Error Not Merchant"> - Errore: Prima di inviare elementi al Marketplace devi essere impostato come rivenditore (gratis). + Prima di inviare gli articoli al Marketplace devi essere impostato come rivenditore (gratis). + </string> + <string name="Marketplace Error Not Accepted"> + L'articolo non può essere spostato in quella cartella. </string> - <string name="Marketplace Error Empty Folder"> - Errore: questa cartella non include alcun contenuto. + <string name="Marketplace Error Unsellable Item"> + Questo articolo non può essere venduto nel Marketplace. </string> - <string name="Marketplace Error Unassociated Products"> - Errore: Oggetto non caricato perché il tuo account venditore ha troppi oggetti che non sono associati con dei prodotti. Per risolvere questo errore, esegui l'accesso al sito di Marketplace e riduci il numero di oggetti non associati. + <string name="MarketplaceNoID"> + no Mkt ID </string> - <string name="Marketplace Error Object Limit"> - Errore: questo elemento contiene troppi oggetti. Per risolvere questo problema, inserisci più oggetti insieme in una scatola per ridurre a meno di 200 il numero totale di oggetti. + <string name="MarketplaceLive"> + in elenco </string> - <string name="Marketplace Error Folder Depth"> - Errore: questo elemento contiene troppi livelli di cartelle nidificate. Riorganizzalo per ottenere un massimo di 3 livelli di cartelle nidificate. + <string name="MarketplaceActive"> + attivi </string> - <string name="Marketplace Error Unsellable Item"> - Errore: Questo elemento non può essere venduto nel Marketplace. + <string name="MarketplaceMax"> + massimo </string> - <string name="Marketplace Error Internal Import"> - Errore: problema con questo elemento. Riprova più tardi. + <string name="MarketplaceStock"> + magazzino + </string> + <string name="MarketplaceNoStock"> + non in magazzino + </string> + <string name="MarketplaceUpdating"> + in aggiornamento... </string> <string name="Open landmarks"> Apri luoghi di riferimento @@ -1460,6 +1553,7 @@ Prova ad accedere nuovamente tra un minuto. Nessun contenuto </string> <string name="WornOnAttachmentPoint" value="(indossato su [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (attivo)"/> <string name="Chat Message" value="Chat:"/> <string name="Sound" value="Suono :"/> @@ -1724,6 +1818,15 @@ Prova ad accedere nuovamente tra un minuto. <string name="Invalid Attachment"> Punto di collegamento non valido </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Errore: articolo mancante + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Errore: articolo di base mancante + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Errore: l'oggetto è nel vestiario corrente ma non è collegato + </string> <string name="YearsMonthsOld"> Nato da [AGEYEARS] [AGEMONTHS] </string> @@ -1859,9 +1962,6 @@ Prova ad accedere nuovamente tra un minuto. <string name="CompileQueueUnknownFailure"> Errore di dowload sconosciuto </string> - <string name="CompileNoExperiencePerm"> - Saltato lo script [SCRIPT] con l'esperienza [EXPERIENCE]. - </string> <string name="CompileQueueTitle"> Avanzamento ricompilazione </string> @@ -1895,6 +1995,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="SaveComplete"> Salvataggio completato. </string> + <string name="UploadFailed"> + Caricamento file non riuscito: + </string> <string name="ObjectOutOfRange"> Script (oggetto fuori portata) </string> @@ -1904,6 +2007,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="GroupsNone"> nessuno </string> + <string name="CompileNoExperiencePerm"> + Saltato lo script [SCRIPT] con l'esperienza [EXPERIENCE]. + </string> <string name="Group" value="(gruppo)"/> <string name="Unknown"> (Sconosciuto) @@ -4983,6 +5089,9 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="Command_Marketplace_Label"> Mercato </string> + <string name="Command_MarketplaceListings_Label"> + Marketplace + </string> <string name="Command_MiniMap_Label"> Mini mappa </string> @@ -5070,6 +5179,9 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="Command_Marketplace_Tooltip"> Vai allo shopping </string> + <string name="Command_MarketplaceListings_Tooltip"> + Vendi le tue creazioni + </string> <string name="Command_MiniMap_Tooltip"> Mostra le persone vicine </string> @@ -5181,6 +5293,18 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="UserDictionary"> [User] </string> + <string name="logging_calls_disabled_log_empty"> + Le conversazioni non vengono registrate. Per iniziare a registrare, seleziona "Salva: Solo registro" oppure "Salva: Registri e trascrizioni" in Preferenze > Chat. + </string> + <string name="logging_calls_disabled_log_not_empty"> + Non verranno registrate più le conversazioni. Per riprendere a registrare, seleziona "Salva: Solo registro" oppure "Salva: Registri e trascrizioni" in Preferenze > Chat. + </string> + <string name="logging_calls_enabled_log_empty"> + Nessuna conversazione in registro. Dopo che hai contattato qualcuno o se qualcuno ti contatta, una voce del registro verrà mostrata qui. + </string> + <string name="loading_chat_logs"> + Caricamento in corso... + </string> <string name="experience_tools_experience"> Esperienza </string> @@ -5262,16 +5386,4 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="ExperiencePermissionShort12"> Autorizzazione </string> - <string name="logging_calls_disabled_log_empty"> - Le conversazioni non vengono registrate. Per iniziare a registrare, seleziona "Salva: Solo registro" oppure "Salva: Registri e trascrizioni" in Preferenze > Chat. - </string> - <string name="logging_calls_disabled_log_not_empty"> - Non verranno registrate più le conversazioni. Per riprendere a registrare, seleziona "Salva: Solo registro" oppure "Salva: Registri e trascrizioni" in Preferenze > Chat. - </string> - <string name="logging_calls_enabled_log_empty"> - Nessuna conversazione in registro. Dopo che hai contattato qualcuno o se qualcuno ti contatta, una voce del registro verrà mostrata qui. - </string> - <string name="loading_chat_logs"> - Caricamento in corso... - </string> </strings> diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index 63a4e69c10..91a61ab225 100755 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -1,74 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="[CAPITALIZED_APP_NAME] ã«ã¤ã„ã¦"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - コンパイラー [COMPILER] [COMPILER_VERSION] ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - </floater.string> - <floater.string name="AboutPosition"> - ã‚ãªãŸã®ç¾åœ¨åœ°ã¯ã€[POSITION_LOCAL_0,number,1]ã€[POSITION_LOCAL_1,number,1]ã€[POSITION_LOCAL_2,number,1] ã® [REGION] ã§ã™ã€‚ä½ç½®ã¯ <nolink>[HOSTNAME]</nolink> ã§ã™ã€‚([HOSTIP]) -SLURL:<nolink>[SLURL]</nolink> -(ã‚°ãƒãƒ¼ãƒãƒ«åº§æ¨™ [POSITION_0,number,1]ã€[POSITION_1,number,1]ã€[POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -メモリ: [MEMORY_MB] MB -OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [OS_VERSION] -ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚«ãƒ¼ãƒ‰è£½é€ å…ƒï¼š [GRAPHICS_CARD_VENDOR] -グラフィックカード: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Windows グラフィックドライãƒãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - OpenGL ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [OPENGL_VERSION] - -libcurl ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [LIBCURL_VERSION] -J2C デコーダãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [J2C_VERSION] -オーディオドライãƒãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [AUDIO_DRIVER_VERSION] -Qt Webkit ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [QT_WEBKIT_VERSION] -ボイスサーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (ãªã—) - </floater.string> - <floater.string name="AboutTraffic"> - パケットãƒã‚¹ï¼š [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - サーãƒãƒ¼ã®ãƒªãƒªãƒ¼ã‚¹ãƒŽãƒ¼ãƒˆã® URL ã‚’å–å¾—ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ - </floater.string> <tab_container name="about_tab"> <panel label="æƒ…å ±" name="support_panel"> <button label="クリップボードã«ã‚³ãƒ”ー" name="copy_btn"/> </panel> <panel label="クレジット" name="credits_panel"> - <text name="linden_intro"> - Second Life ã®æ供元: Lindens ã®ï¼š - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - オープンソースã®æ供: - </text> - <text_editor name="contrib_names"> - Dummy Name ã¯å®Ÿè¡Œæ™‚é–“ã«ç½®ãæ›ãˆ - </text_editor> - <text name="trans_intro"> - 翻訳会社: - </text> - <text_editor name="trans_names"> - Dummy Name ã¯å®Ÿè¡Œæ™‚é–“ã«ç½®ãæ›ãˆ - </text_editor> + <text name="linden_intro">Second Life ã®æ供元: Lindens ã®ã€ +オープンソースã®æ供:</text> + <text_editor name="contrib_names">Dummy Name ã¯å®Ÿè¡Œæ™‚é–“ã«ç½®ãæ›ãˆ</text_editor> </panel> <panel label="ライセンス" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -95,8 +37,7 @@ Second Life ビューワã§ã¯ Havok (TM) Physics ãŒä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚ ç„¡æ–複写・複製・転載をç¦ã˜ã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯ licenses.txt ã‚’ã”å‚ç…§ãã ã•ã„。 -ボイスãƒãƒ£ãƒƒãƒˆã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ï¼šPolycom(R) Siren14(TM) (ITU-T Rec.G.722.1 Annex C) - </text_editor> +ボイスãƒãƒ£ãƒƒãƒˆã®ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ï¼šPolycom(R) Siren14(TM) (ITU-T Rec.G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_associate_listing.xml b/indra/newview/skins/default/xui/ja/floater_associate_listing.xml new file mode 100644 index 0000000000..b106750a6f --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="リストを関連付ã‘ã‚‹"> + <text name="message">リスト ID:</text> + <line_editor name="listing_id">ã“ã“ã« ID を入力</line_editor> + <button label="OK" name="OK"/> + <button label="å–り消ã—" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/ja/floater_edit_hover_height.xml new file mode 100644 index 0000000000..ac5b2839d1 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="ホãƒãƒ¼é«˜ã•ã®è¨å®š"> + <slider label="高ã•" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml index c01c46211e..8d3a655a06 100755 --- a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="インベントリアイテムã®ãƒ—ãƒãƒ‘ティ"> - <floater.string name="unknown"> - (ä¸æ˜Žï¼‰ - </floater.string> - <floater.string name="public"> - (公共) - </floater.string> - <floater.string name="you_can"> - ã§ãã‚‹ã“ã¨ï¼š - </floater.string> - <floater.string name="owner_can"> - オーナーã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™ï¼š - </floater.string> - <floater.string name="acquiredDate"> - [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - åå‰ï¼š - </text> - <text name="LabelItemDescTitle"> - 説明: - </text> - <text name="LabelCreatorTitle"> - クリエーター - </text> + <floater.string name="unknown">(ä¸æ˜Žï¼‰</floater.string> + <floater.string name="public">(公共)</floater.string> + <floater.string name="you_can">ã§ãã‚‹ã“ã¨ï¼š</floater.string> + <floater.string name="owner_can">オーナーã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™ï¼š</floater.string> + <floater.string name="acquiredDate">[year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]</floater.string> + <text name="LabelItemNameTitle">åå‰ï¼š</text> + <text name="LabelItemDescTitle">説明:</text> + <text name="LabelCreatorTitle">クリエーター</text> <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - オーナー: - </text> + <text name="LabelOwnerTitle">オーナー:</text> <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - 入手日時: - </text> - <text name="LabelAcquiredDate"> - 2006å¹´5月24日水曜日12:50:46 - </text> - <text name="OwnerLabel"> - ã‚ãªãŸï¼š - </text> + <text name="LabelAcquiredTitle">入手日時:</text> + <text name="LabelAcquiredDate">2006å¹´5月24日水曜日12:50:46</text> + <text name="OwnerLabel">ã‚ãªãŸï¼š</text> <check_box label="編集" name="CheckOwnerModify"/> <check_box label="コピー" name="CheckOwnerCopy"/> <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - 全員: - </text> + <text name="AnyoneLabel">全員:</text> <check_box label="コピー" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - グループ: - </text> + <text name="GroupLabel">グループ:</text> <check_box label="共有" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="158"> - 次ã®æ‰€æœ‰è€…: - </text> + <text name="NextOwnerLabel" width="158">次ã®æ‰€æœ‰è€…:</text> <check_box label="編集" name="CheckNextOwnerModify"/> <check_box label="コピー" name="CheckNextOwnerCopy"/> <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckNextOwnerTransfer"/> <check_box label="売り出ã—ä¸" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="コピー" name="Copy"/> + <combo_box.item label="コンテンツ" name="Contents"/> <combo_box.item label="オリジナル" name="Original"/> </combo_box> <spinner label="ä¾¡æ ¼ï¼š" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_item_properties.xml b/indra/newview/skins/default/xui/ja/floater_item_properties.xml new file mode 100644 index 0000000000..c8648503d7 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="アイテムã®ãƒ—ãƒãƒ‘ティ"/> diff --git a/indra/newview/skins/default/xui/ja/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/ja/floater_marketplace_listings.xml new file mode 100644 index 0000000000..f6b8e2928e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="マーケットプレイスã®ãƒªã‚¹ãƒˆ"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">ãƒãƒ¼ãƒ‰ä¸...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/ja/floater_marketplace_validation.xml new file mode 100644 index 0000000000..164864ed4e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="マーケットプレイスã®ãƒªã‚¹ãƒˆã®ç›£æŸ»"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_openobject.xml b/indra/newview/skins/default/xui/ja/floater_openobject.xml index 7bdd1e4980..3f2f71511b 100755 --- a/indra/newview/skins/default/xui/ja/floater_openobject.xml +++ b/indra/newview/skins/default/xui/ja/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="æŒã¡ç‰©ã«ã‚³ãƒ”ー" label_selected="æŒã¡ç‰©ã«ã‚³ãƒ”ー" name="copy_to_inventory_button"/> - <button label="コピーã—ã¦ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆã«è¿½åŠ " label_selected="コピーã—ã¦ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆã«è¿½åŠ " name="copy_and_wear_button"/> + <text name="border_note"> + インベントリãŠã‚ˆã³ã‚¦ã‚§ã‚¢ã«ã‚³ãƒ”ー + </text> + <button label="アウトフィットã«è¿½åŠ " label_selected="アウトフィットã«è¿½åŠ " name="copy_and_wear_button"/> + <button label="アウトフィットを交æ›" label_selected="アウトフィットを交æ›" name="copy_and_replace_button"/> + <button label="インベントリã«ã‚³ãƒ”ーã™ã‚‹ã ã‘" label_selected="インベントリã«ã‚³ãƒ”ーã™ã‚‹ã ã‘" name="copy_to_inventory_button"/> + <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_pay.xml b/indra/newview/skins/default/xui/ja/floater_pay.xml index 17965fb60a..0ca0990bd4 100755 --- a/indra/newview/skins/default/xui/ja/floater_pay.xml +++ b/indra/newview/skins/default/xui/ja/floater_pay.xml @@ -1,25 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - グループã«æ”¯æ‰•ã† - </string> - <string name="payee_resident"> - ä½äººã«æ”¯æ‰•ã† - </string> - <text name="payee_label"> - 支払ã†ï¼š - </text> - <icon name="icon_person" tool_tip="ä½äºº"/> - <text name="payee_name"> - éžå¸¸ã«é•·ã„åå‰ãŒé€”ä¸ã§åˆ‡ã‚Œã¦ã„ãªã„ã‹ã‚’テストã—ã¦ç¢ºèª - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - 金é¡ã‚’指定: - </text> - <button label="支払ã†" label_selected="支払ã†" name="pay btn"/> - <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/> + <string name="payee_group">グループã«æ”¯æ‰•ã†</string> + <string name="payee_resident">ä½äººã«æ”¯æ‰•ã†</string> + <text name="paying_text">支払ä¸:</text> + <text name="payee_name">éžå¸¸ã«é•·ã„åå‰ãŒé€”ä¸ã§åˆ‡ã‚Œã¦ã„ãªã„ã‹ã‚’テストã—ã¦ç¢ºèª</text> + <panel label="検索" name="PatternsPanel"> + <button label="L$ 1 支払ã†" label_selected="L$ 1 支払ã†" name="fastpay 1"/> + <button label="L$ 5 支払ã†" label_selected="L$ 5 支払ã†" name="fastpay 5"/> + <button label="L$ 10 支払ã†" label_selected="L$ 10 支払ã†" name="fastpay 10"/> + <button label="L$ 20 支払ã†" label_selected="L$ 20 支払ã†" name="fastpay 20"/> + </panel> + <panel label="検索" name="InputPanel"> + <text name="amount text">ãã®ä»–ã®é‡‘é¡:</text> + <button label="支払ã„" label_selected="支払ã„" name="pay btn"/> + <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_pay_object.xml b/indra/newview/skins/default/xui/ja/floater_pay_object.xml index 637ad496ef..3331cee0e0 100755 --- a/indra/newview/skins/default/xui/ja/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/ja/floater_pay_object.xml @@ -1,29 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - グループã«æ”¯æ‰•ã† - </string> - <string name="payee_resident"> - ä½äººã«æ”¯æ‰•ã† - </string> - <icon name="icon_person" tool_tip="ä½äºº"/> - <text name="payee_name"> - Ericacita Moostopolison - </text> - <text name="object_name_label"> - オブジェクトを介ã—ã¦ï¼š - </text> + <string name="payee_group">グループã«æ”¯æ‰•ã†</string> + <string name="payee_resident">ä½äººã«æ”¯æ‰•ã†</string> + <text name="paying_text">支払ä¸:</text> + <text name="payee_name">Ericacita Moostopolison</text> + <text name="object_name_label">オブジェクトを介ã—ã¦ï¼š</text> <icon name="icon_object" tool_tip="オブジェクト"/> - <text name="object_name_text"> - ... - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - 金é¡ã‚’指定: - </text> - <button label="支払ã„" label_selected="支払ã„" name="pay btn"/> - <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/> + <text name="object_name_text">...</text> + <panel label="検索" name="PatternsPanel"> + <button label="L$ 1 支払ã†" label_selected="L$ 1 支払ã†" name="fastpay 1"/> + <button label="L$ 5 支払ã†" label_selected="L$ 5 支払ã†" name="fastpay 5"/> + <button label="L$ 10 支払ã†" label_selected="L$ 10 支払ã†" name="fastpay 10"/> + <button label="L$ 20 支払ã†" label_selected="L$ 20 支払ã†" name="fastpay 20"/> + </panel> + <panel label="検索" name="InputPanel"> + <text name="amount text">ãã®ä»–ã®é‡‘é¡:</text> + <button label="支払ã„" label_selected="支払ã„" name="pay btn"/> + <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/ja/menu_attachment_self.xml b/indra/newview/skins/default/xui/ja/menu_attachment_self.xml index d87ef8e2a0..e7aa3cfc30 100755 --- a/indra/newview/skins/default/xui/ja/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/ja/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="容姿" name="Change Outfit"/> <menu_item_call label="アウトフィットã®ç·¨é›†" name="Edit Outfit"/> <menu_item_call label="シェイプã®ç·¨é›†" name="Edit My Shape"/> + <menu_item_call label="ホãƒãƒ¼é«˜ã•" name="Hover Height"/> <menu_item_call label="フレンド" name="Friends..."/> <menu_item_call label="グループ" name="Groups..."/> <menu_item_call label="プãƒãƒ•ã‚£ãƒ¼ãƒ«" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/ja/menu_avatar_self.xml b/indra/newview/skins/default/xui/ja/menu_avatar_self.xml index eb8e98059a..a14cfd5876 100755 --- a/indra/newview/skins/default/xui/ja/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/ja/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="容姿" name="Chenge Outfit"/> <menu_item_call label="アウトフィットを編集" name="Edit Outfit"/> <menu_item_call label="シェイプを編集" name="Edit My Shape"/> + <menu_item_call label="ホãƒãƒ¼é«˜ã•" name="Hover Height"/> <menu_item_call label="フレンド" name="Friends..."/> <menu_item_call label="グループ" name="Groups..."/> <menu_item_call label="プãƒãƒ•ã‚£ãƒ¼ãƒ«" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/ja/menu_inventory.xml b/indra/newview/skins/default/xui/ja/menu_inventory.xml index 8d6c983aa7..9a68ed8a6b 100755 --- a/indra/newview/skins/default/xui/ja/menu_inventory.xml +++ b/indra/newview/skins/default/xui/ja/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="リストを作æˆ" name="Marketplace Create Listing"/> + <menu_item_call label="リストを関連付ã‘" name="Marketplace Associate Listing"/> + <menu_item_call label="リストをå–å¾— (æ›´æ–°)" name="Marketplace Get Listing"/> + <menu_item_call label="エラーを確èª" name="Marketplace Check Listing"/> + <menu_item_call label="リストを編集" name="Marketplace Edit Listing"/> + <menu_item_call label="リスト" name="Marketplace List"/> + <menu_item_call label="リストã‹ã‚‰å–り除ã" name="Marketplace Unlist"/> + <menu_item_call label="有効ã«ã™ã‚‹" name="Marketplace Activate"/> + <menu_item_call label="無効ã«ã™ã‚‹" name="Marketplace Deactivate"/> <menu_item_call label="共有" name="Share"/> <menu_item_call label="購入" name="Task Buy"/> <menu_item_call label="é–‹ã" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="è¿½åŠ " name="Wearable Add"/> <menu_item_call label="å–り外ã™" name="Take Off"/> <menu_item_call label="マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«ã‚³ãƒ”ー" name="Merchant Copy"/> - <menu_item_call label="マーケットプレイスã«é€ä¿¡" name="Marketplace Send"/> + <menu_item_call label="マーケットプレイスã®ãƒªã‚¹ãƒˆã«ã‚³ãƒ”ー" name="Marketplace Copy"/> + <menu_item_call label="マーケットプレイスã®ãƒªã‚¹ãƒˆã«ç§»å‹•" name="Marketplace Move"/> <menu_item_call label="ï¼ï¼ã‚ªãƒ—ションãªã—ï¼ï¼" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/ja/menu_marketplace_view.xml b/indra/newview/skins/default/xui/ja/menu_marketplace_view.xml new file mode 100644 index 0000000000..ad36aa3f77 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="åœ¨åº«é«˜é †ã«ä¸¦ã¹æ›¿ãˆ (低ã‹ã‚‰é«˜ã¸)" name="sort_by_stock_amount"/> + <menu_item_check label="リストフォルダã®ã¿è¡¨ç¤º" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml index 40002b4f33..0384dc1efc 100755 --- a/indra/newview/skins/default/xui/ja/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="飛ã¶" name="Fly"/> <menu_item_check label="常ã«èµ°ã‚‹" name="Always Run"/> <menu_item_call label="ç§ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’åœæ¢ã™ã‚‹" name="Stop Animating My Avatar"/> - <menu_item_call label="æ©è¡Œï¼èµ°è¡Œï¼é£›è¡Œ..." name="Walk / run / fly"/> + <menu_item_call label="æ©è¡Œï¼èµ°è¡Œï¼é£›è¡Œ..." name="WalkRunFly"/> </menu> <menu label="ãƒã‚°ã‚¤ãƒ³" name="Status"> <menu_item_check label="一時退å¸ä¸" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="L$ ã®è³¼å…¥..." name="Buy and Sell L$"/> <menu_item_call label="マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹..." name="MerchantOutbox"/> + <menu_item_call label="マーケティングプレイスã®ãƒªã‚¹ãƒˆ..." name="MarketplaceListings"/> <menu_item_call label="マイアカウント..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/> </menu_item_call> @@ -63,7 +64,7 @@ <menu_item_call label="スナップショット" name="Take Snapshot"/> <menu_item_call label="å ´æ‰€ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«" name="Place Profile"/> <menu_item_call label="åœŸåœ°æƒ…å ±" name="About Land"/> - <menu_item_call label="地域 / ä¸å‹•ç”£" name="Region/Estate"/> + <menu_item_call label="地域 / ä¸å‹•ç”£" name="RegionEstate"/> <menu_item_call label="ä¿æœ‰åœ°..." name="My Land"/> <menu_item_call label="ã“ã®åœŸåœ°ã‚’購入" name="Buy Land"/> <menu label="表示" name="LandShow"> @@ -251,6 +252,7 @@ <menu_item_check label="テクスãƒãƒ£ã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Texture Console"/> <menu_item_check label="デãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Debug Console"/> <menu_item_call label="通知コンソール" name="Notifications"/> + <menu_item_check label="地域デãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Region Debug Console"/> <menu_item_check label="ファーストタイマー" name="Fast Timers"/> <menu_item_check label="メモリ" name="Memory"/> <menu_item_check label="風景ã®çµ±è¨ˆ" name="Scene Statistics"/> @@ -354,7 +356,7 @@ <menu_item_check label="挿入ã•ã‚ŒãŸã‚ªãƒ–ジェクトã®ä½ç½®ã® Ping" name="Ping Interpolate Object Positions"/> <menu_item_call label="パケットドãƒãƒƒãƒ—" name="Drop a Packet"/> </menu> - <menu_item_call label="スクリプト付ãカメラをダンプ" name="Dump Scripted Camera"/> + <menu_item_call label="スクリプト付ãカメラをダンプ" name="Dump Scripted Camera"/> <menu label="レコーダー" name="Recorder"> <menu_item_call label="å†ç”Ÿé–‹å§‹" name="Start Playback"/> <menu_item_call label="å†ç”Ÿåœæ¢" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index fba89dc296..5f0ce7a73b 100755 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -128,6 +128,88 @@ システムã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。 <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + 在庫フォルダã¸ã®ã‚³ãƒ”ーã¾ãŸã¯ç§»å‹•ãŒã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ã¾ã—ãŸ: + +'[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + マーケットプレイスã®ãƒªã‚¹ãƒˆã¸ã®ã‚³ãƒ”ーã¾ãŸã¯ç§»å‹•ãŒã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ã¾ã—ãŸ: + +'[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + マーケットプレイスã«ã‚ˆã‚‹å–引ãŒæ¬¡ã®ã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ã¾ã—ãŸ: + +ç†ç”±ï¼š'[ERROR_REASON]' +[ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + ã“ã®è£½å“をリストã«è¡¨ç¤ºã§ããªã„ã‹ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã‚’有効ã«ã§ãã¾ã›ã‚“。通常ã€ã“ã‚Œã¯ãƒªã‚¹ãƒˆèª¬æ˜Žãƒ•ã‚©ãƒ¼ãƒ ã«æƒ…å ±ãŒä¸è¶³ã—ã¦ã„ã‚‹ãŸã‚ã«èµ·ã“ã‚Šã¾ã™ãŒã€ãƒ•ã‚©ãƒ«ãƒ€æ§‹é€ ã®ã‚¨ãƒ©ãƒ¼ãŒåŽŸå› ã®å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚リストを編集ã™ã‚‹ã‹ã€ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ã«ã‚¨ãƒ©ãƒ¼ãŒãªã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。 + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + マーケットプレイスã¸ã®ãƒªã‚¹ãƒˆè¡¨ç¤ºãŒæ¬¡ã®ã‚¨ãƒ©ãƒ¼ã§å¤±æ•—ã—ã¾ã—㟠: + +'[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã®æœ‰åŠ¹åŒ–ãŒæ¬¡ã®ã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ã¾ã—㟠: + +'[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + ã“ã®æ“作ã«ã‚ˆã‚Šã€ã“ã®ãƒªã‚¹ãƒˆã®æœ‰åŠ¹ãªå†…容ãŒå¤‰æ›´ã•ã‚Œã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ + <usetemplate ignoretext="マーケットプレイスã§æœ‰åŠ¹ãªãƒªã‚¹ãƒˆã‚’変更ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + マーケットプレイスã®ãƒªã‚¹ãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã¯å…ƒã®å ´æ‰€ã‹ã‚‰ã‚³ãƒ”ーã•ã‚Œã‚‹ã®ã§ã¯ãªãã€ç§»å‹•ã—ã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ + <usetemplate ignoretext="アイテムをインベントリã‹ã‚‰ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã«ç§»å‹•ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + リストフォルダを移動ã¾ãŸã¯å‰Šé™¤ã™ã‚‹ã¨ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã®ãƒªã‚¹ãƒˆãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚マーケットプレイスã®ãƒªã‚¹ãƒˆã‚’ç¶æŒã™ã‚‹å ´åˆã¯ã€å¤‰æ›´ã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã®ä¸èº«ã‚’移動ã¾ãŸã¯å‰Šé™¤ã—ã¦ãã ã•ã„。続ã‘ã¾ã™ã‹ï¼Ÿ + <usetemplate ignoretext="マーケットプレイスã‹ã‚‰ãƒªã‚¹ãƒˆã‚’移動ã¾ãŸã¯å‰Šé™¤ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã® 1 ã¤ã¾ãŸã¯è¤‡æ•°ã‚’マーケットプレイスã«ã‚³ãƒ”ーã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。移動ã™ã‚‹ã‹ã€ç½®ã去りã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã€‚ + <usetemplate canceltext="å–り消ã—" ignoretext="ã‚³ãƒ”ãƒ¼ä»˜åŠ ã‚¢ã‚¤ãƒ†ãƒ ã‚’å«ã‚€é¸æŠžå†…容をマーケットプレイスã¸ã‚³ãƒ”ーã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="yesnocancelbuttons" notext="アイテムを移動ã—ãªã„" yestext="アイテムを移動"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + ã“ã®æ“作ã«ã‚ˆã‚Šã€ã“ã®ãƒªã‚¹ãƒˆãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ + <usetemplate ignoretext="マーケットプレイスã§æœ‰åŠ¹ãªãƒªã‚¹ãƒˆã‚’削除ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + ã“ã®æ“作ã«ã‚ˆã‚Šã€ç¾åœ¨ã®ãƒªã‚¹ãƒˆã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ + <usetemplate ignoretext="マーケットプレイスã§ãƒªã‚¹ãƒˆã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã‚’無効ã«ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + ã“ã®ãƒªã‚¹ãƒˆã‚’アップデートã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ +[[URL] ã“ã“をクリック] ã—ã¦ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã§ç·¨é›†ã—ã¾ã™ã€‚ + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + マーケットプレイスã®ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ã«ã‚ã‚‹è¡£æœã‚„ボディパーツをç€ç”¨ã§ãã¾ã›ã‚“。 + </notification> + <notification name="AlertMerchantListingInvalidID"> + リスト ID ãŒç„¡åŠ¹ã§ã™ã€‚ + </notification> + <notification name="AlertMerchantListingActivateRequired"> + ã“ã®ãƒªã‚¹ãƒˆã«ã¯è¤‡æ•°ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ãŒã‚ã‚‹ã‹ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ãŒã‚ã‚Šã¾ã›ã‚“。後ã§ã€å˜ç‹¬ã§ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦æœ‰åŠ¹ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + <usetemplate ignoretext="複数ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã®ã‚るリストを作æˆã™ã‚‹ã¨ãã«ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã®æœ‰åŠ¹åŒ–ã«é–¢ã™ã‚‹è¦å‘ŠãŒè¡¨ç¤ºã•ã‚Œã¾ã™" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + å„種ã®åœ¨åº«å“目を別々ã®åœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ã«åˆ†ã‘ãŸãŸã‚ã€ãƒ•ã‚©ãƒ«ãƒ€ã¯ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã§ãるよã†ã«é…ç½®ã•ã‚Œã¦ã„ã¾ã™ã€‚ + <usetemplate ignoretext="リストã«è¡¨ç¤ºã™ã‚‹å‰ã«åœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ãŒåˆ†å‰²ã•ã‚Œã‚‹ã¨ã€è¦å‘ŠãŒè¡¨ç¤ºã•ã‚Œã¾ã™" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + 在庫ãŒç©ºã®ãŸã‚ã€ãƒªã‚¹ãƒˆã‚’削除ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã€åœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ã«ãƒ¦ãƒ‹ãƒƒãƒˆã‚’è¿½åŠ ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + <usetemplate ignoretext="在庫フォルダãŒç©ºã®ãŸã‚ã«ãƒªã‚¹ãƒˆãŒè¡¨ç¤ºã•ã‚Œãªã„ã¨è¦å‘ŠãŒè¡¨ç¤ºã•ã‚Œã¾ã™" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> 次ã®ç†ç”±ã§ã€ã‚¹ã‚¯ãƒªãƒ—ト用テã‚ストã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰æ™‚ã«å•é¡ŒãŒèµ·ã“ã‚Šã¾ã—ãŸã€‚ [REASON] @@ -495,6 +577,10 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã 変更をä¿å˜ã—ã¾ã™ã‹ï¼Ÿ <usetemplate canceltext="å–り消ã—" name="yesnocancelbuttons" notext="ä¿å˜ã—ãªã„" yestext="ä¿å˜"/> </notification> + <notification name="DeleteNotecard"> + ノートカードを削除ã—ã¾ã™ã‹? + <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> ジェスãƒãƒ£ãƒ¼ã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ ステップãŒå¤šã™ãŽã¾ã™ã€‚ @@ -1906,6 +1992,9 @@ http://wiki.secondlife.com/wiki/Setting_your_display_name ã‚’å‚ç…§ã—ã¦ãã ã 訪å•ã—よã†ã¨ã—ã¦ã„る地域(リージョン)ã«ã¯ç¾åœ¨ã®ç’°å¢ƒè¨å®šã‚’超ãˆã‚‹ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚「ミー〠> 「環境è¨å®šã€ > 「一般ã€ã‚’é¸æŠžã—ã¦ã€ç’°å¢ƒè¨å®šã‚’変更ã§ãã¾ã™ã€‚ <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> 訪å•ã—よã†ã¨ã—ã¦ã„る地域(リージョン)ã«ã¯ã€æˆäººã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹ [REGIONMATURITY] コンテンツãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ <url name="url"> @@ -2198,6 +2287,10 @@ L$ [AMOUNT] ã§ã€ã“ã®ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã‚’今ã™ã公開ã—ã¾ã™ã <ignore name="ignore" text="オブジェクトを作æˆä¸ã«ã€money() スクリプトを入れãšã«ã€Œã‚ªãƒ–ジェクトã«æ”¯æ‰•ã†ã€ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’è¨å®šã—ãŸã¨ã"/> </form> </notification> + <notification name="PayConfirmation"> + L$[AMOUNT] ã‚’ [TARGET] ã«æ”¯æ‰•ã†ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 + <usetemplate ignoretext="支払ã„å‰ã«ç¢ºèª (åˆè¨ˆé‡‘é¡ãŒ L$200 以上ã®å ´åˆ)" name="okcancelignore" notext="å–り消ã—" yestext="支払ã„"/> + </notification> <notification name="OpenObjectCannotCopy"> ã“ã®ã‚ªãƒ–ジェクトã«ã¯ã€ã‚ãªãŸãŒã‚³ãƒ”ーã§ãるアイテムã¯ã‚ã‚Šã¾ã›ã‚“。 </notification> @@ -2743,9 +2836,6 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã <notification name="NoValidCircuit"> 回路コードãŒç„¡åŠ¹ã§ã™ã€‚ </notification> - <notification name="NoValidTimestamp"> - タイムスタンプãŒç„¡åŠ¹ã§ã™ã€‚ - </notification> <notification name="NoPendingConnection"> 接続を生æˆã§ãã¾ã›ã‚“。 </notification> @@ -3881,9 +3971,11 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ </notification> <notification name="TeleportedByAttachment"> [ITEM_ID] ã¸ã®ã‚¢ã‚¿ãƒƒãƒãƒ¡ãƒ³ãƒˆã«ã‚ˆã£ã¦ã€ã‚ãªãŸã¯ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚ + <usetemplate ignoretext="テレãƒãƒ¼ãƒˆï¼šã‚¢ã‚¿ãƒƒãƒãƒ¡ãƒ³ãƒˆã«ã‚ˆã‚Šãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¾ã—ãŸ" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> 区画 '[PARCEL_NAME]' ã®ã‚ªãƒ–ジェクト '[OBJECT_NAME]' ã«ã‚ˆã£ã¦ã€ã‚ãªãŸã¯ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚ + <usetemplate ignoretext="テレãƒãƒ¼ãƒˆï¼šåŒºç”»ä¸Šã®ã‚ªãƒ–ジェクトã«ã‚ˆã‚Šãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¾ã—ãŸ" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> [OWNER_ID] ãŒæ‰€æœ‰ã—ã¦ã„るオブジェクト '[OBJECT_NAME]' ã«ã‚ˆã£ã¦ã€ã‚ãªãŸã¯ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚ @@ -4215,7 +4307,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ <usetemplate ignoretext="ファイルを移動ã§ãã¾ã›ã‚“。以å‰ã®ãƒ‘スãŒãƒªã‚¹ãƒˆã‚¢ã•ã‚Œã¾ã—ãŸã€‚" name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - 次ã®ç†ç”±ã«ã‚ˆã‚Šã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆæ¨©é™ã‚’ä¿å˜ã™ã‚‹ã¨ãã«å•é¡ŒãŒã‚ã‚Šã¾ã—ãŸ: [REASON]。後ã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆæ¨©é™ã‚’è¨å®šã—ã¦ãã ã•ã„。 + デフォルトã®ã‚ªãƒ–ジェクト権é™ã‚’ä¿å˜ã™ã‚‹ã¨ãã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ: [REASON]。後ã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®æ¨©é™ã‚’è¨å®šã—ã¦ãã ã•ã„。 <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/ja/panel_login.xml b/indra/newview/skins/default/xui/ja/panel_login.xml index c5d5330eb4..5f2007e0da 100755 --- a/indra/newview/skins/default/xui/ja/panel_login.xml +++ b/indra/newview/skins/default/xui/ja/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=ja - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=ja</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="ユーザーå" name="username_combo" tool_tip="登録時ã«è‡ªåˆ†ã§é¸ã‚“ã ユーザーå(例:bobsmith12ã€Steller Sunshineãªã©ï¼‰"/> <line_editor label="パスワード" name="password_edit"/> - <check_box label="記憶ã™ã‚‹" name="remember_check"/> - <text name="forgot_password_text"> - パスワードを忘れãŸå ´åˆ - </text> - <button label="ãƒã‚°ã‚¤ãƒ³" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - å‰å›žã®å ´æ‰€ - </text> <combo_box label="ãŠæ°—ã«å…¥ã‚Šã®å ´æ‰€" name="start_location_combo"> + <combo_box.item label="最後ã«ãƒã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€" name="MyLastLocation"/> <combo_box.item label="ホーム" name="MyHome"/> </combo_box> - <button label="ãƒã‚°ã‚¤ãƒ³" name="connect_favorite_btn"/> - <line_editor label="å ´æ‰€ã‚’å…¥åŠ›" name="location_edit"/> - <button label="ãƒã‚°ã‚¤ãƒ³" name="connect_location_btn"/> + <button label="ãƒã‚°ã‚¤ãƒ³" name="connect_btn"/> + <check_box label="記憶ã™ã‚‹" name="remember_check"/> + <text name="forgot_password_text">パスワードを忘れãŸå ´åˆ</text> <combo_box label="グリッドをé¸æŠž" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/ja/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/ja/panel_marketplace_listings.xml new file mode 100644 index 0000000000..a9218bebff --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="マーケットプレイス" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="表示/並ã¹æ›¿ãˆã‚ªãƒ—ション"/> + <button name="add_btn" tool_tip="æ–°è¦ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ã®ä½œæˆ"/> + <button label="エラーを確èª" name="audit_btn" tool_tip="マーケットプレイスã®ãƒªã‚¹ãƒˆã‚’確èª"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="マーケットプレイスã®ãƒªã‚¹ãƒˆã‚’フィルタ" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..43cb64d6ba --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ã™ã¹ã¦" name="All Items" tool_tip="ã“ã“ã«ã‚¢ã‚¤ãƒ†ãƒ をドラッグ&ドãƒãƒƒãƒ—ã—ã¦ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã—ã¾ã™"/> diff --git a/indra/newview/skins/default/xui/ja/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..7f27231cbd --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="リストã«æŽ²è¼‰" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..215be9ae6d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="関連付ã‘ã•ã‚Œã¦ã„ãªã„" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..04530477f6 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="リストã‹ã‚‰å‰Šé™¤æ¸ˆã¿" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml index 569c07ad47..569c07ad47 100755..100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml index f09643d562..2e1446d450 100755 --- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - パケットæ失 - </panel.string> - <panel.string name="bandwidth_tooltip"> - 帯域幅 - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt]) - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">パケットæ失</panel.string> + <panel.string name="bandwidth_tooltip">帯域幅</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt])</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel left="-370" name="balance_bg" width="160"> - <text name="balance" tool_tip="クリックã—㦠L$ 残高を更新" value="L$20"/> + <text name="balance" tool_tip="クリックã—㦠L$ 残高を更新" value="L$??"/> <button label="L$ ã®è³¼å…¥" name="buyL" tool_tip="クリックã—㦠L$ を購入ã—ã¾ã™"/> - <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開ã" width="40"/> + <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開ã" width="40"/> </panel> - <text name="TimeText" tool_tip="ç¾åœ¨æ™‚刻(太平洋)"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="ç¾åœ¨æ™‚刻(太平洋)">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="ã™ã¹ã¦ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’開始・åœæ¢ï¼ˆéŸ³æ¥½ã€ãƒ“デオã€Web ページ)"/> <button name="volume_btn" tool_tip="ã‚°ãƒãƒ¼ãƒãƒ«éŸ³é‡è¨å®š"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml index 56a8b0e097..d888470846 100755 --- a/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckNextOwnerTransfer" tool_tip="次ã®æ‰€æœ‰è€…ã¯ã“ã®ã‚ªãƒ–ジェクトを他人ã«ã‚ã’ãŸã‚Šå†è²©ã§ãã¾ã™"/> </panel> <check_box label="販売ä¸" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="コピー" name="Copy"/> + <combo_box.item label="コンテンツ" name="Contents"/> <combo_box.item label="オリジナル" name="Original"/> </combo_box> <spinner label="ä¾¡æ ¼ï¼š L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml b/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml index 4f65c8477b..858307800b 100755 --- a/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="オブジェクトã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«"> - <panel.string name="text deed continued"> - è²æ¸¡ - </panel.string> - <panel.string name="text deed"> - è²æ¸¡ - </panel.string> - <panel.string name="text modify info 1"> - ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™ - </panel.string> - <panel.string name="text modify info 2"> - ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™ - </panel.string> - <panel.string name="text modify info 3"> - ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“ - </panel.string> - <panel.string name="text modify info 4"> - ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“ - </panel.string> - <panel.string name="text modify info 5"> - 地域(リージョン)ã®å¢ƒç•Œã‚’越ãˆã¦ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“ - </panel.string> - <panel.string name="text modify info 6"> - 地域(リージョン)ã®å¢ƒç•Œã‚’越ãˆã¦ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“ - </panel.string> - <panel.string name="text modify warning"> - ã“ã®ã‚ªãƒ–ジェクトã«ã¯ã€ãƒ‘ーツãŒãƒªãƒ³ã‚¯ã•ã‚Œã¦ã„ã¾ã™ - </panel.string> - <panel.string name="Cost Default"> - ä¾¡æ ¼ï¼š L$ - </panel.string> - <panel.string name="Cost Total"> - åˆè¨ˆï¼š L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Price Per: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Mixed Price - </panel.string> - <panel.string name="Sale Mixed"> - Mixed Sale - </panel.string> + <panel.string name="text deed continued">è²æ¸¡</panel.string> + <panel.string name="text deed">è²æ¸¡</panel.string> + <panel.string name="text modify info 1">ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™</panel.string> + <panel.string name="text modify info 2">ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™</panel.string> + <panel.string name="text modify info 3">ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“</panel.string> + <panel.string name="text modify info 4">ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“</panel.string> + <panel.string name="text modify info 5">地域(リージョン)ã®å¢ƒç•Œã‚’越ãˆã¦ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“</panel.string> + <panel.string name="text modify info 6">地域(リージョン)ã®å¢ƒç•Œã‚’越ãˆã¦ã“れらã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã›ã‚“</panel.string> + <panel.string name="text modify warning">ã“ã®ã‚ªãƒ–ジェクトã«ã¯ã€ãƒ‘ーツãŒãƒªãƒ³ã‚¯ã•ã‚Œã¦ã„ã¾ã™</panel.string> + <panel.string name="Cost Default">ä¾¡æ ¼ï¼š L$</panel.string> + <panel.string name="Cost Total">åˆè¨ˆä¾¡æ ¼: L$</panel.string> + <panel.string name="Cost Per Unit">Price Per: L$</panel.string> + <panel.string name="Cost Mixed">Mixed Price</panel.string> + <panel.string name="Sale Mixed">Mixed Sale</panel.string> <text name="title" value="オブジェクトã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«"/> <text name="where" value="(インワールド)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - åå‰ï¼š - </text> - <text name="Description:"> - 説明: - </text> - <text name="CreatorNameLabel"> - 制作者: - </text> - <text name="Owner:"> - 所有者: - </text> - <text name="Group_label"> - グループ: - </text> + <text name="Name:">åå‰ï¼š</text> + <text name="Description:">説明:</text> + <text name="CreatorNameLabel">制作者:</text> + <text name="Owner:">所有者:</text> + <text name="Group_label">グループ:</text> <button name="button set group" tool_tip="ã“ã®ã‚ªãƒ–ジェクト権é™ã‚’共有ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¾ã™"/> <name_box initial_value="ãƒãƒ¼ãƒ‡ã‚£ãƒ³ã‚°..." name="Group Name Proxy"/> <button label="è²æ¸¡" label_selected="è²æ¸¡" name="button deed" tool_tip="ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’è²æ¸¡ã™ã‚‹ã¨ã€Œæ¬¡ã®æ‰€æœ‰è€…ã€ã®æ¨©é™ãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚ グループ共有オブジェクトã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ•ã‚£ã‚µãƒ¼ãŒè²æ¸¡ã§ãã¾ã™ã€‚"/> - <text name="label click action"> - クリックã§ï¼š - </text> + <text name="label click action">クリックã§ï¼š</text> <combo_box name="clickaction"> <combo_box.item label="触る(デフォルト)" name="Touch/grab(default)"/> <combo_box.item label="オブジェクトã«åº§ã‚‹" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="ズーム" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™ - </text> - <text name="Anyone can:"> - 全員: - </text> + <text name="perm_modify">ã“ã®ã‚ªãƒ–ジェクトを修æ£ã§ãã¾ã™</text> + <text name="Anyone can:">全員:</text> <check_box label="コピー" name="checkbox allow everyone copy"/> <check_box label="移動" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - グループ: - </text> + <text name="GroupLabel">グループ:</text> <check_box label="共有" name="checkbox share with group" tool_tip="è¨å®šã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¡ãƒ³ãƒãƒ¼å…¨å“¡ã«ã“ã®ã‚ªãƒ–ジェクトã®ä¿®æ£æ¨©é™ã‚’与ãˆã¾ã™ã€‚ è²æ¸¡ã—ãªã„é™ã‚Šã€å½¹å‰²åˆ¶é™ã‚’有効ã«ã¯ã§ãã¾ã›ã‚“。"/> - <text name="NextOwnerLabel"> - 次ã®æ‰€æœ‰è€…: - </text> + <text name="NextOwnerLabel">次ã®æ‰€æœ‰è€…:</text> <check_box label="ä¿®æ£" name="checkbox next owner can modify"/> <check_box label="コピー" name="checkbox next owner can copy"/> <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="checkbox next owner can transfer" tool_tip="次ã®æ‰€æœ‰è€…ã¯ã“ã®ã‚ªãƒ–ジェクトを他人ã«ã‚ã’ãŸã‚Šå†è²©ã§ãã¾ã™"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="ä¾¡æ ¼ï¼š L$" name="Edit Cost"/> <check_box label="検索ã«è¡¨ç¤º" name="search_check" tool_tip="ã“ã®ã‚ªãƒ–ジェクトを検索çµæžœã«è¡¨ç¤ºã—ã¾ã™"/> - <text name="pathfinding_attributes_label"> - パスファインディング属性: - </text> - <text name="B:"> - B. - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">パスファインディング属性:</text> + <text name="B:">B.</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="é–‹ã" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index e825389895..22eb9ce888 100755 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -453,28 +453,46 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> <string name="TooltipOutboxDragToWorld"> - マーãƒãƒ£ãƒ³ãƒˆãƒœãƒƒã‚¯ã‚¹å†…ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ Rez ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + マーケットプレイスã®ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ã‹ã‚‰ã‚¢ã‚¤ãƒ†ãƒ ã‚’ Rez ã§ãã¾ã›ã‚“ + </string> + <string name="TooltipOutboxWorn"> + ç€ã¦ã„るアイテムをマーケットプレイスã®ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ã«ç½®ãã“ã¨ã¯ã§ãã¾ã›ã‚“ + </string> + <string name="TooltipOutboxFolderLevels"> + ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®æ·±ã•ãŒ [AMOUNT] 階層を超ãˆã¦ã„ã¾ã™å¿…è¦ã«å¿œã˜ã¦ã‚¢ã‚¤ãƒ†ãƒ ã‚’ç®±ã«å…¥ã‚Œã€ãƒ•ã‚©ãƒ«ãƒ€ã®éšŽå±¤ã‚’減らã—ã¾ã™ã€‚ + </string> + <string name="TooltipOutboxTooManyFolders"> + サブフォルダ数㌠[AMOUNT] 個を超ãˆã¦ã„ã¾ã™ã€‚å¿…è¦ã«å¿œã˜ã¦ã‚¢ã‚¤ãƒ†ãƒ ã‚’ç®±ã«å…¥ã‚Œã€ãƒªã‚¹ãƒˆã®ãƒ•ã‚©ãƒ«ãƒ€éšŽå±¤ã‚’減らã—ã¾ã™ã€‚ + </string> + <string name="TooltipOutboxTooManyObjects"> + アイテム数㌠[AMOUNT] 個を超ãˆã¦ã„ã¾ã™ã€‚1 ã¤ã®ãƒªã‚¹ãƒˆå†…㧠[AMOUNT] 個を超ãˆã‚‹ã‚¢ã‚¤ãƒ†ãƒ を販売ã™ã‚‹ãŸã‚ã«ã¯ã€ã„ãã¤ã‹ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ç®±ã«å…¥ã‚Œã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + </string> + <string name="TooltipOutboxTooManyStockItems"> + 在庫アイテム数㌠[AMOUNT] 個を超ãˆã¦ã„ã¾ã™ã€‚ + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + アイテムã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ã¯ã€Œã™ã¹ã¦ã€ã‚¿ãƒ–ã«ã‚ˆã£ã¦ã®ã¿ãƒ‰ãƒãƒƒãƒ—ã§ãã¾ã™ã€‚ã“ã®ã‚¿ãƒ–ã‚’é¸æŠžã—ã¦ã‹ã‚‰ã€ã‚‚ã†ä¸€åº¦ã‚¢ã‚¤ãƒ†ãƒ ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦ãã ã•ã„。 </string> <string name="TooltipOutboxNoTransfer"> - ã“れらオブジェクト㮠1 ã¤ã¾ãŸã¯è¤‡æ•°ã¯å£²ã‚Šæ¸¡ã—ãŸã‚Šè²æ¸¡ã—ãŸã‚Šã§ããªã„ã‚‚ã®ã§ã™ã€‚ + ã“れらã®ã‚ªãƒ–ジェクト㮠1 ã¤ã¾ãŸã¯è¤‡æ•°ã¯å£²ã‚Šæ¸¡ã—ãŸã‚Šè²æ¸¡ã—ãŸã‚Šã§ããªã„ã‚‚ã®ã§ã™ </string> <string name="TooltipOutboxNotInInventory"> - マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã§ã¯ã€ã”自分ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‹ã‚‰ã®ã‚¢ã‚¤ãƒ†ãƒ ã—ã‹å—ã‘入れるã“ã¨ãŒã§ãã¾ã›ã‚“ + アイテムã¯ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‹ã‚‰ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã¸ã®ç§»å‹•ã®ã¿ã§ãã¾ã™ </string> - <string name="TooltipOutboxWorn"> - ç€ç”¨ã—ã¦ã„るアイテムをマーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«å…¥ã‚Œã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + <string name="TooltipOutboxLinked"> + リンクã•ã‚ŒãŸç›¸æ‰‹ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ã‚’マーケットプレイスã«ç½®ãã“ã¨ã¯ã§ãã¾ã›ã‚“ </string> <string name="TooltipOutboxCallingCard"> - コーリングカードをマーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«å…¥ã‚Œã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + コーリングカードをマーケットプレイスã«ç½®ãã“ã¨ã¯ã§ãã¾ã›ã‚“ </string> - <string name="TooltipOutboxFolderLevels"> - ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®æ·±ã•ãŒ 3 を超ãˆã¦ã„ã¾ã™ + <string name="TooltipOutboxDragActive"> + 表示ã•ã‚Œã¦ã„るリストを移動ã§ãã¾ã›ã‚“ </string> - <string name="TooltipOutboxTooManyFolders"> - 最上ä½ãƒ•ã‚©ãƒ«ãƒ€å†…ã®ã‚µãƒ–フォルダ数㌠20 を超ãˆã¦ã„ã¾ã™ + <string name="TooltipOutboxCannotMoveRoot"> + ルートフォルダをリストã«è¡¨ç¤ºã™ã‚‹ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスを移動ã§ãã¾ã›ã‚“ </string> - <string name="TooltipOutboxTooManyObjects"> - 最上ä½ãƒ•ã‚©ãƒ«ãƒ€å†…ã®ã‚¢ã‚¤ãƒ†ãƒ 数㌠200 を超ãˆã¦ã„ã¾ã™ + <string name="TooltipOutboxMixedStock"> + 在庫フォルダ内ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã™ã¹ã¦åŒã˜ç¨®é¡žã¨æ¨©é™ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ </string> <string name="TooltipDragOntoOwnChild"> フォルダをãã®åフォルダã«ç§»å‹•ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ @@ -1062,7 +1080,7 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="AgentNameSubst"> (ã‚ãªãŸ) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> 土地ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã‚’管ç†ã™ã‚‹ã¨ãã«ã‚¢ãƒ©ãƒ¼ãƒˆã‚’表示ã—ãªã„ </string> @@ -1129,6 +1147,12 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="bitmap_image_files"> ãƒ“ãƒƒãƒˆãƒžãƒƒãƒ—ç”»åƒ </string> + <string name="png_image_files"> + PNG ç”»åƒ + </string> + <string name="save_texture_image_files"> + Targa ã¾ãŸã¯ PNG ç”»åƒ + </string> <string name="avi_movie_file"> AVI ムービーファイル </string> @@ -1378,6 +1402,9 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="FavoritesNoMatchingItems"> ã“ã“ã«ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’ドラッグã—ã¦ãŠæ°—ã«å…¥ã‚Šã«è¿½åŠ ã—ã¾ã™ã€‚ </string> + <string name="MarketplaceNoMatchingItems"> + アイテムãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚検索文å—列ã®ã‚¹ãƒšãƒ«ã‚’確èªã—ã¦ã€ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。 + </string> <string name="InventoryNoTexture"> インベントリ内ã«ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚³ãƒ”ーãŒã‚ã‚Šã¾ã›ã‚“ </string> @@ -1425,29 +1452,95 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="InventoryOutboxError"> [[MARKETPLACE_CREATE_STORE_URL] マーケットプレイス ストア] ãŒã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã¦ã„ã¾ã™ã€‚ </string> + <string name="InventoryMarketplaceError"> + ã“ã®æ©Ÿèƒ½ã¯ã€ç¾åœ¨ã€ãƒ™ãƒ¼ã‚¿ç‰ˆã®æ©Ÿèƒ½ã§ã™ã€‚å‚åŠ ã™ã‚‹ã«ã¯ã€ã“ã® [http://goo.gl/forms/FCQ7UXkakz Google form] ã«åå‰ã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + マーケットプレイスã®ãƒªã‚¹ãƒˆãƒ•ã‚©ãƒ«ãƒ€ãŒç©ºã§ã™ã€‚ + </string> + <string name="InventoryMarketplaceListingsNoItems"> + [[MARKETPLACE_DASHBOARD_URL] マーケットプレイス]ã«è²©å£²ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ を一覧ã™ã‚‹ã«ã¯ã€ãƒ•ã‚©ãƒ«ãƒ€ã‚’ã“ã®ã‚¨ãƒªã‚¢ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¾ã™ã€‚ + </string> + <string name="Marketplace Validation Warning Stock"> + ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã«åœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ãŒå«ã¾ã‚Œãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : エラー:在庫フォルダ内ã®ã™ã¹ã¦ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚³ãƒ”ーä¸å¯ã§åŒã˜ç¨®é¡žã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : エラー:在庫フォルダã«ã‚µãƒ–フォルダをå«ã‚ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Warning Empty"> + : è¦å‘Šï¼šãƒ•ã‚©ãƒ«ãƒ€ã«ã‚¢ã‚¤ãƒ†ãƒ ãŒå«ã¾ã‚Œã¦ã„ã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Warning Create Stock"> + : è¦å‘Šï¼šåœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ã‚’作æˆã—ã¦ã„ã¾ã™ + </string> + <string name="Marketplace Validation Warning Create Version"> + : è¦å‘Šï¼šãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ä½œæˆä¸ + </string> + <string name="Marketplace Validation Warning Move"> + : è¦å‘Šï¼šã‚¢ã‚¤ãƒ†ãƒ ç§»å‹•ä¸ + </string> + <string name="Marketplace Validation Warning Delete"> + : è¦å‘Šï¼šãƒ•ã‚©ãƒ«ãƒ€ã®ä¸èº«ãŒåœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ã«ç§»ã•ã‚Œã¾ã—ãŸã€‚空ã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’削除ã—ã¾ã™ + </string> + <string name="Marketplace Validation Error Stock Item"> + : エラー:在庫フォルダã«ã‚³ãƒ”ーä¸å¯ã‚¢ã‚¤ãƒ†ãƒ ã‚’å«ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : è¦å‘Šï¼šãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã«ã‚¢ã‚¤ãƒ†ãƒ ãŒå«ã¾ã‚Œã¦ã„ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Error"> + : エラー: + </string> + <string name="Marketplace Validation Warning"> + : è¦å‘Šï¼š + </string> + <string name="Marketplace Validation Error Empty Version"> + : è¦å‘Šï¼šãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ•ã‚©ãƒ«ãƒ€ã«ã¯ã€æœ€ä½Ž 1 アイテムãŒå«ã¾ã‚Œãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ + </string> + <string name="Marketplace Validation Error Empty Stock"> + : è¦å‘Šï¼šåœ¨åº«ãƒ•ã‚©ãƒ«ãƒ€ã«ã¯ã€æœ€ä½Ž 1 アイテムãŒå«ã¾ã‚Œã¦ã„ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“ + </string> + <string name="Marketplace Validation No Error"> + å ±å‘Šã™ã‚‹ã‚¨ãƒ©ãƒ¼ã¾ãŸã¯è¦å‘Šã¯ã‚ã‚Šã¾ã›ã‚“ + </string> <string name="Marketplace Error None"> エラーãªã— </string> + <string name="Marketplace Error Prefix"> + エラー: + </string> <string name="Marketplace Error Not Merchant"> - エラー:マーケットプレイスã«ã‚¢ã‚¤ãƒ†ãƒ ã‚’é€ã‚‹å‰ã«ã€ã‚ãªãŸè‡ªèº«ã‚’マーãƒãƒ£ãƒ³ãƒˆç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼ˆç™»éŒ²ã¯ç„¡æ–™ã§ã™ï¼‰ã€‚ + マーケットプレイスã«å•†å“ã‚’é€ã‚‹å‰ã«ã€ã‚ãªãŸè‡ªèº«ã‚’マーãƒãƒ£ãƒ³ãƒˆç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼ˆç™»éŒ²ã¯ç„¡æ–™ã§ã™ï¼‰ã€‚ + </string> + <string name="Marketplace Error Not Accepted"> + アイテムをãã®ãƒ•ã‚©ãƒ«ãƒ€ã«ç§»å‹•ã§ãã¾ã›ã‚“。 </string> - <string name="Marketplace Error Empty Folder"> - エラー:ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ã¯ç©ºã§ã™ã€‚ + <string name="Marketplace Error Unsellable Item"> + ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をマーケットプレイスã§è²©å£²ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 </string> - <string name="Marketplace Error Unassociated Products"> - エラー:ã‚ãªãŸã®ãƒžãƒ¼ãƒãƒ£ãƒ³ãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ã€å•†å“ã«é–¢é€£ä»˜ã‘られã¦ã„ãªã„アイテムãŒå¤šã™ãŽã‚‹ãŸã‚ã€ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をアップãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚¨ãƒ©ãƒ¼ã‚’解消ã™ã‚‹ã«ã¯ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイス㮠Web サイトã«ãƒã‚°ã‚¤ãƒ³ã—ã€é–¢é€£ä»˜ã‘られã¦ã„ãªã„アイテムã®æ•°ã‚’減らã—ã¦ãã ã•ã„。 + <string name="MarketplaceNoID"> + Mkt ID ãªã— </string> - <string name="Marketplace Error Object Limit"> - エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã«å«ã¾ã‚Œã‚‹ã‚ªãƒ–ジェクトãŒå¤šã™ãŽã¾ã™ã€‚オブジェクトをã„ãã¤ã‹ãƒœãƒƒã‚¯ã‚¹ã«ã¾ã¨ã‚ã€ã‚ªãƒ–ジェクト数を200以下ã«æ¸›ã‚‰ã—ã¦ãã ã•ã„。 + <string name="MarketplaceLive"> + リスト掲載済㿠</string> - <string name="Marketplace Error Folder Depth"> - エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®éšŽå±¤ãŒå¤šã™ãŽã¾ã™ã€‚ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã‚’ 3 階層以内ã«ã¾ã¨ã‚ç›´ã—ã¦ãã ã•ã„。 + <string name="MarketplaceActive"> + 有効 </string> - <string name="Marketplace Error Unsellable Item"> - エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をマーケットプレイスã§è²©å£²ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + <string name="MarketplaceMax"> + 最大 </string> - <string name="Marketplace Error Internal Import"> - エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã«é–¢ã—ã¦å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ãŠè©¦ã—ãã ã•ã„。 + <string name="MarketplaceStock"> + 在庫 + </string> + <string name="MarketplaceNoStock"> + 在庫ãªã— + </string> + <string name="MarketplaceUpdating"> + アップデートä¸... </string> <string name="Open landmarks"> ランドマークを開ã @@ -1468,6 +1561,7 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 コンテンツãªã— </string> <string name="WornOnAttachmentPoint" value=" ([ATTACHMENT_POINT] ã«è£…ç€ä¸ï¼‰"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (アクティブ)"/> <string name="PermYes"> ã¯ã„ @@ -1738,6 +1832,15 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="Invalid Attachment"> 装ç€å…ˆãŒæ£ã—ãã‚ã‚Šã¾ã›ã‚“ </string> + <string name="ATTACHMENT_MISSING_ITEM"> + エラー:アイテムãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + エラー:ベースアイテムãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + エラー:オブジェクトã¯ç¾åœ¨ã®ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆå†…ã«ã‚ã‚Šã¾ã™ãŒã€æ·»ä»˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] </string> @@ -1873,9 +1976,6 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="CompileQueueUnknownFailure"> åŽŸå› ä¸æ˜Žã®å¤±æ•—ã«ã‚ˆã‚Šãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ãŒã§ãã¾ã›ã‚“ </string> - <string name="CompileNoExperiencePerm"> - [EXPERIENCE] 体験ã«ã‚ˆã‚‹ [SCRIPT] スクリプトã®ã‚¹ã‚ップ。 - </string> <string name="CompileQueueTitle"> リコンパイル進行 </string> @@ -1909,6 +2009,9 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="SaveComplete"> ä¿å˜å®Œäº†ã€‚ </string> + <string name="UploadFailed"> + ファイルã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ãŒå¤±æ•—ã—ã¾ã—ãŸ: + </string> <string name="ObjectOutOfRange"> スクリプト(オブジェクトãŒç¯„囲外ã«ã‚ã‚Šã¾ã™ï¼‰ </string> @@ -1918,6 +2021,9 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="GroupsNone"> ãªã— </string> + <string name="CompileNoExperiencePerm"> + [EXPERIENCE] 体験ã«ã‚ˆã‚‹ [SCRIPT] スクリプトã®ã‚¹ã‚ップ。 + </string> <string name="Group" value=" (グループ)"/> <string name="Unknown"> (ä¸æ˜Žï¼‰ @@ -5069,6 +5175,9 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="Command_Marketplace_Label"> マーケットプレイス </string> + <string name="Command_MarketplaceListings_Label"> + マーケットプレイス + </string> <string name="Command_MiniMap_Label"> ミニマップ </string> @@ -5156,6 +5265,9 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="Command_Marketplace_Tooltip"> ショッピングã«å‡ºæŽ›ã‘ã‚‹ </string> + <string name="Command_MarketplaceListings_Tooltip"> + 創作アイテムを販売ã—ã¾ã™ + </string> <string name="Command_MiniMap_Tooltip"> è¿‘ãã®äººã‚’表示ã™ã‚‹ </string> @@ -5267,6 +5379,18 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="UserDictionary"> [User] </string> + <string name="logging_calls_disabled_log_empty"> + 会話ã¯ãƒã‚°ã«è¨˜éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。ãƒã‚°ã®è¨˜éŒ²ã‚’開始ã™ã‚‹ã«ã¯ã€ã€Œç’°å¢ƒè¨å®šã€>「ãƒãƒ£ãƒƒãƒˆã€ã§ã€Œä¿å˜: ãƒã‚°ã®ã¿ã€ã¾ãŸã¯ã€Œä¿å˜: ãƒã‚°ã¨ä¼šè©±ã®ãƒ†ã‚ストã€ã‚’é¸æŠžã—ã¾ã™ã€‚ + </string> + <string name="logging_calls_disabled_log_not_empty"> + ã“れ以上ã®ä¼šè©±ã¯è¨˜éŒ²ã•ã‚Œã¾ã›ã‚“。ãƒã‚°ã®è¨˜éŒ²ã‚’å†é–‹ã™ã‚‹ã«ã¯ã€ã€Œç’°å¢ƒè¨å®šã€>「ãƒãƒ£ãƒƒãƒˆã€ã§ã€Œä¿å˜: ãƒã‚°ã®ã¿ã€ã¾ãŸã¯ã€Œä¿å˜: ãƒã‚°ã¨ä¼šè©±ã®ãƒ†ã‚ストã€ã‚’é¸æŠžã—ã¾ã™ã€‚ + </string> + <string name="logging_calls_enabled_log_empty"> + ãƒã‚°ã‚¤ãƒ³æ™‚ã®ä¼šè©±ã¯ã‚ã‚Šã¾ã›ã‚“。誰ã‹ã«ã”連絡ã—ãŸå¾Œã€ã¾ãŸã¯èª°ã‹ãŒã‚ãªãŸã«é€£çµ¡ã—ãŸå¾Œã€ãƒã‚°ã‚¨ãƒ³ãƒˆãƒªãŒã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + </string> + <string name="loading_chat_logs"> + ãƒãƒ¼ãƒ‰ä¸... + </string> <string name="experience_tools_experience"> 体験 </string> @@ -5348,16 +5472,4 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="ExperiencePermissionShort12"> æ¨©é™ </string> - <string name="logging_calls_disabled_log_empty"> - 会話ã¯ãƒã‚°ã«è¨˜éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“。ãƒã‚°ã®è¨˜éŒ²ã‚’開始ã™ã‚‹ã«ã¯ã€ã€Œç’°å¢ƒè¨å®šã€>「ãƒãƒ£ãƒƒãƒˆã€ã§ã€Œä¿å˜: ãƒã‚°ã®ã¿ã€ã¾ãŸã¯ã€Œä¿å˜: ãƒã‚°ã¨ä¼šè©±ã®ãƒ†ã‚ストã€ã‚’é¸æŠžã—ã¾ã™ã€‚ - </string> - <string name="logging_calls_disabled_log_not_empty"> - ã“れ以上ã®ä¼šè©±ã¯è¨˜éŒ²ã•ã‚Œã¾ã›ã‚“。ãƒã‚°ã®è¨˜éŒ²ã‚’å†é–‹ã™ã‚‹ã«ã¯ã€ã€Œç’°å¢ƒè¨å®šã€>「ãƒãƒ£ãƒƒãƒˆã€ã§ã€Œä¿å˜: ãƒã‚°ã®ã¿ã€ã¾ãŸã¯ã€Œä¿å˜: ãƒã‚°ã¨ä¼šè©±ã®ãƒ†ã‚ストã€ã‚’é¸æŠžã—ã¾ã™ã€‚ - </string> - <string name="logging_calls_enabled_log_empty"> - ãƒã‚°ã‚¤ãƒ³æ™‚ã®ä¼šè©±ã¯ã‚ã‚Šã¾ã›ã‚“。誰ã‹ã«ã”連絡ã—ãŸå¾Œã€ã¾ãŸã¯èª°ã‹ãŒã‚ãªãŸã«é€£çµ¡ã—ãŸå¾Œã€ãƒã‚°ã‚¨ãƒ³ãƒˆãƒªãŒã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ - </string> - <string name="loading_chat_logs"> - ãƒãƒ¼ãƒ‰ä¸... - </string> </strings> diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml index 61a72ff27d..f5098ba33c 100755 --- a/indra/newview/skins/default/xui/pl/floater_about.xml +++ b/indra/newview/skins/default/xui/pl/floater_about.xml @@ -1,81 +1,42 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="O [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - Buduj z [COMPILER] wersjÄ… [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - PoÅ‚ożenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - Procesor: [CPU] -Pamięć: [MEMORY_MB] MB -Wersja OS: [OS_VERSION] -Sprzedawca karty graficznej: [GRAPHICS_CARD_VENDOR] -Karta graficzna: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Windows Sterownik karty graficznej: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - Wersja OpenGL: [OPENGL_VERSION] - -Wersja libcurl: [LIBCURL_VERSION] -Wersja dekodera J2C: [J2C_VERSION] -Wersja Audio Driver: [AUDIO_DRIVER_VERSION] -Wersja Qt Webkit: [QT_WEBKIT_VERSION] -Wersja serwera gÅ‚osu: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (żadne) - </floater.string> - <floater.string name="AboutTraffic"> - Stracone pakiety: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> <tab_container name="about_tab"> <panel label="Info" name="support_panel"> <button label="Kopiuj do schowka" name="copy_btn"/> </panel> <panel label="PodziÄ™kowania" name="credits_panel"> - <text_editor name="credits_editor"> - Second Life zostaÅ‚o stworzone dla Was przez Philip, Tessa, Andrew, Cory, Ian, James, Phoenix, Ryan, Haney, Dan, Char, Ben, John, Tanya, Eddie, Richard, Mitch, Doug, Eric, Frank, Bruce, Aaron, Peter, Alice, Charlie, Debra, Eileen, Helen, Janet, Steffan, Steve, Tom, Mark, Hunter, Xenon, Burgess, Bill, Jim, Lee, Hamlet, Daniel, Jeff, Todd, Sarah, Tim, Stephanie, Colin, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Jack, Vektor, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Jesse, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Yuko, Makiko, Thomas, Harry, Seth, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Brad, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, Beez, Milo, Hermia, Red, Thrax, Gulliver, Joe, Sally, Paul, Jose, Rejean, Dore, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, Dustin, George, Del, Matthew, Cat, Jacqui, Adrian, Viola, Alfred, Noel, Irfan, Yool, Rika, Jane, Frontier, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Jeremy, JP, Jake, Anthony, Maurice, Madhavi, Leopard, Kyle, Joon, Bert, Belinda, Jon, Kristi, Bridie, Pramod, Socrates, Maria, Aric, Adreanne, Jay, Kari, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Colossus, Zen, BigPapi, Pastrami, Kurz, Mani, Neuro, Mel, Sardonyx, MJ, Rowan, Sgt, Elvis, Samuel, Leo, Bryan, Niko, Austin, Soft, Poppy, Rachel, Aki, Banzai, Alexa, Sue, Bender, CG, Angelo, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Rothman, Niall, Marin, Allison, Katie, Dawn, Dusty, Katt, Judy, Andrea, Ambroff, Infinity, Rico, Gail, Kalpana, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Maestro, Simone, Yang, T, Shannon, Nelson, Khanh, Scott, Courtney, Charlene, Quixote, Susan, Zed, Amanda, Katelin, Enkidu, Roxie, Esbee, JoRoan, Scarlet, Tay, Kevin, Wolfgang, Johnny, Ray, Andren, Merov, Bob, Rand, Howard, Callen, Heff, Galen, Newell, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl, Ashley, JessieAnn, Huseby, Karina, Paris, Kurt, Rick, Lis, Kotler, Theeba, Lynx, Murphy, Doten, Taka, Norm, Jillian, Marcus, Mae, Novack, Esther, Perry, Dana, Ducot, Javier, Porter, Madison, Gecko, Dough, JR, Gisele, Crimp, Norie, Arch, Kimi, Fisher, Barbara, Jason, Peggy, Bernard, Jules, Leroy, Eva, Khederian, Campbell, Vogt, Masido, Karel, Torres, Lo, Breezer, Delby, Rountree, Anna, Servus, Rue, Itiaes, Chuck, Luna, Novella, Zaza, Wen, Gino, Lex, Cassandra, Limey, Nancy, Anukul, Silver, Brodesky, Jinsai, Squid, Gez, Rakesh, Ladan, Edelman, Marcet, Squire, Tatem, Tony, Jerm, Tia, Falcon, BK, Tiggs, Driscoll, Bacon, Timothee, Cru, Carmilla, Coyot, Webb, Kazu, Rudas, LJ, Sea, Ali Wallace, Bewest, Pup, Drub, Dragon, Inoshiro, Byron, Rhett, Xandix, Aimee, Fredrik, Thor, Teddy, Baron, Nelly, Ghengis, Epic, Eli, Stone, Grapes, Irie, Prep, Scobu, Valerie, Alain, and many others. - -PodziÄ™kowania dla nastÄ™pujÄ…cych Rezydentów za pomoc w pracy nad obecnÄ… wersjÄ… Second Life: Drew Dwi, Zai Lynch, Latif Khalifa, Ellla McMahon, Harleen Gretzky, Squirrel Wood, Malarthi Behemoth, Dante Tucker, Buckaroo Mu, Eddi Decosta, Dirk, Talamasca, Torben Trautman, Irene Muni, Aralara Rajal, Aura Dirval, Cayu Cluny, Eva Rau, FreeSL Aeon, Frontera Thor, Inma Rau, Lunita Savira, Minerva Memel, Polo Gufler, Xiki Luik, Lilly Zenovka, Vick Forcella, Sasy Scarborough, Gentle Welinder, Elric Anatine, Techwolf Lupindo, Dusan Writer, WolfPup Lowenhar, Marianne McCann, Fiachra Lach, Sitearm Madonna, Sudane Erato, Sahkolihaa Contepomi, Sachi Vixen, Questar Utu, Dimitrio Lewis, Matto Destiny, Scrim Pinion, Radio Signals, Psi Merlin, Pixel Gausman, Mel Vanbeeck, Laurent Bechir, Lamorna Proctor, Lares Carter, Gwyneth Llewelyn, Hydra Shaftoe, Holger Gilruth, Gentle Heron, Carla Broek, Boroondas Gupte, Fury Rosewood, Flower Ducatillon, Colpo Wexler, gwampa Lomu, Borg Capalini, Beansy Twine, Ardy Lay, , 45ms Zhong, Adeon Writer, Aeonix Aeon, Ai Austin, Aiko Ying, Alexandrea Fride, Alliez Mysterio, Annie Milestone, Annika Genezzia, Ansariel Hiller, ArminasX Saiman, Arya Braveheart, Asaeda Meltingdots, Asturkon Jua, Avallyn Oakleaf, Avatar Quinzet, BabyA Littlething, Bacchus Ireto, Bazaar, Riva, Benjamin Bigdipper, Beth Walcher, Bezilon Kasei, Biancaluce Robbiani, Bill Walach, blakopal Galicia, Blitzckreed Levenque, Bryn Oh, Callipygian Christensen, Cap Carver, Carr Arbenlow, Chantal Harvey, Charles Courtois, Charlie Sazaland, Cherry Cheevers, ChickyBabes Zuzu, Christopher Organiser, Ciaran Laval, Clara Young, Celierra Darling, Corinne Helendale, Corro Moseley, Coughdrop Littlething, Darien Caldwell, Dartagan Shepherd, Debs Regent, Decro Schmooz, Denim Kamachi, DiJodi Dubratt, Dil Spitz, Edgware Marker, Egehan Dryke, Emma Portilo, Emmie Fairymeadow, Evangelista Emerald, Faelon Swordthain, Frenchimmo Sabra, Gaberoonie Zanzibar, Ganymedes Costagravas, Gene Frostbite, GeneJ Composer, Giggles Littlebird, Grady Echegaray, Guni Greenstein, Gypsy Tripsa, Hackshaven Harford, Ham Rambler, Han Shuffle, Hanglow Short, Hatzfeld Runo, herina Bode, Horatio Freund, Hypatia Callisto, Hypatia Pickens, Identity Euler, Imnotgoing Sideways, Innula Zenovka, Iyoba Tarantal, Jack Abraham, Jagga Meredith, Jennifer Boyle, Jeremy Marquez, Jessica Qin, Jinx Nordberg, Jo Bernandes, Jocial Sonnenkern, Joel Savard, Jondan Lundquist, Josef Munster, Josette Windlow, Juilan Tripsa, Juro Kothari, Justin RiversRunRed, Kagehi Kohn, Kaimen Takahe, Keklily Longfall, Ken Lavender, Kestral Karas, Khisme Nitely, Kimar Coba, Kithrak Kirkorian, Kitty Barnett, Kolor Fall, Komiko Okamoto, Korvel Noh, Larry Pixel, Leal Choche, len Starship, Lenae Munz, Lexi Frua, Lillie Cordeaux, Lizzy Macarthur, LSL Scientist, Luban Yiyuan, Luc Starsider, Maccus McCullough, Madison Blanc, Maggie Darwin, Mallory Destiny, Manx Wharton, Marc Claridge, Marc2 Sands, Matthew Anthony, Maxim RiversRunRed, Medhue Simoni, Melinda Latynina, Mencius Watts, Michi Lumin, Midian Farspire, Miles Glaz, Mindy Mathy, Mitch Wagner, Mo Hax, Mourna Biziou, Nao Noe, naofan Teardrop, Naomah Beaumont, Nathiel Siamendes, Nber Medici, Neko Link, Netpat Igaly, Neutron Chesnokov, Newfie Pendragon, Nicholai Laviscu, Nick Rhodes, Nicoladie Gymnast, Ollie Kubrick, Orenj Marat, Orion Delphis, Oryx Tempel, Parvati Silverweb, PeterPunk Mooney, Pixel Scientist, Pounce Teazle, Professor Noarlunga, Quantum Destiny, Quicksilver Hermes, Ralf Setsuko, RAT Quan, RedMokum Bravin, Revolution Perenti, Rezit Sideways, Rich Grainger, Rosco Teardrop, Rose Evans, Rudee Voom, RufusTT Horsefly, Saii Hallard, SaintLEOlions Zimer, Samm Larkham, Satanello Miami, SexySteven Morrisey, Sheet Spotter, Shnurui Troughton, sicarius Thorne, Sicarius Toxx, Sini Nubalo, SLB Wirefly, snowy Sidran, Soupa Segura, ST Mensing, Starshine Halasy, Stickman Ingmann, Synystyr Texan, Takeda Terrawyng, Tali Rosca, Templar Merlin, Tezcatlipoca Bisiani, Tiel Stonecutter, Tony Kembia, TouchaHoney Perhaps, Trey Reanimator, TriloByte Zanzibar, Trinity Dechou, Trinity Dejavu, Unlikely Quintessa, UsikuFarasi Kanarik, Veritas Raymaker, Vex Streeter, Viaticus Speculaas, Villain Baroque, Vixie Durant, Void Singer, Watty Berkson, Westley Schridde, Westley Streeter, Whimsy Winx, Winter Ventura, Wundur Primbee, xstorm Radek, YongYong Francois, Zak Westminster, Zana Kohime, Zaren Alexander, Zeja Pyle, ZenMondo Wormser, Zoex Flanagan, and many others. - + <text name="linden_intro">Second Life zostaÅ‚o dla Ciebie stworzone przez Lindenów, +z wkÅ‚adem open source od::</text> + </panel> + <panel label="Licencje" name="licenses_panel"> + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + APR Copyright (C) 2011 The Apache Software Foundation + Collada DOM Copyright 2006 Sony Computer Entertainment Inc. + cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) + DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. + expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. + FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. + GL Copyright (C) 1999-2004 Brian Paul. + GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. + google-perftools Copyright (c) 2005, Google Inc. + Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. + jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) + jpeglib Copyright (C) 1991-1998, Thomas G. Lane. + ogg/vorbis Copyright (C) 2002, Xiphophorus + OpenSSL Copyright (C) 1998-2008 The OpenSSL Project. + PCRE Copyright (c) 1997-2012 University of Cambridge + SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + xmlrpc-epi Copyright (C) 2000 Epinions, Inc. + zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. + Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. + This software contains source code provided by NVIDIA Corporation. -"The work goes on, the cause endures, the hope still lives, and the dreams shall never die" - Edward Kennedy - </text_editor> - </panel> - <panel label="Licencje" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion - APR Copyright (C) 2000-2004 The Apache Software Foundation - cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) - expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). - GL Copyright (C) 1999-2004 Brian Paul. - Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. - jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) - jpeglib Copyright (C) 1991-1998, Thomas G. Lane. - ogg/vorbis Copyright (C) 2001, Xiphophorus - OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. - SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga - SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. - google-perftools Copyright (c) 2005, Google Inc. - - Wszystkie prawa zastrzeżone. Szczegóły w pliku licenses.txt. + All rights reserved. See licenses.txt for details. - Programowanie dźwiÄ™ku czatu: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_associate_listing.xml b/indra/newview/skins/default/xui/pl/floater_associate_listing.xml new file mode 100644 index 0000000000..b5464dd59b --- /dev/null +++ b/indra/newview/skins/default/xui/pl/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="PRZYPISANE PRZEDMIOTY"> + <text name="message">ID przedmiotu:</text> + <line_editor name="listing_id">Wpisz tutaj ID</line_editor> + <button label="OK" name="OK"/> + <button label="Anuluj" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/pl/floater_edit_hover_height.xml new file mode 100644 index 0000000000..80e481c0bc --- /dev/null +++ b/indra/newview/skins/default/xui/pl/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="USTAW UNIESIENIE"> + <slider label="UnieÅ›" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml index 054d74b234..97d13c4dfe 100755 --- a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="WÅAÅšCIWOÅšCI OBIEKTÓW W SZAFIE"> - <floater.string name="unknown"> - (nieznany) - </floater.string> - <floater.string name="public"> - (publiczny) - </floater.string> - <floater.string name="you_can"> - Opcje: - </floater.string> - <floater.string name="owner_can"> - WÅ‚aÅ›ciciel może: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Nazwa: - </text> - <text name="LabelItemDescTitle"> - Opis: - </text> - <text name="LabelCreatorTitle"> - Twórca: - </text> + <floater.string name="unknown">(nieznany)</floater.string> + <floater.string name="public">(publiczny)</floater.string> + <floater.string name="you_can">Opcje:</floater.string> + <floater.string name="owner_can">WÅ‚aÅ›ciciel może:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Nazwa:</text> + <text name="LabelItemDescTitle">Opis:</text> + <text name="LabelCreatorTitle">Twórca:</text> <button label="Profil..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - WÅ‚aÅ›ciciel: - </text> + <text name="LabelOwnerTitle">WÅ‚aÅ›ciciel:</text> <button label="Profil..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Nabyte: - </text> - <text name="LabelAcquiredDate"> - Wed May 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Ty: - </text> + <text name="LabelAcquiredTitle">Nabyte:</text> + <text name="LabelAcquiredDate">Wed May 24 12:50:46 2006</text> + <text name="OwnerLabel">Ty:</text> <check_box label="Edytuj" name="CheckOwnerModify"/> <check_box label="Kopiuj" name="CheckOwnerCopy"/> <check_box label="Odsprzedaż" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Każdy: - </text> + <text name="AnyoneLabel">Każdy:</text> <check_box label="Kopiuj" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Grupa: - </text> + <text name="GroupLabel">Grupa:</text> <check_box label="UdostÄ™pnij" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel"> - NastÄ™pny wÅ‚aÅ›ciciel: - </text> + <text name="NextOwnerLabel">NastÄ™pny wÅ‚aÅ›ciciel:</text> <check_box label="Edytuj" name="CheckNextOwnerModify"/> <check_box label="Kopiuje" name="CheckNextOwnerCopy"/> <check_box label="Odsprzedaż" name="CheckNextOwnerTransfer"/> <check_box label="Sprzedaż" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="Kopiuj" name="Copy"/> - <combo_box.item label="Oryginalny" name="Original"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Kopia" name="Copy"/> + <combo_box.item label="Zawartość" name="Contents"/> + <combo_box.item label="OryginaÅ‚" name="Original"/> </combo_box> <spinner label="Cena:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_item_properties.xml b/indra/newview/skins/default/xui/pl/floater_item_properties.xml new file mode 100644 index 0000000000..8b0cf31a9a --- /dev/null +++ b/indra/newview/skins/default/xui/pl/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="WÅAÅšCIWOÅšCI"/> diff --git a/indra/newview/skins/default/xui/pl/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/pl/floater_marketplace_listings.xml new file mode 100644 index 0000000000..1917a4985b --- /dev/null +++ b/indra/newview/skins/default/xui/pl/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="RZECZY NA MARKETPLACE"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Wczytywanie...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/pl/floater_marketplace_validation.xml new file mode 100644 index 0000000000..826c72f2cd --- /dev/null +++ b/indra/newview/skins/default/xui/pl/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Sprawdź przedmioty na Marketplace"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_openobject.xml b/indra/newview/skins/default/xui/pl/floater_openobject.xml index 8e94ae821c..20c9760e6f 100755 --- a/indra/newview/skins/default/xui/pl/floater_openobject.xml +++ b/indra/newview/skins/default/xui/pl/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Kopiuj do Szafy" label_selected="Kopiuj do Szafy" name="copy_to_inventory_button"/> - <button label="Kopiuj i zalóż" label_selected="Kopiuj i załóż" name="copy_and_wear_button"/> + <text name="border_note"> + Kopiuj do Szafy i załóż + </text> + <button label="Dodaj do stroju" label_selected="Dodaj do stroju" name="copy_and_wear_button"/> + <button label="ZastÄ…p strój" label_selected="ZastÄ…p strój" name="copy_and_replace_button"/> + <button label="Tylko skopiuj do Szafy" label_selected="Tylko skopiuj do Szafy" name="copy_to_inventory_button"/> + <button label="Anuluj" label_selected="Anuluj" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_pay.xml b/indra/newview/skins/default/xui/pl/floater_pay.xml index 38fe5286a4..cb9c0bd552 100755 --- a/indra/newview/skins/default/xui/pl/floater_pay.xml +++ b/indra/newview/skins/default/xui/pl/floater_pay.xml @@ -1,26 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - ZapÅ‚ać grupie - </string> - <string name="payee_resident"> - ZapÅ‚ać Rezydentowi - </string> - <text name="payee_label"> - ZapÅ‚ać: - </text> - <icon name="icon_person" tool_tip="Osoba"/> - <text name="payee_name"> - Przetestuj nazwÄ™, która jest bardzo dÅ‚uga aby sprawdzić skracanie. - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - lub wybierz kwotÄ™: - </text> - <line_editor left="52" name="amount"/> - <button label="ZapÅ‚ać" label_selected="ZapÅ‚ać" name="pay btn"/> - <button label="Anuluj" label_selected="Anuluj" name="cancel btn"/> + <string name="payee_group">ZapÅ‚ać grupie</string> + <string name="payee_resident">ZapÅ‚ać Rezydentowi</string> + <text name="paying_text">PÅ‚acisz:</text> + <text name="payee_name">Przetestuj nazwÄ™, która jest bardzo dÅ‚uga aby sprawdzić skracanie.</text> + <panel label="Szukaj" name="PatternsPanel"> + <button label="PÅ‚ać 1L$" label_selected="PÅ‚ać 1L$" name="fastpay 1"/> + <button label="PÅ‚ać 5L$" label_selected="PÅ‚ać 5L$" name="fastpay 5"/> + <button label="PÅ‚ać 10L$" label_selected="PÅ‚ać 10L$" name="fastpay 10"/> + <button label="PÅ‚ać 20L$" label_selected="PÅ‚ać 20L$" name="fastpay 20"/> + </panel> + <panel label="Szukaj" name="InputPanel"> + <text name="amount text">Inna kwota:</text> + <button label="ZapÅ‚ać" label_selected="ZapÅ‚ać" name="pay btn"/> + <button label="Anuluj" label_selected="Anuluj" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_pay_object.xml b/indra/newview/skins/default/xui/pl/floater_pay_object.xml index bf88348c87..d196e08fee 100755 --- a/indra/newview/skins/default/xui/pl/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/pl/floater_pay_object.xml @@ -1,30 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string halign="left" name="payee_group" width="100"> - ZapÅ‚ać grupie - </string> - <string halign="left" name="payee_resident" width="120"> - ZapÅ‚ać Rezydentowi - </string> - <icon name="icon_person" tool_tip="Osoba"/> - <text left="125" name="payee_name"> - Ericacita Moostopolison - </text> - <text halign="left" left="5" name="object_name_label" width="95"> - Poprzez obiekt: - </text> + <string halign="left" name="payee_group" width="100">ZapÅ‚ać grupie</string> + <string halign="left" name="payee_resident" width="120">ZapÅ‚ać Rezydentowi</string> + <text name="paying_text">PÅ‚acisz:</text> + <text left="125" name="payee_name">Ericacita Moostopolison</text> + <text halign="left" left="5" name="object_name_label" width="95">Poprzez obiekt:</text> <icon name="icon_object" tool_tip="Obiekt"/> - <text left="105" name="object_name_text"> - Poprzez obiekt - </text> - <button label="L$1" label_selected="L$1" left="105" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" left="190" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" left="105" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" left="190" name="fastpay 20"/> - <text halign="left" left="5" name="amount text"> - lub wybierz kwotÄ™: - </text> - <line_editor left="50" name="amount" width="50"/> - <button label="ZapÅ‚ać" label_selected="ZapÅ‚ać" name="pay btn"/> - <button label="Anuluj" label_selected="Anuluj" name="cancel btn"/> + <text left="105" name="object_name_text">Poprzez obiekt</text> + <panel label="Szukaj" name="PatternsPanel"> + <button label="PÅ‚ać 1L$" label_selected="PÅ‚ać 1L$" name="fastpay 1"/> + <button label="PÅ‚ać 5L$" label_selected="PÅ‚ać 5L$" name="fastpay 5"/> + <button label="PÅ‚ać 10L$" label_selected="PÅ‚ać 10L$" name="fastpay 10"/> + <button label="PÅ‚ać 20L$" label_selected="PÅ‚ać 20L$" name="fastpay 20"/> + </panel> + <panel label="Szukaj" name="InputPanel"> + <text name="amount text">Inna kwota:</text> + <button label="ZapÅ‚ać" label_selected="ZapÅ‚ać" name="pay btn"/> + <button label="Anuluj" label_selected="Anuluj" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/pl/menu_attachment_self.xml b/indra/newview/skins/default/xui/pl/menu_attachment_self.xml index 163b3a231e..ecfc341d73 100755 --- a/indra/newview/skins/default/xui/pl/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/pl/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Mój wyglÄ…d" name="Change Outfit"/> <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Uniesienie" name="Hover Height"/> <menu_item_call label="Moi znajomi" name="Friends..."/> <menu_item_call label="Moje grupy" name="Groups..."/> <menu_item_call label="Mój profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pl/menu_avatar_self.xml b/indra/newview/skins/default/xui/pl/menu_avatar_self.xml index 8eb501c5b8..dafad57d98 100755 --- a/indra/newview/skins/default/xui/pl/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pl/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Mój wyglÄ…d" name="Chenge Outfit"/> <menu_item_call label="Edytuj mój strój" name="Edit Outfit"/> <menu_item_call label="Edytuj mój ksztaÅ‚t" name="Edit My Shape"/> + <menu_item_call label="Uniesienie" name="Hover Height"/> <menu_item_call label="Moi znajomi" name="Friends..."/> <menu_item_call label="Moje grupy" name="Groups..."/> <menu_item_call label="Mój profil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pl/menu_inventory.xml b/indra/newview/skins/default/xui/pl/menu_inventory.xml index 5492f78b26..a0c2b2c6c1 100755 --- a/indra/newview/skins/default/xui/pl/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pl/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Utwórz nowy przedmiot" name="Marketplace Create Listing"/> + <menu_item_call label="Przypisz" name="Marketplace Associate Listing"/> + <menu_item_call label="Pobierz ponownie (odÅ›wież)" name="Marketplace Get Listing"/> + <menu_item_call label="Zweryfikuj" name="Marketplace Check Listing"/> + <menu_item_call label="Edytuj przedmiot" name="Marketplace Edit Listing"/> + <menu_item_call label="Listuj" name="Marketplace List"/> + <menu_item_call label="UsuÅ„ z listy" name="Marketplace Unlist"/> + <menu_item_call label="Aktywuj" name="Marketplace Activate"/> + <menu_item_call label="Dezaktywuj" name="Marketplace Deactivate"/> <menu_item_call label="UdostÄ™pnij" name="Share"/> <menu_item_call label="Kupuj" name="Task Buy"/> <menu_item_call label="Otwórz" name="Task Open"/> @@ -81,5 +90,7 @@ <menu_item_call label="Edytuj" name="Wearable Edit"/> <menu_item_call label="Dodaj" name="Wearable Add"/> <menu_item_call label="Zdejmij" name="Take Off"/> + <menu_item_call label="Kopiuj do przedmiotów Marketplace" name="Marketplace Copy"/> + <menu_item_call label="PrzenieÅ› do przedmiotów Marketplace" name="Marketplace Move"/> <menu_item_call label="--brak opcji--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/pl/menu_marketplace_view.xml b/indra/newview/skins/default/xui/pl/menu_marketplace_view.xml new file mode 100644 index 0000000000..b948074501 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Sortuj wedÅ‚ug iloÅ›ci (rosnÄ…co)" name="sort_by_stock_amount"/> + <menu_item_check label="Pokaż tylko foldery" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml index a354cca9ad..6fd498eea8 100755 --- a/indra/newview/skins/default/xui/pl/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml @@ -1,48 +1,42 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu_bar name="Main Menu"> <menu label="Ja" name="Me"> - <menu_item_call label="Ustawienia" name="Preferences"/> - <menu_item_call label="Dashboard" name="Manage My Account"/> - <menu_item_call label="Kup L$" name="Buy and Sell L$"/> <menu_item_call label="Mój Profil" name="Profile"/> <menu_item_call label="Mój wyglÄ…d" name="ChangeOutfit"/> <menu_item_check label="Moja Szafa" name="Inventory"/> - <menu_item_check label="Moja Szafa" name="ShowSidetrayInventory"/> - <menu_item_check label="Moje gesturki" name="Gestures"/> - <menu_item_check label="Mój gÅ‚os" name="ShowVoice"/> <menu label="Ruch" name="Movement"> <menu_item_call label="UsiÄ…dź" name="Sit Down Here"/> <menu_item_check label="Zacznij latać" name="Fly"/> <menu_item_check label="Zawsze biegnij" name="Always Run"/> <menu_item_call label="Zatrzymaj animacje" name="Stop Animating My Avatar"/> </menu> - <menu label="Mój Status" name="Status"> - <menu_item_call label="Tryb oddalenia" name="Set Away"/> - <menu_item_call label="Tryb pracy" name="Set Busy"/> - </menu> + <menu label="Mój Status" name="Status"/> + <menu_item_call label="Kup L$" name="Buy and Sell L$"/> + <menu_item_call label="Moje rzeczy na Marketplace" name="MarketplaceListings"/> + <menu_item_call label="Dashboard" name="Manage My Account"/> + <menu_item_call label="Ustawienia" name="Preferences"/> <menu_item_call label="WyÅ‚Ä…cz [APP_NAME]" name="Quit"/> </menu> <menu label="Komunikacja" name="Communicate"> - <menu_item_call label="Znajomi" name="My Friends"/> - <menu_item_call label="Grupy" name="My Groups"/> <menu_item_check label="Czat lokalny" name="Nearby Chat"/> - <menu_item_call label="Osoby w pobliżu" name="Active Speakers"/> + <menu_item_check label="Znajomi" name="My Friends"/> + <menu_item_check label="Grupy" name="My Groups"/> + <menu_item_check label="Osoby w pobliżu" name="Active Speakers"/> </menu> <menu label="Åšwiat" name="World"> - <menu_item_check label="Mini-Mapa" name="Mini-Map"/> + <menu_item_call label="ZapamiÄ™taj to miejsce (LM)" name="Create Landmark Here"/> <menu_item_check label="Mapa Åšwiata" name="World Map"/> + <menu_item_check label="Mini-Mapa" name="Mini-Map"/> <menu_item_check label="Szukaj" name="Search"/> + <menu_item_call label="Teleportuj do Miejsca Startu" name="Teleport Home"/> + <menu_item_call label="Ustaw Miejsce Startu" name="Set Home to Here"/> <menu_item_call label="Zrób zdjÄ™cie" name="Take Snapshot"/> - <menu_item_call label="ZapamiÄ™taj to miejsce (LM)" name="Create Landmark Here"/> - <menu_item_separator/> <menu_item_call label="Profil miejsca" name="Place Profile"/> <menu_item_call label="O posiadÅ‚oÅ›ci" name="About Land"/> - <menu_item_call label="Region/MajÄ…tek" name="Region/Estate"/> - <menu_item_call label="Kup posiadÅ‚ość" name="Buy Land"/> + <menu_item_call label="Region/MajÄ…tek" name="RegionEstate"/> <menu_item_call label="Moje posiadÅ‚oÅ›ci" name="My Land"/> + <menu_item_call label="Kup posiadÅ‚ość" name="Buy Land"/> <menu label="Pokaż" name="LandShow"> - <menu_item_check label="Ustawienia ruchu" name="Movement Controls"/> - <menu_item_check label="Zobacz ustawienia" name="Camera Controls"/> <menu_item_check label="Linie bana" name="Ban Lines"/> <menu_item_check label="Emitery" name="beacons"/> <menu_item_check label="Granice posiadÅ‚oÅ›ci" name="Property Lines"/> @@ -51,15 +45,11 @@ <menu_item_check label="WÅ‚aÅ›ciwoÅ›ci posiadÅ‚oÅ›ci" name="Parcel Properties"/> <menu_item_check label="Menu Zaawansowane" name="Show Advanced Menu"/> </menu> - <menu_item_call label="Teleportuj do Miejsca Startu" name="Teleport Home"/> - <menu_item_call label="Ustaw Miejsce Startu" name="Set Home to Here"/> <menu label="SÅ‚oÅ„ce" name="Sun"> - <menu_item_call label="Wschód SÅ‚oÅ„ca" name="Sunrise"/> - <menu_item_call label="PoÅ‚udnie" name="Noon"/> - <menu_item_call label="Zachód SÅ‚oÅ„ca" name="Sunset"/> - <menu_item_call label="Północ" name="Midnight"/> - <menu_item_call label="Używaj czasu Regionu" name="Revert to Region Default"/> - <menu_item_call label="Edytor Å›rodowiska" name="Environment Editor"/> + <menu_item_check label="Wschód SÅ‚oÅ„ca" name="Sunrise"/> + <menu_item_check label="PoÅ‚udnie" name="Noon"/> + <menu_item_check label="Zachód SÅ‚oÅ„ca" name="Sunset"/> + <menu_item_check label="Północ" name="Midnight"/> </menu> </menu> <menu label="Buduj" name="BuildTools"> @@ -86,7 +76,6 @@ <menu_item_call label="Kup" name="Menu Object Buy"/> <menu_item_call label="Weź" name="Menu Object Take"/> <menu_item_call label="Weź kopiÄ™" name="Take Copy"/> - <menu_item_call label="Zapisz obiekt do Szafy" name="Save Object Back to My Inventory"/> <menu_item_call label="Zapisz do treÅ›ci obiektu" name="Save Object Back to Object Contents"/> <menu_item_call label="Zwróć obiekt" name="Return Object back to Owner"/> </menu> @@ -116,17 +105,14 @@ <menu_item_call label="dźwiÄ™k (L$[COST])..." name="Upload Sound"/> <menu_item_call label="animacjÄ™ (L$[COST])..." name="Upload Animation"/> <menu_item_call label="zbiór plików (L$[COST] za jeden plik)..." name="Bulk Upload"/> - <menu_item_call label="Ustaw domyÅ›lne pozwolenia Å‚adowania" name="perm prefs"/> </menu> <menu_item_call label="Cofnij" name="Undo"/> <menu_item_call label="Ponów" name="Redo"/> </menu> <menu label="Pomoc" name="Help"> - <menu_item_call label="[SECOND_LIFE] Portal Pomocy" name="Second Life Help"/> - <menu_item_check label="WÅ‚Ä…cz podpowiedzi" name="Enable Hints"/> <menu_item_call label="Złóż Raport o Nadużyciu" name="Report Abuse"/> <menu_item_call label="ZgÅ‚oÅ› bÅ‚Ä™dy klienta" name="Report Bug"/> - <menu_item_call label="Zderzenia, popchniÄ™cia & uderzenia" name="Bumps, Pushes &amp; Hits"/> + <menu_item_call label="Zderzenia, popchniÄ™cia i uderzenia" name="Bumps, Pushes &amp; Hits"/> <menu_item_call label="O [APP_NAME]" name="About Second Life"/> </menu> <menu label="Zaawansowane" name="Advanced"> @@ -147,7 +133,6 @@ <menu_item_check label="Ukryj czÄ…steczki" name="Hide Particles"/> <menu_item_check label="Ukryj zaznaczone" name="Hide Selected"/> <menu_item_check label="Pokaż przeźroczyste obiekty" name="Highlight Transparent"/> - <menu_item_check label="Pokaż zaÅ‚Ä…czniki HUD" name="Show HUD Attachments"/> <menu_item_check label="Pokaż celownik myszki" name="ShowCrosshairs"/> </menu> <menu label="Rodzaje renderowania" name="Rendering Types"> @@ -178,7 +163,6 @@ <menu_item_call label="Wyczyść bufor danych grupy" name="ClearGroupCache"/> <menu_item_check label="WygÅ‚adzanie ruchu myszki" name="Mouse Smoothing"/> <menu label="Skróty" name="Shortcuts"> - <menu_item_call label="Zwolnij klawisze" name="Release Keys"/> <menu_item_check label="Pokaż menu Zaawansowane - skrót" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Zamknij okno" name="Close Window"/> <menu_item_call label="Zamknij wszystkie okna" name="Close All Windows"/> @@ -199,8 +183,7 @@ <menu_item_check label="Konsola tekstur" name="Texture Console"/> <menu_item_check label="Debugowanie zdarzeÅ„ konsoli" name="Debug Console"/> <menu_item_call label="Konsola powiadomieÅ„" name="Notifications"/> - <menu_item_check label="Konsola rozmiaru tekstury" name="Texture Size"/> - <menu_item_check label="Konsola kategorii tekstur" name="Texture Category"/> + <menu_item_check label="Konsola debugowania regionu" name="Region Debug Console"/> <menu_item_check label="Szybkie timery" name="Fast Timers"/> <menu_item_check label="Pamięć" name="Memory"/> <menu_item_call label="Info Regionu do debugowania konsoli" name="Region Info to Debug Console"/> @@ -240,12 +223,10 @@ <menu_item_check label="OÅ›wietlenie i cienie" name="Advanced Lighting Model"/> <menu_item_check label="Cienie SÅ‚oÅ„ca/Księżyca/Projektory" name="Shadows from Sun/Moon/Projectors"/> <menu_item_check label="SSAO and wygÅ‚adzanie cienia" name="SSAO and Shadow Smoothing"/> - <menu_item_check label="Globalne oÅ›wietlenie (eksperymentalne)" name="Global Illumination"/> <menu_item_check label="Automatyczne maski alpha (deferred)" name="Automatic Alpha Masks (deferred)"/> <menu_item_check label="Automatyczne maski alpha (non-deferred)" name="Automatic Alpha Masks (non-deferred)"/> <menu_item_check label="Tekstury animacji" name="Animation Textures"/> <menu_item_check label="WyÅ‚Ä…cz tekstury" name="Disable Textures"/> - <menu_item_check label="Texture Atlas (experimental)" name="Texture Atlas"/> <menu_item_check label="Renderowania zaÅ‚Ä…czonego Å›wiatÅ‚a" name="Render Attached Lights"/> <menu_item_check label="Renderowanie zaÅ‚Ä…czonych czÄ…steczek" name="Render Attached Particles"/> <menu_item_check label="WyÅ›wietlaj obiekty odblaskowe" name="Hover Glow Objects"/> @@ -253,7 +234,7 @@ <menu label="Sieć" name="Network"> <menu_item_check label="Zatrzymaj awatara" name="AgentPause"/> <menu_item_call label="Upuść pakiet pamiÄ™ci" name="Drop a Packet"/> - </menu> + </menu> <menu label="Åšwiat" name="DevelopWorld"> <menu_item_check label="DomyÅ›lne ustawienia Å›rodowiska Regionu" name="Sim Sun Override"/> <menu_item_check label="Ustalona pogoda" name="Fixed Weather"/> @@ -263,8 +244,6 @@ <menu_item_call label="Test przeglÄ…darki mediów" name="Web Browser Test"/> <menu_item_call label="PrzeglÄ…darka zawartoÅ›ci strony" name="Web Content Browser"/> <menu_item_call label="Drukuj zaznaczone informacje o obiekcie" name="Print Selected Object Info"/> - <menu_item_call label="Statystyki pamiÄ™ci" name="Memory Stats"/> - <menu_item_check label="Konsola debugowania regionu" name="Region Debug Console"/> <menu_item_check label="Debugowanie zdarzeÅ„ klikania" name="Debug Clicks"/> <menu_item_check label="Debugowanie zdarzeÅ„ myszy" name="Debug Mouse Events"/> </menu> @@ -289,7 +268,6 @@ </menu> <menu_item_call label="Powrót do domyÅ›lnych parametrów" name="Force Params to Default"/> <menu_item_check label="Info o animacji" name="Animation Info"/> - <menu_item_check label="Wolne animacje" name="Slow Motion Animations"/> <menu_item_check label="WyÅ‚Ä…cz poziom detalu" name="Disable LOD"/> <menu_item_check label="Pokaż szczegóły kolizji" name="Show Collision Skeleton"/> <menu_item_check label="WyÅ›wietl cel agenta" name="Display Agent Target"/> diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index f255b1b8ea..c4a65d92b4 100755 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -28,7 +28,7 @@ <template name="okcancelignore"> <form> <button name="OK_okcancelignore" text="$yestext"/> - <button name="Cancel_okcancelignore" text="$canceltext"/> + <button name="Cancel_okcancelignore" text="$notext"/> </form> </template> <template name="okhelpbuttons"> @@ -67,6 +67,10 @@ Szczegóły bÅ‚Ä™du: BÅ‚Ä…d o nazwie '[_NAME]' nie zostaÅ‚ odnaleziony [MESSAGE] <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Tak"/> </notification> + <notification name="GenericAlertOK"> + [MESSAGE] + <usetemplate name="okbutton" yestext="OK"/> + </notification> <notification name="BadInstallation"> Podczas aktualizacji [APP_NAME] wystÄ…piÅ‚ bÅ‚Ä…d. ProszÄ™ odwiedzić stronÄ™ [http://get.secondlife.com pobierz najnowsza wersjÄ™] aby Å›ciÄ…gnąć ostatniÄ… wersjÄ™ klienta. <usetemplate name="okbutton" yestext="OK"/> @@ -85,6 +89,88 @@ Upewnij siÄ™, że Twoje poÅ‚Ä…czenie z internetem dziaÅ‚a. Zapisać zmiany dotyczÄ…ce ubrania/części ciaÅ‚a? <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie Zapisuj" yestext="Zapisz"/> </notification> + <notification name="StockPasteFailed"> + Kopiowanie lub przeniesienie do folderu magazynowego nie powiodÅ‚o siÄ™: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Kopiowanie lub przenoszenie przedmiotów na Marketplace nie powiodÅ‚o siÄ™: + +'[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + Transakcja z Marketplace nie powiodÅ‚a siÄ™: + + Powód: '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Wylistowanie tego produktu lub aktywowanie folderu z wersjÄ… nie byÅ‚o możliwe. Zazwyczaj jest to spowodowane brakujÄ…cymi informacjami w formularzu z opisem przedmiotu, ale może to również wynikać z bÅ‚Ä™dów w strukturze folderów. ZmieÅ„ opis przedmiotu lub sprawdź foldery, aby znaleźć bÅ‚Ä™dy. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Listowanie na Marketplace nie powiodÅ‚o siÄ™: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Aktywacja tego folderu wersji nie powiodÅ‚a siÄ™: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + JeÅ›li kontynuujesz, to zmieni siÄ™ aktywna zawartość tego przedmiotu. Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź przed zmodyfikowaniem aktywnego przedmiotu na Marketplace" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Przedmioty przeciÄ…gniÄ™te do okna listowania na Marketplace sÄ… przenoszone z ich oryginalnych lokalizacji, a nie kopiowane. Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź, zanim przeÅ›lÄ™ na Marketplace przedmiot z mojej Szafy" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Przeniesienie lub usuniÄ™cie folderu usunie również Twój przedmiot na Marketplace. JeÅ›li chcesz, aby przedmiot byÅ‚ ciÄ…gle widoczny na Marketplace musisz przesunąć lub usunąć zawartość folderu z wersjÄ…, którÄ… chcesz zmodyfikować. Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź, zanim usunÄ™ lub przeniosÄ™ przedmiot na Marketplace" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Nie masz praw do skopiowania jednego lub wiÄ™cej obiektów na Marketplace. Możesz je przenieść lub pozostawić. + <usetemplate canceltext="Anuluj" ignoretext="Potwierdź, zanim wyÅ›lÄ™ na Marketplace przedmioty bez praw kopiowania" name="yesnocancelbuttons" notext="Nie przenoÅ›" yestext="PrzenieÅ›"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + JeÅ›li kontynuujesz, to ten przedmiot zostanie usuniÄ™ty z listy. Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź, zanim usunÄ™ z listy przedmiot na Marketplace" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + JeÅ›li kontynuujesz, to folder wersji tego przedmiotu zostanie zdeaktywowany. Czy chcesz kontynuować? + <usetemplate ignoretext="Potwierdź przed wyÅ‚Ä…czeniem folderu wersji dla przedmiotu na Marketplace" name="okcancelignore" notext="Anuluj" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Ten przedmiot nie może zostać zaktualizowany. +[[URL] Kliknij tutaj] aby zaktualizować go na Marketplace. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Nie możesz zaÅ‚ożyć ubraÅ„ lub części ciaÅ‚a, które znajdujÄ… siÄ™ w folderze listingów Marketplace. + </notification> + <notification name="AlertMerchantListingInvalidID"> + NieprawidÅ‚owy ID przedmiotu. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Istnieje kilka, lub żadna, wersji folderu dla tego przedmiotu. BÄ™dziesz musiaÅ‚a/ wybrać i uaktywnić jednÄ… oddzielnie później. + <usetemplate ignoretext="Powiadamiaj o aktywacji folderu wersji, gdy tworzÄ™ przedmiot z kilkoma folderami wersji" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Przedmioty z ograniczonymi zasobami magazynowymi różnych typów zostaÅ‚y rozdzielone do osobnych folderów, aby ogólna hierarchia katalogów umożliwiaÅ‚a ich listowanie. + <usetemplate ignoretext="Powiadom, gdy folder magazynowy jest dzielony przed listowaniem" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Twój przedmiot zostaÅ‚ usuniÄ™ty z listy, ponieważ nie ma go już w magazynie. Musisz dodać wiÄ™cej jego jednostek do folderu magazynowego, aby można byÅ‚o go ponownie wyÅ›wietlać na liÅ›cie. + <usetemplate ignoretext="Powiadom, gdy przedmiot jest zdjÄ™ty z listy, bo folder zasobów magazynowych jest pusty" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> W trakcie Å‚adwania tekstu dla skryptu pojawiÅ‚ siÄ™ problem z nastÄ™pujÄ…cego powodu: [REASON]. Spróbuj ponownie za kilka minut. </notification> @@ -391,6 +477,10 @@ PamiÄ™taj: Opcja ta wyczyszcza bufor danych. Zapisać zmiany? <usetemplate canceltext="Anuluj" name="yesnocancelbuttons" notext="Nie zapisuj" yestext="Zapisz"/> </notification> + <notification name="DeleteNotecard"> + Usunąć notkÄ™? + <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Nie można zapisać gesturki. Ta gesturka ma zbyt wiele etapów. @@ -1075,9 +1165,6 @@ Przekazać tÄ… posiadÅ‚ość o powierzchni [AREA] m² grupie '[GROUP_NAME]& <notification name="DisplaySetToSafe"> Ustawienia grafiki zostaÅ‚y zmienione do bezpiecznego poziomu ponieważ opcja -safe zostaÅ‚a wybrana. </notification> - <notification name="DisplaySetToRecommended"> - Ustawienia grafiki zostaÅ‚y zmienione do zalecanego poziomu na podstawie konfiguracji Twojego systemu. - </notification> <notification name="ErrorMessage"> [ERROR_MESSAGE] <usetemplate name="okbutton" yestext="OK"/> @@ -1338,6 +1425,7 @@ W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME]. </notification> <notification name="RequiredUpdateDownloadedDialog"> W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME]. +[[INFO_URL] Information about this update] <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="DeedObjectToGroup"> @@ -1415,12 +1503,6 @@ Chcesz opuÅ›cić grupÄ™? Nie możesz zaoferować znajomoÅ›ci w tym momencie. Spróbuj jeszcze raz za chwilÄ™. <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="BusyModeSet"> - Tryb Pracy jest wÅ‚Ä…czony. -Czat i IM bÄ™dÄ… ukryte. WysÅ‚ane IM bÄ™dÄ… otrzymywaÅ‚y TwojÄ… odpowiedź Trybu Pracy. Propozycje teleportacji bÄ™dÄ… odrzucone. -Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywane w folderze "Kosz" w Twojej szafie. - <usetemplate ignoretext="Status zmieniony na Tryb pracy" name="okignore" yestext="OK"/> - </notification> <notification name="JoinedTooManyGroupsMember"> Należysz już do maksymalnej iloÅ›ci grup. Opuść proszÄ™ przynajmniej jednÄ… grupÄ™ żeby przyjąć czÅ‚onkostwo w tej grupie, albo odmów. [NAME] oferuje Ci czÅ‚onkostwo w grupie. @@ -1434,8 +1516,8 @@ Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywa Wyrzuć tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. <form name="form"> <input name="message"> - Administrator wylogowaÅ‚ CiÄ™. - </input> + Administrator wylogowaÅ‚ CiÄ™. + </input> <button name="OK" text="OK"/> <button name="Cancel" text="Anuluj"/> </form> @@ -1444,8 +1526,8 @@ Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywa Z jakim komunikatem wyrzucić wszystkich użytkowników z regionu? <form name="form"> <input name="message"> - Administrator wylogowaÅ‚ CiÄ™. - </input> + Administrator wylogowaÅ‚ CiÄ™. + </input> <button name="OK" text="OK"/> <button name="Cancel" text="Anuluj"/> </form> @@ -1454,8 +1536,8 @@ Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywa Unieruchom tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. <form name="form"> <input name="message"> - Unieruchomiono CiÄ™. Nie możesz siÄ™ ruszać ani rozmawiać. Administrator skontaktuje siÄ™ z TobÄ… poprzez IM. - </input> + Unieruchomiono CiÄ™. Nie możesz siÄ™ ruszać ani rozmawiać. Administrator skontaktuje siÄ™ z TobÄ… poprzez IM. + </input> <button name="OK" text="OK"/> <button name="Cancel" text="Anuluj"/> </form> @@ -1464,8 +1546,8 @@ Dodatkowo, wszystkie podarowane dla Ciebie obiekty bÄ™dÄ… automatycznie zapisywa Cofnij unieruchomienie tego Rezydenta, wysyÅ‚ajÄ…c nastÄ™pujÄ…cy komunikat. <form name="form"> <input name="message"> - Odblokowano CiÄ™. - </input> + Odblokowano CiÄ™. + </input> <button name="OK" text="OK"/> <button name="Cancel" text="Anuluj"/> </form> @@ -1617,14 +1699,8 @@ Kontynuować? Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="RegionEntryAccessBlocked_KB"> - Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. - -Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. - <url name="url"> - https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 - </url> - <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] </notification> <notification name="RegionEntryAccessBlocked_Notify"> Ze wzglÄ™du na Twój wiek, nie jesteÅ› uprawniony do przebywania w tym regionie. @@ -1648,15 +1724,6 @@ W celu uzyskania dostÄ™pu do tego regiony zmieÅ„ proszÄ™ swój status ustawieÅ„ Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="LandClaimAccessBlocked_KB"> - Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci. - -Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. - <url name="url"> - https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 - </url> - <usetemplate ignoretext="W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz odzyskać tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> - </notification> <notification name="LandClaimAccessBlocked_Notify"> Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci. </notification> @@ -1664,7 +1731,6 @@ Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™p W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz odzyskać tej posiadÅ‚oÅ›ci. Możesz wybrać 'ZmieÅ„ Ustawienia' by dokonać zmian w ustawieniach Twojego wieku by uzyskać dostÄ™p do regionu. Wówczas bÄ™dziesz w stanie znaleźć oraz mieć dostÄ™p do [REGIONMATURITY] treÅ›ci. Jeżeli zdecydujesz siÄ™ na powrót do poprzednich ustawieÅ„, wybierz Ja > Ustawienia > Główne. - <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie możesz odzyskać tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="ZmieÅ„ Ustawienia"/> </notification> <notification name="LandBuyAccessBlocked"> Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku. @@ -1672,15 +1738,6 @@ Możesz wybrać 'ZmieÅ„ Ustawienia' by dokonać zmian w ustawieniach T Upewnij siÄ™, że masz zainstalowanÄ… najnowszÄ… wersjÄ™ klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="LandBuyAccessBlocked_KB"> - Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. - -Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™pu do regionów z podanym rodzajem treÅ›ci jakÄ… zawiera. - <url name="url"> - https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 - </url> - <usetemplate ignoretext="Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="[SECOND_LIFE]:Pomoc"/> - </notification> <notification name="LandBuyAccessBlocked_Notify"> Ze wzglÄ™du na Twój wiek, nie możesz kupić tej posiadÅ‚oÅ›ci. </notification> @@ -1688,7 +1745,6 @@ Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać wiÄ™cej informacji na temat dostÄ™p W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz kupić tej posiadÅ‚oÅ›ci. Możesz wybrać 'ZmieÅ„ Ustawienia' by dokonać zmian w ustawieniach Twojego wieku by uzyskać dostÄ™p do regionu. Wówczas bÄ™dziesz w stanie znaleźć oraz mieć dostÄ™p do [REGIONMATURITY] treÅ›ci. Jeżeli zdecydujesz siÄ™ na powrót do poprzednich ustawieÅ„, wybierz Ja > Ustawienia > Główne. - <usetemplate ignoretext="W zwiÄ…zku ze statusem ustawieÅ„ Twojego wieku, nie możesz kupić tej posiadÅ‚oÅ›ci." name="okcancelignore" notext="Zamknij" yestext="ZmieÅ„ Ustawienia"/> </notification> <notification name="TooManyPrimsSelected"> Zbyt wiele wybranych obiektów. Wybierz [MAX_PRIM_COUNT] lub mniej i spróbuj ponownie @@ -1849,6 +1905,10 @@ Przenieść obiekty szafy? <ignore name="ignore" text="Opcja ZapÅ‚ać Obiektowi zostaÅ‚a aktywowana podczas budowania obiektów bez skryptu z funkcjÄ… money()."/> </form> </notification> + <notification name="PayConfirmation"> + Potwierdź, że na pewno chcesz zapÅ‚acić [AMOUNT]L$ dla [TARGET]. + <usetemplate ignoretext="Potwierdź przed pÅ‚aceniem (kwoty ponad 200 L$)" name="okcancelignore" notext="Anuluj" yestext="PÅ‚ać"/> + </notification> <notification name="OpenObjectCannotCopy"> W tym obiekcie nie ma elementów które możesz skopiować. </notification> @@ -1918,16 +1978,6 @@ Chcesz go zamienić na wybrany obiekt? <button ignore="Nie zamieniaj" name="No" text="Anuluj"/> </form> </notification> - <notification label="Ostrzeżenie Trybu Pracy" name="BusyModePay"> - JesteÅ› w Trybie pracy co oznacza, że nie dostaniesz żadnych obiektów w zamian za tÄ… opÅ‚atÄ™. - -Chcesz wyÅ‚Ä…czyć Tryb pracy przed zakoÅ„czeniem tej tranzakcji? - <form name="form"> - <ignore name="ignore" save_option="true" text="JesteÅ› w Trybie Pracy co oznacza, że nie dostaniesz żadnych obiektów w zamian za tÄ… opÅ‚atÄ™. Chcesz wyÅ‚Ä…czyć Tryb Pracy przed zakoÅ„czeniem tej transakcji?"/> - <button ignore="Zawsz wyÅ‚Ä…czaj tryb pracy" name="Yes" text="OK"/> - <button ignore="Nie wyÅ‚Ä…czaj trybu pracy" name="No" text="Anuluj"/> - </form> - </notification> <notification name="ConfirmDeleteProtectedCategory"> Ten folder '[FOLDERNAME]' to folder systemowy. UsuniÄ™cie foldera systemowego spowoduje niestabilność. Czy na pewno chcesz go skasować? <usetemplate ignoretext="Potwierdź zanim folder systemu zostanie skasowany" name="okcancelignore" notext="Anuluj" yestext="OK"/> @@ -1965,10 +2015,6 @@ Zamieść go na stronie internetowej żeby umożliwić innym Å‚atwy dostÄ™p do t Chcesz zmienić zapisane ustawienia? <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> </notification> - <notification name="WLDeletePresetAlert"> - Chcesz usunąć [SKY]? - <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> - </notification> <notification name="WLNoEditDefault"> Nie możesz edytować lub usunąć domyÅ›lnych ustawieÅ„. </notification> @@ -1979,35 +2025,6 @@ Zamieść go na stronie internetowej żeby umożliwić innym Å‚atwy dostÄ™p do t Efekt post-procesu już istnieje. Chcesz zapisać nowy na jego miejsce? <usetemplate name="okcancelbuttons" notext="Nie" yestext="Tak"/> </notification> - <notification name="NewSkyPreset"> - Nazwij nowe niebo. - <form name="form"> - <input name="message"> - Nowe ustawienie - </input> - <button name="OK" text="OK"/> - <button name="Cancel" text="Anuluj"/> - </form> - </notification> - <notification name="ExistsSkyPresetAlert"> - Ustawienie już istnieje! - </notification> - <notification name="NewWaterPreset"> - Nazwij nowe ustawienie wody. - <form name="form"> - <input name="message"> - Nowe ustawienie - </input> - <button name="OK" text="OK"/> - <button name="Cancel" text="Anuluj"/> - </form> - </notification> - <notification name="ExistsWaterPresetAlert"> - Ustawienie już istnieje! - </notification> - <notification name="WaterNoEditDefault"> - DomyÅ›lne ustawienie nie może być zmienione ani usuniÄ™te. - </notification> <notification name="ChatterBoxSessionStartError"> BÅ‚Ä…d podczas rozpoczynania czatu/IM z [RECIPIENT]. [REASON] @@ -2038,10 +2055,6 @@ Zamieść go na stronie internetowej żeby umożliwić innym Å‚atwy dostÄ™p do t Nie masz dostÄ™pu do tej posiadÅ‚oÅ›ci ze wzglÄ™du na brak weryfikacji Twojego wieku. Czy chcesz odwiedzić stronÄ™ [SECOND_LIFE] żeby to zmienić? [_URL] - <url name="url" option="0"> - https://secondlife.com/account/verification.php - </url> - <usetemplate ignoretext="Brak weryfikacji wieku" name="okcancelignore" notext="Nie" yestext="Tak"/> </notification> <notification name="Cannot enter parcel: no payment info on file"> Nie masz dostÄ™pu do tej posiadÅ‚oÅ›ci ze wzglÄ™du na brak danych o Twoim koncie. Czy chcesz odwiedzić stronÄ™ [SECOND_LIFE] żeby to zmienić? @@ -2076,12 +2089,6 @@ Zamieść go na stronie internetowej żeby umożliwić innym Å‚atwy dostÄ™p do t <notification name="GroupNotice"> Temat: [SUBJECT], Treść: [MESSAGE] </notification> - <notification name="FriendOnline"> - <nolink>[NAME]</nolink> jest w Second Life - </notification> - <notification name="FriendOffline"> - <nolink>[NAME]</nolink> opuszcza Second Life - </notification> <notification name="AddSelfFriend"> Nie możesz dodać siebie do listy znajomych. </notification> @@ -2361,9 +2368,6 @@ Spróbuj ponowanie za kilka minut. <notification name="NoValidCircuit"> Nieważny obwód kodowania. </notification> - <notification name="NoValidTimestamp"> - NiewÅ‚aÅ›ciwy czas zapisu. - </notification> <notification name="NoPendingConnection"> Brak możliwoÅ›ci wykonania poÅ‚Ä…czenia. </notification> @@ -2525,22 +2529,17 @@ Czy siÄ™ zgadzasz? <form name="form"> <button name="Grant" text="Zaakceptuj"/> <button name="Deny" text="Odmów"/> - <button name="Details" text="Szczegóły..."/> </form> </notification> <notification name="ScriptDialog"> [NAME]'s '<nolink>[TITLE]</nolink>' [MESSAGE] - <form name="form"> - <button name="Ignore" text="Zignoruj"/> - </form> + <form name="form"/> </notification> <notification name="ScriptDialogGroup"> [GROUPNAME]'s '<nolink>[TITLE]</nolink>' [MESSAGE] - <form name="form"> - <button name="Ignore" text="Zignoruj"/> - </form> + <form name="form"/> </notification> <notification name="BuyLindenDollarSuccess"> DziÄ™kujemy za wpÅ‚atÄ™! @@ -2857,10 +2856,6 @@ Kliknij i przeciÄ…gnij gdziekolwiek aby obrócić widok. <button name="cancel" text="Anuluj"/> </form> </notification> - <notification label="" name="ModeChange"> - Zmiana trybu wymaga restartu. - <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> - </notification> <notification label="" name="NoClassifieds"> Tworzenie i edycja reklam jest możliwa tylko w trybie zaawansowanym. Czy chcesz wylogować siÄ™ i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> @@ -2889,9 +2884,6 @@ Kliknij i przeciÄ…gnij gdziekolwiek aby obrócić widok. PÅ‚acenie innym Rezydentom jest możliwe tylko w trybie zaawansowanym. Czy chcesz siÄ™ wylogować i zmienić tryb? Opcja wyboru trybu życia jest widoczna na ekranie logowania. <usetemplate name="okcancelbuttons" notext="Nie zamykaj" yestext="Zamknij"/> </notification> - <global name="UnsupportedCPU"> - - PrÄ™dkość Twojego CPU nie speÅ‚nia minimalnych wymagaÅ„. - </global> <global name="UnsupportedGLRequirements"> WyglÄ…da na to, że Twój system nie speÅ‚nia wymagaÅ„ sprzÄ™towych [APP_NAME]. [APP_NAME] wymaga karty graficznej kompatybilnej z OpenGL z multiteksturami. Jeżeli masz takÄ… kartÄ™ zainstaluj najnowsze sterowniki do niej i uaktualnienia systemu operacyjnego. @@ -2916,4 +2908,16 @@ W innym przypadku możesz poszukać na mapie miejsca oznaczone jako "Infohu <global name="You died and have been teleported to your home location"> NastÄ…piÅ‚a Å›mierć i teleportacja do Miejsca Startu. </global> + <notification name="TeleportedByAttachment"> + You have been teleported by an attachment on [ITEM_ID] + <usetemplate ignoretext="ZostaÅ‚eÅ›/aÅ› teleportowany/a przez dodatek" name="notifyignore"/> + </notification> + <notification name="TeleportedByObjectOnParcel"> + You have been teleported by the object '[OBJECT_NAME]' on the parcel '[PARCEL_NAME]' + <usetemplate ignoretext="ZostaÅ‚eÅ›/aÅ› teleportowany/a przez obiekt na dziaÅ‚ce" name="notifyignore"/> + </notification> + <notification name="DefaultObjectPermissions"> + WystÄ…piÅ‚ problem z zapisywaniem domyÅ›lnych zezwoleÅ„ obiektu: [REASON]. Spróbuj ustawić je ponownie później. + <usetemplate name="okbutton" yestext="OK"/> + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/pl/panel_login.xml b/indra/newview/skins/default/xui/pl/panel_login.xml index c87a3d3bd4..42809a8afb 100755 --- a/indra/newview/skins/default/xui/pl/panel_login.xml +++ b/indra/newview/skins/default/xui/pl/panel_login.xml @@ -1,48 +1,11 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php - </panel.string> - <layout_stack name="login_widgets"> - <layout_panel name="login"> - <text name="log_in_text"> - POÅÄ„CZ - </text> - <text name="username_text"> - Użytkownik: - </text> - <combo_box name="username_combo" tool_tip="NazwÄ™ użytkownika wybierasz przy rejestracji, np. bobsmith12 lub Steller Sunshine"/> - <text name="password_text"> - HasÅ‚o: - </text> - </layout_panel> - <layout_panel name="start_location_panel"> - <text name="start_location_text"> - Rozpocznij w: - </text> - <combo_box name="start_location_combo"> - <combo_box.item label="Ostatnie Miejsce" name="MyLastLocation"/> - <combo_box.item label="Moje Miejsce Startu" name="MyHome"/> - <combo_box.item label="<Wpisz Region>" name="Typeregionname"/> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php</panel.string> + <layout_stack name="ui_stack"> + <layout_panel name="ui_container"> + <combo_box label="My favorite places" name="start_location_combo"> + <combo_box.item label="Ostatnia lokalizacja" name="MyLastLocation"/> </combo_box> </layout_panel> - <layout_panel name="links_login_panel"> - <text name="login_help"> - Potrzebujesz pomocy z logowaniem siÄ™? - </text> - <text name="forgot_password_text"> - ZapomniaÅ‚eÅ› swojej nazwy użytkownika lub hasÅ‚a? - </text> - <button label="PoÅ‚Ä…cz" name="connect_btn"/> - <check_box label="ZapamiÄ™taj hasÅ‚o" name="remember_check"/> - </layout_panel> - <layout_panel name="links"> - <text name="create_account_text"> - CREATE YǾUR ACCǾUNT - </text> - <button name="create_new_account_btn" - label="Utwórz nowe konto" - width="120"/> - </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/pl/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/pl/panel_marketplace_listings.xml new file mode 100644 index 0000000000..7db98a106d --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Marketplace" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Opcje widoku/sortowania"/> + <button name="add_btn" tool_tip="Utwórz nowy folder"/> + <button label="Zweryfikuj" name="audit_btn" tool_tip="Sprawdź swoje przedmioty na Marketplace"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Filtruj przedmioty" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pl/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..be4be5b80f --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="WSZYSTKO" name="All Items" tool_tip="PrzeciÄ…gnij tutaj przedmioty, aby je wylistować"/> diff --git a/indra/newview/skins/default/xui/pl/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..3b17298742 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NA LIÅšCIE" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..f818da6821 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NIEPRZYPISANE" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..8031fe78f7 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="UKRYTE" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/pl/panel_status_bar.xml b/indra/newview/skins/default/xui/pl/panel_status_bar.xml index 6aa0d27bb8..e9b1ba89a5 100755 --- a/indra/newview/skins/default/xui/pl/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pl/panel_status_bar.xml @@ -1,33 +1,17 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="StatBarDaysOfWeek"> - Niedziela:PoniedziaÅ‚ek:Wtorek:Åšroda:Czwartek:PiÄ…tek:Sobota - </panel.string> - <panel.string name="StatBarMonthsOfYear"> - StyczeÅ„:Luty:Marzec:KwiecieÅ„:Maj:Czerwiec:Lipiec:StyczeÅ„:WrzesieÅ„:Październik:Listopad:GrudzieÅ„ - </panel.string> - <panel.string name="packet_loss_tooltip"> - Utracone pakiety - </panel.string> - <panel.string name="bandwidth_tooltip"> - Przepustowość - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="StatBarDaysOfWeek">Niedziela:PoniedziaÅ‚ek:Wtorek:Åšroda:Czwartek:PiÄ…tek:Sobota</panel.string> + <panel.string name="StatBarMonthsOfYear">StyczeÅ„:Luty:Marzec:KwiecieÅ„:Maj:Czerwiec:Lipiec:StyczeÅ„:WrzesieÅ„:Październik:Listopad:GrudzieÅ„</panel.string> + <panel.string name="packet_loss_tooltip">Utracone pakiety</panel.string> + <panel.string name="bandwidth_tooltip">Przepustowość</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel name="balance_bg"> - <text name="balance" tool_tip="Kliknij aby odÅ›wieżyć bilans L$" value="L$20"/> + <text name="balance" tool_tip="Kliknij aby odÅ›wieżyć bilans L$" value="L$??"/> <button label="Kup L$" name="buyL" tool_tip="Kliknij aby kupić wiÄ™cej L$"/> </panel> - <text name="TimeText" tool_tip="Obecny czas (Pacyficzny)"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="Obecny czas (Pacyficzny)">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="Start/Stop wszystkie media (Muzyka, Video, WWW)"/> <button name="volume_btn" tool_tip="Regulacja gÅ‚oÅ›noÅ›ci"/> </panel> diff --git a/indra/newview/skins/default/xui/pl/sidepanel_item_info.xml b/indra/newview/skins/default/xui/pl/sidepanel_item_info.xml index 9ec3c480b7..4b3df5cde8 100755 --- a/indra/newview/skins/default/xui/pl/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/pl/sidepanel_item_info.xml @@ -63,9 +63,10 @@ <check_box label="Sprzedaje/ Oddaje" name="CheckNextOwnerTransfer" tool_tip="NastÄ™pny wÅ‚aÅ›ciciel może oddawać lub sprzedawać ten obiekt"/> </panel> <check_box label="Na sprzedaż" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="Kopiuje" name="Copy"/> - <combo_box.item label="Oryginalny" name="Original"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Kopia" name="Copy"/> + <combo_box.item label="Zawartość" name="Contents"/> + <combo_box.item label="OryginaÅ‚" name="Original"/> </combo_box> <spinner label="Cena: L$" name="Edit Cost"/> </panel> diff --git a/indra/newview/skins/default/xui/pl/sidepanel_task_info.xml b/indra/newview/skins/default/xui/pl/sidepanel_task_info.xml index eb8c9cdbbb..503541a96e 100755 --- a/indra/newview/skins/default/xui/pl/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/pl/sidepanel_task_info.xml @@ -1,65 +1,29 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Profil Obiektu"> - <panel.string name="text deed continued"> - Przypisz - </panel.string> - <panel.string name="text deed"> - Przypisz - </panel.string> - <panel.string name="text modify info 1"> - Możesz modyfikować ten obiekt - </panel.string> - <panel.string name="text modify info 2"> - Możesz modyfikować te obiekty - </panel.string> - <panel.string name="text modify info 3"> - Nie możesz modyfikować tego obiektu - </panel.string> - <panel.string name="text modify info 4"> - Nie możesz modyfikować tych obiektów - </panel.string> - <panel.string name="text modify warning"> - Ten obiekt ma części zgrupowane - </panel.string> - <panel.string name="Cost Default"> - Cena: L$ - </panel.string> - <panel.string name="Cost Total"> - Cena caÅ‚kowita: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Cena za jednostkÄ™: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Cena mieszana - </panel.string> - <panel.string name="Sale Mixed"> - Sprzedaż mieszana - </panel.string> + <panel.string name="text deed continued">Przypisz</panel.string> + <panel.string name="text deed">Przypisz</panel.string> + <panel.string name="text modify info 1">Możesz modyfikować ten obiekt</panel.string> + <panel.string name="text modify info 2">Możesz modyfikować te obiekty</panel.string> + <panel.string name="text modify info 3">Nie możesz modyfikować tego obiektu</panel.string> + <panel.string name="text modify info 4">Nie możesz modyfikować tych obiektów</panel.string> + <panel.string name="text modify warning">Ten obiekt ma części zgrupowane</panel.string> + <panel.string name="Cost Default">Cena: L$</panel.string> + <panel.string name="Cost Total">Suma: L$</panel.string> + <panel.string name="Cost Per Unit">Cena za jednostkÄ™: L$</panel.string> + <panel.string name="Cost Mixed">Cena mieszana</panel.string> + <panel.string name="Sale Mixed">Sprzedaż mieszana</panel.string> <text name="title" value="Profil Obiektu"/> <text name="where" value="(W Åšwiecie)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Nazwa: - </text> - <text name="Description:"> - Opis: - </text> - <text name="CreatorNameLabel"> - Twórca: - </text> - <text name="Owner:"> - WÅ‚aÅ›ciciel: - </text> - <text name="Group_label"> - Grupa: - </text> + <text name="Name:">Nazwa:</text> + <text name="Description:">Opis:</text> + <text name="CreatorNameLabel">Twórca:</text> + <text name="Owner:">WÅ‚aÅ›ciciel:</text> + <text name="Group_label">Grupa:</text> <button name="button set group" tool_tip="Wybierz grupÄ™ by udostÄ™pnić jej prawa do tego obiektu"/> <name_box initial_value="Åadowanie..." name="Group Name Proxy"/> <button label="Przypisz" label_selected="Przypisz" name="button deed" tool_tip="Opcja przepisania udostÄ™pnia obiektowi takie same prawa jak zostaÅ‚y zaznaczone dla nastÄ™pnego wÅ‚aÅ›ciciela. Obiekty udostÄ™pnione grupie mogÄ… zostać przepisane dla grupy przez oficera grupy."/> - <text name="label click action"> - Kliknij by: - </text> + <text name="label click action">Kliknij by:</text> <combo_box name="clickaction"> <combo_box.item label="Dotknij (domyÅ›lne)" name="Touch/grab(default)"/> <combo_box.item label="UsiÄ…dź na obiekcie" name="Sitonobject"/> @@ -68,21 +32,13 @@ <combo_box.item label="Otwórz" name="Open"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Możesz modyfikować ten obiekt - </text> - <text name="Anyone can:"> - Każdy: - </text> + <text name="perm_modify">Możesz modyfikować ten obiekt</text> + <text name="Anyone can:">Każdy:</text> <check_box label="Kopiuj" name="checkbox allow everyone copy"/> <check_box label="PrzesuÅ„" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Grupie: - </text> + <text name="GroupLabel">Grupie:</text> <check_box label="UdostÄ™pnij" name="checkbox share with group" tool_tip="UdostÄ™pnij prawa do modyfikacji tego obiektu wszystkim czÅ‚onkom, którzy posiadajÄ… przywilej modyfikacji obiektów grupy. By ograniczyć, przypisz obiekt do grupy."/> - <text name="NextOwnerLabel"> - NastÄ™pny WÅ‚aÅ›ciciel: - </text> + <text name="NextOwnerLabel">NastÄ™pny WÅ‚aÅ›ciciel:</text> <check_box label="Modyfikuj" name="checkbox next owner can modify"/> <check_box label="Kopiuj" name="checkbox next owner can copy"/> <check_box label="Oddaj" name="checkbox next owner can transfer" tool_tip="NastÄ™pny wÅ‚aÅ›ciciel może sprzedać lub oddać ten obiekt"/> @@ -95,24 +51,12 @@ </combo_box> <spinner label="Cena: L$" name="Edit Cost"/> <check_box label="Pokaż w wyszukiwarce" name="search_check" tool_tip="UdostÄ™pnij widzialność tego obiektu w wyszukiwarce"/> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Otwórz" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index f86e393646..7801d50457 100755 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -182,6 +182,48 @@ Tylko pojedynczy obiekt może być tutaj przeciÄ…gniÄ™ty </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> + <string name="TooltipOutboxDragToWorld"> + Nie możesz rezzować obiektów z folderu rzeczy na Marketplace + </string> + <string name="TooltipOutboxWorn"> + Nie możesz umieszczać na Marketplace przedmiotów, które masz na sobie zaÅ‚ożone + </string> + <string name="TooltipOutboxFolderLevels"> + GÅ‚Ä™bokość zagnieżdżonych folderów przekracza [AMOUNT]. Zmniejsz ilość zagdzieżdżeÅ„; Spakuj przedmioty w pudeÅ‚ka, jeÅ›li to pomoże. + </string> + <string name="TooltipOutboxTooManyFolders"> + Ilość podfolderów w folderze najwyższego poziomu przekracza [AMOUNT]. Zmniejsz ilość folderów; Spakuj przedmioty w pudeÅ‚ka, jeÅ›li to pomoże. + </string> + <string name="TooltipOutboxTooManyObjects"> + Ilość pozycji w folderze najwyższego poziomu przekracza [AMOUNT]. JeÅ›li chcesz sprzedać wiÄ™cej, niż [AMOUNT] przedmiotów jako jednÄ… pozycjÄ™, to musisz je spakować w pudeÅ‚ka. + </string> + <string name="TooltipOutboxTooManyStockItems"> + Ilość przedmiotów w folderze magazynowym przekracza [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Możesz przenosić foldery lub przedmioty wyÅ‚Ä…cznie do karty WSZYSTKO. Wybierz teraz tÄ… kartÄ™ i spróbuj ponownie. + </string> + <string name="TooltipOutboxNoTransfer"> + Jeden lub kilka z tych obiektów nie może zostać sprzedany / przetransferowany + </string> + <string name="TooltipOutboxNotInInventory"> + Marketplace akceptuje tylko przedmioty bezpoÅ›rednio z Twojej Szafy. + </string> + <string name="TooltipOutboxLinked"> + Nie możesz sprzedać zlinkowanych folderów lub przedmiotów na Marketplace + </string> + <string name="TooltipOutboxCallingCard"> + Nie możesz umieszczać wizytówek na Marketplace + </string> + <string name="TooltipOutboxDragActive"> + Nie można przenieść wylistowanego przedmiotu + </string> + <string name="TooltipOutboxCannotMoveRoot"> + Nie możesz przenieść folderu głównego przedmiotów na Marketplace + </string> + <string name="TooltipOutboxMixedStock"> + Wszystkie przedmioty w folderze magazynowym muszÄ… mieć ten sam typ i zezwolenia + </string> <string name="TooltipHttpUrl"> Kliknij aby zobaczyć zawartość tej strony internetowej </string> @@ -429,9 +471,6 @@ <string name="AvatarAway"> Åšpi </string> - <string name="AvatarBusy"> - Pracuje - </string> <string name="AvatarMuted"> Wyciszony </string> @@ -723,6 +762,7 @@ <string name="ControlYourCamera"> Kontroluj kamerÄ™ </string> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SIM_ACCESS_PG"> 'General' </string> @@ -777,6 +817,12 @@ <string name="bitmap_image_files"> Obrazy bitmap </string> + <string name="png_image_files"> + Obrazy PNG + </string> + <string name="save_texture_image_files"> + Obrazy Targa lub PNG + </string> <string name="avi_movie_file"> Pliki filmowe AVI </string> @@ -798,18 +844,6 @@ <string name="choose_the_directory"> Wybierz katalog </string> - <string name="AvatarSetNotAway"> - Ustaw Nie Åšpij - </string> - <string name="AvatarSetAway"> - Åšpij - </string> - <string name="AvatarSetNotBusy"> - Ustawiaj Nie Pracuj - </string> - <string name="AvatarSetBusy"> - Pracuj - </string> <string name="shape"> KsztaÅ‚t </string> @@ -1032,10 +1066,102 @@ <string name="FavoritesNoMatchingItems"> PrzeciÄ…gnij landmark tutaj aby dodać go do swoich ulubionych. </string> + <string name="MarketplaceNoMatchingItems"> + Niczego nie znaleziono. Sprawdź pisowniÄ™ i spróbuj ponownie. + </string> <string name="InventoryNoTexture"> Nie posiadasz kopii tej tekstury w Twojej Szafie. </string> - <string name="Unconstrained">Swobodny</string> + <string name="InventoryMarketplaceError"> + Ta funkcjonalność jest obecnie w fazie Beta. Dodaj proszÄ™ swoje imiÄ™ do tego [http://goo.gl/forms/FCQ7UXkakz formularza Google] (w jÄ™zyku angielskim), jeÅ›li chcesz wziąć udziaÅ‚ w programie Beta i pomóc. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Twój folder przedmiotów na Marketplace jest pusty. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + PrzeciÄ…gnij foldery do tego obszaru, aby dodać je na listÄ™ sprzedaży w [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> + <string name="Marketplace Validation Warning Stock"> + folder magazynowy musi być zawarty w folderze wersji + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : BÅ‚Ä…d: wszystkie przedmioty w folderze magazynowym muszÄ… mieć ten sam typ i być niekopiowalne + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : BÅ‚Ä…d: folder magazynowy nie może zawierać podfolderów + </string> + <string name="Marketplace Validation Warning Empty"> + : Uwaga: folder jest pusty + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Uwaga: tworzÄ™ folder magazynowy + </string> + <string name="Marketplace Validation Warning Create Version"> + : Uwaga: tworzÄ™ folder wersji + </string> + <string name="Marketplace Validation Warning Move"> + : Uwaga: przenoszÄ™ przedmioty + </string> + <string name="Marketplace Validation Warning Delete"> + : Uwaga: zawartość folderu przeniesiona do folderu magazynowego, usuwam pusty katalog + </string> + <string name="Marketplace Validation Error Stock Item"> + : BÅ‚Ä…d: przedmioty bez praw kopiowania muszÄ… siÄ™ znajdować w folderze magazynowym + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Uwaga: przedmioty muszÄ… siÄ™ znajdować w folderze wersji + </string> + <string name="Marketplace Validation Error"> + : BÅ‚Ä…d: + </string> + <string name="Marketplace Validation Warning"> + : Uwaga: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Uwaga: folder wersji musi zawierać przynajmniej jednÄ… pozycjÄ™ + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Uwaga: folder magazynowy musi zawierać przynajmniej jednÄ… pozycjÄ™ + </string> + <string name="Marketplace Validation No Error"> + Brak bÅ‚Ä™dów lub ostrzeżeÅ„ + </string> + <string name="Marketplace Error Prefix"> + BÅ‚Ä…d: + </string> + <string name="Marketplace Error Not Merchant"> + Przed wysÅ‚aniem przedmiotów na Marketplace musisz zostać kupcem (darmowe). + </string> + <string name="Marketplace Error Not Accepted"> + Nie można przenieść tego przedmiotu. + </string> + <string name="Marketplace Error Unsellable Item"> + Ta pozycja nie może być sprzedana na Marketplace. + </string> + <string name="MarketplaceNoID"> + no Mkt ID + </string> + <string name="MarketplaceLive"> + na liÅ›cie + </string> + <string name="MarketplaceActive"> + aktywne + </string> + <string name="MarketplaceMax"> + maks + </string> + <string name="MarketplaceStock"> + magazyn + </string> + <string name="MarketplaceNoStock"> + brak w magazynie + </string> + <string name="MarketplaceUpdating"> + aktualizacja... + </string> + <string name="Unconstrained"> + Swobodny + </string> <string name="no_transfer" value=" (brak oddawania)"/> <string name="no_modify" value=" (brak modyfikowania)"/> <string name="no_copy" value=" (brak kopiowania)"/> @@ -1049,6 +1175,7 @@ Brak zawartoÅ›ci </string> <string name="WornOnAttachmentPoint" value=" (zaÅ‚ożony na [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (aktywne)"/> <string name="Chat Message" value="Czat:"/> <string name="Sound" value=" DźwiÄ™k :"/> @@ -1286,6 +1413,15 @@ <string name="Invalid Attachment"> Nieważny punkt zaÅ‚Ä…cznika </string> + <string name="ATTACHMENT_MISSING_ITEM"> + BÅ‚Ä…d: brakujÄ…cy przedmiot + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + BÅ‚Ä…d: brakujÄ…ca baza przedmiotu + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + BÅ‚Ä…d: obiekt jest w obecnym stroju, ale nie jest zaÅ‚ożony + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] </string> @@ -1451,6 +1587,9 @@ <string name="SaveComplete"> Zapisywanie zakoÅ„czone. </string> + <string name="UploadFailed"> + Åadowanie nieudane: + </string> <string name="ObjectOutOfRange"> Skrypt (obiekt poza zasiÄ™giem) </string> @@ -1675,9 +1814,6 @@ <string name="PanelContentsNewScript"> Nowy skrypt </string> - <string name="BusyModeResponseDefault"> - Rezydent, do którego wysÅ‚aÅ‚eÅ› wiadomość prywatnÄ… znajduje siÄ™ w trybie pracy. Oznacza to, iż Twoja wiadomość zostanie zapisana do przejrzenia poźniej. - </string> <string name="MuteByName"> (Nazwa) </string> @@ -1780,9 +1916,6 @@ <string name="GroupMoneyDebits"> Debet </string> - <string name="ViewerObjectContents"> - Zawartość - </string> <string name="AcquiredItems"> Zdobyte obiekty </string> @@ -4338,4 +4471,10 @@ Spróbuj zaÅ‚Ä…czyć Å›cieżkÄ™ do edytora w cytowaniu. <string name="ParticleHiding"> Ukryj czÄ…steczki </string> + <string name="Command_MarketplaceListings_Label"> + Marketplace + </string> + <string name="Command_MarketplaceListings_Tooltip"> + Sprzedaj owoce swojej twórczoÅ›ci + </string> </strings> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 47975a6386..1e2edd7a2f 100755 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -1,73 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="SOBRE [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - ConstruÃdo com [COMPILER] versão [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL: <nolink>[SLURL]</nolink> -(coordenadas globais [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -Memória: [MEMORY_MB] MBs -Versão OS: [OS_VERSION] -Placa de vÃdeo: [GRAPHICS_CARD_VENDOR] -Placa gráfica: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Versão do driver de vÃdeo Windows: [GRAPHICS_CARD_VENDOR] - </floater.string> - <floater.string name="AboutLibs"> - Versão OpenGL: [OPENGL_VERSION] - -Versão libcurl: [LIBCURL_VERSION] -Versão J2C Decoder: [J2C_VERSION] -Versão do driver de áudio: [AUDIO_DRIVER_VERSION] -Versão Qt Webkit: [QT_WEBKIT_VERSION] -Versão do servidor de voz: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (nenhum) - </floater.string> - <floater.string name="AboutTraffic"> - Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Erro ao obter URL de notas de versão do servidor. - </floater.string> <tab_container name="about_tab"> <panel label="Info" name="support_panel"> <button label="Copiar" name="copy_btn"/> </panel> <panel label="Créditos" name="credits_panel"> - <text name="linden_intro"> - O Second Life é trazido a você pela Lindens: - </text> - <text_editor name="linden_names"> - Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase - </text_editor> - <text name="contrib_intro"> - com contribuições de código aberto de: - </text> - <text_editor name="contrib_names"> - Dummy Name substituÃdo durante a execução - </text_editor> - <text name="trans_intro"> - e traduções de: - </text> - <text_editor name="trans_names"> - Dummy Name substituÃdo durante a execução - </text_editor> + <text name="linden_intro">O Second Life é trazido a você pela Lindens, +com contribuições de código aberto de:</text> + <text_editor name="contrib_names">Dummy Name substituÃdo durante a execução</text_editor> </panel> <panel label="Licenças" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -94,8 +37,7 @@ Versão do servidor de voz: [VOICE_VERSION] Todos os direitos reservados. Consulte licenses.txt para obter detalhes. - Codificação de áudio da conversa com voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Codificação de áudio da conversa com voz: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_associate_listing.xml b/indra/newview/skins/default/xui/pt/floater_associate_listing.xml new file mode 100644 index 0000000000..1fac5643b0 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="ASSOCIAR LISTAGEM"> + <text name="message">ID de listagem:</text> + <line_editor name="listing_id">Digite a ID aqui</line_editor> + <button label="OK" name="OK"/> + <button label="Cancelar" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/pt/floater_edit_hover_height.xml new file mode 100644 index 0000000000..163ab440ea --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="DEFINIR ALTURA DE FOCO"> + <slider label="Altura" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml index 8a8f1f5b34..5f04c08531 100755 --- a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="PROPRIEDADES DE ITEM NO INVENTÃRIO"> - <floater.string name="unknown"> - (desconhecido) - </floater.string> - <floater.string name="public"> - (público) - </floater.string> - <floater.string name="you_can"> - Você pode: - </floater.string> - <floater.string name="owner_can"> - Proprietário pode : - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Nome: - </text> - <text name="LabelItemDescTitle"> - Descrição: - </text> - <text name="LabelCreatorTitle"> - Criador: - </text> + <floater.string name="unknown">(desconhecido)</floater.string> + <floater.string name="public">(público)</floater.string> + <floater.string name="you_can">Você pode:</floater.string> + <floater.string name="owner_can">Proprietário pode :</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Nome:</text> + <text name="LabelItemDescTitle">Descrição:</text> + <text name="LabelCreatorTitle">Criador:</text> <button label="Perfil..." label_selected="" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Dono: - </text> + <text name="LabelOwnerTitle">Dono:</text> <button label="Perfil..." label_selected="" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Adquirido: - </text> - <text name="LabelAcquiredDate"> - Qua Mai 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Você: - </text> + <text name="LabelAcquiredTitle">Adquirido:</text> + <text name="LabelAcquiredDate">Qua Mai 24 12:50:46 2006</text> + <text name="OwnerLabel">Você:</text> <check_box label="Editar" name="CheckOwnerModify"/> <check_box label="Copiar" name="CheckOwnerCopy"/> <check_box label="Revender" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Todos: - </text> + <text name="AnyoneLabel">Todos:</text> <check_box label="Cortar" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Grupo: - </text> + <text name="GroupLabel">Grupo:</text> <check_box label="Compartilhar" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel" width="230"> - Próximo proprietário: - </text> + <text name="NextOwnerLabel" width="230">Próximo proprietário:</text> <check_box label="Editar" name="CheckNextOwnerModify"/> <check_box label="Copiar" name="CheckNextOwnerCopy"/> <check_box label="Revender" name="CheckNextOwnerTransfer"/> <check_box label="À venda" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Cortar" name="Copy"/> + <combo_box.item label="Conteúdo" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Preço:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_item_properties.xml b/indra/newview/skins/default/xui/pt/floater_item_properties.xml new file mode 100644 index 0000000000..400196c3c3 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="PROPRIEDADES DO ITEM"/> diff --git a/indra/newview/skins/default/xui/pt/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/pt/floater_marketplace_listings.xml new file mode 100644 index 0000000000..fa4ac50ab0 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="LISTAGENS DO MARKETPLACE"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Carregando...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/pt/floater_marketplace_validation.xml new file mode 100644 index 0000000000..39e59a687f --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Auditar Listagens do Marketplace"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_openobject.xml b/indra/newview/skins/default/xui/pt/floater_openobject.xml index 164bfee3aa..e8b72700c9 100755 --- a/indra/newview/skins/default/xui/pt/floater_openobject.xml +++ b/indra/newview/skins/default/xui/pt/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Copiar para inventário" label_selected="Copiar para inventário" name="copy_to_inventory_button" width="132"/> - <button label="Copiar e adicionar à roupa" label_selected="Copiar e adicionar à roupa" left="152" name="copy_and_wear_button"/> + <text name="border_note"> + Copiar para inventário e vestir + </text> + <button label="Adicionar ao look" label_selected="Adicionar ao look" left="152" name="copy_and_wear_button"/> + <button label="Substituir look" label_selected="Substituir look" name="copy_and_replace_button"/> + <button label="Apenas copiar para inventário" label_selected="Apenas copiar para inventário" name="copy_to_inventory_button" width="132"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_pay.xml b/indra/newview/skins/default/xui/pt/floater_pay.xml index 8094ad376c..77e814b575 100755 --- a/indra/newview/skins/default/xui/pt/floater_pay.xml +++ b/indra/newview/skins/default/xui/pt/floater_pay.xml @@ -1,25 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string name="payee_group"> - Pagar grupo - </string> - <string name="payee_resident"> - Pagar residente - </string> - <text left="5" name="payee_label"> - Pagar: - </text> - <icon name="icon_person" tool_tip="Pessoa"/> - <text name="payee_name"> - Test Name That Is Extremely Long To Check Clipping - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - Outro valor: - </text> - <button label="Pagar" label_selected="Pagar" name="pay btn"/> - <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + <string name="payee_group">Pagar grupo</string> + <string name="payee_resident">Pagar residente</string> + <text name="paying_text">Você está pagando:</text> + <text name="payee_name">Test Name That Is Extremely Long To Check Clipping</text> + <panel label="Buscar" name="PatternsPanel"> + <button label="Pagar L$ 1" label_selected="Pagar L$ 1" name="fastpay 1"/> + <button label="Pagar L$ 5" label_selected="Pagar L$ 5" name="fastpay 5"/> + <button label="Pagar L$ 10" label_selected="Pagar L$ 10" name="fastpay 10"/> + <button label="Pagar L$ 20" label_selected="Pagar L$ 20" name="fastpay 20"/> + </panel> + <panel label="Buscar" name="InputPanel"> + <text name="amount text">Outro valor:</text> + <button label="Pagar" label_selected="Pagar" name="pay btn"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_pay_object.xml b/indra/newview/skins/default/xui/pt/floater_pay_object.xml index a5579f03bf..4f7fa6ca67 100755 --- a/indra/newview/skins/default/xui/pt/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/pt/floater_pay_object.xml @@ -1,30 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money" title=""> - <string halign="left" name="payee_group" width="100"> - Pagar grupo - </string> - <string halign="left" name="payee_resident" width="120"> - Pagar residente - </string> - <icon name="icon_person" tool_tip="Pessoa"/> - <text left="105" name="payee_name"> - Ericacita Moostopolison - </text> - <text halign="left" left="5" name="object_name_label" width="95"> - Via objeto: - </text> + <string halign="left" name="payee_group" width="100">Pagar grupo</string> + <string halign="left" name="payee_resident" width="120">Pagar residente</string> + <text name="paying_text">Você está pagando:</text> + <text left="105" name="payee_name">Ericacita Moostopolison</text> + <text halign="left" left="5" name="object_name_label" width="95">Via objeto:</text> <icon name="icon_object" tool_tip="Objects"/> - <text left="105" name="object_name_text"> - Meu objeto maravilho, fantástico e com nome comprido e imaginativo - </text> - <button label="L$1" label_selected="L$1" left="125" name="fastpay 1" width="70"/> - <button label="L$5" label_selected="L$5" left="200" name="fastpay 5" width="70"/> - <button label="L$10" label_selected="L$10" left="125" name="fastpay 10" width="70"/> - <button label="L$20" label_selected="L$20" left="200" name="fastpay 20" width="70"/> - <text halign="left" left="5" name="amount text"> - Outro valor: - </text> - <line_editor left="60" name="amount" width="50"/> - <button label="Pagar" label_selected="Pagar" name="pay btn"/> - <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + <text left="105" name="object_name_text">Meu objeto maravilho, fantástico e com nome comprido e imaginativo</text> + <panel label="Buscar" name="PatternsPanel"> + <button label="Pagar L$ 1" label_selected="Pagar L$ 1" name="fastpay 1"/> + <button label="Pagar L$ 5" label_selected="Pagar L$ 5" name="fastpay 5"/> + <button label="Pagar L$ 10" label_selected="Pagar L$ 10" name="fastpay 10"/> + <button label="Pagar L$ 20" label_selected="Pagar L$ 20" name="fastpay 20"/> + </panel> + <panel label="Buscar" name="InputPanel"> + <text name="amount text">Outro valor:</text> + <button label="Pagar" label_selected="Pagar" name="pay btn"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml index 2d4cd670e6..ac79422110 100755 --- a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Minha aparência" name="Change Outfit"/> <menu_item_call label="Editar meu look" name="Edit Outfit"/> <menu_item_call label="Editar meu corpo" name="Edit My Shape"/> + <menu_item_call label="Altura de foco" name="Hover Height"/> <menu_item_call label="Meus amigos" name="Friends..."/> <menu_item_call label="Meus grupos" name="Groups..."/> <menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml index 447b77657b..a0ac71e018 100755 --- a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Minha aparência" name="Chenge Outfit"/> <menu_item_call label="Editar meu look" name="Edit Outfit"/> <menu_item_call label="Editar meu corpo" name="Edit My Shape"/> + <menu_item_call label="Altura de foco" name="Hover Height"/> <menu_item_call label="Meus amigos" name="Friends..."/> <menu_item_call label="Meus grupos" name="Groups..."/> <menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml index 636b356c8b..79261ceb1f 100755 --- a/indra/newview/skins/default/xui/pt/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Criar listagem" name="Marketplace Create Listing"/> + <menu_item_call label="Associar listagem" name="Marketplace Associate Listing"/> + <menu_item_call label="Obter listagem (Atualizar)" name="Marketplace Get Listing"/> + <menu_item_call label="Verificar erros" name="Marketplace Check Listing"/> + <menu_item_call label="Editar listagem" name="Marketplace Edit Listing"/> + <menu_item_call label="Listar" name="Marketplace List"/> + <menu_item_call label="Parar de oferecer" name="Marketplace Unlist"/> + <menu_item_call label="Ativar" name="Marketplace Activate"/> + <menu_item_call label="Desativar" name="Marketplace Deactivate"/> <menu_item_call label="Compartilhar" name="Share"/> <menu_item_call label="Comprar" name="Task Buy"/> <menu_item_call label="Abrir" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Adicionar" name="Wearable Add"/> <menu_item_call label="Tirar" name="Take Off"/> <menu_item_call label="Copiar para Caixa de saÃda do lojista" name="Merchant Copy"/> - <menu_item_call label="Enviar para Mercado" name="Marketplace Send"/> + <menu_item_call label="Copiar para Listagens do Marketplace" name="Marketplace Copy"/> + <menu_item_call label="Mover para Listagens do Marketplace" name="Marketplace Move"/> <menu_item_call label="--Sem opções--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/pt/menu_marketplace_view.xml b/indra/newview/skins/default/xui/pt/menu_marketplace_view.xml new file mode 100644 index 0000000000..2236df5c87 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Ordenar por quantidade em estoque stock (baixo a alto)" name="sort_by_stock_amount"/> + <menu_item_check label="Exibir apenas pastas da listagem" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index b5af342754..3d5d9eccc6 100755 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Voar" name="Fly"/> <menu_item_check label="Correr sempre" name="Always Run"/> <menu_item_call label="Parar minha animação" name="Stop Animating My Avatar"/> - <menu_item_call label="Andar/correr/voar..." name="Walk / run / fly"/> + <menu_item_call label="Andar/correr/voar..." name="WalkRunFly"/> </menu> <menu label="Status" name="Status"> <menu_item_check label="Ausente" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="Comprar L$..." name="Buy and Sell L$"/> <menu_item_call label="Caixa de saÃda do lojista..." name="MerchantOutbox"/> + <menu_item_call label="Listagens do Marketplace..." name="MarketplaceListings"/> <menu_item_call label="Painel da conta..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt"/> </menu_item_call> @@ -63,7 +64,7 @@ <menu_item_call label="Foto" name="Take Snapshot"/> <menu_item_call label="Perfil da região" name="Place Profile"/> <menu_item_call label="Sobre terrenos" name="About Land"/> - <menu_item_call label="Região/Propriedade" name="Region/Estate"/> + <menu_item_call label="Região/Propriedade" name="RegionEstate"/> <menu_item_call label="Meus terrenos..." name="My Land"/> <menu_item_call label="Comprar este terreno" name="Buy Land"/> <menu label="Mostrar" name="LandShow"> @@ -177,7 +178,7 @@ <menu_item_call label="Blogs do [SECOND_LIFE]" name="Second Life Blogs"/> <menu_item_call label="Denunciar abuso" name="Report Abuse"/> <menu_item_call label="Relatar bug" name="Report Bug"/> - <menu_item_call label="Empurrões, trombadas e tapas" name="Bumps, Pushes &amp; Hits"/> + <menu_item_call label="Bumps, Pushes & Hits" name="Bumps, Pushes &amp; Hits"/> <menu_item_call label="Sobre [APP_NAME]" name="About Second Life"/> </menu> <menu label="Avançado" name="Advanced"> @@ -250,6 +251,7 @@ <menu_item_check label="Painel de textura" name="Texture Console"/> <menu_item_check label="Console de depuração" name="Debug Console"/> <menu_item_call label="Painel de avisos" name="Notifications"/> + <menu_item_check label="Console de depuração de região" name="Region Debug Console"/> <menu_item_check label="Tempos" name="Fast Timers"/> <menu_item_check label="Memória" name="Memory"/> <menu_item_check label="EstatÃsticas da cena" name="Scene Statistics"/> @@ -325,7 +327,7 @@ <menu label="Rede" name="Network"> <menu_item_check label="Pausar avatar" name="AgentPause"/> <menu_item_call label="Drop a Packet" name="Drop a Packet"/> - </menu> + </menu> <menu label="Mundo" name="DevelopWorld"> <menu_item_check label="Impor sobre sol de simulação" name="Sim Sun Override"/> <menu_item_check label="Clima fixo" name="Fixed Weather"/> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index a01c9c757b..a264495404 100755 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -128,6 +128,88 @@ Nenhuma pasta foi enviada ao Marketplace devido a um erro do sistema ou da rede. Ocorreu uma falha na inicialização do Marketplace devido a um erro do sistema ou da rede. Tente novamente mais tarde. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Copiar ou mover para Pasta de estoque com falha com o erro: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Copiar ou mover para Listagens do Marketplace com falha com o erro: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + Ocorreu uma falha na transação com o Marketplace com o seguinte erro: + + Motivo: '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Não foi possÃvel listar este produto ou ativar a pasta de versões. Geralmente, isso é causado por ausência de informações no formulário de descrição da listagem, mas pode ser causado por erros na estrutura de pastas. Edite a listagem ou verifique se há erros na pasta de listagem. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Falha ao listar no Marketplace com erro: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Falha ao ativar esta pasta de versões com erro: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Esta ação alterará o conteúdo ativo desta listagem. Deseja continuar? + <usetemplate ignoretext="Confirmar antes de alterar uma listagem ativa no Marketplace" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Os itens arrastados para a janela Listagens do Marketplace são movidos de seus locais originais e não copiados. Deseja continuar? + <usetemplate ignoretext="Confirmar antes de mover um item do inventário para o Marketplace" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Mover ou excluir uma pasta de listagem excluirá sua listagem do Marketplace. Se você deseja manter a listagem do Marketplace, mova ou exclua o conteúdo da pasta de versões que você deseja modificar. Deseja continuar? + <usetemplate ignoretext="Confirmar antes de mover ou excluir uma listagem do Marketplace" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Você não tem permissão para copiar um ou mais deste itens para o Marketplace. Você pode movê-los ou deixá-los para trás. + <usetemplate canceltext="Cancelar" ignoretext="Confirmar antes de tentar copiar uma seleção que contenha itens de cópia proibida para o Marketplace" name="yesnocancelbuttons" notext="Não mover item(ns)" yestext="Mover item(ns)"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Esta ação removerá esta listagem. Deseja continuar? + <usetemplate ignoretext="Confirmar antes de remover uma listagem ativa no Marketplace" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Esta ação desativará a pasta de versões da listagem atual. Deseja continuar? + <usetemplate ignoretext="Confirmar antes de desativar a pasta de versões de uma listagem no Marketplace" name="okcancelignore" notext="Cancelar" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + A listagem não pode ser atualizada. +[[URL] Clique aqui] para editá-la no Marketplace. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Não é possÃvel usar roupas ou partes do corpo que estejam na pasta Listagens do Marketplace. + </notification> + <notification name="AlertMerchantListingInvalidID"> + ID de listagem inválida. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Há várias pastas sem versão ou com várias versões nesta listagem. Você precisará selecionar e ativar uma delas separadamente mais tarde. + <usetemplate ignoretext="Alertar sobre a ativação da pasta de versões quando criar uma listagem com várias pastas de versões" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Separamos itens de estoque de tipos diferentes em pastas de estoque diferentes para que sua pasta fique organizada de maneira que possamos listá-la. + <usetemplate ignoretext="Alertar quando a pasta de estoque for dividida antes de ser listada" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Removemos sua listagem porque o estoque está vazio. Você precisa adicionar mais unidades à pasta de estoque para que a listagem seja exibida novamente. + <usetemplate ignoretext="Alertar quando uma listagem não for listada porque a pasta de estoque está vazia" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> Houve um problema com o carregamento do texto para um script devido à seguinte razão: [REASON]. Por favor, tente novamente mais tarde. </notification> @@ -467,6 +549,10 @@ Nota: Este procedimento limpa o cache. Salvar alterações? <usetemplate canceltext="Cancelar" name="yesnocancelbuttons" notext="Não Salvar" yestext="Salvar"/> </notification> + <notification name="DeleteNotecard"> + Excluir nota? + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Falha ao salvar Gesto. Este gesto possui muitos passos. @@ -1860,6 +1946,9 @@ Isto mudará milhares de regiões e fará o spaceserver soluçar. A região que você está tentando visitar tem conteúdo que excede suas preferências atuais. Você pode alterar suas preferências acessando Eu > Preferências > Geral. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> A região que você está tentando visitar tem conteúdo [REGIONMATURITY], acessÃvel apenas para adultos. <url name="url"> @@ -2148,6 +2237,10 @@ Mover para o inventário o(s) item(s)? <ignore name="ignore" text="Definir 'Pagar por objeto' ao construir um objeto sem script money()"/> </form> </notification> + <notification name="PayConfirmation"> + Confirme que você deseja pagar L$[AMOUNT] a [TARGET]. + <usetemplate ignoretext="Confirmar antes de pagar (somas acima de L$ 200)" name="okcancelignore" notext="Cancelar" yestext="Pagar"/> + </notification> <notification name="OpenObjectCannotCopy"> Não há itens neste objeto que você está autorizado a copiar. </notification> @@ -2684,9 +2777,6 @@ Por favor, tente novamente em alguns instantes. <notification name="NoValidCircuit"> Código de circuito inválido. </notification> - <notification name="NoValidTimestamp"> - Hora inválida. - </notification> <notification name="NoPendingConnection"> ImpossÃvel criar a conexão pendente. </notification> @@ -3829,9 +3919,11 @@ Tente novamente em instantes. </notification> <notification name="TeleportedByAttachment"> Você foi teletransportado por um anexo em [ITEM_ID] + <usetemplate ignoretext="Teletransportar: Você foi teletransportado por um anexo" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Você foi teletransportado pelo objeto '[OBJECT_NAME]' no lote '[PARCEL_NAME]' + <usetemplate ignoretext="Teletransportar: Você foi teletransportado por um objeto em um lote" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Você foi teletransportado pelo objeto '[OBJECT_NAME]' de propriedade de [OWNER_ID] @@ -4163,7 +4255,7 @@ Tente selecionar uma quantidade menor de terreno. <usetemplate ignoretext="Não foi possÃvel mover arquivos. Caminho anterior restaurado." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Ocorreu um problema ao salvar as permissões padrão devido ao seguinte motivo: [REASON]. Tente definir as permissões padrão mais tarde. + Ocorreu um problema ao salvar as permissões padrão do objeto: [REASON]. Tente definir as permissões padrão mais tarde. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/pt/panel_login.xml b/indra/newview/skins/default/xui/pt/panel_login.xml index 8ac3e57c4c..ffcf72b1b4 100755 --- a/indra/newview/skins/default/xui/pt/panel_login.xml +++ b/indra/newview/skins/default/xui/pt/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php?lang=pt - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=pt</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Nome de usuário" name="username_combo" tool_tip="O nome de usuário que você escolheu ao fazer seu cadastro, como zecazc12 ou Magia Solar"/> <line_editor label="Senha" name="password_edit"/> - <check_box label="Lembrar-me" name="remember_check"/> - <text name="forgot_password_text"> - Senha esquecida - </text> - <button label="Login" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - no último local - </text> <combo_box label="Meus locais favoritos" name="start_location_combo"> + <combo_box.item label="Última posição" name="MyLastLocation"/> <combo_box.item label="Minha casa" name="MyHome"/> </combo_box> - <button label="Login" name="connect_favorite_btn"/> - <line_editor label="Digite um local" name="location_edit"/> - <button label="Login" name="connect_location_btn"/> + <button label="Login" name="connect_btn"/> + <check_box label="Lembrar-me" name="remember_check"/> + <text name="forgot_password_text">Senha esquecida</text> <combo_box label="Selecionar grade" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/pt/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/pt/panel_marketplace_listings.xml new file mode 100644 index 0000000000..cfa0e10038 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Marketplace" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Opções de exibição/ordenação"/> + <button name="add_btn" tool_tip="Cria uma nova pasta de listagem"/> + <button label="Verificar erros" name="audit_btn" tool_tip="Verificar suas listagens do Marketplace"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Filtrar listagens do Marketplace" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..5967f24628 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="TUDO" name="All Items" tool_tip="Arraste e solte os itens aqui para listá-los"/> diff --git a/indra/newview/skins/default/xui/pt/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..6549f82b5c --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="PUBLICADA" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..1797be5ae8 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="DESASSOCIADA" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..79b8557ec3 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="NÃO PUBLICADA" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml index ab1545a231..ab1545a231 100755..100644 --- a/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml index cb9a6eb757..cfe52ff404 100755 --- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Perda de pacote - </panel.string> - <panel.string name="bandwidth_tooltip"> - Banda - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">Perda de pacote</panel.string> + <panel.string name="bandwidth_tooltip">Banda</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel left="-410" name="balance_bg" width="200"> - <text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/> + <text name="balance" tool_tip="Atualizar saldo de L$" value="L$??"/> <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/> </panel> - <text name="TimeText" tool_tip="Hora atual (PacÃfico)"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="Hora atual (PacÃfico)">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="Tocar/Pausar todas mÃdias (música, vÃdeo, páginas web)"/> <button name="volume_btn" tool_tip="Volume geral"/> </panel> diff --git a/indra/newview/skins/default/xui/pt/sidepanel_item_info.xml b/indra/newview/skins/default/xui/pt/sidepanel_item_info.xml index cf8f12fad8..47ffffaf15 100755 --- a/indra/newview/skins/default/xui/pt/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Transferir" name="CheckNextOwnerTransfer" tool_tip="O próximo dono poderá revender ou dar este objeto"/> </panel> <check_box label="À venda" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="Copiar" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="Cortar" name="Copy"/> + <combo_box.item label="Conteúdo" name="Contents"/> <combo_box.item label="Original" name="Original"/> </combo_box> <spinner label="Preço: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/pt/sidepanel_task_info.xml b/indra/newview/skins/default/xui/pt/sidepanel_task_info.xml index f0fd438cef..bbfaa4a4f5 100755 --- a/indra/newview/skins/default/xui/pt/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Perfil do objeto"> - <panel.string name="text deed continued"> - Doar - </panel.string> - <panel.string name="text deed"> - Doar - </panel.string> - <panel.string name="text modify info 1"> - Você pode modificar este objeto - </panel.string> - <panel.string name="text modify info 2"> - Você pode modificar estes objetos - </panel.string> - <panel.string name="text modify info 3"> - Você não pode modificar este objeto - </panel.string> - <panel.string name="text modify info 4"> - Você não pode modificar estes objetos - </panel.string> - <panel.string name="text modify info 5"> - Não é possÃvel modificar este objeto através de uma demarcação da região - </panel.string> - <panel.string name="text modify info 6"> - Não é possÃvel modificar estes objetos através de uma demarcação da região - </panel.string> - <panel.string name="text modify warning"> - O objeto contém links ligando suas partes - </panel.string> - <panel.string name="Cost Default"> - Preço: L$ - </panel.string> - <panel.string name="Cost Total"> - Preço total: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Preço unitário: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Preço misto - </panel.string> - <panel.string name="Sale Mixed"> - Venda mista - </panel.string> + <panel.string name="text deed continued">Doar</panel.string> + <panel.string name="text deed">Doar</panel.string> + <panel.string name="text modify info 1">Você pode modificar este objeto</panel.string> + <panel.string name="text modify info 2">Você pode modificar estes objetos</panel.string> + <panel.string name="text modify info 3">Você não pode modificar este objeto</panel.string> + <panel.string name="text modify info 4">Você não pode modificar estes objetos</panel.string> + <panel.string name="text modify info 5">Não é possÃvel modificar este objeto através de uma demarcação da região</panel.string> + <panel.string name="text modify info 6">Não é possÃvel modificar estes objetos através de uma demarcação da região</panel.string> + <panel.string name="text modify warning">O objeto contém links ligando suas partes</panel.string> + <panel.string name="Cost Default">Preço: L$</panel.string> + <panel.string name="Cost Total">Preço total: L$</panel.string> + <panel.string name="Cost Per Unit">Preço unitário: L$</panel.string> + <panel.string name="Cost Mixed">Preço misto</panel.string> + <panel.string name="Sale Mixed">Venda mista</panel.string> <text name="title" value="Perfil do objeto"/> <text name="where" value="(Inworld)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Nome: - </text> - <text name="Description:"> - Descrição: - </text> - <text name="CreatorNameLabel"> - Criador: - </text> - <text name="Owner:"> - Proprietário: - </text> - <text name="Group_label"> - Grupo: - </text> + <text name="Name:">Nome:</text> + <text name="Description:">Descrição:</text> + <text name="CreatorNameLabel">Criador:</text> + <text name="Owner:">Proprietário:</text> + <text name="Group_label">Grupo:</text> <button name="button set group" tool_tip="Selecione o grupo que terá acesso à autorização do objeto"/> <name_box initial_value="Carregando..." name="Group Name Proxy"/> <button label="Doar" label_selected="Doar" name="button deed" tool_tip="Ao doar este item, o próximo dono terá permissões de próximo dono. Objetos de grupos podem ser doados por um oficial do grupo."/> - <text name="label click action"> - Clique para: - </text> + <text name="label click action">Clique para:</text> <combo_box name="clickaction"> <combo_box.item label="Tocar (padrão)" name="Touch/grab(default)"/> <combo_box.item label="Sentar em objeto" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Zoom" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Você pode modificar este objeto - </text> - <text name="Anyone can:"> - Todos: - </text> + <text name="perm_modify">Você pode modificar este objeto</text> + <text name="Anyone can:">Todos:</text> <check_box label="Copiar" name="checkbox allow everyone copy"/> <check_box label="Movimentar" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Grupo: - </text> + <text name="GroupLabel">Grupo:</text> <check_box label="Compartilhar" name="checkbox share with group" tool_tip="Permitir que todos os membros do grupo tenham o seu nÃvel de modificação para este objeto. Faça uma doação para ativar restrições de função."/> - <text name="NextOwnerLabel"> - Próximo proprietário: - </text> + <text name="NextOwnerLabel">Próximo proprietário:</text> <check_box label="Modificar" name="checkbox next owner can modify"/> <check_box label="Copiar" name="checkbox next owner can copy"/> <check_box label="Transferir" name="checkbox next owner can transfer" tool_tip="O próximo dono poderá revender ou dar este objeto"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Preço: L$" name="Edit Cost"/> <check_box label="Mostrar nos resultados de busca" name="search_check" tool_tip="Incluir o objeto nos resultados de busca"/> - <text name="pathfinding_attributes_label"> - Atributos do pathfinding: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Atributos do pathfinding:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Abrir" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 6c1e6ab7f6..3eef691d8d 100755 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -406,28 +406,46 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para </string> <string name="TooltipPrice" value="L$[AMOUNT]"/> <string name="TooltipOutboxDragToWorld"> - Não é possÃvel fazer rez do itens em sua caixa de saÃda do lojista + Não é possÃvel fazer rez de itens da pasta Listagens do Marketplace + </string> + <string name="TooltipOutboxWorn"> + Não é possÃvel colocar itens que você estiver usando na pasta Listagens do Marketplace + </string> + <string name="TooltipOutboxFolderLevels"> + A profundidade das pastas aninhadas excede [AMOUNT]. Diminua a profundidade das pastas dentro de pastas. Agrupe os itens se necessário. + </string> + <string name="TooltipOutboxTooManyFolders"> + O número de subpastas excede [AMOUNT]. Diminua a o número de pastas em sua listagem. Agrupe os itens se necessário. + </string> + <string name="TooltipOutboxTooManyObjects"> + O número de itens excede [AMOUNT]. Para vender mais que [AMOUNT] itens em uma listagem, você deve agrupar alguns deles. + </string> + <string name="TooltipOutboxTooManyStockItems"> + O número de itens de estoque excede [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Você pode soltar somente itens ou pastas na aba TUDO. Selecione essa aba e mova seus itens ou pastas novamente. </string> <string name="TooltipOutboxNoTransfer"> - Um ou mais destes objetos não podem ser vendidos ou transferidos. + Um ou mais objetos não podem ser vendidos ou transferidos </string> <string name="TooltipOutboxNotInInventory"> - Sua caixa de saÃda do lojista aceita apenas itens direto do seu inventário + É possÃvel colocar somente itens do seu inventário no Marketplace </string> - <string name="TooltipOutboxWorn"> - Você não pode colocar os itens que está vestindo na sua caixa de saÃda do lojista + <string name="TooltipOutboxLinked"> + Não é possÃvel colocar itens ou pastas vinculadas no Marketplace </string> <string name="TooltipOutboxCallingCard"> - Não é possÃvel colocar cartões de visita em sua caixa de saÃda do lojista + Não é possÃvel colocar cartões de visitas no Marketplace </string> - <string name="TooltipOutboxFolderLevels"> - A profundidade das pastas aninhadas excede 3 + <string name="TooltipOutboxDragActive"> + Não é possÃvel mover uma listagem publicada </string> - <string name="TooltipOutboxTooManyFolders"> - A contagem de subpastas na pasta de nÃvel superior excede 20 + <string name="TooltipOutboxCannotMoveRoot"> + Não é possÃvel mover a pasta raiz das listagens do Marketplace </string> - <string name="TooltipOutboxTooManyObjects"> - A contagem de itens na pasta de nÃvel superior excede 200 + <string name="TooltipOutboxMixedStock"> + Todos os itens em uma pasta de estoque têm o mesmo tipo e permissão </string> <string name="TooltipDragOntoOwnChild"> Não é possÃvel mover uma pasta para seu filho @@ -1009,7 +1027,7 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="AgentNameSubst"> (Você) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Suprimir alertas ao gerenciar listas de acesso ao terreno </string> @@ -1076,6 +1094,12 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="bitmap_image_files"> Imagens Bitmap </string> + <string name="png_image_files"> + Imagens PNG + </string> + <string name="save_texture_image_files"> + Imagens targa ou PNG + </string> <string name="avi_movie_file"> Arquivo de vÃdeo AVI </string> @@ -1325,6 +1349,9 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="FavoritesNoMatchingItems"> Arraste um marco para adicioná-lo aos seus favoritos. </string> + <string name="MarketplaceNoMatchingItems"> + Nenhum item correspondente encontrado. Verifique a ortografia de sua cadeia de pesquisa e tente novamente. + </string> <string name="InventoryNoTexture"> Você não possui uma cópia desta textura no seu inventário </string> @@ -1372,29 +1399,95 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="InventoryOutboxError"> A loja [[MARKETPLACE_CREATE_STORE_URL] no Marketplace] está retornando erros. </string> + <string name="InventoryMarketplaceError"> + Esse recurso está em beta. Inscreva-se neste [http://goo.gl/forms/FCQ7UXkakz formulário do Google] se você deseja participar. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Sua pasta Listagens do Marketplace está vazia. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Arraste pastas para esta área para listá-las para venda no [Marketplace [MARKETPLACE_DASHBOARD_URL]]. + </string> + <string name="Marketplace Validation Warning Stock"> + a pasta de estoque deve estar em uma pasta de versões + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Erro: todos os itens em uma pasta de estoque devem ser de cópia proibida e todos do mesmo tipo + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Erro: a pasta de estoque não pode ter subpastas + </string> + <string name="Marketplace Validation Warning Empty"> + : Aviso: a pasta não contém itens + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Aviso: criando pasta de estoque + </string> + <string name="Marketplace Validation Warning Create Version"> + : Aviso: criando pasta de versões + </string> + <string name="Marketplace Validation Warning Move"> + : Aviso: movendo itens + </string> + <string name="Marketplace Validation Warning Delete"> + : Aviso: conteúdo da pasta transferido para pasta de estoque, removendo pasta vazia + </string> + <string name="Marketplace Validation Error Stock Item"> + : Erro: itens de cópia proibida devem estar em uma pasta de estoque + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Aviso: os itens devem estar em uma pasta de versões + </string> + <string name="Marketplace Validation Error"> + : Erro: + </string> + <string name="Marketplace Validation Warning"> + : Aviso: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Aviso: a pasta de versões deve conter pelo menos 1 item + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Aviso: a pasta de estoque deve conter pelo menos 1 item + </string> + <string name="Marketplace Validation No Error"> + Não há erros ou avisos + </string> <string name="Marketplace Error None"> Sem erros </string> + <string name="Marketplace Error Prefix"> + Erro: + </string> <string name="Marketplace Error Not Merchant"> - Erro: antes de enviar os itens para o Mercado, é necessário que você se defina como um lojista (sem custos). + antes de enviar os itens para o Marketplace, é necessário que você se defina como um lojista (sem custos). + </string> + <string name="Marketplace Error Not Accepted"> + Não é possÃvel mover o item nessa pasta. </string> - <string name="Marketplace Error Empty Folder"> - Erro: esta pasta está vazia. + <string name="Marketplace Error Unsellable Item"> + Este item não pode ser vendido no Marketplace. </string> - <string name="Marketplace Error Unassociated Products"> - Erro: ocorreu uma falha ao enviar este item, pois sua conta de lojista tem muitos itens não associados a produtos. Para corrigir esse erro, faça o login no site do mercado e reduza a contagem de itens não associados. + <string name="MarketplaceNoID"> + no Mkt ID </string> - <string name="Marketplace Error Object Limit"> - Erro: este item contém muitos objetos. Corrija esse erro unindo os objetos em caixa para reduzir a contagem total a menos de 200. + <string name="MarketplaceLive"> + publicada </string> - <string name="Marketplace Error Folder Depth"> - Erro: este item contém muitos nÃveis de pastas aninhadas. Reorganize-o em até 3 nÃveis de pastas aninhadas, no máximo. + <string name="MarketplaceActive"> + ativo </string> - <string name="Marketplace Error Unsellable Item"> - Erro: este item não pode ser vendido no mercado. + <string name="MarketplaceMax"> + máx </string> - <string name="Marketplace Error Internal Import"> - Erro: ocorreu um problema com este item. Tente novamente mais tarde. + <string name="MarketplaceStock"> + estoque + </string> + <string name="MarketplaceNoStock"> + esgotado + </string> + <string name="MarketplaceUpdating"> + atualizando... </string> <string name="Open landmarks"> Marcos abertos @@ -1415,6 +1508,7 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para Nenhum conteúdo </string> <string name="WornOnAttachmentPoint" value="(vestido em [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (ativado)"/> <string name="Chat Message" value="Bate-papo:"/> <string name="Sound" value="Som"/> @@ -1679,6 +1773,15 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="Invalid Attachment"> Ponto de encaixe inválido </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Erro: item ausente + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Erro: item base ausente + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Erro: o objeto está no look atual, mas não foi anexado + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] de idade </string> @@ -1814,9 +1917,6 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="CompileQueueUnknownFailure"> Falha desconhecida para download </string> - <string name="CompileNoExperiencePerm"> - Pulando script [SCRIPT] com experiência [EXPERIENCE] - </string> <string name="CompileQueueTitle"> Progresso do recompilamento </string> @@ -1850,6 +1950,9 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="SaveComplete"> Salvo. </string> + <string name="UploadFailed"> + Falha ao carregar arquivo: + </string> <string name="ObjectOutOfRange"> Script (objeto fora de alcance) </string> @@ -1859,6 +1962,9 @@ Pessoas com contas gratuitas não poderão acessar o Second Life no momento para <string name="GroupsNone"> nenhum </string> + <string name="CompileNoExperiencePerm"> + Pulando script [SCRIPT] com experiência [EXPERIENCE] + </string> <string name="Group" value="(grupo)"/> <string name="Unknown"> (Desconhecido) @@ -4940,6 +5046,9 @@ Tente colocar o caminho do editor entre aspas. <string name="Command_Marketplace_Label"> Mercado </string> + <string name="Command_MarketplaceListings_Label"> + Marketplace + </string> <string name="Command_MiniMap_Label"> Mini Mapa </string> @@ -5027,6 +5136,9 @@ Tente colocar o caminho do editor entre aspas. <string name="Command_Marketplace_Tooltip"> Faça compras </string> + <string name="Command_MarketplaceListings_Tooltip"> + Venda suas criações + </string> <string name="Command_MiniMap_Tooltip"> Mostrar quem está aqui </string> @@ -5138,6 +5250,18 @@ Tente colocar o caminho do editor entre aspas. <string name="UserDictionary"> [Usuário] </string> + <string name="logging_calls_disabled_log_empty"> + As conversas não estão sendo registradas. Para começar a manter um registro, selecione "Salvar: apenas registro" ou "Salvar: registro e transcrições" em Preferências> Bate-papo. + </string> + <string name="logging_calls_disabled_log_not_empty"> + Nenhuma conversa será registrada. Para recomeçar a gravação de registros, selecione "Salvar: apenas registro" ou "Salvar: registro e transcrições" em Preferências> Bate-papo. + </string> + <string name="logging_calls_enabled_log_empty"> + Não há conversas registradas. Depois que você entrar em contato com alguém, ou alguém entrar em contato com você, um registro será exibido aqui. + </string> + <string name="loading_chat_logs"> + Carregando... + </string> <string name="experience_tools_experience"> Experiência </string> @@ -5219,16 +5343,4 @@ Tente colocar o caminho do editor entre aspas. <string name="ExperiencePermissionShort12"> Autorização </string> - <string name="logging_calls_disabled_log_empty"> - As conversas não estão sendo registradas. Para começar a manter um registro, selecione "Salvar: apenas registro" ou "Salvar: registro e transcrições" em Preferências> Bate-papo. - </string> - <string name="logging_calls_disabled_log_not_empty"> - Nenhuma conversa será registrada. Para recomeçar a gravação de registros, selecione "Salvar: apenas registro" ou "Salvar: registro e transcrições" em Preferências> Bate-papo. - </string> - <string name="logging_calls_enabled_log_empty"> - Não há conversas registradas. Depois que você entrar em contato com alguém, ou alguém entrar em contato com você, um registro será exibido aqui. - </string> - <string name="loading_chat_logs"> - Carregando... - </string> </strings> diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml index 9494106e96..0f75856a91 100755 --- a/indra/newview/skins/default/xui/ru/floater_about.xml +++ b/indra/newview/skins/default/xui/ru/floater_about.xml @@ -1,70 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="О [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - ИÑпользован компилÑтор [COMPILER], верÑÐ¸Ñ [COMPILER_VERSION] - </floater.string> - <floater.string name="AboutPosition"> - Ð’Ñ‹ в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», раÑположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP]) -SLURL: <nolink>[SLURL]</nolink> -(глобальные координаты [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - ЦП: [CPU] -ПамÑÑ‚ÑŒ: [MEMORY_MB] МБ -ВерÑÐ¸Ñ ÐžÐ¡: [OS_VERSION] -Производитель графичеÑкой платы: [GRAPHICS_CARD_VENDOR] -ГрафичеÑÐºÐ°Ñ Ð¿Ð»Ð°Ñ‚Ð°: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - ВерÑÐ¸Ñ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑкого драйвера Windows: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - ВерÑÐ¸Ñ OpenGL: [OPENGL_VERSION] -ВерÑÐ¸Ñ libcurl: [LIBCURL_VERSION] -ВерÑÐ¸Ñ Ð´ÐµÐºÐ¾Ð´ÐµÑ€Ð° J2C: [J2C_VERSION] -ВерÑÐ¸Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð° звука: [AUDIO_DRIVER_VERSION] -ВерÑÐ¸Ñ Qt Webkit: [QT_WEBKIT_VERSION] -ВерÑÐ¸Ñ Ð³Ð¾Ð»Ð¾Ñового Ñервера: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (нет) - </floater.string> - <floater.string name="AboutTraffic"> - ПотерÑно пакетов: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Ошибка при получении URL-адреÑа заметок о выпуÑке Ñервера. - </floater.string> <tab_container name="about_tab"> <panel label="Данные" name="support_panel"> <button label="Копировать в буфер обмена" name="copy_btn"/> </panel> <panel label="Создатели" name="credits_panel"> - <text name="linden_intro"> - Игра Second Life разработана лабораторией Lindens: - </text> - <text name="contrib_intro"> - в напиÑании открытого кода учаÑтвовали: - </text> - <text_editor name="contrib_names"> - ПÑевдо-Ð¸Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾ при запуÑке - </text_editor> - <text name="trans_intro"> - перевод: - </text> - <text_editor name="trans_names"> - ПÑевдо-Ð¸Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾ при запуÑке - </text_editor> + <text name="linden_intro">Игра Second Life разработана лабораторией Lindens, +в напиÑании открытого кода учаÑтвовали:</text> + <text_editor name="contrib_names">ПÑевдо-Ð¸Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾ при запуÑке</text_editor> </panel> <panel label="Лицензии" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK (C) 1992-2009 3Dconnexion APR (C) 2011 The Apache Software Foundation Collada DOM (C) 2006 Sony Computer Entertainment Inc. cURL (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -91,8 +37,7 @@ SLURL: <nolink>[SLURL]</nolink> Ð’Ñе права защищены. Подробные ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ñм. в файле licenses.txt. - Кодирование звука Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñового чата: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Кодирование звука Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñового чата: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_associate_listing.xml b/indra/newview/skins/default/xui/ru/floater_associate_listing.xml new file mode 100644 index 0000000000..fc9a19730b --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="СВЯЗÐТЬ СПИСОК"> + <text name="message">ID ÑпиÑка:</text> + <line_editor name="listing_id">Введите ID</line_editor> + <button label="OK" name="OK"/> + <button label="Отмена" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/ru/floater_edit_hover_height.xml new file mode 100644 index 0000000000..292128d295 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="ЗÐДÐЙТЕ ВЫСОТУ ПÐРЕÐИЯ"> + <slider label="Ð’Ñ‹Ñота" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/ru/floater_inventory_item_properties.xml index 9021b71fe2..c988825756 100755 --- a/indra/newview/skins/default/xui/ru/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/ru/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="СВОЙСТВРПРЕДМЕТÐ"> - <floater.string name="unknown"> - (неизвеÑтно) - </floater.string> - <floater.string name="public"> - (публичное) - </floater.string> - <floater.string name="you_can"> - Ð’Ñ‹ можете: - </floater.string> - <floater.string name="owner_can"> - Владелец может: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local], [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Ðазвание: - </text> - <text name="LabelItemDescTitle"> - ОпиÑание: - </text> - <text name="LabelCreatorTitle"> - Создатель: - </text> + <floater.string name="unknown">(неизвеÑтно)</floater.string> + <floater.string name="public">(публичное)</floater.string> + <floater.string name="you_can">Ð’Ñ‹ можете:</floater.string> + <floater.string name="owner_can">Владелец может:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local], [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Ðазвание:</text> + <text name="LabelItemDescTitle">ОпиÑание:</text> + <text name="LabelCreatorTitle">Создатель:</text> <button label="Профиль…" name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Владелец: - </text> + <text name="LabelOwnerTitle">Владелец:</text> <button label="Профиль…" name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Приобретено: - </text> - <text name="LabelAcquiredDate"> - Ср 24 Май 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Ð’Ñ‹: - </text> + <text name="LabelAcquiredTitle">Приобретено:</text> + <text name="LabelAcquiredDate">Ср 24 Май 12:50:46 2006</text> + <text name="OwnerLabel">Ð’Ñ‹:</text> <check_box label="Изменить" name="CheckOwnerModify"/> <check_box label="Копировать" name="CheckOwnerCopy"/> <check_box label="Перепродать" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Ð’Ñе: - </text> + <text name="AnyoneLabel">Ð’Ñе:</text> <check_box label="Копировать" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Группа: - </text> + <text name="GroupLabel">Группа:</text> <check_box label="ПоделитьÑÑ" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel"> - Следующий владелец: - </text> + <text name="NextOwnerLabel">Следующий владелец:</text> <check_box label="Изменить" name="CheckNextOwnerModify"/> <check_box label="Копировать" name="CheckNextOwnerCopy"/> <check_box label="Перепродать" name="CheckNextOwnerTransfer"/> <check_box label="Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð¸" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Копировать" name="Copy"/> + <combo_box.item label="Содержимое" name="Contents"/> <combo_box.item label="Оригинал" name="Original"/> </combo_box> <spinner label="Цена:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_item_properties.xml b/indra/newview/skins/default/xui/ru/floater_item_properties.xml new file mode 100644 index 0000000000..abd75902fd --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="СВОЙСТВРПРЕДМЕТÐ"/> diff --git a/indra/newview/skins/default/xui/ru/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/ru/floater_marketplace_listings.xml new file mode 100644 index 0000000000..b231997307 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="СПИСКИ ТОВÐРОВ Ð’ ТОРГОВОМ ЦЕÐТРЕ"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Загрузка...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/ru/floater_marketplace_validation.xml new file mode 100644 index 0000000000..6b293014bc --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Проверить ÑпиÑки товаров в торговом центре"> + <button label="OK" label_selected="OK" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_openobject.xml b/indra/newview/skins/default/xui/ru/floater_openobject.xml index 5459604268..a4b6e2af11 100755 --- a/indra/newview/skins/default/xui/ru/floater_openobject.xml +++ b/indra/newview/skins/default/xui/ru/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Копировать в инвентарь" label_selected="Копировать в инвентарь" name="copy_to_inventory_button"/> - <button label="Копировать и добавить в коÑтюм" label_selected="Копировать и добавить в коÑтюм" name="copy_and_wear_button"/> + <text name="border_note"> + Копировать в инвентарь и надеть + </text> + <button label="Добавить в коÑтюм" label_selected="Добавить в коÑтюм" name="copy_and_wear_button"/> + <button label="Заменить коÑтюм" label_selected="Заменить коÑтюм" name="copy_and_replace_button"/> + <button label="Только копировать в инвентарь" label_selected="Только копировать в инвентарь" name="copy_to_inventory_button"/> + <button label="Отмена" label_selected="Отмена" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_pay.xml b/indra/newview/skins/default/xui/ru/floater_pay.xml index 1471a7e133..0a269b9e00 100755 --- a/indra/newview/skins/default/xui/ru/floater_pay.xml +++ b/indra/newview/skins/default/xui/ru/floater_pay.xml @@ -1,21 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - Заплатить группе - </string> - <string name="payee_resident"> - Заплатить жителю - </string> - <text name="payee_name"> - Слишком длинное теÑтовое Ð¸Ð¼Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ Ð¾Ð±Ñ€ÐµÐ·Ð°Ð½Ð¸Ñ - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - Или введите количеÑтво: - </text> - <button label="Заплатить" label_selected="Заплатить" name="pay btn"/> - <button label="Отмена" label_selected="Отмена" name="cancel btn"/> + <string name="payee_group">Заплатить группе</string> + <string name="payee_resident">Заплатить жителю</string> + <text name="paying_text">Ð’Ñ‹ платите:</text> + <text name="payee_name">Слишком длинное теÑтовое Ð¸Ð¼Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ обрезаниÑ</text> + <panel label="ПоиÑк" name="PatternsPanel"> + <button label="Оплатить L$ 1" label_selected="Оплатить L$ 1" name="fastpay 1"/> + <button label="Оплатить L$ 5" label_selected="Оплатить L$ 5" name="fastpay 5"/> + <button label="Оплатить L$ 10" label_selected="Оплатить L$ 10" name="fastpay 10"/> + <button label="Оплатить L$ 20" label_selected="Оплатить L$ 20" name="fastpay 20"/> + </panel> + <panel label="ПоиÑк" name="InputPanel"> + <text name="amount text">Ð”Ñ€ÑƒÐ³Ð°Ñ Ñумма:</text> + <button label="Оплатить" label_selected="Оплатить" name="pay btn"/> + <button label="Отмена" label_selected="Отмена" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_pay_object.xml b/indra/newview/skins/default/xui/ru/floater_pay_object.xml index 7d2da44ac1..9a7b233ca2 100755 --- a/indra/newview/skins/default/xui/ru/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/ru/floater_pay_object.xml @@ -1,28 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - Заплатить группе - </string> - <string name="payee_resident"> - Заплатить жителю - </string> - <text name="payee_name"> - Ericacita Moostopolison - </text> - <text name="object_name_label"> - Через объект: - </text> + <string name="payee_group">Заплатить группе</string> + <string name="payee_resident">Заплатить жителю</string> + <text name="paying_text">Ð’Ñ‹ платите:</text> + <text name="payee_name">Ericacita Moostopolison</text> + <text name="object_name_label">Через объект:</text> <icon name="icon_object" tool_tip="Объекты"/> - <text name="object_name_text"> - Мой офигенный объект Ñ Ð½ÐµÑпичеÑки длинным названием - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - Или введите количеÑтво: - </text> - <button label="Заплатить" label_selected="Заплатить" name="pay btn"/> - <button label="Отмена" label_selected="Отмена" name="cancel btn"/> + <text name="object_name_text">Мой офигенный объект Ñ Ð½ÐµÑпичеÑки длинным названием</text> + <panel label="ПоиÑк" name="PatternsPanel"> + <button label="Оплатить L$ 1" label_selected="Оплатить L$ 1" name="fastpay 1"/> + <button label="Оплатить L$ 5" label_selected="Оплатить L$ 5" name="fastpay 5"/> + <button label="Оплатить L$ 10" label_selected="Оплатить L$ 10" name="fastpay 10"/> + <button label="Оплатить L$ 20" label_selected="Оплатить L$ 20" name="fastpay 20"/> + </panel> + <panel label="ПоиÑк" name="InputPanel"> + <text name="amount text">Ð”Ñ€ÑƒÐ³Ð°Ñ Ñумма:</text> + <button label="Оплатить" label_selected="Оплатить" name="pay btn"/> + <button label="Отмена" label_selected="Отмена" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/ru/menu_attachment_self.xml b/indra/newview/skins/default/xui/ru/menu_attachment_self.xml index 2b1291a8d5..033d36484b 100755 --- a/indra/newview/skins/default/xui/ru/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/ru/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Мой внешний вид" name="Change Outfit"/> <menu_item_call label="Изменить коÑтюм" name="Edit Outfit"/> <menu_item_call label="Изменить фигуру" name="Edit My Shape"/> + <menu_item_call label="Ð’Ñ‹Ñота парениÑ" name="Hover Height"/> <menu_item_call label="Мои друзьÑ" name="Friends..."/> <menu_item_call label="Мои группы" name="Groups..."/> <menu_item_call label="Мой профиль" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/ru/menu_avatar_self.xml b/indra/newview/skins/default/xui/ru/menu_avatar_self.xml index e09117226c..8feaa3b99a 100755 --- a/indra/newview/skins/default/xui/ru/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/ru/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Мой внешний вид" name="Chenge Outfit"/> <menu_item_call label="Изменить коÑтюм" name="Edit Outfit"/> <menu_item_call label="Изменить фигуру" name="Edit My Shape"/> + <menu_item_call label="Ð’Ñ‹Ñота парениÑ" name="Hover Height"/> <menu_item_call label="Мои друзьÑ" name="Friends..."/> <menu_item_call label="Мои группы" name="Groups..."/> <menu_item_call label="Мой профиль" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/ru/menu_inventory.xml b/indra/newview/skins/default/xui/ru/menu_inventory.xml index 308549c254..b8cbef8246 100755 --- a/indra/newview/skins/default/xui/ru/menu_inventory.xml +++ b/indra/newview/skins/default/xui/ru/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Создать ÑпиÑок" name="Marketplace Create Listing"/> + <menu_item_call label="СвÑзать ÑпиÑок" name="Marketplace Associate Listing"/> + <menu_item_call label="Получить (обновить) ÑпиÑок" name="Marketplace Get Listing"/> + <menu_item_call label="Проверка на ошибки" name="Marketplace Check Listing"/> + <menu_item_call label="Изменить ÑпиÑок" name="Marketplace Edit Listing"/> + <menu_item_call label="Опубликовать" name="Marketplace List"/> + <menu_item_call label="Отменить публикацию" name="Marketplace Unlist"/> + <menu_item_call label="Ðктивировать" name="Marketplace Activate"/> + <menu_item_call label="Деактивировать" name="Marketplace Deactivate"/> <menu_item_call label="ПоделитьÑÑ" name="Share"/> <menu_item_call label="Купить" name="Task Buy"/> <menu_item_call label="Открыть" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Добавить" name="Wearable Add"/> <menu_item_call label="СнÑÑ‚ÑŒ" name="Take Off"/> <menu_item_call label="Копировать в «Торговые иÑходÑщие»" name="Merchant Copy"/> - <menu_item_call label="Отправить в торговый центр" name="Marketplace Send"/> + <menu_item_call label="Копировать в ÑпиÑки товаров торгового центра" name="Marketplace Copy"/> + <menu_item_call label="ПеремеÑтить в ÑпиÑки товаров торгового центра" name="Marketplace Move"/> <menu_item_call label="- нет дейÑтвий -" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/ru/menu_marketplace_view.xml b/indra/newview/skins/default/xui/ru/menu_marketplace_view.xml new file mode 100644 index 0000000000..b299c8202f --- /dev/null +++ b/indra/newview/skins/default/xui/ru/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Сортировать по объему запаÑов (от малых к большим)" name="sort_by_stock_amount"/> + <menu_item_check label="Показывать только папки ÑпиÑков" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml index 69bb4c4af9..d22ca845f9 100755 --- a/indra/newview/skins/default/xui/ru/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Полет" name="Fly"/> <menu_item_check label="Ð’Ñегда бегать" name="Always Run"/> <menu_item_call label="ОÑтановить анимацию" name="Stop Animating My Avatar"/> - <menu_item_call label="Ходьба / бег / полет..." name="Walk / run / fly"/> + <menu_item_call label="Ходьба / бег / полет..." name="WalkRunFly"/> </menu> <menu label="СтатуÑ" name="Status"> <menu_item_check label="Ðет на меÑте" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="Купить L$..." name="Buy and Sell L$"/> <menu_item_call label="Торговые иÑходÑщие..." name="MerchantOutbox"/> + <menu_item_call label="СпиÑки товаров торгового центра..." name="MarketplaceListings"/> <menu_item_call label="Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ аккаунта..." name="Manage My Account"/> <menu_item_call label="ÐаÑтройки..." name="Preferences"/> <menu_item_call label="Кнопки панели инÑтрументов..." name="Toolbars"/> @@ -61,7 +62,7 @@ <menu_item_call label="Снимок" name="Take Snapshot"/> <menu_item_call label="Профиль меÑта" name="Place Profile"/> <menu_item_call label="О земле" name="About Land"/> - <menu_item_call label="Регион/землевладение" name="Region/Estate"/> + <menu_item_call label="Регион/землевладение" name="RegionEstate"/> <menu_item_call label="Мои владениÑ..." name="My Land"/> <menu_item_call label="Купить Ñту землю" name="Buy Land"/> <menu label="Показать" name="LandShow"> @@ -248,6 +249,7 @@ <menu_item_check label="КонÑоль текÑтур" name="Texture Console"/> <menu_item_check label="КонÑоль отладки" name="Debug Console"/> <menu_item_call label="КонÑоль уведомлений" name="Notifications"/> + <menu_item_check label="КонÑоль отладки региона" name="Region Debug Console"/> <menu_item_check label="Оперативные таймеры" name="Fast Timers"/> <menu_item_check label="ПамÑÑ‚ÑŒ" name="Memory"/> <menu_item_check label="СтатиÑтика по Ñцене" name="Scene Statistics"/> @@ -351,7 +353,7 @@ <menu_item_check label="Прикрепить объекты Ð´Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ñции" name="Ping Interpolate Object Positions"/> <menu_item_call label="ОпуÑтить пакет" name="Drop a Packet"/> </menu> - <menu_item_call label="Дамп камеры Ñо Ñкриптами" name="Dump Scripted Camera"/> + <menu_item_call label="Дамп камеры Ñо Ñкриптами" name="Dump Scripted Camera"/> <menu label="Диктофон" name="Recorder"> <menu_item_call label="Ðачать воÑпроизведение" name="Start Playback"/> <menu_item_call label="ОÑтановить воÑпроизведение" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index 206be2e2df..70b9a25590 100755 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -129,6 +129,88 @@ Ðе удалоÑÑŒ инициализировать торговый центр из-за ошибки ÑиÑтемы или Ñети. Повторите попытку позже. <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="StockPasteFailed"> + Ðе удалоÑÑŒ Ñкопировать или перемеÑтить в папку запаÑов, ошибка: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantPasteFailed"> + Ðе удалоÑÑŒ Ñкопировать или перемеÑтить в ÑпиÑки товаров торгового центра, ошибка: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantTransactionFailed"> + Ðе удалоÑÑŒ выполнить транзакцию Ñ Ñ‚Ð¾Ñ€Ð³Ð¾Ð²Ñ‹Ð¼ центром, ошибка: + + Причина: '[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Ðе удалоÑÑŒ опубликовать Ñтот продукт или активировать папку верÑии. Обычно Ñто проиÑходит из-за отÑутÑÑ‚Ð²Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ в форме опиÑÐ°Ð½Ð¸Ñ ÑпиÑка, но также может быть ÑвÑзано Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸ в Ñтруктуре папки. Отредактируйте ÑпиÑок или проверьте папку ÑпиÑка на отÑутÑтвие ошибок. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantListingFailed"> + Ðе удалоÑÑŒ опубликовать в торговом центре, ошибка: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Ðе удалоÑÑŒ активировать Ñту папку верÑии, ошибка: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Ðто дейÑтвие вызовет изменение активного Ñодержимого данного ÑпиÑка. Продолжить? + <usetemplate ignoretext="Подтверждать Ñмену активного ÑпиÑка в торговом центре" name="okcancelignore" notext="Отмена" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + При перетаÑкивании в окно ÑпиÑков товаров торгового центра предметы перемещаютÑÑ Ñо Ñвоего иÑходного меÑта, а не копируютÑÑ. Продолжить? + <usetemplate ignoretext="Подтверждать перемещение предмета из Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ Ð² торговый центр" name="okcancelignore" notext="Отмена" yestext="OK"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Ð’ результате Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¿ÐºÐ¸ ÑпиÑка будет удален ваш ÑпиÑок товаров в торговом центре. ЕÑли требуетÑÑ Ñохранить ÑпиÑок в торговом центре, перемеÑтите или удалите Ñодержимое папки верÑии, которое необходимо изменить. Продолжить? + <usetemplate ignoretext="Подтверждать перемещение или удаление ÑпиÑка из торгового центра" name="okcancelignore" notext="Отмена" yestext="OK"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на копирование Ñтих предметов в торговый центр. ПеремеÑтите их или оÑтавьте здеÑÑŒ. + <usetemplate canceltext="Отмена" ignoretext="Подтверждать попытку ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½ÐµÐºÐ¾Ð¿Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ñ… предметов в торговый центр" name="yesnocancelbuttons" notext="Ðе перемещать предмет(Ñ‹)" yestext="ПеремеÑтить предмет(Ñ‹)"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Ðто дейÑтвие вызовет отмену публикации ÑпиÑка. Продолжить? + <usetemplate ignoretext="Подтверждать отмену публикации активного ÑпиÑка в торговом центре" name="okcancelignore" notext="Отмена" yestext="OK"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Ðто дейÑтвие вызовет деактивацию папки верÑии текущего ÑпиÑка. Продолжить? + <usetemplate ignoretext="Подтверждать деактивирование папки верÑии ÑпиÑка в торговом центре" name="okcancelignore" notext="Отмена" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Ðе удалоÑÑŒ обновить Ñтот ÑпиÑок. +[[URL] Щелкните здеÑÑŒ], чтобы изменить его в торговом центре. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + ÐÐµÐ»ÑŒÐ·Ñ Ð½Ð°Ð´ÐµÑ‚ÑŒ одежду или чаÑÑ‚ÑŒ тела, еÑли они находÑÑ‚ÑÑ Ð² папке ÑпиÑков товаров торгового центра. + </notification> + <notification name="AlertMerchantListingInvalidID"> + Ðеверный идентификатор ÑпиÑка. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Ð’ Ñтом ÑпиÑке неÑколько папок верÑий или нет ни одной. СамоÑтоÑтельно выберите и активируйте одну папку позже. + <usetemplate ignoretext="Предупреждать об активировании папки верÑии, еÑли Ñоздан ÑпиÑок Ñ Ð½ÐµÑколькими папками верÑий" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Предметы разных типов раÑпределены по отдельным папкам запаÑов, поÑтому папка ÑиÑтематизирована так, чтобы ее можно было опубликовать. + <usetemplate ignoretext="Предупреждать о разделении папки запаÑов перед публикацией" name="okignore" yestext="OK"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + ÐŸÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑпиÑка прекращена, так как папка запаÑов пуÑта. Добавьте предметы в папку запаÑов, чтобы опубликовать ÑпиÑок Ñнова. + <usetemplate ignoretext="Оповещать о неудавшейÑÑ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸ ÑпиÑка из-за того, что папка запаÑов пуÑта" name="okignore" yestext="OK"/> + </notification> <notification name="CompileQueueSaveText"> Ошибка при передаче текÑта Ñкрипта по Ñледующей причине: [REASON]. Повторите попытку позже. </notification> @@ -473,6 +555,10 @@ Сохранить изменениÑ? <usetemplate canceltext="Отмена" name="yesnocancelbuttons" notext="Ðе ÑохранÑÑ‚ÑŒ" yestext="Сохранить"/> </notification> + <notification name="DeleteNotecard"> + Удалить заметку? + <usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Ðе удалоÑÑŒ Ñохранить жеÑÑ‚. ЖеÑÑ‚ Ñодержит Ñлишком много Ñтапов. @@ -1868,6 +1954,9 @@ http://secondlife.com/download. Ð’Ñ‹ пытаетеÑÑŒ поÑетить регион, контент в котором не ÑоответÑтвует вашим наÑтройкам. Попробуйте изменить наÑтройки в меню «Я > ÐаÑтройки > Общие». <usetemplate name="okbutton" yestext="OK"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> Ð’Ñ‹ пытаетеÑÑŒ поÑетить регион, контент в котором имеет рейтинг [REGIONMATURITY] и предназначен только Ð´Ð»Ñ Ð²Ð·Ñ€Ð¾Ñлых. <url name="url"> @@ -2155,6 +2244,10 @@ http://secondlife.com/download. <ignore name="ignore" text="УÑтановлено дейÑтвие «Заплатить за объект» при поÑтроении объекта без Ñкрипта money()"/> </form> </notification> + <notification name="PayConfirmation"> + Подтвердите оплату L$[AMOUNT] Ð´Ð»Ñ [TARGET]. + <usetemplate ignoretext="Подтверждать перед оплатой (Ð´Ð»Ñ Ñумм более L$200)" name="okcancelignore" notext="Отмена" yestext="Оплатить"/> + </notification> <notification name="OpenObjectCannotCopy"> Ð’ Ñтом объекте нет вещей, которые вам разрешено копировать. </notification> @@ -2695,9 +2788,6 @@ http://secondlife.com/download. <notification name="NoValidCircuit"> Ðет подходÑщего кода канала. </notification> - <notification name="NoValidTimestamp"> - Ðет подходÑщей метки времени. - </notification> <notification name="NoPendingConnection"> Ðевозможно Ñоздать отложенное Ñоединение. </notification> @@ -3841,9 +3931,11 @@ http://secondlife.com/download. </notification> <notification name="TeleportedByAttachment"> Ð’Ñ‹ были телепортированы прикрепленным объектом [ITEM_ID] + <usetemplate ignoretext="ТелепортациÑ: вы были телепортированы прикрепленным объектом" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> Ð’Ñ‹ были телепортированы объектом «[OBJECT_NAME]» на учаÑтке «[PARCEL_NAME]» + <usetemplate ignoretext="ТелепортациÑ: вы были телепортированы объектом на учаÑтке" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Ð’Ñ‹ были телепортированы объектом «[OBJECT_NAME]», владелец – [OWNER_ID] @@ -4175,7 +4267,7 @@ http://secondlife.com/download. <usetemplate ignoretext="Ðевозможно перемеÑтить файлы. ВоÑÑтановлен прежний путь." name="okignore" yestext="OK"/> </notification> <notification name="DefaultObjectPermissions"> - Ошибка при Ñохранении Ñтандартных разрешений по Ñледующей причине: [REASON]. Попробуйте задать Ñтандартные Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· некоторое времÑ. + Ошибка при Ñохранении Ñтандартных разрешений на объект: [REASON]. Попробуйте задать Ñтандартные Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· некоторое времÑ. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/ru/panel_login.xml b/indra/newview/skins/default/xui/ru/panel_login.xml index a19304f2fd..2e0ae89b28 100755 --- a/indra/newview/skins/default/xui/ru/panel_login.xml +++ b/indra/newview/skins/default/xui/ru/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" name="username_combo" tool_tip="Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, которое вы выбрали при региÑтрации, например, «bobsmith12» или «Steller Sunshine»"/> <line_editor label="Пароль" name="password_edit"/> - <check_box label="Запомнить менÑ" name="remember_check"/> - <text name="forgot_password_text"> - Забыли пароль? - </text> - <button label="Войти" name="connect_btn"/> - <text name="At_My_Last_Location_Label" font="SansSerifSmall"> - Ð’ поÑледнее меÑто - </text> <combo_box label="Мои любимые меÑта" name="start_location_combo"> + <combo_box.item label="ПоÑледнее меÑтоположение" name="MyLastLocation"/> <combo_box.item label="Мой дом" name="MyHome"/> </combo_box> - <button label="Войти" name="connect_favorite_btn"/> - <line_editor label="Введите меÑтоположение" name="location_edit" font="SansSerifSmall" /> - <button label="Войти" name="connect_location_btn"/> + <button label="Войти" name="connect_btn"/> + <check_box label="Запомнить менÑ" name="remember_check"/> + <text name="forgot_password_text">Забыли пароль?</text> <combo_box label="Выберите Ñетку" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/ru/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/ru/panel_marketplace_listings.xml new file mode 100644 index 0000000000..1f903b1046 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Торговый центр" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Параметры проÑмотра/Ñортировки"/> + <button name="add_btn" tool_tip="Создать новую папку ÑпиÑка"/> + <button label="Проверка на ошибки" name="audit_btn" tool_tip="Проверьте Ñвои ÑпиÑки товаров в торговом центре"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Фильтровать ÑпиÑки товаров в торговом центре" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..ff7b30188f --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ВСЕ" name="All Items" tool_tip="Перетащите Ñюда предметы, чтобы внеÑти их в ÑпиÑок"/> diff --git a/indra/newview/skins/default/xui/ru/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..b42a82084f --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ОПУБЛИКОВÐÐÐЫЕ" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..fc69e3c362 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ÐЕ СВЯЗÐÐÐЫЕ" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..c630129d44 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="ÐЕОПУБЛИКОВÐÐÐЫЕ" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml index 8f6ab612ff..8f6ab612ff 100755..100644 --- a/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml index 9c84ff1fd8..630925fa60 100755 --- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Потери пакетов - </panel.string> - <panel.string name="bandwidth_tooltip"> - Ширина канала - </panel.string> - <panel.string name="time"> - [hour, datetime, slt]:[min, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">Потери пакетов</panel.string> + <panel.string name="bandwidth_tooltip">Ширина канала</panel.string> + <panel.string name="time">[hour, datetime, slt]:[min, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel left="-450" name="balance_bg" width="240"> - <text name="balance" tool_tip="Щелкните Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ баланÑа L$" value="L$20"/> + <text name="balance" tool_tip="Щелкните Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ баланÑа L$" value="L$??"/> <button label="Купить L$" name="buyL" tool_tip="Щелкните Ð´Ð»Ñ Ð¿Ð¾ÐºÑƒÐ¿ÐºÐ¸ L$"/> <button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/> </panel> - <text name="TimeText" tool_tip="Текущее Ð²Ñ€ÐµÐ¼Ñ (тихоокеанÑкое)"> - 00:00 (тихоокеанÑкое времÑ) - </text> + <text name="TimeText" tool_tip="Текущее Ð²Ñ€ÐµÐ¼Ñ (тихоокеанÑкое)">00:00 (тихоокеанÑкое времÑ)</text> <button name="media_toggle_btn" tool_tip="ЗапуÑк/оÑтановка вÑех медиа (музыка, видео, веб-Ñтраницы)"/> <button name="volume_btn" tool_tip="РегулÑтор громкоÑти"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/sidepanel_item_info.xml b/indra/newview/skins/default/xui/ru/sidepanel_item_info.xml index c42586b7b8..c434dcd6a8 100755 --- a/indra/newview/skins/default/xui/ru/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/ru/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Передать" name="CheckNextOwnerTransfer" tool_tip="Следующий владелец может отдать или перепродать объект"/> </panel> <check_box label="Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð¸" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Копировать" name="Copy"/> + <combo_box.item label="Содержимое" name="Contents"/> <combo_box.item label="Оригинал" name="Original"/> </combo_box> <spinner label="Цена: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/ru/sidepanel_task_info.xml b/indra/newview/skins/default/xui/ru/sidepanel_task_info.xml index 5502530ca4..4059a800f0 100755 --- a/indra/newview/skins/default/xui/ru/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/ru/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Профиль объекта"> - <panel.string name="text deed continued"> - Сделка - </panel.string> - <panel.string name="text deed"> - Сделка - </panel.string> - <panel.string name="text modify info 1"> - Ðтот объект можно изменÑÑ‚ÑŒ - </panel.string> - <panel.string name="text modify info 2"> - Ðти объекты можно изменÑÑ‚ÑŒ - </panel.string> - <panel.string name="text modify info 3"> - Ðтот объект Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ - </panel.string> - <panel.string name="text modify info 4"> - Ðти объекты Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ - </panel.string> - <panel.string name="text modify info 5"> - Ðтот объект Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ через границу региона - </panel.string> - <panel.string name="text modify info 6"> - Ðти объекты Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ через границу региона - </panel.string> - <panel.string name="text modify warning"> - Ðтот объект Ñодержит объединенные чаÑти - </panel.string> - <panel.string name="Cost Default"> - Цена: L$ - </panel.string> - <panel.string name="Cost Total"> - Ð’Ñего: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Цена за: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Ð¡Ð¼ÐµÑˆÐ°Ð½Ð½Ð°Ñ Ñ†ÐµÐ½Ð° - </panel.string> - <panel.string name="Sale Mixed"> - Ð¡Ð¼ÐµÑˆÐ°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð° - </panel.string> + <panel.string name="text deed continued">Сделка</panel.string> + <panel.string name="text deed">Сделка</panel.string> + <panel.string name="text modify info 1">Ðтот объект можно изменÑÑ‚ÑŒ</panel.string> + <panel.string name="text modify info 2">Ðти объекты можно изменÑÑ‚ÑŒ</panel.string> + <panel.string name="text modify info 3">Ðтот объект Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ</panel.string> + <panel.string name="text modify info 4">Ðти объекты Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ</panel.string> + <panel.string name="text modify info 5">Ðтот объект Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ через границу региона</panel.string> + <panel.string name="text modify info 6">Ðти объекты Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ через границу региона</panel.string> + <panel.string name="text modify warning">Ðтот объект Ñодержит объединенные чаÑти</panel.string> + <panel.string name="Cost Default">Цена: L$</panel.string> + <panel.string name="Cost Total">Ð˜Ñ‚Ð¾Ð³Ð¾Ð²Ð°Ñ Ñ†ÐµÐ½Ð°: L$</panel.string> + <panel.string name="Cost Per Unit">Цена за: L$</panel.string> + <panel.string name="Cost Mixed">Ð¡Ð¼ÐµÑˆÐ°Ð½Ð½Ð°Ñ Ñ†ÐµÐ½Ð°</panel.string> + <panel.string name="Sale Mixed">Ð¡Ð¼ÐµÑˆÐ°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð°</panel.string> <text name="title" value="Профиль объекта"/> <text name="where" value="(в мире)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Ðазвание: - </text> - <text name="Description:"> - ОпиÑание: - </text> - <text name="CreatorNameLabel"> - Создатель: - </text> - <text name="Owner:"> - Владелец: - </text> - <text name="Group_label"> - Группа: - </text> + <text name="Name:">Ðазвание:</text> + <text name="Description:">ОпиÑание:</text> + <text name="CreatorNameLabel">Создатель:</text> + <text name="Owner:">Владелец:</text> + <text name="Group_label">Группа:</text> <button name="button set group" tool_tip="Выберите группу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð¸ ей прав доÑтупа к объекту"/> <name_box initial_value="Загрузка..." name="Group Name Proxy"/> <button label="Сделка" label_selected="Сделка" name="button deed" tool_tip="Ð’ результате Ñделки объект передаетÑÑ Ð³Ñ€ÑƒÐ¿Ð¿Ðµ, при Ñтом права на него будут ÑоответÑтвовать правам Ñледующего владельца. Переданный группе объект может передаватьÑÑ Ð´Ð¾Ð»Ð¶Ð½Ð¾Ñтным лицом группы."/> - <text name="label click action"> - ДейÑтвие по щелчку: - </text> + <text name="label click action">ДейÑтвие по щелчку:</text> <combo_box name="clickaction"> <combo_box.item label="КоÑнутьÑÑ (по умолчанию)" name="Touch/grab(default)"/> <combo_box.item label="СеÑÑ‚ÑŒ на объект" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="Приблизить" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Ðтот объект можно изменÑÑ‚ÑŒ - </text> - <text name="Anyone can:"> - Ð’Ñе: - </text> + <text name="perm_modify">Ðтот объект можно изменÑÑ‚ÑŒ</text> + <text name="Anyone can:">Ð’Ñе:</text> <check_box label="Копировать" name="checkbox allow everyone copy"/> <check_box label="ПеремеÑтить" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Группа: - </text> + <text name="GroupLabel">Группа:</text> <check_box label="ПоделитьÑÑ" name="checkbox share with group" tool_tip="Позволить вÑем учаÑтникам выбранной группы получить уÑтановленные вам права на Ñтот объект. Ð”Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ€Ð¾Ð»ÐµÐ²Ñ‹Ñ… ограничений необходимо произвеÑти Ñделку."/> - <text name="NextOwnerLabel"> - Следующий владелец: - </text> + <text name="NextOwnerLabel">Следующий владелец:</text> <check_box label="ИзменÑÑ‚ÑŒ" name="checkbox next owner can modify"/> <check_box label="Копировать" name="checkbox next owner can copy"/> <check_box label="Передать" name="checkbox next owner can transfer" tool_tip="Следующий владелец может отдать или перепродать объект"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Цена: L$" name="Edit Cost"/> <check_box label="Показать в результатах поиÑка" name="search_check" tool_tip="Показывать объект в результатах поиÑка"/> - <text name="pathfinding_attributes_label"> - Ðтрибуты поиÑка пути: - </text> - <text name="B:"> - Ð: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - Ð’: - </text> - <text name="N:"> - С: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Ðтрибуты поиÑка пути:</text> + <text name="B:">Ð:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">Ð’:</text> + <text name="N:">С:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Открыть" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index ba63881094..0d64b2cae9 100755 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -454,28 +454,46 @@ support@secondlife.com. </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> <string name="TooltipOutboxDragToWorld"> - ÐÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ предметы из папке «Торговые иÑходÑщие» + ÐÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ предметы из папки ÑпиÑков товаров торгового центра + </string> + <string name="TooltipOutboxWorn"> + ÐÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить предметы, которые вы ноÑите, в папку ÑпиÑков товаров торгового центра + </string> + <string name="TooltipOutboxFolderLevels"> + Глубина Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¿Ð¾Ðº превышает [AMOUNT]. Уменьшите глубину вложениÑ; при необходимоÑти Ñгруппируйте предметы. + </string> + <string name="TooltipOutboxTooManyFolders"> + КоличеÑтво подпапок не может превышать [AMOUNT]. Уменьшите количеÑтво папок в ÑпиÑке; при необходимоÑти Ñгруппируйте предметы. + </string> + <string name="TooltipOutboxTooManyObjects"> + КоличеÑтво предметов не может превышать [AMOUNT]. Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð¸ более чем [AMOUNT] предм. в одном ÑпиÑке некоторые из них Ñледует Ñгруппировать. + </string> + <string name="TooltipOutboxTooManyStockItems"> + КоличеÑтво предметов не может превышать [AMOUNT]. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Можно перетаÑкивать предметы или папки только на вкладку «ВСЕ». Выберите Ñту вкладку и перемеÑтите предметы или папки Ñнова. </string> <string name="TooltipOutboxNoTransfer"> - ЧаÑÑ‚ÑŒ Ñтих объектов Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ или передать. + ЧаÑÑ‚ÑŒ Ñтих объектов Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ или передать </string> <string name="TooltipOutboxNotInInventory"> - Ваша папка «Торговые иÑходÑщие» может получать вещи только непоÑредÑтвенно из вашего Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ + Ð’ торговый центр можно помеÑтить только предметы из Ñвоего Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ </string> - <string name="TooltipOutboxWorn"> - ÐоÑимые предметы Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить в папку «Торговые иÑходÑщие» + <string name="TooltipOutboxLinked"> + ПривÑзанные предметы или папки Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить в торговый центр </string> <string name="TooltipOutboxCallingCard"> - Визитки Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить в папку «Торговые иÑходÑщие» + ÐÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить визитки в торговый центр </string> - <string name="TooltipOutboxFolderLevels"> - Глубина Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¿Ð¾Ðº превышает 3 + <string name="TooltipOutboxDragActive"> + Опубликованный ÑпиÑок Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить </string> - <string name="TooltipOutboxTooManyFolders"> - Ð’ папке верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð±Ð¾Ð»ÐµÐµ 20 подпапок + <string name="TooltipOutboxCannotMoveRoot"> + Корневую папку ÑпиÑков товаров торгового центра Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰Ð°Ñ‚ÑŒ </string> - <string name="TooltipOutboxTooManyObjects"> - Ð’ папке верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð±Ð¾Ð»ÐµÐµ 200 предметов + <string name="TooltipOutboxMixedStock"> + У вÑех предметов в папке запаÑов должен быть один и тот же тип и разрешение </string> <string name="TooltipDragOntoOwnChild"> Папку Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить в ее подпапку @@ -1060,7 +1078,7 @@ support@secondlife.com. <string name="AgentNameSubst"> (Ð’Ñ‹) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Отключить Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ управлении ÑпиÑками доÑтупа к землевладениÑм </string> @@ -1127,6 +1145,12 @@ support@secondlife.com. <string name="bitmap_image_files"> Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ BMP </string> + <string name="png_image_files"> + Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ PNG + </string> + <string name="save_texture_image_files"> + Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Targa или PNG + </string> <string name="avi_movie_file"> Видео AVI </string> @@ -1376,6 +1400,9 @@ support@secondlife.com. <string name="FavoritesNoMatchingItems"> Перетащите Ñюда закладку, чтобы добавить ее в ÑпиÑок избранного. </string> + <string name="MarketplaceNoMatchingItems"> + Предметы не найдены. Проверьте правильноÑÑ‚ÑŒ Ñтроки поиÑка и повторите попытку. + </string> <string name="InventoryNoTexture"> Ð’ вашем инвентаре нет копии Ñтой текÑтуры </string> @@ -1423,29 +1450,95 @@ support@secondlife.com. <string name="InventoryOutboxError"> [[MARKETPLACE_CREATE_STORE_URL] Магазин] возвращает ошибки. </string> + <string name="InventoryMarketplaceError"> + Ðто бета-верÑÐ¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸. ЕÑли вы хотите учаÑтвовать в ее теÑтировании, заполните Ñту [http://goo.gl/forms/FCQ7UXkakz форму Google]. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Папка ÑпиÑков товаров торгового центра пуÑта. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Перетащите папки в Ñту облаÑÑ‚ÑŒ, чтобы выÑтавить их на продажу в [[MARKETPLACE_DASHBOARD_URL] Торговом центре]. + </string> + <string name="Marketplace Validation Warning Stock"> + Ð’ папке верÑии должна быть папка запаÑов + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Ошибка: вÑе предметы в папке запаÑов должны быть некопируемыми и одного типа + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Ошибка: папка запаÑов не может Ñодержать подпапки + </string> + <string name="Marketplace Validation Warning Empty"> + : Предупреждение: папка не Ñодержит предметов + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Предупреждение: ÑоздаетÑÑ Ð¿Ð°Ð¿ÐºÐ° запаÑов + </string> + <string name="Marketplace Validation Warning Create Version"> + : Предупреждение: ÑоздаетÑÑ Ð¿Ð°Ð¿ÐºÐ° верÑии + </string> + <string name="Marketplace Validation Warning Move"> + : Предупреждение: перемещаютÑÑ Ð¿Ñ€ÐµÐ´Ð¼ÐµÑ‚Ñ‹ + </string> + <string name="Marketplace Validation Warning Delete"> + : Предупреждение: Ñодержимое папки переноÑитÑÑ Ð² папку запаÑов, пуÑÑ‚Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° удалÑетÑÑ + </string> + <string name="Marketplace Validation Error Stock Item"> + : Ошибка: в папке запаÑов должны ÑодержатьÑÑ Ð½ÐµÐºÐ¾Ð¿Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ðµ предметы + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Предупреждение: в папке верÑии должны быть предметы + </string> + <string name="Marketplace Validation Error"> + : Ошибка: + </string> + <string name="Marketplace Validation Warning"> + : Предупреждение: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Предупреждение: папка верÑии должна Ñодержать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ 1 предмет + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Предупреждение: папка запаÑов должна Ñодержать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ 1 предмет + </string> + <string name="Marketplace Validation No Error"> + Ðет ошибок и предупреждений + </string> <string name="Marketplace Error None"> Ошибок нет </string> + <string name="Marketplace Error Prefix"> + Ошибка: + </string> <string name="Marketplace Error Not Merchant"> - Ошибка. Прежде чем отправлÑÑ‚ÑŒ вещи в магазин, необходимо зарегиÑтрироватьÑÑ ÐºÐ°Ðº торговец (беÑплатно). + Прежде чем отправлÑÑ‚ÑŒ предметы в торговый центр, необходимо зарегиÑтрироватьÑÑ ÐºÐ°Ðº торговец (беÑплатно). + </string> + <string name="Marketplace Error Not Accepted"> + Ðевозможно перемеÑтить предмет в Ñту папку. </string> - <string name="Marketplace Error Empty Folder"> - Ошибка. Ð’ Ñтой папке нет контента. + <string name="Marketplace Error Unsellable Item"> + Ðтот предмет Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ в торговом центре. </string> - <string name="Marketplace Error Unassociated Products"> - Ошибка. Ðе удаетÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚ÑŒ Ñту вещь, поÑкольку в вашем торговом аккаунте Ñлишком много вещей, не ÑвÑзанных Ñ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð°Ð¼Ð¸. Чтобы иÑправить Ñту ошибку, войдите на веб-Ñайт торгового центра и уменьшите чиÑло Ñвоих вещей, которые ни Ñ Ñ‡ÐµÐ¼ не ÑвÑзаны. + <string name="MarketplaceNoID"> + нет ID торг. центра </string> - <string name="Marketplace Error Object Limit"> - Ошибка. Ðта вещь Ñодержит Ñлишком много объектов. ИÑправьте Ñту ошибку, Ñложив объекты в коробки и уменьшив их общее чиÑло (должно быть меньше 200). + <string name="MarketplaceLive"> + опубликовано </string> - <string name="Marketplace Error Folder Depth"> - Ошибка. Ðта вещь Ñодержит Ñлишком много уровней вложенных папок. Измените Ñтруктуру так, чтобы уровней вложенных папок было не более 3. + <string name="MarketplaceActive"> + активно </string> - <string name="Marketplace Error Unsellable Item"> - Ошибка. Ðту вещь Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ в магазине. + <string name="MarketplaceMax"> + макÑ. </string> - <string name="Marketplace Error Internal Import"> - Ошибка. Ðта вещь Ñоздает проблему. Повторите попытку позже. + <string name="MarketplaceStock"> + Ð·Ð°Ð¿Ð°Ñ + </string> + <string name="MarketplaceNoStock"> + нет в запаÑе + </string> + <string name="MarketplaceUpdating"> + обновление... </string> <string name="Open landmarks"> Открыть закладки @@ -1466,6 +1559,7 @@ support@secondlife.com. Ðет контента </string> <string name="WornOnAttachmentPoint" value="(где ноÑитÑÑ: [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (активно)"/> <string name="PermYes"> Да @@ -1736,6 +1830,15 @@ support@secondlife.com. <string name="Invalid Attachment"> ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ° приÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Ошибка: отÑутÑтвует предмет + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Ошибка: отÑутÑтвует базовый предмет + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Ошибка: объект входит в текущий коÑтюм, но не прикреплен + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] </string> @@ -1871,9 +1974,6 @@ support@secondlife.com. <string name="CompileQueueUnknownFailure"> ÐеизвеÑтный Ñбой загрузки </string> - <string name="CompileNoExperiencePerm"> - ПропуÑк Ñкрипта [SCRIPT] Ñ Ð¿Ñ€Ð¸ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸ÐµÐ¼ [EXPERIENCE]. - </string> <string name="CompileQueueTitle"> Ход повторной компилÑции </string> @@ -1907,6 +2007,9 @@ support@secondlife.com. <string name="SaveComplete"> Сохранение завершено. </string> + <string name="UploadFailed"> + Ðе удалоÑÑŒ загрузить файл: + </string> <string name="ObjectOutOfRange"> Скрипт (объект вне облаÑти) </string> @@ -1916,6 +2019,9 @@ support@secondlife.com. <string name="GroupsNone"> нет </string> + <string name="CompileNoExperiencePerm"> + ПропуÑк Ñкрипта [SCRIPT] Ñ Ð¿Ñ€Ð¸ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸ÐµÐ¼ [EXPERIENCE]. + </string> <string name="Group" value="(группа)"/> <string name="Unknown"> (ÐеизвеÑтно) @@ -5076,6 +5182,9 @@ support@secondlife.com. <string name="Command_Marketplace_Label"> Торговый центр </string> + <string name="Command_MarketplaceListings_Label"> + Торговый центр + </string> <string name="Command_MiniMap_Label"> Миникарта </string> @@ -5163,6 +5272,9 @@ support@secondlife.com. <string name="Command_Marketplace_Tooltip"> Покупки </string> + <string name="Command_MarketplaceListings_Tooltip"> + Продайте Ñвои Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð¸Ñ + </string> <string name="Command_MiniMap_Tooltip"> Показать людей поблизоÑти </string> @@ -5274,6 +5386,18 @@ support@secondlife.com. <string name="UserDictionary"> [Пользователь] </string> + <string name="logging_calls_disabled_log_empty"> + Разговоры не запиÑываютÑÑ. Чтобы начать запиÑÑŒ разговора, в меню «ÐаÑтройки > Чат» выберите «СохранÑÑ‚ÑŒ: только журнал» или «СохранÑÑ‚ÑŒ: журнал и запиÑи». + </string> + <string name="logging_calls_disabled_log_not_empty"> + Разговоры больше не будут запиÑыватьÑÑ. Чтобы воÑÑтановить запиÑÑŒ разговора, в меню «ÐаÑтройки > Чат» выберите «СохранÑÑ‚ÑŒ: только журнал» или «СохранÑÑ‚ÑŒ: журнал и запиÑи». + </string> + <string name="logging_calls_enabled_log_empty"> + Ðет зарегиÑтрированных разговоров. ЕÑли вы обратитеÑÑŒ к кому-то или наоборот, в журнале поÑвитÑÑ Ð½Ð¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ. + </string> + <string name="loading_chat_logs"> + Загрузка... + </string> <string name="experience_tools_experience"> Приключение </string> @@ -5355,16 +5479,4 @@ support@secondlife.com. <string name="ExperiencePermissionShort12"> Разрешение </string> - <string name="logging_calls_disabled_log_empty"> - Разговоры не запиÑываютÑÑ. Чтобы начать запиÑÑŒ разговора, в меню «ÐаÑтройки > Чат» выберите «СохранÑÑ‚ÑŒ: только журнал» или «СохранÑÑ‚ÑŒ: журнал и запиÑи». - </string> - <string name="logging_calls_disabled_log_not_empty"> - Разговоры больше не будут запиÑыватьÑÑ. Чтобы воÑÑтановить запиÑÑŒ разговора, в меню «ÐаÑтройки > Чат» выберите «СохранÑÑ‚ÑŒ: только журнал» или «СохранÑÑ‚ÑŒ: журнал и запиÑи». - </string> - <string name="logging_calls_enabled_log_empty"> - Ðет зарегиÑтрированных разговоров. ЕÑли вы обратитеÑÑŒ к кому-то или наоборот, в журнале поÑвитÑÑ Ð½Ð¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ. - </string> - <string name="loading_chat_logs"> - Загрузка... - </string> </strings> diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml index 7b925e8830..7034de64c9 100755 --- a/indra/newview/skins/default/xui/tr/floater_about.xml +++ b/indra/newview/skins/default/xui/tr/floater_about.xml @@ -1,71 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="[CAPITALIZED_APP_NAME] HAKKINDA"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [Sürüm Notları]] - </floater.string> - <floater.string name="AboutCompiler"> - [COMPILER] [COMPILER_VERSION] sürümü ile oluÅŸturuldu - </floater.string> - <floater.string name="AboutPosition"> - <nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız -SLURL: <nolink>[SLURL]</nolink> -(küresel koordinatlar [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU: [CPU] -Bellek: [MEMORY_MB] MB -Ä°ÅŸl. Sis. Sürümü: [OS_VERSION] -Grafik Kartı Ãœreticisi: [GRAPHICS_CARD_VENDOR] -Grafik Kartı: [GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Windows Grafik Sürücüsü Sürümü: [GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - OpenGL Sürümü: [OPENGL_VERSION] - -libcurl Sürümü: [LIBCURL_VERSION] -J2C Kod Çözücü Sürümü: [J2C_VERSION] -Ses Sürücüsü Sürümü: [AUDIO_DRIVER_VERSION] -Qt Web Kit Sürümü: [QT_WEBKIT_VERSION] -Ses Sunucusu Sürümü: [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (hiçbiri) - </floater.string> - <floater.string name="AboutTraffic"> - Kaybolan Paketler: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - Sunucu sürümü notları URL'si alınırken hata oluÅŸtu. - </floater.string> <tab_container name="about_tab"> <panel label="Bilgi" name="support_panel"> <button label="Panoya Kopyala" name="copy_btn"/> </panel> <panel label="Katkıda Bulunanlar" name="credits_panel"> - <text name="linden_intro"> - Second Life, Linden'lar tarafından geliÅŸtirilmiÅŸtir: - </text> - <text name="contrib_intro"> - Açık kaynak kod katkısında bulunanlar: - </text> - <text_editor name="contrib_names"> - Geçici Ad çalıştırma sırasında deÄŸiÅŸtirilir - </text_editor> - <text name="trans_intro"> - Çevirileri yapanlar: - </text> - <text_editor name="trans_names"> - Geçici Ad çalıştırma sırasında deÄŸiÅŸtirilir - </text_editor> + <text name="linden_intro">Second Life, Lindens tarafından geliÅŸtirilmiÅŸtir ve +açık kaynak kod katkısında bulunanlar ÅŸunlardır:</text> + <text_editor name="contrib_names">Geçici Ad çalıştırma sırasında deÄŸiÅŸtirilir</text_editor> </panel> <panel label="Lisanslar" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Telif Hakkı (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Telif Hakkı (C) 1992-2009 3Dconnexion APR Telif Hakkı (C) 2011 The Apache Software Foundation Collada DOM Telif Hakkı 2006 Sony Computer Entertainment Inc. cURL Telif Hakkı (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -92,8 +37,7 @@ Ses Sunucusu Sürümü: [VOICE_VERSION] Tüm hakları saklıdır. Ayrıntılı bilgi için bkz. licenses.txt - Sesli sohbet için Ses kodlaması: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + Sesli sohbet için Ses kodlaması: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_associate_listing.xml b/indra/newview/skins/default/xui/tr/floater_associate_listing.xml new file mode 100644 index 0000000000..bf78929931 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="Ä°LANI Ä°LÄ°ÅžKÄ°LENDÄ°R"> + <text name="message">Ä°lan KimliÄŸi:</text> + <line_editor name="listing_id">KimliÄŸi buraya girin</line_editor> + <button label="Tamam" name="OK"/> + <button label="Ä°ptal" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/tr/floater_edit_hover_height.xml new file mode 100644 index 0000000000..237d886c45 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="KONUM YÃœKSEKLİĞİNÄ° AYARLA"> + <slider label="Yükseklik" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/tr/floater_inventory_item_properties.xml index e49fef1f46..c6a5515c6e 100755 --- a/indra/newview/skins/default/xui/tr/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/tr/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="ENVANTER ÖGESÄ° ÖZELLÄ°KLERÄ°"> - <floater.string name="unknown"> - (bilinmiyor) - </floater.string> - <floater.string name="public"> - (kamuya açık) - </floater.string> - <floater.string name="you_can"> - Åžunu yapabilirsiniz: - </floater.string> - <floater.string name="owner_can"> - Sahip ÅŸunu yapabilir: - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - Ad: - </text> - <text name="LabelItemDescTitle"> - Açıklama: - </text> - <text name="LabelCreatorTitle"> - OluÅŸturan: - </text> + <floater.string name="unknown">(bilinmiyor)</floater.string> + <floater.string name="public">(kamuya açık)</floater.string> + <floater.string name="you_can">Åžunu yapabilirsiniz:</floater.string> + <floater.string name="owner_can">Sahip ÅŸunu yapabilir:</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">Ad:</text> + <text name="LabelItemDescTitle">Açıklama:</text> + <text name="LabelCreatorTitle">OluÅŸturan:</text> <button label="Profil..." name="BtnCreator"/> - <text name="LabelOwnerTitle"> - Sahip: - </text> + <text name="LabelOwnerTitle">Sahip:</text> <button label="Profil..." name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - Alınan: - </text> - <text name="LabelAcquiredDate"> - 24 Mayıs ÇarÅŸ 12:50:46 2006 - </text> - <text name="OwnerLabel"> - Siz: - </text> + <text name="LabelAcquiredTitle">Alınan:</text> + <text name="LabelAcquiredDate">24 Mayıs ÇarÅŸ 12:50:46 2006</text> + <text name="OwnerLabel">Siz:</text> <check_box label="Düzenle" name="CheckOwnerModify"/> <check_box label="Kopyala" name="CheckOwnerCopy"/> <check_box label="Tekrar Sat" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - Herkes: - </text> + <text name="AnyoneLabel">Herkes:</text> <check_box label="Kopyala" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - Grup: - </text> + <text name="GroupLabel">Grup:</text> <check_box label="PaylaÅŸ" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel"> - Sonraki sahip: - </text> + <text name="NextOwnerLabel">Sonraki sahip:</text> <check_box label="Düzenle" name="CheckNextOwnerModify"/> <check_box label="Kopyala" name="CheckNextOwnerCopy"/> <check_box label="Tekrar Sat" name="CheckNextOwnerTransfer"/> <check_box label="Satılık" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Kopyala" name="Copy"/> + <combo_box.item label="İçerik" name="Contents"/> <combo_box.item label="Orijinal" name="Original"/> </combo_box> <spinner label="Fiyat:" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_item_properties.xml b/indra/newview/skins/default/xui/tr/floater_item_properties.xml new file mode 100644 index 0000000000..3146384b33 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="ÖĞE ÖZELLÄ°KLERÄ°"/> diff --git a/indra/newview/skins/default/xui/tr/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/tr/floater_marketplace_listings.xml new file mode 100644 index 0000000000..f4837a300f --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="PAZARYERÄ° Ä°LANLARI"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">Yükleniyor...</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/tr/floater_marketplace_validation.xml new file mode 100644 index 0000000000..ec563535d1 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="Pazaryeri Ä°lanlarını Denetle"> + <button label="Tamam" label_selected="Tamam" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_openobject.xml b/indra/newview/skins/default/xui/tr/floater_openobject.xml index adcf5dede2..3876439428 100755 --- a/indra/newview/skins/default/xui/tr/floater_openobject.xml +++ b/indra/newview/skins/default/xui/tr/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="Envantere kopyala" label_selected="Envantere kopyala" name="copy_to_inventory_button"/> - <button label="Kopyala ve dış görünüme ekle" label_selected="Kopyala ve dış görünüme ekle" name="copy_and_wear_button"/> + <text name="border_note"> + Envantere kopyala ve giy + </text> + <button label="Dış görünüme ekle" label_selected="Dış görünüme ekle" name="copy_and_wear_button"/> + <button label="Dış görünümü deÄŸiÅŸtir" label_selected="Dış görünümü deÄŸiÅŸtir" name="copy_and_replace_button"/> + <button label="Sadece envantere kopyala" label_selected="Sadece envantere kopyala" name="copy_to_inventory_button"/> + <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_pay.xml b/indra/newview/skins/default/xui/tr/floater_pay.xml index 6604e5c37a..63334db910 100755 --- a/indra/newview/skins/default/xui/tr/floater_pay.xml +++ b/indra/newview/skins/default/xui/tr/floater_pay.xml @@ -1,21 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - Gruba Öde - </string> - <string name="payee_resident"> - Sakine Öde - </string> - <text name="payee_name"> - Kırpmayı Kontrol İçin Test Adı Çok Uzun - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - veya tutarı seç: - </text> - <button label="Öde" label_selected="Öde" name="pay btn"/> - <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel btn"/> + <string name="payee_group">Gruba Öde</string> + <string name="payee_resident">Sakine Öde</string> + <text name="paying_text">ÖdeyeceÄŸiniz miktar:</text> + <text name="payee_name">Kırpmayı Kontrol İçin Test Adı Çok Uzun</text> + <panel label="Ara" name="PatternsPanel"> + <button label="1 L$ Öde" label_selected="1 L$ Öde" name="fastpay 1"/> + <button label="5 L$ Öde" label_selected="5 L$ Öde" name="fastpay 5"/> + <button label="10 L$ Öde" label_selected="10 L$ Öde" name="fastpay 10"/> + <button label="20 L$ Öde" label_selected="20 L$ Öde" name="fastpay 20"/> + </panel> + <panel label="Ara" name="InputPanel"> + <text name="amount text">DiÄŸer bir tutar:</text> + <button label="Öde" label_selected="Öde" name="pay btn"/> + <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_pay_object.xml b/indra/newview/skins/default/xui/tr/floater_pay_object.xml index 7772d3b101..d736ededfd 100755 --- a/indra/newview/skins/default/xui/tr/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/tr/floater_pay_object.xml @@ -1,28 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - Gruba Öde - </string> - <string name="payee_resident"> - Sakine Öde - </string> - <text name="payee_name"> - Ericacita Moostopolison - </text> - <text name="object_name_label"> - Nesne yoluyla: - </text> + <string name="payee_group">Gruba Öde</string> + <string name="payee_resident">Sakine Öde</string> + <text name="paying_text">ÖdeyeceÄŸiniz miktar:</text> + <text name="payee_name">Ericacita Moostopolison</text> + <text name="object_name_label">Nesne yoluyla:</text> <icon name="icon_object" tool_tip="Nesneler"/> - <text name="object_name_text"> - Harika nesnem gerçekten uzun bir adla - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - veya tutarı seç: - </text> - <button label="Öde" label_selected="Öde" name="pay btn"/> - <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel btn"/> + <text name="object_name_text">Harika nesnem gerçekten uzun bir adla</text> + <panel label="Ara" name="PatternsPanel"> + <button label="1 L$ Öde" label_selected="1 L$ Öde" name="fastpay 1"/> + <button label="5 L$ Öde" label_selected="5 L$ Öde" name="fastpay 5"/> + <button label="10 L$ Öde" label_selected="10 L$ Öde" name="fastpay 10"/> + <button label="20 L$ Öde" label_selected="20 L$ Öde" name="fastpay 20"/> + </panel> + <panel label="Ara" name="InputPanel"> + <text name="amount text">DiÄŸer bir tutar:</text> + <button label="Öde" label_selected="Öde" name="pay btn"/> + <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/tr/menu_attachment_self.xml b/indra/newview/skins/default/xui/tr/menu_attachment_self.xml index ff7c718979..c49f817a45 100755 --- a/indra/newview/skins/default/xui/tr/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/tr/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="Görünümüm" name="Change Outfit"/> <menu_item_call label="Dış Görünümümü Düzenle" name="Edit Outfit"/> <menu_item_call label="Åžeklimi Düzenle" name="Edit My Shape"/> + <menu_item_call label="Konum YüksekliÄŸi" name="Hover Height"/> <menu_item_call label="ArkadaÅŸlarım" name="Friends..."/> <menu_item_call label="Gruplarım" name="Groups..."/> <menu_item_call label="Profilim" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/tr/menu_avatar_self.xml b/indra/newview/skins/default/xui/tr/menu_avatar_self.xml index 6996dc612f..4dfa42c347 100755 --- a/indra/newview/skins/default/xui/tr/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/tr/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="Görünümüm" name="Chenge Outfit"/> <menu_item_call label="Dış Görünümümü Düzenle" name="Edit Outfit"/> <menu_item_call label="Åžeklimi Düzenle" name="Edit My Shape"/> + <menu_item_call label="Konum YüksekliÄŸi" name="Hover Height"/> <menu_item_call label="ArkadaÅŸlarım" name="Friends..."/> <menu_item_call label="Gruplarım" name="Groups..."/> <menu_item_call label="Profilim" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/tr/menu_inventory.xml b/indra/newview/skins/default/xui/tr/menu_inventory.xml index 7239c4be06..784e4d18a4 100755 --- a/indra/newview/skins/default/xui/tr/menu_inventory.xml +++ b/indra/newview/skins/default/xui/tr/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="Ä°lan oluÅŸtur" name="Marketplace Create Listing"/> + <menu_item_call label="Ä°lanı iliÅŸkilendir" name="Marketplace Associate Listing"/> + <menu_item_call label="Ä°lanı al (yenile)" name="Marketplace Get Listing"/> + <menu_item_call label="Hata kontrolü yap" name="Marketplace Check Listing"/> + <menu_item_call label="Ä°lanı düzenle" name="Marketplace Edit Listing"/> + <menu_item_call label="Listele" name="Marketplace List"/> + <menu_item_call label="Listeden kaldır" name="Marketplace Unlist"/> + <menu_item_call label="EtkinleÅŸtir" name="Marketplace Activate"/> + <menu_item_call label="Devre Dışı Bırak" name="Marketplace Deactivate"/> <menu_item_call label="PaylaÅŸ" name="Share"/> <menu_item_call label="Satın Al" name="Task Buy"/> <menu_item_call label="Aç" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="Ekle" name="Wearable Add"/> <menu_item_call label="Çıkar" name="Take Off"/> <menu_item_call label="Satıcı Giden Kutusuna Kopyala" name="Merchant Copy"/> - <menu_item_call label="Pazaryerine Gönder" name="Marketplace Send"/> + <menu_item_call label="Pazaryeri Ä°lanlarına Kopyala" name="Marketplace Copy"/> + <menu_item_call label="Pazaryeri Ä°lanlarına Taşı" name="Marketplace Move"/> <menu_item_call label="--seçenek yok--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/tr/menu_marketplace_view.xml b/indra/newview/skins/default/xui/tr/menu_marketplace_view.xml new file mode 100644 index 0000000000..c114f50c92 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="Stok miktarına göre sırala (düşükten yükseÄŸe)" name="sort_by_stock_amount"/> + <menu_item_check label="Sadece ilan klasörlerini göster" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml index 25414b35fb..cea57011dd 100755 --- a/indra/newview/skins/default/xui/tr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="Uç" name="Fly"/> <menu_item_check label="Daima KoÅŸ" name="Always Run"/> <menu_item_call label="Beni Anime Etmeyi Durdur" name="Stop Animating My Avatar"/> - <menu_item_call label="Yürü / koÅŸ / uç..." name="Walk / run / fly"/> + <menu_item_call label="Yürü / koÅŸ / uç..." name="WalkRunFly"/> </menu> <menu label="Durum" name="Status"> <menu_item_check label="Uzakta" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="L$ Satın Al..." name="Buy and Sell L$"/> <menu_item_call label="Satıcı Giden Kutusu..." name="MerchantOutbox"/> + <menu_item_call label="Pazaryeri ilanları..." name="MarketplaceListings"/> <menu_item_call label="Hesap kontrol paneli..." name="Manage My Account"/> <menu_item_call label="Tercihler..." name="Preferences"/> <menu_item_call label="Araç çubuÄŸu düğmeleri..." name="Toolbars"/> @@ -61,7 +62,7 @@ <menu_item_call label="Anlık Görüntü" name="Take Snapshot"/> <menu_item_call label="Profili yerleÅŸtir" name="Place Profile"/> <menu_item_call label="Arazi hakkında" name="About Land"/> - <menu_item_call label="Bölge / Gayrimenkul" name="Region/Estate"/> + <menu_item_call label="Bölge / Gayrimenkul" name="RegionEstate"/> <menu_item_call label="Sahip olduÄŸum arazi parçaları..." name="My Land"/> <menu_item_call label="Bu araziyi satın al" name="Buy Land"/> <menu label="Göster" name="LandShow"> @@ -249,6 +250,7 @@ <menu_item_check label="Doku Konsolu" name="Texture Console"/> <menu_item_check label="Hata Ayıklama Konsolu" name="Debug Console"/> <menu_item_call label="Bildirimler Konsolu" name="Notifications"/> + <menu_item_check label="Bölge Hata Ayıklama Konsolu" name="Region Debug Console"/> <menu_item_check label="Hızlı Zamanlayıcılar" name="Fast Timers"/> <menu_item_check label="Bellek" name="Memory"/> <menu_item_check label="Sahne Ä°statistikleri" name="Scene Statistics"/> @@ -352,7 +354,7 @@ <menu_item_check label="Nesne Konumlarını Ping Ä°le Ä°nterpole Edin" name="Ping Interpolate Object Positions"/> <menu_item_call label="Paket Bırakın" name="Drop a Packet"/> </menu> - <menu_item_call label="Komut Dosyalı Kameranın Dökümünü Al" name="Dump Scripted Camera"/> + <menu_item_call label="Komut Dosyalı Kameranın Dökümünü Al" name="Dump Scripted Camera"/> <menu label="Kaydedici" name="Recorder"> <menu_item_call label="Oynatmayı BaÅŸlat" name="Start Playback"/> <menu_item_call label="Oynatmayı Durdur" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index b854d3964b..df22251b3d 100755 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -129,6 +129,88 @@ Bir sistem veya aÄŸ hatası nedeniyle Pazaryerine hiçbir klasör gönderilemedi Bir sistem veya aÄŸ hatası nedeniyle Pazaryeri baÅŸlatılamadı. Daha sonra tekrar deneyin. <usetemplate name="okbutton" yestext="Tamam"/> </notification> + <notification name="StockPasteFailed"> + Stok Klasörüne kopyalama ya da taşıma baÅŸarısız oldu. Hata kodu: + + "[ERROR_CODE]" + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="MerchantPasteFailed"> + Pazaryeri Ä°lanlarına kopyalama ya da taşıma baÅŸarısız oldu. Hata kodu: + + "[ERROR_CODE]" + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="MerchantTransactionFailed"> + Pazaryerinde yapılan iÅŸlem baÅŸarısız oldu. Hata kodu: + + Neden: "[ERROR_REASON]" + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + Bu ürünü listeleyemiyoruz ya da sürüm klasörünü etkinleÅŸtiremiyoruz. Bu sorun genellikle ilan açıklama formunda eksik bilgi olmasından kaynaklanır ama klasör yapısındaki hatalar yüzünden de gerçekleÅŸmiÅŸ olabilir. Ä°lanı düzenleyin ya da ilan klasöründe hata olup olmadığını kontrol edin. + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="MerchantListingFailed"> + Ä°lan Pazaryerinde yayınlanamadı. Hata kodu: + + "[ERROR_CODE]" + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + Bu sürüm klasörünü etkinleÅŸtirilemedi. Hata kodu: + + "[ERROR_CODE]" + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + Bu eylem, bu ilanın etkin içeriÄŸini deÄŸiÅŸtirecek. Devam etmek istiyor musunuz? + <usetemplate ignoretext="Pazaryerindeki etkin bir ilanı deÄŸiÅŸtirmek istediÄŸimde doÄŸrulama iste" name="okcancelignore" notext="Ä°ptal" yestext="Tamam"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + Pazaryeri Ä°lanları penceresine sürüklenen öğeler kopyalanmaz, orijinal konumlarından buraya taşınırlar. Devam etmek istiyor musunuz? + <usetemplate ignoretext="Bir öğeyi envanterden Pazaryerine taşımak istediÄŸimde doÄŸrulama iste" name="okcancelignore" notext="Ä°ptal" yestext="Tamam"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + Bir ilan klasörü taşınır veya silinirse, Pazaryerindeki ilanınız silinir. Pazaryeri ilanını saklamak isterseniz, deÄŸiÅŸtirmek istediÄŸiniz sürüm klasörünün içeriÄŸini taşıyın veya silin. Devam etmek istiyor musunuz? + <usetemplate ignoretext="Bir ilanı Pazaryerine taşımak ya da Pazaryerinden silmek istediÄŸim zaman doÄŸrulama iste" name="okcancelignore" notext="Ä°ptal" yestext="Tamam"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + Bu öğelerden birini ya da birden fazlasını Pazaryerine kopyalama izniniz yok. Bunları taşıyabilir veya bırakabilirsiniz. + <usetemplate canceltext="Ä°ptal" ignoretext="Kopyalanamaz öğeler içeren bir seçimi Pazaryerine kopyalamaya çalıştığım zaman doÄŸrulama iste" name="yesnocancelbuttons" notext="Öğeleri taşıma" yestext="Öğeleri taşı"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + Bu eylem ilanı listeden kaldıracak. Devam etmek istiyor musunuz? + <usetemplate ignoretext="Pazaryerindeki etkin bir ilanı listeden kaldırmak istediÄŸimde doÄŸrulama iste" name="okcancelignore" notext="Ä°ptal" yestext="Tamam"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + Bu eylem, mevcut ilanın sürüm klasörünü devre dışı bırakacak. Devam etmek istiyor musunuz? + <usetemplate ignoretext="Pazaryerindeki bir ilanın sürüm klasörünü devre dışı bırakmak istediÄŸimde doÄŸrulama iste" name="okcancelignore" notext="Ä°ptal" yestext="Tamam"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + Bu ilan güncellenemedi. +Bu öğeyi Pazaryeri üzerinde düzenlemek için [[URL] buraya tıklayın]. + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + Pazaryeri Ä°lanları klasöründe bulunan giysileri ve vücut bölümlerini kullanamazsınız. + </notification> + <notification name="AlertMerchantListingInvalidID"> + Geçersiz ilan kimliÄŸi. + </notification> + <notification name="AlertMerchantListingActivateRequired"> + Bu ilanda ya birden fazla sürüm klasörü var ya da hiç sürüm klasörü yok. Daha sonra bir sürüm klasörünü bağımsız olarak seçip etkinleÅŸtirmeniz gerekiyor. + <usetemplate ignoretext="Birden fazla sürüm klasörü içeren bir ilan oluÅŸturduÄŸum zaman sürüm klasörünün etkinleÅŸtirilmesi hakkında uyar" name="okignore" yestext="Tamam"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + Farklı türdeki stok öğelerini ayrı stok klasörlerine yerleÅŸtirdik. Böylece klasörünüz listeleyebileceÄŸimiz bir ÅŸekilde düzenlenir. + <usetemplate ignoretext="Stok klasörü listelenmeden önce bölündüğünde uyar" name="okignore" yestext="Tamam"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + Stok boÅŸ olduÄŸu için ilanınızı yayından kaldırdık. Ä°lanı yeniden yayınlamak için stok klasörüne daha fazla birim eklemeniz gerekir. + <usetemplate ignoretext="Bir ilan, stok klasörü boÅŸ olduÄŸu için listeden kaldırılınca uyar" name="okignore" yestext="Tamam"/> + </notification> <notification name="CompileQueueSaveText"> AÅŸağıdaki nedenden dolayı, bir komut dosyası için metin karşıya yüklenirken bir sorun oluÅŸtu: [REASON]. Lütfen daha sonra tekrar deneyin. </notification> @@ -473,6 +555,10 @@ Not: Bu iÅŸlem önbelleÄŸi temizleyecek. DeÄŸiÅŸiklikler Kaydedilsin mi? <usetemplate canceltext="Ä°ptal" name="yesnocancelbuttons" notext="Kaydetme" yestext="Kaydet"/> </notification> + <notification name="DeleteNotecard"> + Not kartı silinsin mi? + <usetemplate name="okcancelbuttons" notext="Ä°ptal" yestext="Tamam"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> Mimik kaydedilemedi. Bu mimikte çok fazla adım var. @@ -1868,6 +1954,9 @@ Binlerce bölgeyi deÄŸiÅŸtirecek ve alan sunucusunu kesintiye uÄŸratacaktır. Ziyaret etmeye çalıştığınız bölge, mevcut tercihlerinizi aÅŸan içeriÄŸe sahip. Ben > Tercihler > Genel sekmesini kullanarak tercihlerinizi deÄŸiÅŸtirebilirsiniz. <usetemplate name="okbutton" yestext="Tamam"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> Ziyaret etmeye çalıştığınız bölge [REGIONMATURITY] içeriÄŸe sahip, buna sadece yetiÅŸkinler eriÅŸebilir. <url name="url"> @@ -2155,6 +2244,10 @@ Envanter öğesi/öğeleri taşınsın mı? <ignore name="ignore" text="Para() komut dosyası içermeyen bir nesne oluÅŸtururken 'Nesne için ödeme yap' eylemi ayarladım"/> </form> </notification> + <notification name="PayConfirmation"> + [TARGET] hedefine [AMOUNT]L$ ödemek istediÄŸinizi doÄŸrulayın. + <usetemplate ignoretext="Ödeme yapılmadan önce doÄŸrulama iste (200L$ üzerinde tutarlar için)" name="okcancelignore" notext="Ä°ptal" yestext="Öde"/> + </notification> <notification name="OpenObjectCannotCopy"> Bu nesne içinde kopyalama izniniz olan bir öğe yok. </notification> @@ -2695,9 +2788,6 @@ Lütfen biraz sonra tekrar deneyin. <notification name="NoValidCircuit"> Geçerli bir devre kodu yok. </notification> - <notification name="NoValidTimestamp"> - Geçerli bir zaman damgası yok. - </notification> <notification name="NoPendingConnection"> Beklemedeki baÄŸlantı oluÅŸturulamıyor. </notification> @@ -3835,9 +3925,11 @@ Lütfen bir dakika sonra tekrar deneyin. </notification> <notification name="TeleportedByAttachment"> You have been teleported by an attachment on [ITEM_ID] + <usetemplate ignoretext="Işınlama: Bir ek tarafından ışınlandınız" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> '[PARCEL_NAME]' parseli üzerindeki '[OBJECT_NAME]' nesnesi tarafından ışınlandınız + <usetemplate ignoretext="Işınlama: Bir parsel üzerindeki bir nesne tarafından ışınlandınız" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> Sahibi [OWNER_ID] olan '[OBJECT_NAME]' nesnesi tarafından ışınlandınız @@ -4169,7 +4261,7 @@ Daha küçük bir arazi parçası seçmeyi deneyin. <usetemplate ignoretext="Dosyalar taşınamıyor. Önceki yol geri yüklendi." name="okignore" yestext="Tamam"/> </notification> <notification name="DefaultObjectPermissions"> - AÅŸağıdaki nedenden dolayı, varsayılan izinler kaydedilirken bir sorun oluÅŸtu: [REASON]. Varsayılan izinleri ayarlamayı lütfen daha sonra tekrar deneyin. + Varsayılan nesne izinleri kaydedilirken bir sorun oluÅŸtu: [REASON]. Varsayılan izinleri kaydetmeyi lütfen daha sonra tekrar deneyin. <usetemplate name="okbutton" yestext="Tamam"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/tr/panel_login.xml b/indra/newview/skins/default/xui/tr/panel_login.xml index ce1519be89..8b320ce9aa 100755 --- a/indra/newview/skins/default/xui/tr/panel_login.xml +++ b/indra/newview/skins/default/xui/tr/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="Kullanıcı Adı" name="username_combo" tool_tip="KaydolduÄŸunuzda seçtiÄŸiniz kullanıcı adı, örn. mustafayalcin12 veya Faruk Gungoren"/> <line_editor label="Parola" name="password_edit"/> - <check_box label="Beni hatırla" name="remember_check"/> - <text name="forgot_password_text"> - Parolamı unuttum - </text> - <button label="Oturum Aç" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - son konumum - </text> <combo_box label="Sık kullandığım yerler" name="start_location_combo"> + <combo_box.item label="Son konumum" name="MyLastLocation"/> <combo_box.item label="Ana konumum" name="MyHome"/> </combo_box> - <button label="Oturum Aç" name="connect_favorite_btn"/> - <line_editor label="Bir yer adı yazın" name="location_edit"/> - <button label="Oturum Aç" name="connect_location_btn"/> + <button label="Oturum Aç" name="connect_btn"/> + <check_box label="Beni hatırla" name="remember_check"/> + <text name="forgot_password_text">Parolamı unuttum</text> <combo_box label="AÄŸ seç" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/tr/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/tr/panel_marketplace_listings.xml new file mode 100644 index 0000000000..50acc0f92a --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Pazaryeri" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="Seçenekleri görüntüleyin/sıralayın"/> + <button name="add_btn" tool_tip="Yeni bir ilan klasörü oluÅŸturun"/> + <button label="Hatalara Karşı Kontrol Et" name="audit_btn" tool_tip="Pazaryeri ilanlarınızı kontrol edin"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="Pazaryeri Ä°lanlarını Filtrele" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..8d857d20f0 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="TÃœMÃœ" name="All Items" tool_tip="Öğeleri listelemek için buraya sürükleyin ve bırakın"/> diff --git a/indra/newview/skins/default/xui/tr/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..c647a11246 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="LÄ°STELENMÄ°Åž" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..ec9213ff35 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="Ä°LÄ°ÅžKÄ°LENDÄ°RÄ°LMEMÄ°Åž" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..d8c1b0a6d0 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="LÄ°STELENMEMÄ°Åž" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml index ecb47b2218..ecb47b2218 100755..100644 --- a/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml index 178cbda4a2..9e2669ec2b 100755 --- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - Paket Kaybı - </panel.string> - <panel.string name="bandwidth_tooltip"> - Bant geniÅŸliÄŸi - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">Paket Kaybı</panel.string> + <panel.string name="bandwidth_tooltip">Bant geniÅŸliÄŸi</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel left="-425" name="balance_bg" width="215"> - <text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$20"/> + <text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$??"/> <button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/> <button label="AlışveriÅŸ yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/> </panel> - <text name="TimeText" tool_tip="Geçerli zaman (Pasifik)"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="Geçerli zaman (Pasifik)">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="Tüm Ortam Öğelerini BaÅŸlat/Durdur (Müzik, Video, Web sayfaları)"/> <button name="volume_btn" tool_tip="Küresel Ses Kontrolü"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/tr/sidepanel_item_info.xml index 433da27946..92d57deb12 100755 --- a/indra/newview/skins/default/xui/tr/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/tr/sidepanel_item_info.xml @@ -72,8 +72,9 @@ <check_box label="Aktar" name="CheckNextOwnerTransfer" tool_tip="Sonraki sahibi bu nesneyi verebilir veya tekrar satabilir"/> </panel> <check_box label="Satılık" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> + <combo_box name="ComboBoxSaleType"> <combo_box.item label="Kopyala" name="Copy"/> + <combo_box.item label="İçerik" name="Contents"/> <combo_box.item label="Orijinal" name="Original"/> </combo_box> <spinner label="Fiyat: L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/tr/sidepanel_task_info.xml b/indra/newview/skins/default/xui/tr/sidepanel_task_info.xml index 9a4cf54fa7..ddb4bbf160 100755 --- a/indra/newview/skins/default/xui/tr/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/tr/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="Nesne Profili"> - <panel.string name="text deed continued"> - Devret - </panel.string> - <panel.string name="text deed"> - Devret - </panel.string> - <panel.string name="text modify info 1"> - Bu nesneyi deÄŸiÅŸtirebilirsiniz - </panel.string> - <panel.string name="text modify info 2"> - Bu nesneleri deÄŸiÅŸtirebilirsiniz - </panel.string> - <panel.string name="text modify info 3"> - Bu nesneyi deÄŸiÅŸtiremezsiniz - </panel.string> - <panel.string name="text modify info 4"> - Bu nesneleri deÄŸiÅŸtiremezsiniz - </panel.string> - <panel.string name="text modify info 5"> - Bir bölge sınırı üzerinden bu nesneyi deÄŸiÅŸtiremezsiniz - </panel.string> - <panel.string name="text modify info 6"> - Bir bölge sınırı üzerinden bu nesneleri deÄŸiÅŸtiremezsiniz - </panel.string> - <panel.string name="text modify warning"> - Bu nesne baÄŸlantılı parçalara sahip - </panel.string> - <panel.string name="Cost Default"> - Fiyat: L$ - </panel.string> - <panel.string name="Cost Total"> - Toplam Fiyat: L$ - </panel.string> - <panel.string name="Cost Per Unit"> - Birim Fiyatı: L$ - </panel.string> - <panel.string name="Cost Mixed"> - Karma Fiyat - </panel.string> - <panel.string name="Sale Mixed"> - Karma Satış - </panel.string> + <panel.string name="text deed continued">Devret</panel.string> + <panel.string name="text deed">Devret</panel.string> + <panel.string name="text modify info 1">Bu nesneyi deÄŸiÅŸtirebilirsiniz</panel.string> + <panel.string name="text modify info 2">Bu nesneleri deÄŸiÅŸtirebilirsiniz</panel.string> + <panel.string name="text modify info 3">Bu nesneyi deÄŸiÅŸtiremezsiniz</panel.string> + <panel.string name="text modify info 4">Bu nesneleri deÄŸiÅŸtiremezsiniz</panel.string> + <panel.string name="text modify info 5">Bir bölge sınırı üzerinden bu nesneyi deÄŸiÅŸtiremezsiniz</panel.string> + <panel.string name="text modify info 6">Bir bölge sınırı üzerinden bu nesneleri deÄŸiÅŸtiremezsiniz</panel.string> + <panel.string name="text modify warning">Bu nesne baÄŸlantılı parçalara sahip</panel.string> + <panel.string name="Cost Default">Fiyat: L$</panel.string> + <panel.string name="Cost Total">Toplam Fiyat: L$</panel.string> + <panel.string name="Cost Per Unit">Birim Fiyatı: L$</panel.string> + <panel.string name="Cost Mixed">Karma Fiyat</panel.string> + <panel.string name="Sale Mixed">Karma Satış</panel.string> <text name="title" value="Nesne Profili"/> <text name="where" value="(SL Dünyası)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - Ad: - </text> - <text name="Description:"> - Açıklama: - </text> - <text name="CreatorNameLabel"> - OluÅŸturan: - </text> - <text name="Owner:"> - Sahip: - </text> - <text name="Group_label"> - Grup: - </text> + <text name="Name:">Ad:</text> + <text name="Description:">Açıklama:</text> + <text name="CreatorNameLabel">OluÅŸturan:</text> + <text name="Owner:">Sahip:</text> + <text name="Group_label">Grup:</text> <button name="button set group" tool_tip="Bu nesnenin izinlerini paylaÅŸmak için bir grup seçin"/> <name_box initial_value="Yükleniyor..." name="Group Name Proxy"/> <button label="Devret" label_selected="Devret" name="button deed" tool_tip="Bu nesne devredilerek verildiÄŸinde, nesnenin sonraki sahibi için izinler geçerli olur. Grup içerisinde paylaşılan nesneler bir grup yetkilisi tarafından devredilebilir."/> - <text name="label click action"> - Åžu eylem için tıklayın: - </text> + <text name="label click action">Åžu eylem için tıklayın:</text> <combo_box name="clickaction"> <combo_box.item label="Dokun (varsayılan)" name="Touch/grab(default)"/> <combo_box.item label="Nesnenin üzerine otur" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="YakınlaÅŸtır" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - Bu nesneyi deÄŸiÅŸtirebilirsiniz - </text> - <text name="Anyone can:"> - Herkes: - </text> + <text name="perm_modify">Bu nesneyi deÄŸiÅŸtirebilirsiniz</text> + <text name="Anyone can:">Herkes:</text> <check_box label="Kopyala" name="checkbox allow everyone copy"/> <check_box label="Hareket Et" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - Grup: - </text> + <text name="GroupLabel">Grup:</text> <check_box label="PaylaÅŸ" name="checkbox share with group" tool_tip="Ayarlanan grubun tüm üyelerinin, bu nesne için deÄŸiÅŸtirme izinlerinizi paylaÅŸmasına izin verir. Rol kısıtlamalarını etkinleÅŸtirmek için Devretme yapmalısınız."/> - <text name="NextOwnerLabel"> - Sonraki sahip: - </text> + <text name="NextOwnerLabel">Sonraki sahip:</text> <check_box label="DeÄŸiÅŸtir" name="checkbox next owner can modify"/> <check_box label="Kopyala" name="checkbox next owner can copy"/> <check_box label="Aktar" name="checkbox next owner can transfer" tool_tip="Sonraki sahibi bu nesneyi verebilir veya tekrar satabilir"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="Fiyat: L$" name="Edit Cost"/> <check_box label="Aramada göster" name="search_check" tool_tip="KiÅŸiler arama sonuçlarında bu nesneyi görebilsin"/> - <text name="pathfinding_attributes_label"> - Yol bulma özellikleri: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">Yol bulma özellikleri:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="Aç" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index b1a513fbf5..80fe2b3986 100755 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -454,28 +454,46 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> <string name="TooltipOutboxDragToWorld"> - Satıcı giden kutunuzda öğeler oluÅŸturamazsınız + Pazaryeri Ä°lanları klasöründen öğe oluÅŸturamazsınız + </string> + <string name="TooltipOutboxWorn"> + Ãœzerinizde bulunan öğeleri Pazaryeri Ä°lanları klasörüne koyamazsınız + </string> + <string name="TooltipOutboxFolderLevels"> + İç içe geçmiÅŸ klasörlerin derinliÄŸi [AMOUNT] deÄŸerini geçiyor. İç içe geçmiÅŸ klasörlerin derinliÄŸini azaltın; gerekirse öğeleri kutu içine alın. + </string> + <string name="TooltipOutboxTooManyFolders"> + Alt klasör sayısı [AMOUNT] deÄŸerini geçiyor. Ä°lanınızdaki klasör sayısını azaltın; gerekirse öğeleri kutu içine alın. + </string> + <string name="TooltipOutboxTooManyObjects"> + Öğe sayısı [AMOUNT] deÄŸerini geçiyor. Bir ilanda [AMOUNT] öğeden fazlasını satmak için bazılarını kutu içine almalısınız. + </string> + <string name="TooltipOutboxTooManyStockItems"> + Stok öğelerinin sayısı [AMOUNT] deÄŸerini geçiyor. + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + Öğeleri veya klasörleri sadece TÃœMÃœ sekmesine bırakabilirsiniz. Lütfen bu sekmeyi seçin ve öğelerinizi ya da klasörlerinizi yeniden taşıyın. </string> <string name="TooltipOutboxNoTransfer"> - Bu nesnelerden bir veya daha fazlası satılamaz veya aktarılamaz. + Bu nesnelerden bir veya daha fazlası satılamaz veya aktarılamaz </string> <string name="TooltipOutboxNotInInventory"> - Satıcı giden kutunuza sadece doÄŸrudan kendi envanterinizden öğeler koyabilirsiniz + Pazaryerine sadece envanterinizdeki öğelerden koyabilirsiniz </string> - <string name="TooltipOutboxWorn"> - Giymekte olduÄŸunuz öğeleri Satıcı giden kutunuza koyamazsınız. + <string name="TooltipOutboxLinked"> + BaÄŸlı öğeleri veya klasörleri Pazaryerine koyamazsınız </string> <string name="TooltipOutboxCallingCard"> - Satıcı giden kutunuza arama kartları koyamazsınız + Arama kartlarını Pazaryerine koyamazsınız </string> - <string name="TooltipOutboxFolderLevels"> - İç içe geçmiÅŸ klasörlerin derinliÄŸi üçü geçiyor + <string name="TooltipOutboxDragActive"> + Listeye alınmış bir ilanı taşıyamazsınız </string> - <string name="TooltipOutboxTooManyFolders"> - Ãœst seviyedeki klasördeki alt klasör sayısı 20'yi geçiyor + <string name="TooltipOutboxCannotMoveRoot"> + Pazaryeri ilanları kök klasörünü taşıyamazsınız </string> - <string name="TooltipOutboxTooManyObjects"> - Ãœst seviyedeki klasördeki öğe sayısı 200'ü geçiyor + <string name="TooltipOutboxMixedStock"> + Bir stok klasöründeki tüm öğelerin tipi ve izni aynı olmalıdır </string> <string name="TooltipDragOntoOwnChild"> Bir klasörü alt klasörüne taşıyamazsınız @@ -1060,7 +1078,7 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="AgentNameSubst"> (Siz) </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> Gayri menkul eriÅŸim listelerini yönetirken uyarıları bastır </string> @@ -1127,6 +1145,12 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="bitmap_image_files"> Bitmap Görüntüler </string> + <string name="png_image_files"> + PNG Görüntüleri + </string> + <string name="save_texture_image_files"> + Targa veya PNG Görüntüleri + </string> <string name="avi_movie_file"> AVI Film Dosyası </string> @@ -1376,6 +1400,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="FavoritesNoMatchingItems"> Bir yer imini favorilerinize eklemek için buraya sürükleyin. </string> + <string name="MarketplaceNoMatchingItems"> + Öğe bulunamadı. Arama dizenizin yazımını kontrol edin ve yeniden deneyin. + </string> <string name="InventoryNoTexture"> Envanterinizde bu dokunun kopyası yok </string> @@ -1423,29 +1450,95 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="InventoryOutboxError"> [[MARKETPLACE_CREATE_STORE_URL] MaÄŸazası] hata döndürüyor. </string> + <string name="InventoryMarketplaceError"> + Bu özellik ÅŸu anda Beta aÅŸamasında. Katılmak istiyorsanız lütfen adınızı bu [http://goo.gl/forms/FCQ7UXkakz Google formuna] ekleyin. + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + Pazaryeri Ä°lanları klasörünüz boÅŸ. + </string> + <string name="InventoryMarketplaceListingsNoItems"> + Klasörleri [[MARKETPLACE_DASHBOARD_URL] Pazaryerinde] satılık olarak listelemek için bu alana sürükleyin. + </string> + <string name="Marketplace Validation Warning Stock"> + stok klasörü bir sürüm klasöründe bulunmalıdır + </string> + <string name="Marketplace Validation Error Mixed Stock"> + : Hata: Bir stok klasöründeki tüm öğeler aynı tipte ve kopyalanamaz olmalıdır + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + : Hata: stok klasörü alt klasörler içeremez + </string> + <string name="Marketplace Validation Warning Empty"> + : Uyarı: Klasör hiçbir öğe içermiyor + </string> + <string name="Marketplace Validation Warning Create Stock"> + : Uyarı: stok klasörü oluÅŸturuluyor + </string> + <string name="Marketplace Validation Warning Create Version"> + : Uyarı: sürüm klasörü oluÅŸturuluyor + </string> + <string name="Marketplace Validation Warning Move"> + : Uyarı: Öğeler taşınıyor + </string> + <string name="Marketplace Validation Warning Delete"> + : Uyarı: klasör içeriÄŸi stok klasörüne aktarıldı, boÅŸ klasör kaldırılıyor + </string> + <string name="Marketplace Validation Error Stock Item"> + : Hata: Kopyalanamaz öğeler stok klasöründe saklanmalıdır + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + : Uyarı: Öğeler bir sürüm klasöründe bulunmalıdır + </string> + <string name="Marketplace Validation Error"> + : Hata: + </string> + <string name="Marketplace Validation Warning"> + : Uyarı: + </string> + <string name="Marketplace Validation Error Empty Version"> + : Uyarı: sürüm klasörü en az 1 öğe içermelidir + </string> + <string name="Marketplace Validation Error Empty Stock"> + : Uyarı: Stok klasörü en az 1 öğe içermelidir + </string> + <string name="Marketplace Validation No Error"> + Raporlanacak hiçbir hata ya da uyarı yok + </string> <string name="Marketplace Error None"> Hata yok </string> + <string name="Marketplace Error Prefix"> + Hata: + </string> <string name="Marketplace Error Not Merchant"> - Hata: Öğeleri Pazaryerine göndermeden önce kendinizi bir satıcı olarak belirlemelisiniz (ücretsizdir). + Öğeleri Pazaryerine göndermeden önce kendinizi bir satıcı olarak belirtmeniz gerekir (ücretsizdir). + </string> + <string name="Marketplace Error Not Accepted"> + Öğe bu klasöre taşınamıyor. </string> - <string name="Marketplace Error Empty Folder"> - Hata: Bu klasörün içeriÄŸi boÅŸ. + <string name="Marketplace Error Unsellable Item"> + Bu öğe Pazaryerinde satılamaz. </string> - <string name="Marketplace Error Unassociated Products"> - Hata: Bu öğe karşıya yüklenemedi çünkü satıcı hesabınızda ürünlerle iliÅŸkisiz çok fazla öğe mevcut. Bu hatayı düzeltmek için Pazaryeri web sitesine oturum açın ve iliÅŸkisiz öğe sayınızı azaltın. + <string name="MarketplaceNoID"> + no Mkt ID </string> - <string name="Marketplace Error Object Limit"> - Hata: Bu öğe çok fazla nesne içeriyor. Bu hatayı düzeltmek için nesneleri birlikte kutulara yerleÅŸtirerek, toplam nesne sayısını 200'ün altına düşürün. + <string name="MarketplaceLive"> + listelenmiÅŸ </string> - <string name="Marketplace Error Folder Depth"> - Hata: Bu öğede çok fazla iç içe geçmiÅŸ klasör seviyesi var. Bunu tekrar düzenleyerek maksimum 3 iç içe geçmiÅŸ klasör seviyesine indirin. + <string name="MarketplaceActive"> + etkin </string> - <string name="Marketplace Error Unsellable Item"> - Hata: Bu öğe Pazaryerinde satılamaz. + <string name="MarketplaceMax"> + maks. </string> - <string name="Marketplace Error Internal Import"> - Hata: Bu öğede bir sorun var. Daha sonra tekrar deneyin. + <string name="MarketplaceStock"> + stok + </string> + <string name="MarketplaceNoStock"> + stokta kalmadı + </string> + <string name="MarketplaceUpdating"> + güncelleniyor... </string> <string name="Open landmarks"> Açık yer imleri @@ -1466,6 +1559,7 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. İçerik yok </string> <string name="WornOnAttachmentPoint" value="([ATTACHMENT_POINT] üzerinde giyilmiÅŸ)"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL] (etkin)"/> <string name="PermYes"> Evet @@ -1736,6 +1830,15 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="Invalid Attachment"> Geçersiz Aksesuar Noktası </string> + <string name="ATTACHMENT_MISSING_ITEM"> + Hata: eksik öğe + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + Hata: Eksik temel öğe + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + Hata: Nesne mevcut dış görünüme dahil ama eklenmemiÅŸ + </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS]'lık </string> @@ -1871,9 +1974,6 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="CompileQueueUnknownFailure"> Karşıdan yüklerken bilinmeyen hata </string> - <string name="CompileNoExperiencePerm"> - [SCRIPT] komut dizisi [EXPERIENCE] deneyimiyle atlanıyor. - </string> <string name="CompileQueueTitle"> Tekrar Derleme Ä°lerlemesi </string> @@ -1907,6 +2007,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="SaveComplete"> Kaydetme tamamlandı. </string> + <string name="UploadFailed"> + Dosya karşıya yüklenemedi: + </string> <string name="ObjectOutOfRange"> Komut dosyası (nesne kapsam dışı) </string> @@ -1916,6 +2019,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="GroupsNone"> hiçbiri </string> + <string name="CompileNoExperiencePerm"> + [SCRIPT] komut dizisi [EXPERIENCE] deneyimiyle atlanıyor. + </string> <string name="Group" value="(grup)"/> <string name="Unknown"> (Bilinmiyor) @@ -5077,6 +5183,9 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="Command_Marketplace_Label"> Pazaryeri </string> + <string name="Command_MarketplaceListings_Label"> + Pazaryeri + </string> <string name="Command_MiniMap_Label"> Mini-harita </string> @@ -5164,6 +5273,9 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="Command_Marketplace_Tooltip"> AlışveriÅŸ yap </string> + <string name="Command_MarketplaceListings_Tooltip"> + OluÅŸturduÄŸunuz öğeleri satın + </string> <string name="Command_MiniMap_Tooltip"> Yakındaki kiÅŸileri göster </string> @@ -5275,6 +5387,18 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="UserDictionary"> [User] </string> + <string name="logging_calls_disabled_log_empty"> + Sohbetlerin günlüğü tutulmuyor. Bir günlük tutmaya baÅŸlamak için, Tercihler > Sohbet altında "Kaydet: Sadece günlük" veya "Kaydet: Günlük ve dökümler" seçimini yapın. + </string> + <string name="logging_calls_disabled_log_not_empty"> + Bundan böyle sohbetlerin günlükleri tutulmayacak. Bir günlük tutmaya devam etmek için, Tercihler > Sohbet altında "Kaydet: Sadece günlük" veya "Kaydet: Günlük ve dökümler" seçimini yapın. + </string> + <string name="logging_calls_enabled_log_empty"> + Günlüğü tutulmuÅŸ sohbet yok. Siz biriyle iletiÅŸime geçtikten sonra veya biri sizinle iletiÅŸime geçtikten sonra, burada bir günlük giriÅŸi gösterilir. + </string> + <string name="loading_chat_logs"> + Yükleniyor... + </string> <string name="experience_tools_experience"> Deneyim </string> @@ -5356,16 +5480,4 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="ExperiencePermissionShort12"> Ä°zin </string> - <string name="logging_calls_disabled_log_empty"> - Sohbetlerin günlüğü tutulmuyor. Bir günlük tutmaya baÅŸlamak için, Tercihler > Sohbet altında "Kaydet: Sadece günlük" veya "Kaydet: Günlük ve dökümler" seçimini yapın. - </string> - <string name="logging_calls_disabled_log_not_empty"> - Bundan böyle sohbetlerin günlükleri tutulmayacak. Bir günlük tutmaya devam etmek için, Tercihler > Sohbet altında "Kaydet: Sadece günlük" veya "Kaydet: Günlük ve dökümler" seçimini yapın. - </string> - <string name="logging_calls_enabled_log_empty"> - Günlüğü tutulmuÅŸ sohbet yok. Siz biriyle iletiÅŸime geçtikten sonra veya biri sizinle iletiÅŸime geçtikten sonra, burada bir günlük giriÅŸi gösterilir. - </string> - <string name="loading_chat_logs"> - Yükleniyor... - </string> </strings> diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index 2dfb35fa54..250cbe67e0 100755 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -1,71 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_about" title="關於 [CAPITALIZED_APP_NAME]"> - <floater.string name="AboutHeader"> - [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) -[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - </floater.string> - <floater.string name="AboutCompiler"> - 以 [COMPILER_VERSION] 版本 [COMPILER] 建置 - </floater.string> - <floater.string name="AboutPosition"> - ä½ çš„æ–¹ä½æ˜¯ [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地å€å:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP]) -第二人生 URL:<nolink>[SLURL]</nolink> -(全域å標:[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) -[SERVER_VERSION] -[SERVER_RELEASE_NOTES_URL] - </floater.string> - <floater.string name="AboutSystem"> - CPU:[CPU] -記憶體:[MEMORY_MB] MB -作æ¥ç³»çµ±ç‰ˆæœ¬ï¼š[OS_VERSION] -顯示å¡ä¾›æ‡‰å•†ï¼š[GRAPHICS_CARD_VENDOR] -顯示å¡ï¼š[GRAPHICS_CARD] - </floater.string> - <floater.string name="AboutDriver"> - Windows 顯示驅動程å¼ç‰ˆæœ¬ï¼š[GRAPHICS_DRIVER_VERSION] - </floater.string> - <floater.string name="AboutLibs"> - OpenGL 版本:[OPENGL_VERSION] - -libcurl 版本: [LIBCURL_VERSION] -J2C 解碼器版本: [J2C_VERSION] -音效驅動程å¼ç‰ˆæœ¬ï¼š [AUDIO_DRIVER_VERSION] -Qt Webkit 版本: [QT_WEBKIT_VERSION] -語音伺æœå™¨ç‰ˆæœ¬ï¼š [VOICE_VERSION] - </floater.string> - <floater.string name="none"> - (無) - </floater.string> - <floater.string name="AboutTraffic"> - å°åŒ…æ失:[PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) - </floater.string> - <floater.string name="ErrorFetchingServerReleaseNotesURL"> - æ“·å–伺æœå™¨ç‰ˆæœ¬èªªæ˜Ž URL 時出錯。 - </floater.string> <tab_container name="about_tab"> <panel label="資訊" name="support_panel"> <button label="覆製到剪貼簿" name="copy_btn"/> </panel> <panel label="貸記" name="credits_panel"> - <text name="linden_intro"> - 「第二人生ã€ç”±ä»¥ä¸‹çš„ Linden 家æ—å¸¶çµ¦ä½ ï¼š - </text> - <text name="contrib_intro"> - 這些人士åšäº†é–‹æ”¾æºç¢¼çš„è²¢ç»ï¼š - </text> - <text_editor name="contrib_names"> - 執行時期被å–代的å‡å稱 - </text_editor> - <text name="trans_intro"> - 以下人士æ供翻è¯ï¼š - </text> - <text_editor name="trans_names"> - 執行時期被å–代的å‡å稱 - </text_editor> + <text name="linden_intro">Second Life 由以下的 Linden 家æ—å¸¶çµ¦ä½ ï¼š +這些人士åšäº†é–‹æ”¾æºç¢¼çš„è²¢ç»ï¼š</text> + <text_editor name="contrib_names">執行時期被å–代的å‡å稱</text_editor> </panel> <panel label="許å¯" name="licenses_panel"> - <text_editor name="credits_editor"> - 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion + <text_editor name="licenses_editor">3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) @@ -92,8 +37,7 @@ Qt Webkit 版本: [QT_WEBKIT_VERSION] ä¿ç•™ä¸€åˆ‡æ¬Šåˆ©ã€‚ 詳情見 licenses.txt。 - 語音èŠå¤©éŸ³é »æŠ€è¡“:Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - </text_editor> + 語音èŠå¤©éŸ³é »æŠ€è¡“:Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)</text_editor> </panel> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_associate_listing.xml b/indra/newview/skins/default/xui/zh/floater_associate_listing.xml new file mode 100644 index 0000000000..ab0a84dd18 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_associate_listing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="associate listing" title="è¯çµåˆŠç™»"> + <text name="message">刊登 ID:</text> + <line_editor name="listing_id">在æ¤éµå…¥ ID</line_editor> + <button label="確定" name="OK"/> + <button label="å–消" name="Cancel"/> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/zh/floater_edit_hover_height.xml new file mode 100644 index 0000000000..d7c4728183 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_edit_hover_height.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="HoverHeight" title="è¨å®šæ‡¸æµ®é«˜åº¦"> + <slider label="高度" name="HoverHeightSlider"/> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml index 6998df75f3..4f17b96579 100755 --- a/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml @@ -1,67 +1,36 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="item properties" title="收ç´å€ç‰©å“屬性"> - <floater.string name="unknown"> - (未知) - </floater.string> - <floater.string name="public"> - (公開) - </floater.string> - <floater.string name="you_can"> - ä½ å¯ä»¥ï¼š - </floater.string> - <floater.string name="owner_can"> - 所有人å¯ä»¥ï¼š - </floater.string> - <floater.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] - </floater.string> - <text name="LabelItemNameTitle"> - å稱: - </text> - <text name="LabelItemDescTitle"> - æ述: - </text> - <text name="LabelCreatorTitle"> - å‰µé€ è€…ï¼š - </text> + <floater.string name="unknown">(未知)</floater.string> + <floater.string name="public">(公開)</floater.string> + <floater.string name="you_can">ä½ å¯ä»¥ï¼š</floater.string> + <floater.string name="owner_can">所有人å¯ä»¥ï¼š</floater.string> + <floater.string name="acquiredDate">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</floater.string> + <text name="LabelItemNameTitle">å稱:</text> + <text name="LabelItemDescTitle">æ述:</text> + <text name="LabelCreatorTitle">å‰µé€ è€…ï¼š</text> <button label="檔案..." name="BtnCreator"/> - <text name="LabelOwnerTitle"> - 所有人: - </text> + <text name="LabelOwnerTitle">所有人:</text> <button label="檔案..." name="BtnOwner"/> - <text name="LabelAcquiredTitle"> - å–得於: - </text> - <text name="LabelAcquiredDate"> - Wed May 24 12:50:46 2006 - </text> - <text name="OwnerLabel"> - ä½ ï¼š - </text> + <text name="LabelAcquiredTitle">å–得於:</text> + <text name="LabelAcquiredDate">Wed May 24 12:50:46 2006</text> + <text name="OwnerLabel">ä½ ï¼š</text> <check_box label="編輯" name="CheckOwnerModify"/> <check_box label="æšåº¨" name="CheckOwnerCopy"/> <check_box label="轉售" name="CheckOwnerTransfer"/> - <text name="AnyoneLabel"> - 任何人: - </text> + <text name="AnyoneLabel">任何人:</text> <check_box label="æšåº¨" name="CheckEveryoneCopy"/> - <text name="GroupLabel"> - 群組: - </text> + <text name="GroupLabel">群組:</text> <check_box label="分享" name="CheckShareWithGroup"/> - <text name="NextOwnerLabel"> - 下一個所有人: - </text> + <text name="NextOwnerLabel">下一個所有人:</text> <check_box label="編輯" name="CheckNextOwnerModify"/> <check_box label="æšåº¨" name="CheckNextOwnerCopy"/> <check_box label="轉售" name="CheckNextOwnerTransfer"/> <check_box label="出售" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="æšåº¨" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="複製" name="Copy"/> + <combo_box.item label="內容" name="Contents"/> <combo_box.item label="原件" name="Original"/> </combo_box> <spinner label="åƒ¹æ ¼ï¼š" name="Edit Cost"/> - <text name="CurrencySymbol"> - L$ - </text> + <text name="CurrencySymbol">L$</text> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_item_properties.xml b/indra/newview/skins/default/xui/zh/floater_item_properties.xml new file mode 100644 index 0000000000..35dfae62b3 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_item_properties.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Item Properties" title="物å“屬性"/> diff --git a/indra/newview/skins/default/xui/zh/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/zh/floater_marketplace_listings.xml new file mode 100644 index 0000000000..6da718f230 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_marketplace_listings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_listings" title="MARKETPLACE 刊登"> + <panel name="marketplace_listings_panel"> + <panel> + <panel name="marketplace_listings_inventory_placeholder_panel"> + <text name="marketplace_listings_inventory_placeholder_title">載入ä¸â€¦</text> + </panel> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_marketplace_validation.xml b/indra/newview/skins/default/xui/zh/floater_marketplace_validation.xml new file mode 100644 index 0000000000..ef89de95ad --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_marketplace_validation.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_marketplace_validation" title="æŸ¥æ ¸ Marketplace 刊登清單"> + <button label="確定" label_selected="確定" name="OK"/> + <text_editor name="validation_text">MARKETPLACE_VALIDATION_TEXT</text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_openobject.xml b/indra/newview/skins/default/xui/zh/floater_openobject.xml index fa8cb0bdf3..29140eceb9 100755 --- a/indra/newview/skins/default/xui/zh/floater_openobject.xml +++ b/indra/newview/skins/default/xui/zh/floater_openobject.xml @@ -3,6 +3,11 @@ <text name="object_name"> [DESC]: </text> - <button label="覆製到收ç´å€" label_selected="覆製到收ç´å€" name="copy_to_inventory_button"/> - <button label="複製並新增到è£æ‰®" label_selected="複製並新增到è£æ‰®" name="copy_and_wear_button"/> + <text name="border_note"> + 複製到收ç´å€ä¸¦åŠ 以穿戴 + </text> + <button label="新增到è£æ‰®" label_selected="新增到è£æ‰®" name="copy_and_wear_button"/> + <button label="å–代è£æ‰®" label_selected="å–代è£æ‰®" name="copy_and_replace_button"/> + <button label="åªè¤‡è£½åˆ°æ”¶ç´å€" label_selected="åªè¤‡è£½åˆ°æ”¶ç´å€" name="copy_to_inventory_button"/> + <button label="å–消" label_selected="å–消" name="cancel_button"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_pay.xml b/indra/newview/skins/default/xui/zh/floater_pay.xml index 69427605a4..026ead9574 100755 --- a/indra/newview/skins/default/xui/zh/floater_pay.xml +++ b/indra/newview/skins/default/xui/zh/floater_pay.xml @@ -1,21 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - 支付群組 - </string> - <string name="payee_resident"> - 支付居民 - </string> - <text name="payee_name"> - 測試一個長度éžå¸¸éžå¸¸éžå¸¸é•·çš„å稱,檢查是å¦è¢«åˆ‡æ–· - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - 或é¸æ“‡ä¸€å€‹é‡‘é¡ï¼š - </text> - <button label="支付" label_selected="支付" name="pay btn"/> - <button label="å–消" label_selected="å–消" name="cancel btn"/> + <string name="payee_group">支付群組</string> + <string name="payee_resident">支付居民</string> + <text name="paying_text">ä½ æ£åœ¨æ”¯ä»˜ï¼š</text> + <text name="payee_name">測試一個長度éžå¸¸éžå¸¸éžå¸¸é•·çš„å稱,檢查是å¦è¢«åˆ‡æ–·</text> + <panel label="æœå°‹" name="PatternsPanel"> + <button label="支付 L$ 1" label_selected="支付 L$ 1" name="fastpay 1"/> + <button label="支付 L$ 5" label_selected="支付 L$ 5" name="fastpay 5"/> + <button label="支付 L$ 10" label_selected="支付 L$ 10" name="fastpay 10"/> + <button label="支付 L$ 20" label_selected="支付 L$ 20" name="fastpay 20"/> + </panel> + <panel label="æœå°‹" name="InputPanel"> + <text name="amount text">其他金é¡ï¼š</text> + <button label="支付" label_selected="支付" name="pay btn"/> + <button label="å–消" label_selected="å–消" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_pay_object.xml b/indra/newview/skins/default/xui/zh/floater_pay_object.xml index 7d20b44bc6..c32243a115 100755 --- a/indra/newview/skins/default/xui/zh/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/zh/floater_pay_object.xml @@ -1,28 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> - <string name="payee_group"> - 支付群組 - </string> - <string name="payee_resident"> - 支付居民 - </string> - <text name="payee_name"> - Ericacita Moostopolison - </text> - <text name="object_name_label"> - 經由物件: - </text> + <string name="payee_group">支付群組</string> + <string name="payee_resident">支付居民</string> + <text name="paying_text">ä½ æ£åœ¨æ”¯ä»˜ï¼š</text> + <text name="payee_name">Ericacita Moostopolison</text> + <text name="object_name_label">經由物件:</text> <icon name="icon_object" tool_tip="物件"/> - <text name="object_name_text"> - 這是我å稱很長很長很長很長的一個很棒的物件 - </text> - <button label="L$1" label_selected="L$1" name="fastpay 1"/> - <button label="L$5" label_selected="L$5" name="fastpay 5"/> - <button label="L$10" label_selected="L$10" name="fastpay 10"/> - <button label="L$20" label_selected="L$20" name="fastpay 20"/> - <text name="amount text"> - 或é¸æ“‡ä¸€å€‹é‡‘é¡ï¼š - </text> - <button label="支付" label_selected="支付" name="pay btn"/> - <button label="å–消" label_selected="å–消" name="cancel btn"/> + <text name="object_name_text">這是我å稱很長很長很長很長的一個很棒的物件</text> + <panel label="æœå°‹" name="PatternsPanel"> + <button label="支付 L$ 1" label_selected="支付 L$ 1" name="fastpay 1"/> + <button label="支付 L$ 5" label_selected="支付 L$ 5" name="fastpay 5"/> + <button label="支付 L$ 10" label_selected="支付 L$ 10" name="fastpay 10"/> + <button label="支付 L$ 20" label_selected="支付 L$ 20" name="fastpay 20"/> + </panel> + <panel label="æœå°‹" name="InputPanel"> + <text name="amount text">其他金é¡ï¼š</text> + <button label="支付" label_selected="支付" name="pay btn"/> + <button label="å–消" label_selected="å–消" name="cancel btn"/> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/zh/menu_attachment_self.xml b/indra/newview/skins/default/xui/zh/menu_attachment_self.xml index eb1bad0ca2..d9e6eff897 100755 --- a/indra/newview/skins/default/xui/zh/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/zh/menu_attachment_self.xml @@ -8,6 +8,7 @@ <menu_item_call label="我的外觀" name="Change Outfit"/> <menu_item_call label="編輯我的è£æ‰®" name="Edit Outfit"/> <menu_item_call label="編輯我的體形" name="Edit My Shape"/> + <menu_item_call label="懸浮高度" name="Hover Height"/> <menu_item_call label="我的朋å‹" name="Friends..."/> <menu_item_call label="我的群組" name="Groups..."/> <menu_item_call label="我的個人檔案" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/zh/menu_avatar_self.xml b/indra/newview/skins/default/xui/zh/menu_avatar_self.xml index 68d0600141..a644a45df6 100755 --- a/indra/newview/skins/default/xui/zh/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/zh/menu_avatar_self.xml @@ -25,6 +25,7 @@ <menu_item_call label="我的外觀" name="Chenge Outfit"/> <menu_item_call label="編輯我的è£æ‰®" name="Edit Outfit"/> <menu_item_call label="編輯我的體形" name="Edit My Shape"/> + <menu_item_call label="懸浮高度" name="Hover Height"/> <menu_item_call label="我的朋å‹" name="Friends..."/> <menu_item_call label="我的群組" name="Groups..."/> <menu_item_call label="我的個人檔案" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/zh/menu_inventory.xml b/indra/newview/skins/default/xui/zh/menu_inventory.xml index 478f987035..b346e82b77 100755 --- a/indra/newview/skins/default/xui/zh/menu_inventory.xml +++ b/indra/newview/skins/default/xui/zh/menu_inventory.xml @@ -1,5 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="Popup"> + <menu_item_call label="新建刊登" name="Marketplace Create Listing"/> + <menu_item_call label="è¯çµåˆŠç™»" name="Marketplace Associate Listing"/> + <menu_item_call label="å–得(刷新)刊登" name="Marketplace Get Listing"/> + <menu_item_call label="檢查是å¦æœ‰èª¤" name="Marketplace Check Listing"/> + <menu_item_call label="編輯刊登" name="Marketplace Edit Listing"/> + <menu_item_call label="刊登" name="Marketplace List"/> + <menu_item_call label="åœæ¢åˆŠç™»" name="Marketplace Unlist"/> + <menu_item_call label="啟用" name="Marketplace Activate"/> + <menu_item_call label="åœç”¨" name="Marketplace Deactivate"/> <menu_item_call label="分享" name="Share"/> <menu_item_call label="購買" name="Task Buy"/> <menu_item_call label="打開" name="Task Open"/> @@ -87,6 +96,7 @@ <menu_item_call label="æ·»åŠ " name="Wearable Add"/> <menu_item_call label="脫下" name="Take Off"/> <menu_item_call label="複製到商家發件匣" name="Merchant Copy"/> - <menu_item_call label="é€å¾€ç¬¬äºŒäººç”Ÿè³¼ç‰©å¸‚集" name="Marketplace Send"/> + <menu_item_call label="複製到 Marketplace 刊登" name="Marketplace Copy"/> + <menu_item_call label="移到 Marketplace 刊登" name="Marketplace Move"/> <menu_item_call label="-- ç„¡é¸é … --" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/zh/menu_marketplace_view.xml b/indra/newview/skins/default/xui/zh/menu_marketplace_view.xml new file mode 100644 index 0000000000..5396b2a866 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/menu_marketplace_view.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="menu_marketplace_sort"> + <menu_item_check label="按å˜é‡æŽ’åºï¼ˆç”±å°‘到多)" name="sort_by_stock_amount"/> + <menu_item_check label="åªé¡¯ç¤ºåˆŠç™»è³‡æ–™å¤¾" name="show_only_listing_folders"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml index 45d3feec26..9572ad49d3 100755 --- a/indra/newview/skins/default/xui/zh/menu_viewer.xml +++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml @@ -15,7 +15,7 @@ <menu_item_check label="飛行" name="Fly"/> <menu_item_check label="以跑代æ¥" name="Always Run"/> <menu_item_call label="åœæ¢æˆ‘身上的動作" name="Stop Animating My Avatar"/> - <menu_item_call label="行走 / è·‘æ¥ / 飛行…" name="Walk / run / fly"/> + <menu_item_call label="行走 / è·‘æ¥ / 飛行…" name="WalkRunFly"/> </menu> <menu label="狀態" name="Status"> <menu_item_check label="離開" name="Away"/> @@ -23,6 +23,7 @@ </menu> <menu_item_call label="購買 L$…" name="Buy and Sell L$"/> <menu_item_call label="商家發件匣…" name="MerchantOutbox"/> + <menu_item_call label="Marketplace 刊登…" name="MarketplaceListings"/> <menu_item_call label="帳戶主控臺…" name="Manage My Account"/> <menu_item_call label="å好è¨å®šâ€¦" name="Preferences"/> <menu_item_call label="工具列按鈕…" name="Toolbars"/> @@ -61,7 +62,7 @@ <menu_item_call label="å¿«ç…§" name="Take Snapshot"/> <menu_item_call label="地點å°æª”案" name="Place Profile"/> <menu_item_call label="土地資料" name="About Land"/> - <menu_item_call label="地å€/é ˜åœ°" name="Region/Estate"/> + <menu_item_call label="地å€/é ˜åœ°" name="RegionEstate"/> <menu_item_call label="我所æ“有的土地…" name="My Land"/> <menu_item_call label="購買這塊土地" name="Buy Land"/> <menu label="顯示" name="LandShow"> @@ -249,6 +250,7 @@ <menu_item_check label="æ質控制å°" name="Texture Console"/> <menu_item_check label="除錯控制å°" name="Debug Console"/> <menu_item_call label="通知控制å°" name="Notifications"/> + <menu_item_check label="地å€é™¤éŒ¯æŽ§åˆ¶å°" name="Region Debug Console"/> <menu_item_check label="快速碼錶" name="Fast Timers"/> <menu_item_check label="記憶體" name="Memory"/> <menu_item_check label="å ´æ™¯çµ±è¨ˆè³‡æ–™" name="Scene Statistics"/> @@ -352,7 +354,7 @@ <menu_item_check label="探詢內æ’物件ä½ç½®" name="Ping Interpolate Object Positions"/> <menu_item_call label="丟出一個å°åŒ…" name="Drop a Packet"/> </menu> - <menu_item_call label="傾å°è…³æœ¬æŽ§åˆ¶çš„æ”影機" name="Dump Scripted Camera"/> + <menu_item_call label="傾å°è…³æœ¬æŽ§åˆ¶çš„æ”影機" name="Dump Scripted Camera"/> <menu label="錄製器" name="Recorder"> <menu_item_call label="開始æ’放" name="Start Playback"/> <menu_item_call label="åœæ¢æ’放" name="Stop Playback"/> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index 5b520dd745..0a98101b60 100755 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -129,6 +129,88 @@ 購物市集åˆå§‹åŒ–失敗,系統或網路出錯。 è«‹ç¨å€™å†è©¦ä¸€æ¬¡ã€‚ <usetemplate name="okbutton" yestext="確定"/> </notification> + <notification name="StockPasteFailed"> + 複製或移到é™é‡è³‡æ–™å¤¾æ™‚發生å•é¡Œï¼š + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="MerchantPasteFailed"> + 複製或移到 Marketplace 刊登時發生å•é¡Œï¼š + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="MerchantTransactionFailed"> + å’Œ Marketplace 進行的交易發生如下錯誤: + + åŽŸå› ï¼š'[ERROR_REASON]' + [ERROR_DESCRIPTION] + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="MerchantUnprocessableEntity"> + 我們無法刊登這產å“或啓用版本資料夾。 é€šå¸¸é€™æ˜¯å› ç‚ºåˆŠç™»å…§å®¹è¡¨çš„è³‡æ–™ä¸é½Šï¼Œä½†ä¹Ÿå¯èƒ½å› 為資料夾çµæ§‹æœ‰éŒ¯æ‰€è‡´ã€‚ 請編輯刊登內容或檢查刊登資料夾看是å¦æœ‰èª¤ã€‚ + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="MerchantListingFailed"> + 刊登到 Marketplace 時,發生錯誤: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="MerchantFolderActivationFailed"> + 啓用æ¤ç‰ˆæœ¬è³‡æ–™å¤¾æ™‚發生錯誤: + + '[ERROR_CODE]' + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="ConfirmMerchantActiveChange"> + 這個動作會改變æ¤åˆŠç™»çš„內容。 ä½ ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ + <usetemplate ignoretext="在我變更 Marketplace çš„ä¸€é …åˆŠç™»å…§å®¹ä¹‹å‰ï¼Œå…ˆè·Ÿæˆ‘確èª" name="okcancelignore" notext="å–消" yestext="確定"/> + </notification> + <notification name="ConfirmMerchantMoveInventory"> + ä½ æ‹–æ›³åˆ° Marketplace åˆŠç™»è¦–çª—çš„ç‰©é …ï¼Œæœƒå¾žåŽŸä¾†çš„ä½ç½®ç§»å‡ºä¾†ï¼Œä¸æœƒè¢«è¤‡è£½ã€‚ ä½ ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ + <usetemplate ignoretext="åœ¨æˆ‘æŠŠç‰©é …å¾žæ”¶ç´å€ç§»åˆ° Marketplace 之å‰ï¼Œå…ˆè·Ÿæˆ‘確èª" name="okcancelignore" notext="å–消" yestext="確定"/> + </notification> + <notification name="ConfirmListingCutOrDelete"> + ç§»å‹•æˆ–åˆªé™¤åˆŠç™»è³‡æ–™å¤¾å°‡æœƒåˆªé™¤ä½ çš„ Marketplace 刊登。 å¦‚ä½ å¸Œæœ›ä¿ç•™ Marketplace 刊登,請改而移動或刪除所想修改的版本資料夾的內容。 ä½ ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ + <usetemplate ignoretext="åœ¨æˆ‘æŠŠç‰©é …å¾ž Marketplace 移出或刪除之å‰ï¼Œå…ˆè·Ÿæˆ‘確èª" name="okcancelignore" notext="å–消" yestext="確定"/> + </notification> + <notification name="ConfirmCopyToMarketplace"> + ä½ ç„¡æ¬Šå°‡é€™äº›ç‰©é …çš„ä¸€æˆ–å¤šå€‹è¤‡è£½åˆ° Marketplace。 ä½ å¯ä»¥ç§»å‹•é€™äº›ç‰©é …,或ä¿ç•™ä¸å‹•ã€‚ + <usetemplate canceltext="å–消" ignoretext="我試著é¸æ“‡è¤‡è£½åˆ° Marketplace 的內容如果å«æœ‰ã€Œç¦æ¢è¤‡è£½ã€çš„ç‰©é …ï¼Œå…ˆå‘我確èª" name="yesnocancelbuttons" notext="ä¿ç•™ä¸ç§»å‹•ç‰©é …" yestext="ç§»å‹•ç‰©é …"/> + </notification> + <notification name="ConfirmMerchantUnlist"> + 這動作會åœç™»é€™å€‹åˆŠç™»ã€‚ ä½ ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ + <usetemplate ignoretext="在我åœç™» Marketplace çš„ç¾æœ‰åˆŠç™»å…§å®¹å‰ï¼Œå…ˆè·Ÿæˆ‘確èª" name="okcancelignore" notext="å–消" yestext="確定"/> + </notification> + <notification name="ConfirmMerchantClearVersion"> + 這個動作會åœç”¨æ¤åˆŠç™»çš„版本資料夾。 ä½ ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ + <usetemplate ignoretext="在我åœç”¨ Marketplace æŸé …刊登的版本資料夾之å‰ï¼Œå…ˆè·Ÿæˆ‘確èªã€‚" name="okcancelignore" notext="å–消" yestext="確定"/> + </notification> + <notification name="AlertMerchantListingNotUpdated"> + 這刊登無法更新。 +[[URL] 點按這裡]å³å¯åœ¨ Marketplace 進行編輯。 + <usetemplate name="okbutton" yestext="確定"/> + </notification> + <notification name="AlertMerchantListingCannotWear"> + ä½ ä¸èƒ½ç©¿æˆ´ä½åœ¨ Marketplace 刊登資料夾裡的衣物或身體部ä½ã€‚ + </notification> + <notification name="AlertMerchantListingInvalidID"> + 無效的刊登 ID。 + </notification> + <notification name="AlertMerchantListingActivateRequired"> + 這個刊登有多個版本資料夾或缺少版本資料夾。 ä½ äº‹å¾Œå¿…é ˆé¸æ“‡ä¸€å€‹åŠ 以啓用。 + <usetemplate ignoretext="當我è¦æ–°å»ºå¸¶æœ‰å¤šå€‹ç‰ˆæœ¬è³‡æ–™å¤¾çš„刊登å‰ï¼Œæ醒我啓動一個版本資料夾" name="okignore" yestext="確定"/> + </notification> + <notification name="AlertMerchantStockFolderSplit"> + 我們已經將ä¸åŒé¡žåž‹çš„é™é‡ç‰©é …分開放置到ä¸åŒçš„å˜é‡è³‡æ–™å¤¾ï¼Œé€™æ¨£ä½ 的資料夾æ‰èƒ½å¤ 刊登。 + <usetemplate ignoretext="刊登å‰æŠŠé™é‡è³‡æ–™å¤¾ä¸€åˆ†ç‚ºäºŒæ™‚,告知我" name="okignore" yestext="確定"/> + </notification> + <notification name="AlertMerchantStockFolderEmpty"> + å› ç‚ºå˜é‡çˆ²é›¶ï¼Œæˆ‘å€‘å·²ç¶“æŠŠä½ çš„åˆŠç™»ç‰©ä¸‹æž¶ã€‚ ä½ è‹¥å¸Œæœ›é‡æ–°åˆŠç™»ï¼Œå¿…é ˆå…ˆå¢žåŠ å˜é‡ã€‚ + <usetemplate ignoretext="é™é‡è³‡æ–™å¤¾å¦‚æžœæˆç©ºã€å°Žè‡´åˆŠç™»ç‰©ä¸‹æž¶ï¼Œå‘ŠçŸ¥æˆ‘" name="okignore" yestext="確定"/> + </notification> <notification name="CompileQueueSaveText"> 上傳腳本文å—時出å•é¡Œï¼ŒåŽŸå› :[REASON]。 è«‹ç¨å€™å†è©¦ä¸€æ¬¡ã€‚ </notification> @@ -473,6 +555,10 @@ 儲å˜è®Šæ›´ï¼Ÿ <usetemplate canceltext="å–消" name="yesnocancelbuttons" notext="ä¸è¦å„²å˜" yestext="儲å˜"/> </notification> + <notification name="DeleteNotecard"> + 刪除記事å¡ï¼Ÿ + <usetemplate name="okcancelbuttons" notext="å–消" yestext="確定"/> + </notification> <notification name="GestureSaveFailedTooManySteps"> 姿勢儲å˜å¤±æ•—。 這個姿勢æ¥é©Ÿå¤ªå¤šã€‚ @@ -1859,6 +1945,9 @@ SHA1 指紋:[MD5_DIGEST] ä½ æ‰€æ¬²å‰å¾€çš„地å€å«æœ‰è¶…éŽä½ ç›®å‰å好的分級的內容。 ä½ å¯ä»¥åˆ°ã€Œæˆ‘自己 > å好è¨å®š > 一般è¨å®šã€è®Šæ›´ä½ çš„å好è¨å®šã€‚ <usetemplate name="okbutton" yestext="確定"/> </notification> + <notification name="SLM_UPDATE_FOLDER"> + [MESSAGE] + </notification> <notification name="RegionEntryAccessBlocked_AdultsOnlyContent"> ä½ æ‰€æ¬²å‰å¾€çš„地å€å«æœ‰ [REGIONMATURITY] 的分級內容,僅é™æˆäººã€‚ <url name="url"> @@ -2146,6 +2235,10 @@ SHA1 指紋:[MD5_DIGEST] <ignore name="ignore" text="我在創建ä¸å« money() 腳本的物件時è¨å®šäº†ã€Œæ”¯ä»˜ç‰©ä»¶ã€å‹•ä½œ"/> </form> </notification> + <notification name="PayConfirmation"> + 確èªä½ 真è¦æ”¯ä»˜ L$[AMOUNT] 給 [TARGET]。 + <usetemplate ignoretext="付款å‰è·Ÿæˆ‘確èªï¼ˆè¶…éŽ L$200 的總é¡ï¼‰" name="okcancelignore" notext="å–消" yestext="支付"/> + </notification> <notification name="OpenObjectCannotCopy"> 這物件ä¸æ²’æœ‰ä»»ä½•å‡†è¨±ä½ è¤‡è£½çš„ç‰©é …ã€‚ </notification> @@ -2685,9 +2778,6 @@ SHA1 指紋:[MD5_DIGEST] <notification name="NoValidCircuit"> 沒有有效的線路碼。 </notification> - <notification name="NoValidTimestamp"> - 沒有有效的時間戳記。 - </notification> <notification name="NoPendingConnection"> 無法建立待通的連線。 </notification> @@ -3832,9 +3922,11 @@ SHA1 指紋:[MD5_DIGEST] </notification> <notification name="TeleportedByAttachment"> ä½ å·²æˆåŠŸè¢« [ITEM_ID] ä¸Šçš„ä¸€å€‹é™„ä»¶çž¬é–“å‚³é€ + <usetemplate ignoretext="瞬間傳é€ï¼šä½ å·²æˆåŠŸè¢«ä¸€å€‹é™„件瞬間傳é€" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOnParcel"> ä½ å·²æˆåŠŸè¢« '[PARCEL_NAME]' 地段的物件 '[OBJECT_NAME]' çž¬é–“å‚³é€ + <usetemplate ignoretext="瞬間傳é€ï¼šä½ 已被一個物件或地段瞬間傳é€æˆåŠŸ" name="notifyignore"/> </notification> <notification name="TeleportedByObjectOwnedBy"> ä½ å·²æˆåŠŸè¢« [OWNER_ID] æ“有的物件 '[OBJECT_NAME]' çž¬é–“å‚³é€ @@ -4166,7 +4258,7 @@ SHA1 指紋:[MD5_DIGEST] <usetemplate ignoretext="無法移動檔案。 å·²æ¢å¾©å‰ä¸€å€‹è·¯å¾‘。" name="okignore" yestext="確定"/> </notification> <notification name="DefaultObjectPermissions"> - 儲å˜é è¨æ¬Šé™æ™‚出å•é¡Œï¼ŒåŽŸå› :[REASON]。 è«‹ç¨å¾Œå†å˜—試儲å˜é è¨æ¬Šé™ã€‚ + 儲å˜é è¨ç‰©ä»¶æ¬Šé™æ™‚出å•é¡Œï¼ŒåŽŸå› :[REASON]。 è«‹ç¨å¾Œå†å˜—試儲å˜é è¨æ¬Šé™ã€‚ <usetemplate name="okbutton" yestext="確定"/> </notification> <notification name="ChatHistoryIsBusyAlert"> diff --git a/indra/newview/skins/default/xui/zh/panel_login.xml b/indra/newview/skins/default/xui/zh/panel_login.xml index 09a1af5cf8..5292e5fc38 100755 --- a/indra/newview/skins/default/xui/zh/panel_login.xml +++ b/indra/newview/skins/default/xui/zh/panel_login.xml @@ -1,26 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_login"> - <panel.string name="forgot_password_url"> - http://secondlife.com/account/request.php - </panel.string> + <panel.string name="forgot_password_url">http://secondlife.com/account/request.php</panel.string> <layout_stack name="ui_stack"> <layout_panel name="ui_container"> <combo_box label="使用者å稱" name="username_combo" tool_tip="使用者åç¨±æ˜¯ä½ è¨»å†Šæ™‚æ‰€æŒ‘é¸çš„,例如 bobsmith12 或 Steller Sunshine"/> <line_editor label="密碼" name="password_edit"/> - <check_box label="記得我" name="remember_check"/> - <text name="forgot_password_text"> - 忘記密碼 - </text> - <button label="登入" name="connect_btn"/> - <text name="At_My_Last_Location_Label"> - 到我上次去的地點 - </text> <combo_box label="我的最愛" name="start_location_combo"> + <combo_box.item label="我上一次ä½ç½®" name="MyLastLocation"/> <combo_box.item label="我的家" name="MyHome"/> </combo_box> - <button label="登入" name="connect_favorite_btn"/> - <line_editor label="éµå…¥ä¸€å€‹åœ°é»ž" name="location_edit"/> - <button label="登入" name="connect_location_btn"/> + <button label="登入" name="connect_btn"/> + <check_box label="記得我" name="remember_check"/> + <text name="forgot_password_text">忘記密碼</text> <combo_box label="é¸æ“‡æ¨¡æ“¬ä¸–ç•Œ" name="server_combo"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/zh/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/zh/panel_marketplace_listings.xml new file mode 100644 index 0000000000..2eae87c6a0 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_marketplace_listings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Marketplace" name="Marketplace Panel"> + <panel name="tool_panel"> + <menu_button name="sort_btn" tool_tip="檢視/排åºçš„é¸é …"/> + <button name="add_btn" tool_tip="新建一個刊登資料夾"/> + <button label="檢查是å¦æœ‰èª¤" name="audit_btn" tool_tip="æª¢æŸ¥ä½ çš„ Marketplace 刊登"/> + </panel> + <panel name="tab_container_panel"> + <filter_editor label="éŽæ¿¾ Marketplace 刊登清單" name="filter_editor"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_marketplace_listings_inventory.xml b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_inventory.xml new file mode 100644 index 0000000000..a052a50bd1 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_inventory.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="全部" name="All Items" tool_tip="拖曳並置放物å“到這裡,å³å¯åˆŠç™»"/> diff --git a/indra/newview/skins/default/xui/zh/panel_marketplace_listings_listed.xml b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_listed.xml new file mode 100644 index 0000000000..3adc66a1d4 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_listed.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="已刊登" name="Active Items"/> diff --git a/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unassociated.xml b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unassociated.xml new file mode 100644 index 0000000000..d582e6615c --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unassociated.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="å·²å–消è¯çµ" name="Unassociated Items"/> diff --git a/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unlisted.xml b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unlisted.xml new file mode 100644 index 0000000000..6d00f3d9b7 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_marketplace_listings_unlisted.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<inventory_panel label="未刊登" name="Inactive Items"/> diff --git a/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml index 77f8b335db..77f8b335db 100755..100644 --- a/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml diff --git a/indra/newview/skins/default/xui/zh/panel_status_bar.xml b/indra/newview/skins/default/xui/zh/panel_status_bar.xml index b4cdff9d6b..2de31eb526 100755 --- a/indra/newview/skins/default/xui/zh/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/zh/panel_status_bar.xml @@ -1,28 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="status"> - <panel.string name="packet_loss_tooltip"> - å°åŒ…æ失 - </panel.string> - <panel.string name="bandwidth_tooltip"> - é »å¯¬ - </panel.string> - <panel.string name="time"> - [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] - </panel.string> - <panel.string name="timeTooltip"> - [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] - </panel.string> - <panel.string name="buycurrencylabel"> - L$ [AMT] - </panel.string> + <panel.string name="packet_loss_tooltip">å°åŒ…æ失</panel.string> + <panel.string name="bandwidth_tooltip">é »å¯¬</panel.string> + <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> + <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> + <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> <panel name="balance_bg"> - <text name="balance" tool_tip="點按以é‡æ–°æ›´æ–°ä½ çš„ L$ 帳戶餘é¡" value="L$20"/> + <text name="balance" tool_tip="點按以é‡æ–°æ›´æ–°ä½ çš„ L$ 帳戶餘é¡" value="L$??"/> <button label="購買 L$" name="buyL" tool_tip="點按以購買更多 L$"/> <button label="購物" name="goShop" tool_tip="打開第二人生購物市集"/> </panel> - <text name="TimeText" tool_tip="ç›®å‰æ™‚å€ï¼ˆå¤ªå¹³æ´‹ï¼‰"> - 24:00 AM PST - </text> + <text name="TimeText" tool_tip="ç›®å‰æ™‚å€ï¼ˆå¤ªå¹³æ´‹ï¼‰">24:00 AM PST</text> <button name="media_toggle_btn" tool_tip="開始/åœæ¢å…¨éƒ¨åª’體(音樂ã€å½±ç‰‡ã€ç¶²é )"/> <button name="volume_btn" tool_tip="全域音é‡æŽ§åˆ¶"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml b/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml index dcb709d2e3..9c5798d256 100755 --- a/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml @@ -54,12 +54,12 @@ ä½ å¯ä»¥ï¼š </text> <check_box label="修改" name="CheckOwnerModify"/> - <check_box label="æšåº¨" name="CheckOwnerCopy"/> + <check_box label="複製" name="CheckOwnerCopy"/> <check_box label="轉移" name="CheckOwnerTransfer"/> <text name="AnyoneLabel"> 任何人: </text> - <check_box label="æšåº¨" name="CheckEveryoneCopy"/> + <check_box label="複製" name="CheckEveryoneCopy"/> <text name="GroupLabel"> 群組: </text> @@ -68,12 +68,13 @@ 下一個所有人: </text> <check_box label="修改" name="CheckNextOwnerModify"/> - <check_box label="æšåº¨" name="CheckNextOwnerCopy"/> + <check_box label="複製" name="CheckNextOwnerCopy"/> <check_box label="轉移" name="CheckNextOwnerTransfer" tool_tip="下一個所有人å¯è´ˆé€æˆ–轉售這個物件"/> </panel> <check_box label="出售" name="CheckPurchase"/> - <combo_box name="combobox sale copy"> - <combo_box.item label="æšåº¨" name="Copy"/> + <combo_box name="ComboBoxSaleType"> + <combo_box.item label="複製" name="Copy"/> + <combo_box.item label="內容" name="Contents"/> <combo_box.item label="原件" name="Original"/> </combo_box> <spinner label="åƒ¹æ ¼ï¼š L$" name="Edit Cost"/> diff --git a/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml b/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml index 60f44a3d88..0884f1789b 100755 --- a/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml @@ -1,71 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="object properties" title="物件檔案"> - <panel.string name="text deed continued"> - 讓渡 - </panel.string> - <panel.string name="text deed"> - 讓渡 - </panel.string> - <panel.string name="text modify info 1"> - ä½ èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶ - </panel.string> - <panel.string name="text modify info 2"> - ä½ èƒ½ä¿®æ”¹é€™äº›ç‰©ä»¶ - </panel.string> - <panel.string name="text modify info 3"> - ä½ ä¸èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶ - </panel.string> - <panel.string name="text modify info 4"> - ä½ ä¸èƒ½ä¿®æ”¹é€™äº›ç‰©ä»¶ - </panel.string> - <panel.string name="text modify info 5"> - 無法跨地å€ä¿®æ”¹é€™å€‹ç‰©ä»¶ - </panel.string> - <panel.string name="text modify info 6"> - 無法跨地å€ä¿®æ”¹é€™äº›ç‰©ä»¶ - </panel.string> - <panel.string name="text modify warning"> - 這個物件å«æœ‰è¯çµçš„部分 - </panel.string> - <panel.string name="Cost Default"> - åƒ¹æ ¼ï¼š L$ - </panel.string> - <panel.string name="Cost Total"> - 總價:L$ - </panel.string> - <panel.string name="Cost Per Unit"> - 單價:L$ - </panel.string> - <panel.string name="Cost Mixed"> - æ··åˆåƒ¹æ ¼ - </panel.string> - <panel.string name="Sale Mixed"> - æ··åˆéŠ·å”® - </panel.string> + <panel.string name="text deed continued">讓渡</panel.string> + <panel.string name="text deed">讓渡</panel.string> + <panel.string name="text modify info 1">ä½ èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶</panel.string> + <panel.string name="text modify info 2">ä½ èƒ½ä¿®æ”¹é€™äº›ç‰©ä»¶</panel.string> + <panel.string name="text modify info 3">ä½ ä¸èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶</panel.string> + <panel.string name="text modify info 4">ä½ ä¸èƒ½ä¿®æ”¹é€™äº›ç‰©ä»¶</panel.string> + <panel.string name="text modify info 5">無法跨地å€ä¿®æ”¹é€™å€‹ç‰©ä»¶</panel.string> + <panel.string name="text modify info 6">無法跨地å€ä¿®æ”¹é€™äº›ç‰©ä»¶</panel.string> + <panel.string name="text modify warning">這個物件å«æœ‰è¯çµçš„部分</panel.string> + <panel.string name="Cost Default">åƒ¹æ ¼ï¼š L$</panel.string> + <panel.string name="Cost Total">ç¸½åƒ¹æ ¼ï¼šL$</panel.string> + <panel.string name="Cost Per Unit">單價:L$</panel.string> + <panel.string name="Cost Mixed">æ··åˆåƒ¹æ ¼</panel.string> + <panel.string name="Sale Mixed">æ··åˆéŠ·å”®</panel.string> <text name="title" value="物件檔案"/> <text name="where" value="(在虛擬世界)"/> <panel label="" name="properties_panel"> - <text name="Name:"> - å稱: - </text> - <text name="Description:"> - æ述: - </text> - <text name="CreatorNameLabel"> - å‰µé€ è€…ï¼š - </text> - <text name="Owner:"> - 所有人: - </text> - <text name="Group_label"> - 群組: - </text> + <text name="Name:">å稱:</text> + <text name="Description:">æ述:</text> + <text name="CreatorNameLabel">å‰µé€ è€…ï¼š</text> + <text name="Owner:">所有人:</text> + <text name="Group_label">群組:</text> <button name="button set group" tool_tip="é¸æ“‡ä¸€å€‹ç¾¤çµ„以分享這物件的權é™"/> <name_box initial_value="載入ä¸..." name="Group Name Proxy"/> <button label="讓渡" label_selected="讓渡" name="button deed" tool_tip="「讓渡ã€æœƒæŠŠé€™ç‰©ä»¶è´ˆé€å‡ºåŽ»ä¸¦è³¦äºˆã€Œä¸‹ä¸€å€‹æ‰€æœ‰äººã€æ¬Šé™ã€‚ 群組所分享的物件å¯ç”±ç¾¤çµ„è·å“¡åŠ 以讓渡。"/> - <text name="label click action"> - 點按以: - </text> + <text name="label click action">點按以:</text> <combo_box name="clickaction"> <combo_box.item label="觸碰(é è¨ï¼‰" name="Touch/grab(default)"/> <combo_box.item label="å在物件上" name="Sitonobject"/> @@ -75,21 +35,13 @@ <combo_box.item label="縮放" name="Zoom"/> </combo_box> <panel name="perms_inv"> - <text name="perm_modify"> - ä½ èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶ - </text> - <text name="Anyone can:"> - 任何人: - </text> + <text name="perm_modify">ä½ èƒ½ä¿®æ”¹é€™å€‹ç‰©ä»¶</text> + <text name="Anyone can:">任何人:</text> <check_box label="æšåº¨" name="checkbox allow everyone copy"/> <check_box label="移動" name="checkbox allow everyone move"/> - <text name="GroupLabel"> - 群組: - </text> + <text name="GroupLabel">群組:</text> <check_box label="分享" name="checkbox share with group" tool_tip="å…許æ¤ç¾¤çµ„所有æˆå“¡å…±äº«ä½ 修改æ¤ç‰©ä»¶çš„權é™ã€‚ ä½ å¿…é ˆè®“æ¸¡æ‰èƒ½å•Ÿå‹•è§’色é™åˆ¶ã€‚"/> - <text name="NextOwnerLabel"> - 下一個所有人: - </text> + <text name="NextOwnerLabel">下一個所有人:</text> <check_box label="修改" name="checkbox next owner can modify"/> <check_box label="æšåº¨" name="checkbox next owner can copy"/> <check_box label="轉移" name="checkbox next owner can transfer" tool_tip="下一個所有人å¯è´ˆé€æˆ–轉售這個物件"/> @@ -102,27 +54,13 @@ </combo_box> <spinner label="åƒ¹æ ¼ï¼š L$" name="Edit Cost"/> <check_box label="顯示在æœå°‹ä¸" name="search_check" tool_tip="讓其他人å¯ä»¥åœ¨æœå°‹çµæžœä¸å¯Ÿçœ‹åˆ°æ¤ç‰©ä»¶"/> - <text name="pathfinding_attributes_label"> - 尋徑屬性: - </text> - <text name="B:"> - B: - </text> - <text name="O:"> - O: - </text> - <text name="G:"> - G: - </text> - <text name="E:"> - E: - </text> - <text name="N:"> - N: - </text> - <text name="F:"> - F: - </text> + <text name="pathfinding_attributes_label">尋徑屬性:</text> + <text name="B:">B:</text> + <text name="O:">O:</text> + <text name="G:">G:</text> + <text name="E:">E:</text> + <text name="N:">N:</text> + <text name="F:">F:</text> </panel> <panel name="button_panel"> <button label="打開" name="open_btn"/> diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index e8edf1270b..6493864b92 100755 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -449,28 +449,46 @@ http://secondlife.com/viewer-access-faq </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> <string name="TooltipOutboxDragToWorld"> - å•†å®¶ç™¼ä»¶åŒ£å…§çš„ç‰©é …ç„¡æ³•ç”¢ç”Ÿåˆ°è™›æ“¬ä¸–ç•Œ + ä½ ä¸èƒ½å¾ž Marketplace 的刊登資料夾產生物件。 + </string> + <string name="TooltipOutboxWorn"> + ä½ ä¸èƒ½æŠŠæ£åœ¨ç©¿æˆ´çš„物件放到 Marketplace 的刊登資料夾 + </string> + <string name="TooltipOutboxFolderLevels"> + å·¢ç‹€è³‡æ–™å¤¾æ·±åº¦è¶…éŽ [AMOUNT]。 請減少巢狀資料夾的深度,必è¦çš„話請把物件併整起來。 + </string> + <string name="TooltipOutboxTooManyFolders"> + åè³‡æ–™å¤¾æ•¸ç›®è¶…éŽ [AMOUNT]。 請減少刊登的資料夾數目,必è¦çš„話請把物件併整起來。 + </string> + <string name="TooltipOutboxTooManyObjects"> + ç‰©ä»¶æ•¸ç›®è¶…éŽ [AMOUNT]。 若想在åŒä¸€åˆŠç™»ä¸å‡ºå”®è¶…éŽ [AMOUNT] å€‹ç‰©ä»¶ï¼Œä½ éœ€è¦æŠŠç‰©ä»¶ä½µæ•´èµ·ä¾†ã€‚ + </string> + <string name="TooltipOutboxTooManyStockItems"> + é™é‡ç‰©ä»¶æ•¸ç›®è¶…éŽ [AMOUNT]。 + </string> + <string name="TooltipOutboxCannotDropOnRoot"> + ä½ åªèƒ½æŠŠç‰©é …或資料夾拖放到「所有ã€(ALL)é 籤 è«‹é¸å–該é 籤,å†ç§»å‹•ä½ çš„ç‰©é …æˆ–è³‡æ–™å¤¾ã€‚ </string> <string name="TooltipOutboxNoTransfer"> - 至少一個物件無法出售或轉移。 + 至少一個物件無法出售或轉移 </string> <string name="TooltipOutboxNotInInventory"> - ä½ çš„å•†å®¶ç™¼ä»¶åŒ£åªèƒ½æŽ¥å—直接來自收ç´å€çš„ç‰©é …ã€‚ + ä½ åªèƒ½å°‡ç‰©ä»¶å¾žæ”¶ç´å€æ”¾åˆ° Marketplace。 </string> - <string name="TooltipOutboxWorn"> - ä½ ç©¿è‘—ä¸çš„ç‰©é …ç„¡æ³•æ”¾å…¥å•†å®¶ç™¼ä»¶åŒ£ã€‚ + <string name="TooltipOutboxLinked"> + ä½ ä¸èƒ½æŠŠè¯çµçš„物件或資料夾放到 Marketplace </string> <string name="TooltipOutboxCallingCard"> - å片ä¸å¾—放入商家發件匣 + ä½ ä¸èƒ½æŠŠå片放到 Marketplace </string> - <string name="TooltipOutboxFolderLevels"> - å·¢ç‹€è³‡æ–™å¤¾æ·±åº¦è¶…éŽ 3 + <string name="TooltipOutboxDragActive"> + 已登出的刊登內容ä¸å¾—移動 </string> - <string name="TooltipOutboxTooManyFolders"> - é ‚å±¤è³‡æ–™å¤¾çš„åè³‡æ–™å¤¾æ•¸ç›®è¶…éŽ 20 + <string name="TooltipOutboxCannotMoveRoot"> + ä½ ä¸èƒ½ç§»å‹• Marketplace åˆŠç™»çš„æ ¹ç›®éŒ„ </string> - <string name="TooltipOutboxTooManyObjects"> - é ‚å±¤è³‡æ–™å¤¾ç‰©é …æ•¸ç›®è¶…éŽ 200 + <string name="TooltipOutboxMixedStock"> + é™é‡è³‡æ–™å¤¾çš„æ‰€æœ‰ç‰©ä»¶å¿…é ˆæ˜¯ç›¸åŒçš„é¡žåž‹å’Œæ¬Šé™ </string> <string name="TooltipDragOntoOwnChild"> 資料夾ä¸å¾—移到其å資料夾底下 @@ -1055,7 +1073,7 @@ http://secondlife.com/viewer-access-faq <string name="AgentNameSubst"> ï¼ˆä½ ï¼‰ </string> - <string name="JoinAnExperience"/> + <string name="JoinAnExperience"/><!-- intentionally blank --> <string name="SilentlyManageEstateAccess"> 管ç†é ˜å‡ºå…¥è¨±å¯å單時,ä¸é¡¯ç¤ºè¦ç¤º </string> @@ -1122,6 +1140,12 @@ http://secondlife.com/viewer-access-faq <string name="bitmap_image_files"> Bitmap åœ–åƒ </string> + <string name="png_image_files"> + PNG åœ–åƒ + </string> + <string name="save_texture_image_files"> + Targa 或 PNG åœ–åƒ + </string> <string name="avi_movie_file"> AVI è¦–é »æª”æ¡ˆ </string> @@ -1371,6 +1395,9 @@ http://secondlife.com/viewer-access-faq <string name="FavoritesNoMatchingItems"> å°‡ä¸€å€‹åœ°æ¨™æ‹–æ›³åˆ°é€™è£¡ï¼ŒåŠ é€²ã€Œæˆ‘çš„æœ€æ„›ã€ã€‚ </string> + <string name="MarketplaceNoMatchingItems"> + 找ä¸åˆ°ç‰©é …。 請檢查æœå°‹å—串的拼寫,å†è©¦ä¸€æ¬¡ã€‚ + </string> <string name="InventoryNoTexture"> ä½ çš„æ”¶ç´å€è£¡æ²’有這個æ質的副本 </string> @@ -1418,29 +1445,95 @@ http://secondlife.com/viewer-access-faq <string name="InventoryOutboxError"> [[MARKETPLACE_CREATE_STORE_URL] 購物市集商店]æ£å‚³å›žéŒ¯èª¤ã€‚ </string> + <string name="InventoryMarketplaceError"> + 這功能尚在 Beta 測試階段。 å¦‚ä½ æƒ³åƒèˆ‡ï¼Œè«‹åˆ°é€™å€‹[http://goo.gl/forms/FCQ7UXkakz Google 表單]填寫姓å。 + </string> + <string name="InventoryMarketplaceListingsNoItemsTitle"> + ä½ çš„ Marketplace 刊登資料夾是空的。 + </string> + <string name="InventoryMarketplaceListingsNoItems"> + 將資料夾拖曳到這個å€åŸŸï¼Œå³å¯åœ¨[[MARKETPLACE_DASHBOARD_URL] Marketplace]刊登出售。 + </string> + <string name="Marketplace Validation Warning Stock"> + é™é‡è³‡æ–™å¤¾å¿…é ˆæ”¾åœ¨ç‰ˆæœ¬è³‡æ–™å¤¾è£¡ + </string> + <string name="Marketplace Validation Error Mixed Stock"> + :錯誤:é™é‡è³‡æ–™å¤¾çš„æ‰€æœ‰ç‰©ä»¶å¿…é ˆæ˜¯ã€Œç¦æ¢è¤‡è£½ã€ä¸”åŒä¸€é¡žåž‹ + </string> + <string name="Marketplace Validation Error Subfolder In Stock"> + :錯誤:é™é‡è³‡æ–™å¤¾ä¸å¾—å«æœ‰å資料夾 + </string> + <string name="Marketplace Validation Warning Empty"> + :è¦å‘Šï¼šè³‡æ–™å¤¾è£¡æ²’有æ±è¥¿ + </string> + <string name="Marketplace Validation Warning Create Stock"> + :è¦å‘Šï¼šæ–°å»ºé™é‡è³‡æ–™å¤¾ + </string> + <string name="Marketplace Validation Warning Create Version"> + :è¦å‘Šï¼šæ–°å»ºç‰ˆæœ¬è³‡æ–™å¤¾ + </string> + <string name="Marketplace Validation Warning Move"> + :è¦å‘Šï¼šç§»å‹•ç‰©é … + </string> + <string name="Marketplace Validation Warning Delete"> + :è¦å‘Šï¼šè³‡æ–™å¤¾å…§å®¹å·²è½‰ç§»åˆ°é™é‡è³‡æ–™å¤¾ï¼Œç©ºçš„資料夾已移除 + </string> + <string name="Marketplace Validation Error Stock Item"> + :錯誤:「ç¦æ¢è¤‡è£½ã€ç‰©ä»¶å¿…é ˆæ”¾åœ¨é™é‡è³‡æ–™å¤¾è£¡ + </string> + <string name="Marketplace Validation Warning Unwrapped Item"> + :è¦å‘Šï¼šç‰©é …å¿…é ˆæ”¾åœ¨ä¸€å€‹ç‰ˆæœ¬è³‡æ–™å¤¾è£¡ + </string> + <string name="Marketplace Validation Error"> + :錯誤: + </string> + <string name="Marketplace Validation Warning"> + :è¦å‘Šï¼š + </string> + <string name="Marketplace Validation Error Empty Version"> + :è¦å‘Šï¼šç‰ˆæœ¬è³‡æ–™å¤¾å¿…é ˆåŒ…å«è‡³å°‘ä¸€å€‹ç‰©é … + </string> + <string name="Marketplace Validation Error Empty Stock"> + :è¦å‘Šï¼šé™é‡è³‡æ–™å¤¾å¿…é ˆåŒ…å«è‡³å°‘ä¸€å€‹ç‰©é … + </string> + <string name="Marketplace Validation No Error"> + 沒有需è¦å ±å‘Šçš„錯誤或è¦å‘Š + </string> <string name="Marketplace Error None"> 零錯誤 </string> + <string name="Marketplace Error Prefix"> + 錯誤: + </string> <string name="Marketplace Error Not Merchant"> - ç™¼ç”ŸéŒ¯èª¤ï¼šå°‡ç‰©é …é€å¾€ç¬¬äºŒäººç”Ÿè³¼ç‰©å¸‚集之å‰ï¼Œä½ å¿…é ˆå–得商家的身份(å…費)。 + 將物件移到 Marketplace å‰ï¼Œä½ å¿…é ˆå–得商家的身份(å…費)。 + </string> + <string name="Marketplace Error Not Accepted"> + ç„¡æ³•ç§»å‹•è©²è³‡æ–™å¤¾çš„ç‰©é …ã€‚ </string> - <string name="Marketplace Error Empty Folder"> - 錯誤:æ¤è³‡æ–™å¤¾æ²’有內容。 + <string name="Marketplace Error Unsellable Item"> + æ¤ç‰©é …無法在 Marketplace 出售。 </string> - <string name="Marketplace Error Unassociated Products"> - 錯誤:æ¤ç‰©é …ä¸Šå‚³å¤±æ•—ï¼Œå› ç‚ºä½ çš„å•†å®¶å¸³æˆ¶æœ‰å¤ªå¤šå’Œç”¢å“ç„¡é—œè¯çš„ç‰©é …ã€‚ è¦è§£æ±ºé€™å€‹å•é¡Œï¼Œè«‹ç™»å…¥ç¬¬äºŒäººç”Ÿè³¼ç‰©å¸‚é›†ç¶²ç«™ï¼Œæ¸›ä½Žä½ çš„ç„¡é—œè¯ç‰©é …數目。 + <string name="MarketplaceNoID"> + 沒有 Mkt ID </string> - <string name="Marketplace Error Object Limit"> - 錯誤:æ¤ç‰©é …包å«å¤ªå¤šç‰©ä»¶ã€‚ è¦è§£æ±ºé€™éŒ¯èª¤ï¼Œè«‹å°‡ç‰©ä»¶è£ç®±ï¼Œä½¿ç¸½ç‰©ä»¶æ•¸ç›®ä¸è¶…éŽ 200。 + <string name="MarketplaceLive"> + 已刊登 </string> - <string name="Marketplace Error Folder Depth"> - 錯誤:æ¤ç‰©é …å«æœ‰å¤ªå¤šå±¤çš„巢狀資料夾。 è«‹åŠ ä»¥é‡æ–°æ•´ç†ï¼Œè‡³å¤šå…許 3 層的巢狀資料夾。 + <string name="MarketplaceActive"> + ä½¿ç”¨ä¸ </string> - <string name="Marketplace Error Unsellable Item"> - 錯誤:æ¤ç‰©é …無法在第二人生購物市集出售。 + <string name="MarketplaceMax"> + 最多 </string> - <string name="Marketplace Error Internal Import"> - éŒ¯èª¤ï¼šé€™å€‹ç‰©é …æœ‰å•é¡Œã€‚ è«‹ç¨å€™å†è©¦ä¸€æ¬¡ã€‚ + <string name="MarketplaceStock"> + é™é‡ + </string> + <string name="MarketplaceNoStock"> + 缺貨 + </string> + <string name="MarketplaceUpdating"> + æ£åœ¨æ›´æ–°â€¦ </string> <string name="Open landmarks"> 開啟地標 @@ -1461,6 +1554,7 @@ http://secondlife.com/viewer-access-faq 無內容 </string> <string name="WornOnAttachmentPoint" value="(已穿 [ATTACHMENT_POINT])"/> + <string name="AttachmentErrorMessage" value="([ATTACHMENT_ERROR])"/> <string name="ActiveGesture" value="[GESLABEL](使用ä¸ï¼‰"/> <string name="PermYes"> 是 @@ -1731,6 +1825,15 @@ http://secondlife.com/viewer-access-faq <string name="Invalid Attachment"> 無效的附接點 </string> + <string name="ATTACHMENT_MISSING_ITEM"> + 錯誤:缺少物件 + </string> + <string name="ATTACHMENT_MISSING_BASE_ITEM"> + éŒ¯èª¤ï¼šç¼ºå°‘åŸºæœ¬ç‰©é … + </string> + <string name="ATTACHMENT_NOT_ATTACHED"> + 錯誤:物件在目å‰çš„è£æ‰®è£¡ï¼Œå¯æ˜¯å»æœªé™„è‘— + </string> <string name="YearsMonthsOld"> 年齡:[AGEYEARS] å¹´ [AGEMONTHS] 月 </string> @@ -1866,9 +1969,6 @@ http://secondlife.com/viewer-access-faq <string name="CompileQueueUnknownFailure"> ä¸‹è¼‰å¤±æ•—ï¼ŒåŽŸå› ä¸æ˜Ž </string> - <string name="CompileNoExperiencePerm"> - ç•¥éŽé«”é©— [EXPERIENCE] 的腳本 [SCRIPT]。 - </string> <string name="CompileQueueTitle"> é‡æ–°ç·¨è¯é€²åº¦ </string> @@ -1902,6 +2002,9 @@ http://secondlife.com/viewer-access-faq <string name="SaveComplete"> 儲å˜å®Œç•¢ã€‚ </string> + <string name="UploadFailed"> + 檔案上傳失敗: + </string> <string name="ObjectOutOfRange"> 腳本(物件超出範åœï¼‰ </string> @@ -1911,6 +2014,9 @@ http://secondlife.com/viewer-access-faq <string name="GroupsNone"> ç„¡ </string> + <string name="CompileNoExperiencePerm"> + ç•¥éŽé«”é©— [EXPERIENCE] 的腳本 [SCRIPT]。 + </string> <string name="Group" value="(群組)"/> <string name="Unknown"> (未知) @@ -4400,7 +4506,7 @@ http://secondlife.com/viewer-access-faq 女性姿勢 </string> <string name="Other Gestures"> - 其他���勢 + 其他姿勢 </string> <string name="Speech Gestures"> 演說姿勢 @@ -4662,7 +4768,7 @@ http://secondlife.com/viewer-access-faq 刪除所é¸å–的物å“? </string> <string name="DeleteItem"> - 刪除所é¸å–的物���? + 刪除所é¸å–的物å“? </string> <string name="EmptyOutfitText"> 沒有任何物å“在這個è£æ‰®å…§ @@ -5074,6 +5180,9 @@ http://secondlife.com/viewer-access-faq <string name="Command_Marketplace_Label"> 第二人生購物市集 </string> + <string name="Command_MarketplaceListings_Label"> + Marketplace + </string> <string name="Command_MiniMap_Label"> è¿·ä½ åœ°åœ– </string> @@ -5161,6 +5270,9 @@ http://secondlife.com/viewer-access-faq <string name="Command_Marketplace_Tooltip"> å‰å¾€è³¼ç‰© </string> + <string name="Command_MarketplaceListings_Tooltip"> + å‡ºå”®ä½ çš„å‰µä½œç‰© + </string> <string name="Command_MiniMap_Tooltip"> 顯示附近的人 </string> @@ -5272,6 +5384,18 @@ http://secondlife.com/viewer-access-faq <string name="UserDictionary"> [User] </string> + <string name="logging_calls_disabled_log_empty"> + 交談未留記錄。 若想開始留記錄,請到「å好è¨å®š > èŠå¤©ã€ï¼Œé¸æ“‡ã€Œå„²å˜ï¼šåªç•™æ·å²è¨˜éŒ„ã€æˆ–「儲å˜ï¼šæ·å²è¨˜éŒ„兼交談內容ã€ã€‚ + </string> + <string name="logging_calls_disabled_log_not_empty"> + å°‡ä¸å†ç‚ºäº¤è«‡ç•™è¨˜éŒ„。 若想æ¢å¾©ç•™å˜è¨˜éŒ„,請到「å好è¨å®š > èŠå¤©ã€ï¼Œé¸æ“‡ã€Œå„²å˜ï¼šåªç•™æ·å²è¨˜éŒ„ã€æˆ–「儲å˜ï¼šæ·å²è¨˜éŒ„兼交談內容ã€ã€‚ + </string> + <string name="logging_calls_enabled_log_empty"> + ç›®å‰æ²’有交談記錄。 åœ¨ä½ è¯çµ¡æŸäººæˆ–æŸäººè¯çµ¡ä½ 之後,這裡將留å˜è¨˜éŒ„。 + </string> + <string name="loading_chat_logs"> + 載入ä¸â€¦ + </string> <string name="experience_tools_experience"> 體驗 </string> @@ -5353,16 +5477,4 @@ http://secondlife.com/viewer-access-faq <string name="ExperiencePermissionShort12"> æ¬Šé™ </string> - <string name="logging_calls_disabled_log_empty"> - 交談未留記錄。 若想開始留記錄,請到「å好è¨å®š > èŠå¤©ã€ï¼Œé¸æ“‡ã€Œå„²å˜ï¼šåªç•™æ·å²è¨˜éŒ„ã€æˆ–「儲å˜ï¼šæ·å²è¨˜éŒ„兼交談內容ã€ã€‚ - </string> - <string name="logging_calls_disabled_log_not_empty"> - å°‡ä¸å†ç‚ºäº¤è«‡ç•™è¨˜éŒ„。 若想æ¢å¾©ç•™å˜è¨˜éŒ„,請到「å好è¨å®š > èŠå¤©ã€ï¼Œé¸æ“‡ã€Œå„²å˜ï¼šåªç•™æ·å²è¨˜éŒ„ã€æˆ–「儲å˜ï¼šæ·å²è¨˜éŒ„兼交談內容ã€ã€‚ - </string> - <string name="logging_calls_enabled_log_empty"> - ç›®å‰æ²’有交談記錄。 åœ¨ä½ è¯çµ¡æŸäººæˆ–æŸäººè¯çµ¡ä½ 之後,這裡將留å˜è¨˜éŒ„。 - </string> - <string name="loading_chat_logs"> - 載入ä¸â€¦ - </string> </strings> diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 2bc0d5a086..4694f657b6 100755 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -39,7 +39,21 @@ namespace static const char * const TEST_FILENAME("llslurl_test.xml"); } - + +// +// Stub implementation for LLTrans +// +class LLTrans +{ +public: + static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); +}; + +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +{ + return std::string(); +} + //---------------------------------------------------------------------------- // Mock objects for the dependencies of the code we're testing diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index 0eb0ab6500..e68da14fe9 100755 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -38,6 +38,31 @@ namespace static const char * const TEST_FILENAME("llviewernetwork_test.xml"); } + +// +// Stub implementation for LLTrans +// +class LLTrans +{ +public: + static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); +}; + +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +{ + std::string grid_label = std::string(); + if(xml_desc == "AgniGridLabel") + { + grid_label = "Second Life Main Grid (Agni)"; + } + else if(xml_desc == "AditiGridLabel") + { + grid_label = "Second Life Beta Test Grid (Aditi)"; + } + + return grid_label; +} + //---------------------------------------------------------------------------- // Mock objects for the dependencies of the code we're testing diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index c152493a51..788955a1b2 100755 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -132,6 +132,7 @@ public: void startChecking(bool install_if_ready); void stopChecking(); + bool forceCheck(); bool isChecking(); LLUpdaterService::eUpdaterState getState(); @@ -266,6 +267,46 @@ void LLUpdaterServiceImpl::stopChecking() setState(LLUpdaterService::TERMINAL); } +bool LLUpdaterServiceImpl::forceCheck() +{ + if (!mIsDownloading && getState() != LLUpdaterService::CHECKING_FOR_UPDATE) + { + if (mIsChecking) + { + // Service is running, just reset the timer + if (mTimer.getStarted()) + { + mTimer.setTimerExpirySec(0); + setState(LLUpdaterService::CHECKING_FOR_UPDATE); + return true; + } + } + else if (!mChannel.empty() && !mVersion.empty()) + { + // one time check + bool has_install = checkForInstall(false); + if (!has_install) + { + std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); + if (!query_url.empty()) + { + setState(LLUpdaterService::CHECKING_FOR_UPDATE); + mUpdateChecker.checkVersion(query_url, mChannel, mVersion, + mPlatform, mPlatformVersion, mUniqueId, + mWillingToTest); + return true; + } + else + { + LL_WARNS("UpdaterService") + << "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() << LL_ENDL; + } + } + } + } + return false; +} + bool LLUpdaterServiceImpl::isChecking() { return mIsChecking; @@ -402,9 +443,9 @@ bool LLUpdaterServiceImpl::checkForResume() void LLUpdaterServiceImpl::error(std::string const & message) { + setState(LLUpdaterService::TEMPORARY_ERROR); if(mIsChecking) { - setState(LLUpdaterService::TEMPORARY_ERROR); restartTimer(mCheckPeriod); } } @@ -449,8 +490,12 @@ void LLUpdaterServiceImpl::response(LLSD const & content) else { LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in " - << mCheckPeriod << " seconds" << LL_ENDL; - restartTimer(mCheckPeriod); + << mCheckPeriod << " seconds" << LL_ENDL; + setState(LLUpdaterService::TEMPORARY_ERROR); + if (mIsChecking) + { + restartTimer(mCheckPeriod); + } } } @@ -672,6 +717,11 @@ void LLUpdaterService::stopChecking() mImpl->stopChecking(); } +bool LLUpdaterService::forceCheck() +{ + return mImpl->forceCheck(); +} + bool LLUpdaterService::isChecking() { return mImpl->isChecking(); diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 0ddf24935b..95bbe1695c 100755 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -84,6 +84,7 @@ public: void startChecking(bool install_if_ready = false); void stopChecking(); + bool forceCheck(); bool isChecking(); eUpdaterState getState(); |