diff options
Diffstat (limited to 'indra')
358 files changed, 8386 insertions, 4805 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index bb64152407..c35799bbb9 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -379,7 +379,7 @@ namespace { /* This pattern, of returning a reference to a static function variable, is to ensure that this global is constructed before - it is used, no matter what the global initializeation sequence + it is used, no matter what the global initialization sequence is. See C++ FAQ Lite, sections 10.12 through 10.14 */ diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 4a42241c4f..b3e604f8e8 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -39,7 +39,7 @@ Information for most users: - Code can log messages with constuctions like this: + Code can log messages with constructions like this: LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id << " denied due to timeout" << LL_ENDL; @@ -47,9 +47,9 @@ Messages can be logged to one of four increasing levels of concern, using one of four "streams": - LL_DEBUGS("StringTag") - debug messages that are normally supressed - LL_INFOS("StringTag") - informational messages that are normall shown - LL_WARNS("StringTag") - warning messages that singal a problem + LL_DEBUGS("StringTag") - debug messages that are normally suppressed + LL_INFOS("StringTag") - informational messages that are normal shown + LL_WARNS("StringTag") - warning messages that signal a problem LL_ERRS("StringTag") - error messages that are major, unrecoverable failures The later (LL_ERRS("StringTag")) automatically crashes the process after the message @@ -90,7 +90,7 @@ WARN: LLFoo::doSomething: called with a big value for i: 283 - Which messages are logged and which are supressed can be controled at run + Which messages are logged and which are suppressed can be controlled at run time from the live file logcontrol.xml based on function, class and/or source file. See etc/logcontrol-dev.xml for details. @@ -106,7 +106,7 @@ namespace LLError enum ELevel { LEVEL_ALL = 0, - // used to indicate that all messagess should be logged + // used to indicate that all messages should be logged LEVEL_DEBUG = 0, LEVEL_INFO = 1, @@ -220,7 +220,7 @@ namespace LLError // See top of file for example of how to use this typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; - // Outside a class declartion, or in class without LOG_CLASS(), this + // Outside a class declaration, or in class without LOG_CLASS(), this // typedef causes the messages to not be associated with any class. diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index b4891eba67..afb714c71c 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -92,7 +92,7 @@ public: public: typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t; - key_iter(typename InstanceMap::iterator& it) + key_iter(typename InstanceMap::iterator it) : mIterator(it) { ++sIterationNestDepth; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 7aee1bb85f..00757be277 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -100,12 +100,6 @@ private: DELETED } EInitState; - static void deleteSingleton() - { - delete getData().mSingletonInstance; - getData().mSingletonInstance = NULL; - } - // stores pointer to singleton instance // and tracks initialization state of singleton struct SingletonInstanceData @@ -120,7 +114,11 @@ private: ~SingletonInstanceData() { - deleteSingleton(); + SingletonInstanceData& data = getData(); + if (data.mInitState != DELETED) + { + deleteSingleton(); + } } }; @@ -132,6 +130,14 @@ public: data.mInitState = DELETED; } + // Can be used to control when the singleton is deleted. Not normally needed. + static void deleteSingleton() + { + delete getData().mSingletonInstance; + getData().mSingletonInstance = NULL; + getData().mInitState = DELETED; + } + static SingletonInstanceData& getData() { // this is static to cache the lookup results diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index fa2b3bff36..324507fe7a 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 0; -const S32 LL_VERSION_PATCH = 2; +const S32 LL_VERSION_PATCH = 4; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 3caf49aa6e..80b35bbdc3 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -90,79 +90,79 @@ namespace tut ensure_equals(Keyed::instanceCount(), 0); } - // template<> template<> - // void object::test<2>() - // { - // ensure_equals(Unkeyed::instanceCount(), 0); - // { - // Unkeyed one; - // ensure_equals(Unkeyed::instanceCount(), 1); - // Unkeyed* found = Unkeyed::getInstance(&one); - // ensure_equals(found, &one); - // { - // boost::scoped_ptr<Unkeyed> two(new Unkeyed); - // ensure_equals(Unkeyed::instanceCount(), 2); - // Unkeyed* found = Unkeyed::getInstance(two.get()); - // ensure_equals(found, two.get()); - // } - // ensure_equals(Unkeyed::instanceCount(), 1); - // } - // ensure_equals(Unkeyed::instanceCount(), 0); - // } + template<> template<> + void object::test<2>() + { + ensure_equals(Unkeyed::instanceCount(), 0); + { + Unkeyed one; + ensure_equals(Unkeyed::instanceCount(), 1); + Unkeyed* found = Unkeyed::getInstance(&one); + ensure_equals(found, &one); + { + boost::scoped_ptr<Unkeyed> two(new Unkeyed); + ensure_equals(Unkeyed::instanceCount(), 2); + Unkeyed* found = Unkeyed::getInstance(two.get()); + ensure_equals(found, two.get()); + } + ensure_equals(Unkeyed::instanceCount(), 1); + } + ensure_equals(Unkeyed::instanceCount(), 0); + } - // template<> template<> - // void object::test<3>() - // { - // Keyed one("one"), two("two"), three("three"); - // // We don't want to rely on the underlying container delivering keys - // // in any particular order. That allows us the flexibility to - // // reimplement LLInstanceTracker using, say, a hash map instead of a - // // std::map. We DO insist that every key appear exactly once. - // typedef std::vector<std::string> StringVector; - // StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); - // std::sort(keys.begin(), keys.end()); - // StringVector::const_iterator ki(keys.begin()); - // ensure_equals(*ki++, "one"); - // ensure_equals(*ki++, "three"); - // ensure_equals(*ki++, "two"); - // // Use ensure() here because ensure_equals would want to display - // // mismatched values, and frankly that wouldn't help much. - // ensure("didn't reach end", ki == keys.end()); + template<> template<> + void object::test<3>() + { + Keyed one("one"), two("two"), three("three"); + // We don't want to rely on the underlying container delivering keys + // in any particular order. That allows us the flexibility to + // reimplement LLInstanceTracker using, say, a hash map instead of a + // std::map. We DO insist that every key appear exactly once. + typedef std::vector<std::string> StringVector; + StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); + std::sort(keys.begin(), keys.end()); + StringVector::const_iterator ki(keys.begin()); + ensure_equals(*ki++, "one"); + ensure_equals(*ki++, "three"); + ensure_equals(*ki++, "two"); + // Use ensure() here because ensure_equals would want to display + // mismatched values, and frankly that wouldn't help much. + ensure("didn't reach end", ki == keys.end()); - // // Use a somewhat different approach to order independence with - // // beginInstances(): explicitly capture the instances we know in a - // // set, and delete them as we iterate through. - // typedef std::set<Keyed*> InstanceSet; - // InstanceSet instances; - // instances.insert(&one); - // instances.insert(&two); - // instances.insert(&three); - // for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); - // ii != iend; ++ii) - // { - // Keyed& ref = *ii; - // ensure_equals("spurious instance", instances.erase(&ref), 1); - // } - // ensure_equals("unreported instance", instances.size(), 0); - // } + // Use a somewhat different approach to order independence with + // beginInstances(): explicitly capture the instances we know in a + // set, and delete them as we iterate through. + typedef std::set<Keyed*> InstanceSet; + InstanceSet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); + for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); + ii != iend; ++ii) + { + Keyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + ensure_equals("unreported instance", instances.size(), 0); + } + + template<> template<> + void object::test<4>() + { + Unkeyed one, two, three; + typedef std::set<Unkeyed*> KeySet; + + KeySet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); - // template<> template<> - // void object::test<4>() - // { - // Unkeyed one, two, three; - // typedef std::set<Unkeyed*> KeySet; - // - // KeySet instances; - // instances.insert(&one); - // instances.insert(&two); - // instances.insert(&three); - - //for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii) - //{ - // Unkeyed& ref = *ii; - // ensure_equals("spurious instance", instances.erase(&ref), 1); - //} - - // ensure_equals("unreported instance", instances.size(), 0); - // } + for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii) + { + Unkeyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + + ensure_equals("unreported instance", instances.size(), 0); + } } // namespace tut diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index c5f82cf052..0f40a670fa 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -65,6 +65,7 @@ set(llmessage_SOURCE_FILES llpacketbuffer.cpp llpacketring.cpp llpartdata.cpp + llproxy.cpp llpumpio.cpp llregionpresenceverifier.cpp llsdappservices.cpp @@ -161,6 +162,7 @@ set(llmessage_HEADER_FILES llpacketring.h llpartdata.h llpumpio.h + llproxy.h llqueryflags.h llregionflags.h llregionhandle.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1a86a69a04..bfdf49c74b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1,5 +1,5 @@ /** - * @file llcurl.h + * @file llcurl.cpp * @author Zero / Donovan * @date 2006-10-15 * @brief Implementation of wrapper around libcurl. @@ -26,7 +26,6 @@ * $/LicenseInfo$ */ - #if LL_WINDOWS #define SAFE_SSL 1 #elif LL_DARWIN @@ -47,8 +46,9 @@ #endif #include "llbufferstream.h" -#include "llstl.h" +#include "llproxy.h" #include "llsdserialize.h" +#include "llstl.h" #include "llthread.h" #include "lltimer.h" @@ -209,7 +209,7 @@ namespace boost void intrusive_ptr_release(LLCurl::Responder* p) { - if(p && 0 == --p->mReferenceCount) + if (p && 0 == --p->mReferenceCount) { delete p; } @@ -219,73 +219,6 @@ namespace boost ////////////////////////////////////////////////////////////////////////////// - -class LLCurl::Easy -{ - LOG_CLASS(Easy); - -private: - Easy(); - -public: - static Easy* getEasy(); - ~Easy(); - - CURL* getCurlHandle() const { return mCurlEasyHandle; } - - void setErrorBuffer(); - void setCA(); - - void setopt(CURLoption option, S32 value); - // These assume the setter does not free value! - void setopt(CURLoption option, void* value); - void setopt(CURLoption option, char* value); - // Copies the string so that it is gauranteed to stick around - void setoptString(CURLoption option, const std::string& value); - - void slist_append(const char* str); - void setHeaders(); - - U32 report(CURLcode); - void getTransferInfo(LLCurl::TransferInfo* info); - - void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false); - - const char* getErrorBuffer(); - - std::stringstream& getInput() { return mInput; } - std::stringstream& getHeaderOutput() { return mHeaderOutput; } - LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } - const LLChannelDescriptors& getChannels() { return mChannels; } - - void resetState(); - - static CURL* allocEasyHandle(); - static void releaseEasyHandle(CURL* handle); - -private: - friend class LLCurl; - - CURL* mCurlEasyHandle; - struct curl_slist* mHeaders; - - std::stringstream mRequest; - LLChannelDescriptors mChannels; - LLIOPipe::buffer_ptr_t mOutput; - std::stringstream mInput; - std::stringstream mHeaderOutput; - char mErrorBuffer[CURL_ERROR_SIZE]; - - // Note: char*'s not strings since we pass pointers to curl - std::vector<char*> mStrings; - - ResponderPtr mResponder; - - static std::set<CURL*> sFreeHandles; - static std::set<CURL*> sActiveHandles; - static LLMutex* sHandleMutex; -}; - std::set<CURL*> LLCurl::Easy::sFreeHandles; std::set<CURL*> LLCurl::Easy::sActiveHandles; LLMutex* LLCurl::Easy::sHandleMutex = NULL; @@ -409,11 +342,11 @@ const char* LLCurl::Easy::getErrorBuffer() void LLCurl::Easy::setCA() { - if(!sCAPath.empty()) + if (!sCAPath.empty()) { setoptString(CURLOPT_CAPATH, sCAPath); } - if(!sCAFile.empty()) + if (!sCAFile.empty()) { setoptString(CURLOPT_CAINFO, sCAFile); } @@ -536,9 +469,12 @@ void LLCurl::Easy::prepRequest(const std::string& url, if (post) setoptString(CURLOPT_ENCODING, ""); - //setopt(CURLOPT_VERBOSE, 1); // usefull for debugging + //setopt(CURLOPT_VERBOSE, 1); // useful for debugging setopt(CURLOPT_NOSIGNAL, 1); + // Set the CURL options for either Socks or HTTP proxy + LLProxy::getInstance()->applyProxySettings(this); + mOutput.reset(new LLBufferArray); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); @@ -550,7 +486,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, setopt(CURLOPT_HEADERDATA, (void*)this); // Allow up to five redirects - if(responder && responder->followRedir()) + if (responder && responder->followRedir()) { setopt(CURLOPT_FOLLOWLOCATION, 1); setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -563,7 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, //don't verify host name so urls with scrubbed host names will work (improves DNS performance) setopt(CURLOPT_SSL_VERIFYHOST, 0); - setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); + setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); setoptString(CURLOPT_URL, url); @@ -584,56 +520,6 @@ void LLCurl::Easy::prepRequest(const std::string& url, //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi : public LLThread -{ - LOG_CLASS(Multi); -public: - - typedef enum - { - PERFORM_STATE_READY=0, - PERFORM_STATE_PERFORMING=1, - PERFORM_STATE_COMPLETED=2 - } ePerformState; - - Multi(); - ~Multi(); - - Easy* allocEasy(); - bool addEasy(Easy* easy); - - void removeEasy(Easy* easy); - - S32 process(); - void perform(); - void doPerform(); - - virtual void run(); - - CURLMsg* info_read(S32* msgs_in_queue); - - S32 mQueued; - S32 mErrorCount; - - S32 mPerformState; - - LLCondition* mSignal; - bool mQuitting; - bool mThreaded; - -private: - void easyFree(Easy*); - - CURLM* mCurlMultiHandle; - - typedef std::set<Easy*> easy_active_list_t; - easy_active_list_t mEasyActiveList; - typedef std::map<CURL*, Easy*> easy_active_map_t; - easy_active_map_t mEasyActiveMap; - typedef std::set<Easy*> easy_free_list_t; - easy_free_list_t mEasyFreeList; -}; - LLCurl::Multi::Multi() : LLThread("Curl Multi"), mQueued(0), @@ -1071,6 +957,8 @@ LLCurlEasyRequest::LLCurlEasyRequest() { mEasy->setErrorBuffer(); mEasy->setCA(); + // Set proxy settings if configured to do so. + LLProxy::getInstance()->applyProxySettings(mEasy); } } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index f7518c8e5c..5ab4dc35b9 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -187,6 +187,122 @@ private: static const unsigned int MAX_REDIRECTS; }; +class LLCurl::Easy +{ + LOG_CLASS(Easy); + +private: + Easy(); + +public: + static Easy* getEasy(); + ~Easy(); + + CURL* getCurlHandle() const { return mCurlEasyHandle; } + + void setErrorBuffer(); + void setCA(); + + void setopt(CURLoption option, S32 value); + // These assume the setter does not free value! + void setopt(CURLoption option, void* value); + void setopt(CURLoption option, char* value); + // Copies the string so that it is guaranteed to stick around + void setoptString(CURLoption option, const std::string& value); + + void slist_append(const char* str); + void setHeaders(); + + U32 report(CURLcode); + void getTransferInfo(LLCurl::TransferInfo* info); + + void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false); + + const char* getErrorBuffer(); + + std::stringstream& getInput() { return mInput; } + std::stringstream& getHeaderOutput() { return mHeaderOutput; } + LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } + const LLChannelDescriptors& getChannels() { return mChannels; } + + void resetState(); + + static CURL* allocEasyHandle(); + static void releaseEasyHandle(CURL* handle); + +private: + friend class LLCurl; + + CURL* mCurlEasyHandle; + struct curl_slist* mHeaders; + + std::stringstream mRequest; + LLChannelDescriptors mChannels; + LLIOPipe::buffer_ptr_t mOutput; + std::stringstream mInput; + std::stringstream mHeaderOutput; + char mErrorBuffer[CURL_ERROR_SIZE]; + + // Note: char*'s not strings since we pass pointers to curl + std::vector<char*> mStrings; + + ResponderPtr mResponder; + + static std::set<CURL*> sFreeHandles; + static std::set<CURL*> sActiveHandles; + static LLMutex* sHandleMutex; +}; + +class LLCurl::Multi : public LLThread +{ + LOG_CLASS(Multi); +public: + + typedef enum + { + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 + } ePerformState; + + Multi(); + ~Multi(); + + Easy* allocEasy(); + bool addEasy(Easy* easy); + + void removeEasy(Easy* easy); + + S32 process(); + void perform(); + void doPerform(); + + virtual void run(); + + CURLMsg* info_read(S32* msgs_in_queue); + + S32 mQueued; + S32 mErrorCount; + + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + bool mThreaded; + +private: + void easyFree(Easy*); + + CURLM* mCurlMultiHandle; + + typedef std::set<Easy*> easy_active_list_t; + easy_active_list_t mEasyActiveList; + typedef std::map<CURL*, Easy*> easy_active_map_t; + easy_active_map_t mEasyActiveMap; + typedef std::set<Easy*> easy_free_list_t; + easy_free_list_t mEasyFreeList; +}; + namespace boost { void intrusive_ptr_add_ref(LLCurl::Responder* p); @@ -243,6 +359,8 @@ public: bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); + LLCurl::Easy* getEasy() const { return mEasy; } + private: CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info); @@ -253,4 +371,7 @@ private: bool mResultReturned; }; +void check_curl_code(CURLcode code); +void check_curl_multi_code(CURLMcode code); + #endif // LL_LLCURL_H diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 5a38b7fd9f..2bca517e97 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -33,6 +33,7 @@ #include "indra_constants.h" #include "message.h" +#include "llproxy.h" #include "llvfile.h" #include "llvfs.h" @@ -232,6 +233,10 @@ void LLHTTPAssetRequest::setupCurlHandle() { // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC mCurlHandle = curl_easy_init(); + + // Apply proxy settings if configured to do so + LLProxy::getInstance()->applyProxySettings(mCurlHandle); + curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0e5206a520..dd4e3a6300 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -428,6 +428,9 @@ static LLSD blocking_request( std::string body_str; // other request method checks root cert first, we skip? + + // Apply configured proxy settings + LLProxy::getInstance()->applyProxySettings(curlp); // * Set curl handle options curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts @@ -436,7 +439,7 @@ static LLSD blocking_request( curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - + // * Setup headers (don't forget to free them after the call!) curl_slist* headers_list = NULL; if (headers.isMap()) diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index b717e321bf..ee9379f205 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -251,10 +251,12 @@ LLSocket::~LLSocket() { ll_debug_socket("Destroying socket", mSocket); apr_socket_close(mSocket); + mSocket = NULL; } if(mPool) { apr_pool_destroy(mPool); + mPool = NULL; } } diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index e0f6c1e34d..be0f7dfcc6 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -145,13 +145,6 @@ public: */ apr_socket_t* getSocket() const { return mSocket; } -protected: - /** - * @brief Protected constructor since should only make sockets - * with one of the two <code>create()</code> calls. - */ - LLSocket(apr_socket_t* socket, apr_pool_t* pool); - /** * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us. * @param timeout Number of microseconds to wait on this socket. Any @@ -164,6 +157,13 @@ protected: */ void setNonBlocking(); +protected: + /** + * @brief Protected constructor since should only make sockets + * with one of the two <code>create()</code> calls. + */ + LLSocket(apr_socket_t* socket, apr_pool_t* pool); + public: /** * @brief Do not call this directly. diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8999dec64a..7628984de4 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -28,11 +28,20 @@ #include "llpacketring.h" +#if LL_WINDOWS + #include <winsock2.h> +#else + #include <sys/socket.h> + #include <netinet/in.h> +#endif + // linden library includes #include "llerror.h" #include "lltimer.h" -#include "timing.h" +#include "llproxy.h" #include "llrand.h" +#include "message.h" +#include "timing.h" #include "u64.h" /////////////////////////////////////////////////////////// @@ -216,8 +225,32 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) else { // no delay, pull straight from net - packet_size = receive_packet(socket, datap); - mLastSender = ::get_sender(); + if (LLProxy::isSOCKSProxyEnabled()) + { + U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer)); + + if (packet_size > SOCKS_HEADER_SIZE) + { + // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) + memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); + proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer); + mLastSender.setAddress(header->addr); + mLastSender.setPort(ntohs(header->port)); + + packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size + } + else + { + packet_size = 0; + } + } + else + { + packet_size = receive_packet(socket, datap); + mLastSender = ::get_sender(); + } + mLastReceivingIF = ::get_receiving_interface(); if (packet_size) // did we actually get a packet? @@ -243,7 +276,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL BOOL status = TRUE; if (!mUseOutThrottle) { - return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + return sendPacketImpl(h_socket, send_buffer, buf_size, host ); } else { @@ -264,7 +297,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL mOutBufferLength -= packetp->getSize(); packet_size = packetp->getSize(); - status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); + status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost()); delete packetp; // Update the throttle @@ -273,7 +306,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL else { // If the queue's empty, we can just send this packet right away. - status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + status = sendPacketImpl(h_socket, send_buffer, buf_size, host ); packet_size = buf_size; // Update the throttle @@ -311,3 +344,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL return status; } + +BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +{ + + if (!LLProxy::isSOCKSProxyEnabled()) + { + return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); + } + + proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer); + socks_header->rsv = 0; + socks_header->addr = host.getAddress(); + socks_header->port = htons(host.getPort()); + socks_header->atype = ADDRESS_IPV4; + socks_header->frag = 0; + + memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + + return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); +} diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index e6409d2048..7edcc834db 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -30,11 +30,11 @@ #include <queue> -#include "llpacketbuffer.h" #include "llhost.h" -#include "net.h" +#include "llpacketbuffer.h" +#include "llproxy.h" #include "llthrottle.h" - +#include "net.h" class LLPacketRing { @@ -82,6 +82,12 @@ protected: LLHost mLastSender; LLHost mLastReceivingIF; + + + U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + +private: + BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp new file mode 100644 index 0000000000..3f4a6accbf --- /dev/null +++ b/indra/llmessage/llproxy.cpp @@ -0,0 +1,551 @@ +/** + * @file llproxy.cpp + * @brief UDP and HTTP proxy communications + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llproxy.h" + +#include <string> +#include <curl/curl.h> + +#include "llapr.h" +#include "llcurl.h" +#include "llhost.h" + +// Static class variable instances + +// We want this to be static to avoid excessive indirection on every +// incoming packet just to do a simple bool test. The getter for this +// member is also static +bool LLProxy::sUDPProxyEnabled = false; + +// Some helpful TCP static functions. +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host); // Open a TCP channel to a given host +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel + +LLProxy::LLProxy(): + mHTTPProxyEnabled(false), + mProxyMutex(0), + mUDPProxy(), + mTCPProxy(), + mPool(gAPRPoolp), + mHTTPProxy(), + mProxyType(LLPROXY_SOCKS), + mAuthMethodSelected(METHOD_NOAUTH), + mSocksUsername(), + mSocksPassword() +{ +} + +LLProxy::~LLProxy() +{ + stopSOCKSProxy(); + sUDPProxyEnabled = false; + mHTTPProxyEnabled = false; +} + +/** + * @brief Open the SOCKS 5 TCP control channel. + * + * Perform a SOCKS 5 authentication and UDP association to the proxy server. + * + * @param proxy The SOCKS 5 server to connect to. + * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h. + */ +S32 LLProxy::proxyHandshake(LLHost proxy) +{ + S32 result; + + /* SOCKS 5 Auth request */ + socks_auth_request_t socks_auth_request; + socks_auth_response_t socks_auth_response; + + socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5 + socks_auth_request.num_methods = 1; // Sending 1 method. + socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method. + + result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); + if (result != APR_SUCCESS) + { + LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) + { + LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_NOT_ACCEPTABLE; + } + + // SOCKS 5 USERNAME/PASSWORD authentication + if (socks_auth_response.method == METHOD_PASSWORD) + { + // The server has requested a username/password combination + std::string socks_username(getSocksUser()); + std::string socks_password(getSocksPwd()); + U32 request_size = socks_username.size() + socks_password.size() + 3; + char * password_auth = new char[request_size]; + password_auth[0] = 0x01; + password_auth[1] = socks_username.size(); + memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); + password_auth[socks_username.size() + 2] = socks_password.size(); + memcpy(&password_auth[socks_username.size()+3], socks_password.c_str(), socks_password.size()); + + authmethod_password_reply_t password_reply; + + result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); + delete[] password_auth; + + if (result != APR_SUCCESS) + { + LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (password_reply.status != AUTH_SUCCESS) + { + LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_AUTH_FAIL; + } + } + + /* SOCKS5 connect request */ + + socks_command_request_t connect_request; + socks_command_response_t connect_reply; + + connect_request.version = SOCKS_VERSION; // SOCKS V5 + connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP + connect_request.reserved = FIELD_RESERVED; + connect_request.atype = ADDRESS_IPV4; + connect_request.address = htonl(0); // 0.0.0.0 + connect_request.port = htons(0); // 0 + // "If the client is not in possession of the information at the time of the UDP ASSOCIATE, + // the client MUST use a port number and address of all zeros. RFC 1928" + + result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); + if (result != APR_SUCCESS) + { + LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (connect_reply.reply != REPLY_REQUEST_GRANTED) + { + LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL; + stopSOCKSProxy(); + return SOCKS_UDP_FWD_NOT_GRANTED; + } + + mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order + mUDPProxy.setAddress(proxy.getAddress()); + // The connection was successful. We now have the UDP port to send requests that need forwarding to. + LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; + return SOCKS_OK; +} + +/** + * @brief Initiates a SOCKS 5 proxy session. + * + * Performs basic checks on host to verify that it is a valid address. Opens the control channel + * and then negotiates the proxy connection with the server. + * + * + * @param host Socks server to connect to. + * @return SOCKS_OK if successful, otherwise a SOCKS error code defined in llproxy.h. + */ +S32 LLProxy::startSOCKSProxy(LLHost host) +{ + S32 status = SOCKS_OK; + + if (host.isOk()) + { + mTCPProxy = host; + } + else + { + status = SOCKS_INVALID_HOST; + } + + if (mProxyControlChannel && status == SOCKS_OK) + { + tcp_close_channel(&mProxyControlChannel); + } + + if (status == SOCKS_OK) + { + mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); + if (!mProxyControlChannel) + { + status = SOCKS_HOST_CONNECT_FAILED; + } + } + + if (status == SOCKS_OK) + { + status = proxyHandshake(mTCPProxy); + } + if (status == SOCKS_OK) + { + sUDPProxyEnabled = true; + } + else + { + stopSOCKSProxy(); + } + return status; +} + +/** + * @brief Stop using the SOCKS 5 proxy. + * + * This will stop sending UDP packets through the SOCKS 5 proxy + * and will also stop the HTTP proxy if it is configured to use SOCKS. + * The proxy control channel will also be disconnected. + */ +void LLProxy::stopSOCKSProxy() +{ + sUDPProxyEnabled = false; + + // If the SOCKS proxy is requested to stop and we are using that for HTTP as well + // then we must shut down any HTTP proxy operations. But it is allowable if web + // proxy is being used to continue proxying HTTP. + + if (LLPROXY_SOCKS == getHTTPProxyType()) + { + void disableHTTPProxy(); + } + + if (mProxyControlChannel) + { + tcp_close_channel(&mProxyControlChannel); + } +} + +/** + * @brief Set the proxy's SOCKS authentication method to none. + */ +void LLProxy::setAuthNone() +{ + LLMutexLock lock(&mProxyMutex); + + mAuthMethodSelected = METHOD_NOAUTH; +} + +/** + * @brief Set the proxy's SOCKS authentication method to password. + * + * Check whether the lengths of the supplied username + * and password conform to the lengths allowed by the + * SOCKS protocol. + * + * @param username The SOCKS username to send. + * @param password The SOCKS password to send. + * @return Return true if applying the settings was successful. No changes are made if false. + * + */ +bool LLProxy::setAuthPassword(const std::string &username, const std::string &password) +{ + if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN || + username.length() < SOCKSMINUSERNAMELEN || password.length() < SOCKSMINPASSWORDLEN) + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 password or username length." << LL_ENDL; + return false; + } + + LLMutexLock lock(&mProxyMutex); + + mAuthMethodSelected = METHOD_PASSWORD; + mSocksUsername = username; + mSocksPassword = password; + + return true; +} + +/** + * @brief Enable the HTTP proxy for either SOCKS or HTTP. + * + * Check the supplied host to see if it is a valid IP and port. + * + * @param httpHost Proxy server to connect to. + * @param type Is the host a SOCKS or HTTP proxy. + * @return Return true if applying the setting was successful. No changes are made if false. + */ +bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{ + if (!httpHost.isOk()) + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL; + return false; + } + + LLMutexLock lock(&mProxyMutex); + + mHTTPProxy = httpHost; + mProxyType = type; + + mHTTPProxyEnabled = true; + + return true; +} + +/** + * @brief Enable the HTTP proxy without changing the proxy settings. + * + * This should not be called unless the proxy has already been set up. + * + * @return Return true only if the current settings are valid and the proxy was enabled. + */ +bool LLProxy::enableHTTPProxy() +{ + bool ok; + + LLMutexLock lock(&mProxyMutex); + + ok = (mHTTPProxy.isOk()); + if (ok) + { + mHTTPProxyEnabled = true; + } + + return ok; +} + +/** + * @brief Disable the HTTP proxy. + */ +void LLProxy::disableHTTPProxy() +{ + LLMutexLock lock(&mProxyMutex); + + mHTTPProxyEnabled = false; +} + +/** + * @brief Get the HTTP proxy address and port + */ +// +LLHost LLProxy::getHTTPProxy() const +{ + LLMutexLock lock(&mProxyMutex); + return mHTTPProxy; +} + +/** + * @brief Get the currently selected HTTP proxy type + */ +LLHttpProxyType LLProxy::getHTTPProxyType() const +{ + LLMutexLock lock(&mProxyMutex); + return mProxyType; +} + +/** + * @brief Get the SOCKS 5 password. + */ +std::string LLProxy::getSocksPwd() const +{ + LLMutexLock lock(&mProxyMutex); + return mSocksPassword; +} + +/** + * @brief Get the SOCKS 5 username. + */ +std::string LLProxy::getSocksUser() const +{ + LLMutexLock lock(&mProxyMutex); + return mSocksUsername; +} + +/** + * @brief Get the currently selected SOCKS 5 authentication method. + * + * @return Returns either none or password. + */ +LLSocks5AuthType LLProxy::getSelectedAuthMethod() const +{ + LLMutexLock lock(&mProxyMutex); + return mAuthMethodSelected; +} + +/** + * @brief Stop the LLProxy and make certain that any APR pools and classes are deleted before terminating APR. + * + * Deletes the LLProxy singleton, destroying the APR pool used by the control channel as well as . + */ +//static +void LLProxy::cleanupClass() +{ + getInstance()->stopSOCKSProxy(); + deleteSingleton(); +} + +void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) +{ + applyProxySettings(handle->getEasy()); +} + +void LLProxy::applyProxySettings(LLCurl::Easy* handle) +{ + applyProxySettings(handle->getCurlHandle()); +} + +/** + * @brief Apply proxy settings to a CuRL request if an HTTP proxy is enabled. + * + * This method has been designed to be safe to call from + * any thread in the viewer. This allows requests in the + * texture fetch thread to be aware of the proxy settings. + * When the HTTP proxy is enabled, the proxy mutex will + * be locked every time this method is called. + * + * @param handle A pointer to a valid CURL request, before it has been performed. + */ +void LLProxy::applyProxySettings(CURL* handle) +{ + // Do a faster unlocked check to see if we are supposed to proxy. + if (mHTTPProxyEnabled) + { + // We think we should proxy, lock the proxy mutex. + LLMutexLock lock(&mProxyMutex); + // Now test again to verify that the proxy wasn't disabled between the first check and the lock. + if (mHTTPProxyEnabled) + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + + if (mProxyType == LLPROXY_SOCKS) + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + if (mAuthMethodSelected == METHOD_PASSWORD) + { + std::string auth_string = mSocksUsername + ":" + mSocksPassword; + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); + } + } + else + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); + } + } + } +} + +/** + * @brief Send one TCP packet and receive one in return. + * + * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking + * operation would impact the operation of the viewer. + * + * @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP. + * @param dataout Data to send. + * @param outlen Length of dataout. + * @param datain Buffer for received data. Undefined if return value is not APR_SUCCESS. + * @param maxinlen Maximum possible length of received data. Short reads are allowed. + * @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received. + */ +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +{ + apr_socket_t* apr_socket = handle->getSocket(); + apr_status_t rv = APR_SUCCESS; + + apr_size_t expected_len = outlen; + + handle->setBlocking(1000); + + rv = apr_socket_send(apr_socket, dataout, &outlen); + if (APR_SUCCESS != rv) + { + LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << LL_ENDL; + ll_apr_warn_status(rv); + } + else if (expected_len != outlen) + { + LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len << + " Sent: " << outlen << LL_ENDL; + rv = -1; + } + + if (APR_SUCCESS == rv) + { + expected_len = maxinlen; + rv = apr_socket_recv(apr_socket, datain, &maxinlen); + if (rv != APR_SUCCESS) + { + LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; + ll_apr_warn_status(rv); + } + else if (expected_len < maxinlen) + { + LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len << + " Received: " << maxinlen << LL_ENDL; + rv = -1; + } + } + + handle->setNonBlocking(); + + return rv; +} + +/** + * @brief Open a LLSocket and do a blocking connect to the chosen host. + * + * Checks for a successful connection, and makes sure the connection is closed if it fails. + * + * @param pool APR pool to pass into the LLSocket. + * @param host The host to open the connection to. + * @return The created socket. Will evaluate as NULL if the connection is unsuccessful. + */ +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) +{ + LLSocket::ptr_t socket = LLSocket::create(pool, LLSocket::STREAM_TCP); + bool connected = socket->blockingConnect(host); + if (!connected) + { + tcp_close_channel(&socket); + } + + return socket; +} + +/** + * @brief Close the socket. + * + * @param handle_ptr A pointer-to-pointer to avoid increasing the use count. + */ +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) +{ + LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL; + handle_ptr->reset(); +} diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h new file mode 100644 index 0000000000..29e7e28567 --- /dev/null +++ b/indra/llmessage/llproxy.h @@ -0,0 +1,342 @@ +/** + * @file llproxy.h + * @brief UDP and HTTP proxy communications + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PROXY_H +#define LL_PROXY_H + +#include "llcurl.h" +#include "llhost.h" +#include "lliosocket.h" +#include "llmemory.h" +#include "llsingleton.h" +#include "llthread.h" +#include <string> + +// SOCKS error codes returned from the StartProxy method + +#define SOCKS_OK 0 +#define SOCKS_CONNECT_ERROR (-1) +#define SOCKS_NOT_PERMITTED (-2) +#define SOCKS_NOT_ACCEPTABLE (-3) +#define SOCKS_AUTH_FAIL (-4) +#define SOCKS_UDP_FWD_NOT_GRANTED (-5) +#define SOCKS_HOST_CONNECT_FAILED (-6) +#define SOCKS_INVALID_HOST (-7) + + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ +#endif + +#define SOCKSMAXUSERNAMELEN 255 +#define SOCKSMAXPASSWORDLEN 255 + +#define SOCKSMINUSERNAMELEN 1 +#define SOCKSMINPASSWORDLEN 1 + +#define SOCKS_VERSION 0x05 // we are using SOCKS 5 + +#define SOCKS_HEADER_SIZE 10 + +// SOCKS 5 address/hostname types +#define ADDRESS_IPV4 0x01 +#define ADDRESS_HOSTNAME 0x03 +#define ADDRESS_IPV6 0x04 + +// Lets just use our own ipv4 struct rather than dragging in system +// specific headers +union ipv4_address_t { + U8 octets[4]; + U32 addr32; +}; + +// SOCKS 5 control channel commands +#define COMMAND_TCP_STREAM 0x01 +#define COMMAND_TCP_BIND 0x02 +#define COMMAND_UDP_ASSOCIATE 0x03 + +// SOCKS 5 command replies +#define REPLY_REQUEST_GRANTED 0x00 +#define REPLY_GENERAL_FAIL 0x01 +#define REPLY_RULESET_FAIL 0x02 +#define REPLY_NETWORK_UNREACHABLE 0x03 +#define REPLY_HOST_UNREACHABLE 0x04 +#define REPLY_CONNECTION_REFUSED 0x05 +#define REPLY_TTL_EXPIRED 0x06 +#define REPLY_PROTOCOL_ERROR 0x07 +#define REPLY_TYPE_NOT_SUPPORTED 0x08 + +#define FIELD_RESERVED 0x00 + +// The standard SOCKS 5 request packet +// Push current alignment to stack and set alignment to 1 byte boundary +// This enabled us to use structs directly to set up and receive network packets +// into the correct fields, without fear of boundary alignment causing issues +#pragma pack(push,1) + +// SOCKS 5 command packet +struct socks_command_request_t { + U8 version; + U8 command; + U8 reserved; + U8 atype; + U32 address; + U16 port; +}; + +// Standard SOCKS 5 reply packet +struct socks_command_response_t { + U8 version; + U8 reply; + U8 reserved; + U8 atype; + U8 add_bytes[4]; + U16 port; +}; + +#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available +#define AUTH_SUCCESS 0x00 // reply if authentication successful + +// SOCKS 5 authentication request, stating which methods the client supports +struct socks_auth_request_t { + U8 version; + U8 num_methods; + U8 methods; // We are only using a single method currently +}; + +// SOCKS 5 authentication response packet, stating server preferred method +struct socks_auth_response_t { + U8 version; + U8 method; +}; + +// SOCKS 5 password reply packet +struct authmethod_password_reply_t { + U8 version; + U8 status; +}; + +// SOCKS 5 UDP packet header +struct proxywrap_t { + U16 rsv; + U8 frag; + U8 atype; + U32 addr; + U16 port; +}; + +#pragma pack(pop) /* restore original alignment from stack */ + + +// Currently selected HTTP proxy type +enum LLHttpProxyType +{ + LLPROXY_SOCKS = 0, + LLPROXY_HTTP = 1 +}; + +// Auth types +enum LLSocks5AuthType +{ + METHOD_NOAUTH = 0x00, // Client supports no auth + METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported) + METHOD_PASSWORD = 0x02 // Client supports username/password +}; + +/** + * @brief Manage SOCKS 5 UDP proxy and HTTP proxy. + * + * This class is responsible for managing two interconnected tasks, + * connecting to a SOCKS 5 proxy for use by LLPacketRing to send UDP + * packets and managing proxy settings for HTTP requests. + * + * <h1>Threading:</h1> + * Because HTTP requests can be generated in threads outside the + * main thread, it is necessary for some of the information stored + * by this class to be available to other threads. The members that + * need to be read across threads are in a labeled section below. + * To protect those members, a mutex, mProxyMutex should be locked + * before reading or writing those members. Methods that can lock + * mProxyMutex are in a labeled section below. Those methods should + * not be called while the mutex is already locked. + * + * There is also a LLAtomic type flag (mHTTPProxyEnabled) that is used + * to track whether the HTTP proxy is currently enabled. This allows + * for faster unlocked checks to see if the proxy is enabled. This + * allows us to cut down on the performance hit when the proxy is + * disabled compared to before this class was introduced. + * + * <h1>UDP Proxying:</h1> + * UDP datagrams are proxied via a SOCKS 5 proxy with the UDP associate + * command. To initiate the proxy, a TCP socket connection is opened + * to the SOCKS 5 host, and after a handshake exchange, the server + * returns a port and address to send the UDP traffic that is to be + * proxied to. The LLProxy class tracks this address and port after the + * exchange and provides it to LLPacketRing when required to. All UDP + * proxy management occurs in the main thread. + * + * <h1>HTTP Proxying:</h1> + * This class allows all viewer HTTP packets to be sent through a proxy. + * The user can select whether to send HTTP packets through a standard + * "web" HTTP proxy, through a SOCKS 5 proxy, or to not proxy HTTP + * communication. This class does not manage the integrated web browser + * proxy, which is handled in llviewermedia.cpp. + * + * The implementation of HTTP proxying is handled by libcurl. LLProxy + * is responsible for managing the HTTP proxy options and provides a + * thread-safe method to apply those options to a curl request + * (LLProxy::applyProxySettings()). This method is overloaded + * to accommodate the various abstraction libcurl layers that exist + * throughout the viewer (LLCurlEasyRequest, LLCurl::Easy, and CURL). + * + * If you are working with LLCurl or LLCurlEasyRequest objects, + * the configured proxy settings will be applied in the constructors + * of those request handles. If you are working with CURL objects + * directly, you will need to pass the handle of the request to + * applyProxySettings() before issuing the request. + * + * To ensure thread safety, all LLProxy members that relate to the HTTP + * proxy require the LLProxyMutex to be locked before accessing. + */ +class LLProxy: public LLSingleton<LLProxy> +{ + LOG_CLASS(LLProxy); +public: + // METHODS THAT DO NOT LOCK mProxyMutex! + + LLProxy(); + + // static check for enabled status for UDP packets + static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } + + // check for enabled status for HTTP packets + // mHTTPProxyEnabled is atomic, so no locking is required for thread safety. + bool isHTTPProxyEnabled() const { return mHTTPProxyEnabled; } + + // Get the UDP proxy address and port + LLHost getUDPProxy() const { return mUDPProxy; } + + // Get the SOCKS 5 TCP control channel address and port + LLHost getTCPProxy() const { return mTCPProxy; } + + // END OF NON-LOCKING METHODS + + // METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + + ~LLProxy(); + + // Start a connection to the SOCKS 5 proxy + S32 startSOCKSProxy(LLHost host); + + // Disconnect and clean up any connection to the SOCKS 5 proxy + void stopSOCKSProxy(); + + // Delete LLProxy singleton, destroying the APR pool used by the control channel. + static void cleanupClass(); + + // Set up to use Password auth when connecting to the SOCKS proxy + bool setAuthPassword(const std::string &username, const std::string &password); + + // Set up to use No Auth when connecting to the SOCKS proxy + void setAuthNone(); + + // Get the currently selected auth method. + LLSocks5AuthType getSelectedAuthMethod() const; + + // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy + // as specified in type + bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); + bool enableHTTPProxy(); + + // Stop proxying HTTP packets + void disableHTTPProxy(); + + // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. + void applyProxySettings(CURL* handle); + void applyProxySettings(LLCurl::Easy* handle); + void applyProxySettings(LLCurlEasyRequest* handle); + + // Get the HTTP proxy address and port + LLHost getHTTPProxy() const; + + // Get the currently selected HTTP proxy type + LLHttpProxyType getHTTPProxyType() const; + + std::string getSocksPwd() const; + std::string getSocksUser() const; + + // END OF LOCKING METHODS +private: + // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort + S32 proxyHandshake(LLHost proxy); + +private: + // Is the HTTP proxy enabled? + // Safe to read in any thread, do not write directly, + // use enableHTTPProxy() and disableHTTPProxy() instead. + mutable LLAtomic32<bool> mHTTPProxyEnabled; + + // Mutex to protect shared members in non-main thread calls to applyProxySettings() + mutable LLMutex mProxyMutex; + + // MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE! + + // Is the UDP proxy enabled? + static bool sUDPProxyEnabled; + + // UDP proxy address and port + LLHost mUDPProxy; + // TCP proxy control channel address and port + LLHost mTCPProxy; + + // socket handle to proxy TCP control channel + LLSocket::ptr_t mProxyControlChannel; + + // APR pool for the socket + apr_pool_t* mPool; + + // END OF UNSHARED MEMBERS + + // MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex! + + // HTTP proxy address and port + LLHost mHTTPProxy; + + // Currently selected HTTP proxy type. Can be web or socks. + LLHttpProxyType mProxyType; + + // SOCKS 5 auth method selected + LLSocks5AuthType mAuthMethodSelected; + + // SOCKS 5 username + std::string mSocksUsername; + // SOCKS 5 password + std::string mSocksPassword; + + // END OF SHARED MEMBERS +}; + +#endif diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index e8e35d00a2..d5400e4169 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -35,6 +35,7 @@ #include "llcurl.h" #include "llioutil.h" #include "llmemtype.h" +#include "llproxy.h" #include "llpumpio.h" #include "llsd.h" #include "llstring.h" @@ -227,8 +228,7 @@ void LLURLRequest::useProxy(bool use_proxy) } } - - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; + LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL; if (env_proxy && use_proxy) { diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 97611c3b51..85aef5da00 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -50,7 +50,6 @@ #include "lltimer.h" #include "indra_constants.h" - // Globals #if LL_WINDOWS @@ -174,7 +173,7 @@ U32 ip_string_to_u32(const char* ip_string) // use wildcard addresses. -Ambroff U32 ip = inet_addr(ip_string); if (ip == INADDR_NONE - && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) + && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) { llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << llendl; return INVALID_HOST_IP_ADDRESS; @@ -188,11 +187,11 @@ U32 ip_string_to_u32(const char* ip_string) ////////////////////////////////////////////////////////////////////////////////////////// #if LL_WINDOWS - + S32 start_net(S32& socket_out, int& nPort) { // Create socket, make non-blocking - // Init WinSock + // Init WinSock int nRet; int hSocket; @@ -201,7 +200,7 @@ S32 start_net(S32& socket_out, int& nPort) int buff_size = 4; // Initialize windows specific stuff - if(WSAStartup(0x0202, &stWSAData)) + if (WSAStartup(0x0202, &stWSAData)) { S32 err = WSAGetLastError(); WSACleanup(); @@ -210,8 +209,8 @@ S32 start_net(S32& socket_out, int& nPort) } // Get a datagram socket - hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); - if (hSocket == INVALID_SOCKET) + hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); + if (hSocket == INVALID_SOCKET) { S32 err = WSAGetLastError(); WSACleanup(); @@ -304,7 +303,7 @@ S32 start_net(S32& socket_out, int& nPort) // Setup a destination address stDstAddr.sin_family = AF_INET; stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS; - stDstAddr.sin_port = htons(nPort); + stDstAddr.sin_port = htons(nPort); socket_out = hSocket; return 0; @@ -393,10 +392,10 @@ S32 start_net(S32& socket_out, int& nPort) int rec_size = RECEIVE_BUFFER_SIZE; socklen_t buff_size = 4; - + // Create socket - hSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (hSocket < 0) + hSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (hSocket < 0) { llwarns << "socket() failed" << llendl; return 1; @@ -429,7 +428,7 @@ S32 start_net(S32& socket_out, int& nPort) } else { - // Name the socket (assign the local port number to receive on) + // Name the socket (assign the local port number to receive on) stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = htons(nPort); @@ -474,7 +473,7 @@ S32 start_net(S32& socket_out, int& nPort) nPort = attempt_port; } // Set socket to be non-blocking - fcntl(hSocket, F_SETFL, O_NONBLOCK); + fcntl(hSocket, F_SETFL, O_NONBLOCK); // set a large receive buffer nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size); if (nRet) @@ -510,8 +509,8 @@ S32 start_net(S32& socket_out, int& nPort) // Setup a destination address char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; - stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); - stDstAddr.sin_port = htons(nPort); + stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); + stDstAddr.sin_port = htons(nPort); socket_out = hSocket; return 0; @@ -537,7 +536,7 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro iov[0].iov_base = buf; iov[0].iov_len = len; - memset( &msg, 0, sizeof msg ); + memset(&msg, 0, sizeof msg); msg.msg_name = from; msg.msg_namelen = *fromlen; msg.msg_iov = iov; @@ -545,14 +544,14 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro msg.msg_control = &cmsg; msg.msg_controllen = sizeof(cmsg); - size = recvmsg( socket, &msg, 0 ); + size = recvmsg(socket, &msg, 0); - if( size == -1 ) + if (size == -1) { return -1; } - for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr)) { if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO ) { @@ -650,7 +649,7 @@ BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient, } } } - while ( resend && send_attempts < 3); + while (resend && send_attempts < 3); if (send_attempts >= 3) { diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9f4f5c5821..0f2437479d 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -46,10 +46,10 @@ S32 receive_packet(int hSocket, char * receiveBuffer); BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort); // Returns TRUE on success. //void get_sender(char * tmp); -LLHost get_sender(); +LLHost get_sender(); U32 get_sender_port(); U32 get_sender_ip(void); -LLHost get_receiving_interface(); +LLHost get_receiving_interface(); U32 get_receiving_interface_ip(void); const char* u32_to_ip_string(U32 ip); // Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index d081109acc..9cd3216ab2 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1,1424 +1,1445 @@ -/** - * @file llpluginclassmedia.cpp - * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class. - * - * @cond - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "linden_common.h" -#include "indra_constants.h" - -#include "llpluginclassmedia.h" -#include "llpluginmessageclasses.h" - -#include "llqtwebkit.h" - -static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256; - -static int nextPowerOf2( int value ) -{ - int next_power_of_2 = 1; - while ( next_power_of_2 < value ) - { - next_power_of_2 <<= 1; - } - - return next_power_of_2; -} - -LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) -{ - mOwner = owner; - mPlugin = NULL; - reset(); - - //debug use - mDeleteOK = true ; -} - - -LLPluginClassMedia::~LLPluginClassMedia() -{ - llassert_always(mDeleteOK) ; - reset(); -} - -bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug) -{ - LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; - LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL; - LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; - - mPlugin = new LLPluginProcessParent(this); - mPlugin->setSleepTime(mSleepTime); - - // Queue up the media init message -- it will be sent after all the currently queued messages. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init"); - message.setValue("target", mTarget); - sendMessage(message); - - mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug); - - return true; -} - - -void LLPluginClassMedia::reset() -{ - if(mPlugin != NULL) - { - delete mPlugin; - mPlugin = NULL; - } - - mTextureParamsReceived = false; - mRequestedTextureDepth = 0; - mRequestedTextureInternalFormat = 0; - mRequestedTextureFormat = 0; - mRequestedTextureType = 0; - mRequestedTextureSwapBytes = false; - mRequestedTextureCoordsOpenGL = false; - mTextureSharedMemorySize = 0; - mTextureSharedMemoryName.clear(); - mDefaultMediaWidth = 0; - mDefaultMediaHeight = 0; - mNaturalMediaWidth = 0; - mNaturalMediaHeight = 0; - mSetMediaWidth = -1; - mSetMediaHeight = -1; - mRequestedMediaWidth = 0; - mRequestedMediaHeight = 0; - mRequestedTextureWidth = 0; - mRequestedTextureHeight = 0; - mFullMediaWidth = 0; - mFullMediaHeight = 0; - mTextureWidth = 0; - mTextureHeight = 0; - mMediaWidth = 0; - mMediaHeight = 0; - mDirtyRect = LLRect::null; - mAutoScaleMedia = false; - mRequestedVolume = 1.0f; - mPriority = PRIORITY_NORMAL; - mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; - mAllowDownsample = false; - mPadding = 0; - mLastMouseX = 0; - mLastMouseY = 0; - mStatus = LLPluginClassMediaOwner::MEDIA_NONE; - mSleepTime = 1.0f / 100.0f; - mCanCut = false; - mCanCopy = false; - mCanPaste = false; - mMediaName.clear(); - mMediaDescription.clear(); - mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f); - - // media_browser class - mNavigateURI.clear(); - mNavigateResultCode = -1; - mNavigateResultString.clear(); - mHistoryBackAvailable = false; - mHistoryForwardAvailable = false; - mStatusText.clear(); - mProgressPercent = 0; - mClickURL.clear(); - mClickNavType.clear(); - mClickTarget.clear(); - mClickUUID.clear(); - mStatusCode = 0; - - // media_time class - mCurrentTime = 0.0f; - mDuration = 0.0f; - mCurrentRate = 0.0f; - mLoadedDuration = 0.0f; -} - -void LLPluginClassMedia::idle(void) -{ - if(mPlugin) - { - mPlugin->idle(); - } - - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL)) - { - // Can't process a size change at this time - } - else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight)) - { - // Calculate the correct size for the media texture - mRequestedTextureHeight = mRequestedMediaHeight; - if(mPadding < 0) - { - // negative values indicate the plugin wants a power of 2 - mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth); - } - else - { - mRequestedTextureWidth = mRequestedMediaWidth; - - if(mPadding > 1) - { - // Pad up to a multiple of the specified number of bytes per row - int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth; - int pad = rowbytes % mPadding; - if(pad != 0) - { - rowbytes += mPadding - pad; - } - - if(rowbytes % mRequestedTextureDepth == 0) - { - mRequestedTextureWidth = rowbytes / mRequestedTextureDepth; - } - else - { - LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL; - } - } - } - - - // Size change has been requested but not initiated yet. - size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth; - - // Add an extra line for padding, just in case. - newsize += mRequestedTextureWidth * mRequestedTextureDepth; - - if(newsize != mTextureSharedMemorySize) - { - if(!mTextureSharedMemoryName.empty()) - { - // Tell the plugin to remove the old memory segment - mPlugin->removeSharedMemory(mTextureSharedMemoryName); - mTextureSharedMemoryName.clear(); - } - - mTextureSharedMemorySize = newsize; - mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize); - if(!mTextureSharedMemoryName.empty()) - { - void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); - - // clear texture memory to avoid random screen visual fuzz from uninitialized texture data - memset( addr, 0x00, newsize ); - - // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, - // so it may not be worthwhile. - // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight); - } - } - - // This is our local indicator that a change is in progress. - mTextureWidth = -1; - mTextureHeight = -1; - mMediaWidth = -1; - mMediaHeight = -1; - - // This invalidates any existing dirty rect. - resetDirty(); - - // Send a size change message to the plugin - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change"); - message.setValue("name", mTextureSharedMemoryName); - message.setValueS32("width", mRequestedMediaWidth); - message.setValueS32("height", mRequestedMediaHeight); - message.setValueS32("texture_width", mRequestedTextureWidth); - message.setValueS32("texture_height", mRequestedTextureHeight); - message.setValueReal("background_r", mBackgroundColor.mV[VX]); - message.setValueReal("background_g", mBackgroundColor.mV[VY]); - message.setValueReal("background_b", mBackgroundColor.mV[VZ]); - message.setValueReal("background_a", mBackgroundColor.mV[VW]); - mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. - - LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; - } - } - - if(mPlugin && mPlugin->isRunning()) - { - // Send queued messages - while(!mSendQueue.empty()) - { - LLPluginMessage message = mSendQueue.front(); - mSendQueue.pop(); - mPlugin->sendMessage(message); - } - } -} - -int LLPluginClassMedia::getTextureWidth() const -{ - return nextPowerOf2(mTextureWidth); -} - -int LLPluginClassMedia::getTextureHeight() const -{ - return nextPowerOf2(mTextureHeight); -} - -unsigned char* LLPluginClassMedia::getBitsData() -{ - unsigned char *result = NULL; - if((mPlugin != NULL) && !mTextureSharedMemoryName.empty()) - { - result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); - } - return result; -} - -void LLPluginClassMedia::setSize(int width, int height) -{ - if((width > 0) && (height > 0)) - { - mSetMediaWidth = width; - mSetMediaHeight = height; - } - else - { - mSetMediaWidth = -1; - mSetMediaHeight = -1; - } - - setSizeInternal(); -} - -void LLPluginClassMedia::setSizeInternal(void) -{ - if((mSetMediaWidth > 0) && (mSetMediaHeight > 0)) - { - mRequestedMediaWidth = mSetMediaWidth; - mRequestedMediaHeight = mSetMediaHeight; - } - else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0)) - { - mRequestedMediaWidth = mNaturalMediaWidth; - mRequestedMediaHeight = mNaturalMediaHeight; - } - else - { - mRequestedMediaWidth = mDefaultMediaWidth; - mRequestedMediaHeight = mDefaultMediaHeight; - } - - // Save these for size/interest calculations - mFullMediaWidth = mRequestedMediaWidth; - mFullMediaHeight = mRequestedMediaHeight; - - if(mAllowDownsample) - { - switch(mPriority) - { - case PRIORITY_SLIDESHOW: - case PRIORITY_LOW: - // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit - while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) - { - mRequestedMediaWidth /= 2; - mRequestedMediaHeight /= 2; - } - break; - - default: - // Don't adjust texture size - break; - } - } - - if(mAutoScaleMedia) - { - mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth); - mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight); - } - - if(mRequestedMediaWidth > 2048) - mRequestedMediaWidth = 2048; - - if(mRequestedMediaHeight > 2048) - mRequestedMediaHeight = 2048; -} - -void LLPluginClassMedia::setAutoScale(bool auto_scale) -{ - if(auto_scale != mAutoScaleMedia) - { - mAutoScaleMedia = auto_scale; - setSizeInternal(); - } -} - -bool LLPluginClassMedia::textureValid(void) -{ - if( - !mTextureParamsReceived || - mTextureWidth <= 0 || - mTextureHeight <= 0 || - mMediaWidth <= 0 || - mMediaHeight <= 0 || - mRequestedMediaWidth != mMediaWidth || - mRequestedMediaHeight != mMediaHeight || - getBitsData() == NULL - ) - return false; - - return true; -} - -bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) -{ - bool result = !mDirtyRect.isEmpty(); - - if(dirty_rect != NULL) - { - *dirty_rect = mDirtyRect; - } - - return result; -} - -void LLPluginClassMedia::resetDirty(void) -{ - mDirtyRect = LLRect::null; -} - -std::string LLPluginClassMedia::translateModifiers(MASK modifiers) -{ - std::string result; - - - if(modifiers & MASK_CONTROL) - { - result += "control|"; - } - - if(modifiers & MASK_ALT) - { - result += "alt|"; - } - - if(modifiers & MASK_SHIFT) - { - result += "shift|"; - } - - // TODO: should I deal with platform differences here or in callers? - // TODO: how do we deal with the Mac "command" key? -/* - if(modifiers & MASK_SOMETHING) - { - result += "meta|"; - } -*/ - return result; -} - -void LLPluginClassMedia::jsEnableObject( bool enable ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object"); - message.setValueBoolean( "enable", enable ); - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location"); - message.setValueReal( "x", x ); - message.setValueReal( "y", y ); - message.setValueReal( "z", z ); - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location"); - message.setValueReal( "x", x ); - message.setValueReal( "y", y ); - message.setValueReal( "z", z ); - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentOrientationEvent( double angle ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation"); - message.setValueReal( "angle", angle ); - - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language"); - message.setValue( "language", language ); - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region"); - message.setValue( "region", region ); - sendMessage( message ); -} - -void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity ) -{ - if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) - { - return; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity"); - message.setValue( "maturity", maturity ); - sendMessage( message ); -} - -void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) -{ - if(type == MOUSE_EVENT_MOVE) - { - if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked()) - { - // Don't queue up mouse move events that can't be delivered. - return; - } - - if((x == mLastMouseX) && (y == mLastMouseY)) - { - // Don't spam unnecessary mouse move events. - return; - } - - mLastMouseX = x; - mLastMouseY = y; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event"); - std::string temp; - switch(type) - { - case MOUSE_EVENT_DOWN: temp = "down"; break; - case MOUSE_EVENT_UP: temp = "up"; break; - case MOUSE_EVENT_MOVE: temp = "move"; break; - case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break; - } - message.setValue("event", temp); - - message.setValueS32("button", button); - - message.setValueS32("x", x); - - // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it. - if(!mRequestedTextureCoordsOpenGL) - { - // TODO: Should I use mMediaHeight or mRequestedMediaHeight here? - y = mMediaHeight - y; - } - message.setValueS32("y", y); - - message.setValue("modifiers", translateModifiers(modifiers)); - - sendMessage(message); -} - -bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data) -{ - bool result = true; - - // FIXME: - // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode. - // For now, return false for the ones the webkit plugin won't handle properly. - - switch(key_code) - { - case KEY_BACKSPACE: - case KEY_TAB: - case KEY_RETURN: - case KEY_PAD_RETURN: - case KEY_SHIFT: - case KEY_CONTROL: - case KEY_ALT: - case KEY_CAPSLOCK: - case KEY_ESCAPE: - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_END: - case KEY_HOME: - case KEY_LEFT: - case KEY_UP: - case KEY_RIGHT: - case KEY_DOWN: - case KEY_INSERT: - case KEY_DELETE: - // These will be handled - break; - - default: - // regular ASCII characters will also be handled - if(key_code >= KEY_SPECIAL) - { - // Other "special" codes will not work properly. - result = false; - } - break; - } - -#if LL_DARWIN - if(modifiers & MASK_ALT) - { - // Option-key modified characters should be handled by the unicode input path instead of this one. - result = false; - } -#endif - - if(result) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); - std::string temp; - switch(type) - { - case KEY_EVENT_DOWN: temp = "down"; break; - case KEY_EVENT_UP: temp = "up"; break; - case KEY_EVENT_REPEAT: temp = "repeat"; break; - } - message.setValue("event", temp); - - message.setValueS32("key", key_code); - - message.setValue("modifiers", translateModifiers(modifiers)); - message.setValueLLSD("native_key_data", native_key_data); - - sendMessage(message); - } - - return result; -} - -void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event"); - - message.setValueS32("x", x); - message.setValueS32("y", y); - message.setValue("modifiers", translateModifiers(modifiers)); - - sendMessage(message); -} - -bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event"); - - message.setValue("text", text); - message.setValue("modifiers", translateModifiers(modifiers)); - message.setValueLLSD("native_key_data", native_key_data); - - sendMessage(message); - - return true; -} - -void LLPluginClassMedia::loadURI(const std::string &uri) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri"); - - message.setValue("uri", uri); - - sendMessage(message); -} - -const char* LLPluginClassMedia::priorityToString(EPriority priority) -{ - const char* result = "UNKNOWN"; - switch(priority) - { - case PRIORITY_UNLOADED: result = "unloaded"; break; - case PRIORITY_STOPPED: result = "stopped"; break; - case PRIORITY_HIDDEN: result = "hidden"; break; - case PRIORITY_SLIDESHOW: result = "slideshow"; break; - case PRIORITY_LOW: result = "low"; break; - case PRIORITY_NORMAL: result = "normal"; break; - case PRIORITY_HIGH: result = "high"; break; - } - - return result; -} - -void LLPluginClassMedia::setPriority(EPriority priority) -{ - if(mPriority != priority) - { - mPriority = priority; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority"); - - std::string priority_string = priorityToString(priority); - switch(priority) - { - case PRIORITY_UNLOADED: - mSleepTime = 1.0f; - break; - case PRIORITY_STOPPED: - mSleepTime = 1.0f; - break; - case PRIORITY_HIDDEN: - mSleepTime = 1.0f; - break; - case PRIORITY_SLIDESHOW: - mSleepTime = 1.0f; - break; - case PRIORITY_LOW: - mSleepTime = 1.0f / 25.0f; - break; - case PRIORITY_NORMAL: - mSleepTime = 1.0f / 50.0f; - break; - case PRIORITY_HIGH: - mSleepTime = 1.0f / 100.0f; - break; - } - - message.setValue("priority", priority_string); - - sendMessage(message); - - if(mPlugin) - { - mPlugin->setSleepTime(mSleepTime); - } - - LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; - - // This may affect the calculated size, so recalculate it here. - setSizeInternal(); - } -} - -void LLPluginClassMedia::setLowPrioritySizeLimit(int size) -{ - int power = nextPowerOf2(size); - if(mLowPrioritySizeLimit != power) - { - mLowPrioritySizeLimit = power; - - // This may affect the calculated size, so recalculate it here. - setSizeInternal(); - } -} - -F64 LLPluginClassMedia::getCPUUsage() -{ - F64 result = 0.0f; - - if(mPlugin) - { - result = mPlugin->getCPUUsage(); - } - - return result; -} - -void LLPluginClassMedia::sendPickFileResponse(const std::string &file) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response"); - message.setValue("file", file); - if(mPlugin && mPlugin->isBlocked()) - { - // If the plugin sent a blocking pick-file request, the response should unblock it. - message.setValueBoolean("blocking_response", true); - } - sendMessage(message); -} - -void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response"); - message.setValueBoolean("ok", ok); - message.setValue("username", username); - message.setValue("password", password); - if(mPlugin && mPlugin->isBlocked()) - { - // If the plugin sent a blocking pick-file request, the response should unblock it. - message.setValueBoolean("blocking_response", true); - } - sendMessage(message); -} - -void LLPluginClassMedia::cut() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); - sendMessage(message); -} - -void LLPluginClassMedia::copy() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy"); - sendMessage(message); -} - -void LLPluginClassMedia::paste() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste"); - sendMessage(message); -} - -void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); - message.setValue("path", user_data_path); - sendMessage(message); -} - -void LLPluginClassMedia::setLanguageCode(const std::string &language_code) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code"); - message.setValue("language", language_code); - sendMessage(message); -} - -void LLPluginClassMedia::setPluginsEnabled(const bool enabled) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled"); - message.setValueBoolean("enable", enabled); - sendMessage(message); -} - -void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled"); - message.setValueBoolean("enable", enabled); - sendMessage(message); -} - -void LLPluginClassMedia::setTarget(const std::string &target) -{ - mTarget = target; -} - -/* virtual */ -void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) -{ - std::string message_class = message.getClass(); - - if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - std::string message_name = message.getName(); - if(message_name == "texture_params") - { - mRequestedTextureDepth = message.getValueS32("depth"); - mRequestedTextureInternalFormat = message.getValueU32("internalformat"); - mRequestedTextureFormat = message.getValueU32("format"); - mRequestedTextureType = message.getValueU32("type"); - mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes"); - mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl"); - - // These two are optional, and will default to 0 if they're not specified. - mDefaultMediaWidth = message.getValueS32("default_width"); - mDefaultMediaHeight = message.getValueS32("default_height"); - - mAllowDownsample = message.getValueBoolean("allow_downsample"); - mPadding = message.getValueS32("padding"); - - setSizeInternal(); - - mTextureParamsReceived = true; - } - else if(message_name == "updated") - { - if(message.hasValue("left")) - { - LLRect newDirtyRect; - newDirtyRect.mLeft = message.getValueS32("left"); - newDirtyRect.mTop = message.getValueS32("top"); - newDirtyRect.mRight = message.getValueS32("right"); - newDirtyRect.mBottom = message.getValueS32("bottom"); - - // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion. - // If they're backwards, swap them. - if(newDirtyRect.mTop < newDirtyRect.mBottom) - { - S32 temp = newDirtyRect.mTop; - newDirtyRect.mTop = newDirtyRect.mBottom; - newDirtyRect.mBottom = temp; - } - - if(mDirtyRect.isEmpty()) - { - mDirtyRect = newDirtyRect; - } - else - { - mDirtyRect.unionWith(newDirtyRect); - } - - LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" - << newDirtyRect.mLeft << ", " - << newDirtyRect.mTop << ", " - << newDirtyRect.mRight << ", " - << newDirtyRect.mBottom << "), new dirty rect is: (" - << mDirtyRect.mLeft << ", " - << mDirtyRect.mTop << ", " - << mDirtyRect.mRight << ", " - << mDirtyRect.mBottom << ")" - << LL_ENDL; - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED); - } - - - bool time_duration_updated = false; - int previous_percent = mProgressPercent; - - if(message.hasValue("current_time")) - { - mCurrentTime = message.getValueReal("current_time"); - time_duration_updated = true; - } - if(message.hasValue("duration")) - { - mDuration = message.getValueReal("duration"); - time_duration_updated = true; - } - - if(message.hasValue("current_rate")) - { - mCurrentRate = message.getValueReal("current_rate"); - } - - if(message.hasValue("loaded_duration")) - { - mLoadedDuration = message.getValueReal("loaded_duration"); - time_duration_updated = true; - } - else - { - // If the message doesn't contain a loaded_duration param, assume it's equal to duration - mLoadedDuration = mDuration; - } - - // Calculate a percentage based on the loaded duration and total duration. - if(mDuration != 0.0f) // Don't divide by zero. - { - mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration); - } - - if(time_duration_updated) - { - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED); - } - - if(previous_percent != mProgressPercent) - { - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); - } - } - else if(message_name == "media_status") - { - std::string status = message.getValue("status"); - - LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL; - - if(status == "loading") - { - mStatus = LLPluginClassMediaOwner::MEDIA_LOADING; - } - else if(status == "loaded") - { - mStatus = LLPluginClassMediaOwner::MEDIA_LOADED; - } - else if(status == "error") - { - mStatus = LLPluginClassMediaOwner::MEDIA_ERROR; - } - else if(status == "playing") - { - mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING; - } - else if(status == "paused") - { - mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED; - } - else if(status == "done") - { - mStatus = LLPluginClassMediaOwner::MEDIA_DONE; - } - else - { - // empty string or any unknown string - mStatus = LLPluginClassMediaOwner::MEDIA_NONE; - } - } - else if(message_name == "size_change_request") - { - S32 width = message.getValueS32("width"); - S32 height = message.getValueS32("height"); - std::string name = message.getValue("name"); - - // TODO: check that name matches? - mNaturalMediaWidth = width; - mNaturalMediaHeight = height; - - setSizeInternal(); - } - else if(message_name == "size_change_response") - { - std::string name = message.getValue("name"); - - // TODO: check that name matches? - - mTextureWidth = message.getValueS32("texture_width"); - mTextureHeight = message.getValueS32("texture_height"); - mMediaWidth = message.getValueS32("width"); - mMediaHeight = message.getValueS32("height"); - - // This invalidates any existing dirty rect. - resetDirty(); - - // TODO: should we verify that the plugin sent back the right values? - // Two size changes in a row may cause them to not match, due to queueing, etc. - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED); - } - else if(message_name == "cursor_changed") - { - mCursorName = message.getValue("name"); - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED); - } - else if(message_name == "edit_state") - { - if(message.hasValue("cut")) - { - mCanCut = message.getValueBoolean("cut"); - } - if(message.hasValue("copy")) - { - mCanCopy = message.getValueBoolean("copy"); - } - if(message.hasValue("paste")) - { - mCanPaste = message.getValueBoolean("paste"); - } - } - else if(message_name == "name_text") - { - mMediaName = message.getValue("name"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); - } - else if(message_name == "pick_file") - { - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); - } - else if(message_name == "auth_request") - { - mAuthURL = message.getValue("url"); - mAuthRealm = message.getValue("realm"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); - } - else - { - LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - std::string message_name = message.getName(); - if(message_name == "navigate_begin") - { - mNavigateURI = message.getValue("uri"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN); - } - else if(message_name == "navigate_complete") - { - mNavigateURI = message.getValue("uri"); - mNavigateResultCode = message.getValueS32("result_code"); - mNavigateResultString = message.getValue("result_string"); - mHistoryBackAvailable = message.getValueBoolean("history_back_available"); - mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE); - } - else if(message_name == "progress") - { - mProgressPercent = message.getValueS32("percent"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); - } - else if(message_name == "status_text") - { - mStatusText = message.getValue("status"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED); - } - else if(message_name == "location_changed") - { - mLocation = message.getValue("uri"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED); - } - else if(message_name == "click_href") - { - mClickURL = message.getValue("uri"); - mClickTarget = message.getValue("target"); - mClickUUID = message.getValue("uuid"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); - } - else if(message_name == "click_nofollow") - { - mClickURL = message.getValue("uri"); - mClickNavType = message.getValue("nav_type"); - mClickTarget.clear(); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); - } - else if(message_name == "navigate_error_page") - { - mStatusCode = message.getValueS32("status_code"); - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE); - } - else if(message_name == "cookie_set") - { - if(mOwner) - { - mOwner->handleCookieSet(this, message.getValue("cookie")); - } - } - else if(message_name == "close_request") - { - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST); - } - else if(message_name == "geometry_change") - { - mClickUUID = message.getValue("uuid"); - mGeometryX = message.getValueS32("x"); - mGeometryY = message.getValueS32("y"); - mGeometryWidth = message.getValueS32("width"); - mGeometryHeight = message.getValueS32("height"); - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE); - } - else if(message_name == "link_hovered") - { - // text is not currently used -- the tooltip hover text is taken from the "title". - mHoverLink = message.getValue("link"); - mHoverText = message.getValue("title"); - // message.getValue("text"); - - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED); - } - else - { - LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - std::string message_name = message.getName(); - - // This class hasn't defined any incoming messages yet. -// if(message_name == "message_name") -// { -// } -// else - { - LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; - } - } - -} - -/* virtual */ -void LLPluginClassMedia::pluginLaunchFailed() -{ - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH); -} - -/* virtual */ -void LLPluginClassMedia::pluginDied() -{ - mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED); -} - -void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event) -{ - if(mOwner) - { - mOwner->handleMediaEvent(this, event); - } -} - -void LLPluginClassMedia::sendMessage(const LLPluginMessage &message) -{ - if(mPlugin && mPlugin->isRunning()) - { - mPlugin->sendMessage(message); - } - else - { - // The plugin isn't set up yet -- queue this message to be sent after initialization. - mSendQueue.push(message); - } -} - -//////////////////////////////////////////////////////////// -// MARK: media_browser class functions -bool LLPluginClassMedia::pluginSupportsMediaBrowser(void) -{ - std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER); - return !version.empty(); -} - -void LLPluginClassMedia::focus(bool focused) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus"); - - message.setValueBoolean("focused", focused); - - sendMessage(message); -} - -void LLPluginClassMedia::clear_cache() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache"); - sendMessage(message); -} - -void LLPluginClassMedia::clear_cookies() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies"); - sendMessage(message); -} - -void LLPluginClassMedia::set_cookies(const std::string &cookies) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); - message.setValue("cookies", cookies); - sendMessage(message); -} - -void LLPluginClassMedia::enable_cookies(bool enable) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); - message.setValueBoolean("enable", enable); - sendMessage(message); -} - -void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup"); - - message.setValueBoolean("enable", enable); - message.setValue("host", host); - message.setValueS32("port", port); - - sendMessage(message); -} - -void LLPluginClassMedia::browse_stop() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop"); - sendMessage(message); -} - -void LLPluginClassMedia::browse_reload(bool ignore_cache) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload"); - - message.setValueBoolean("ignore_cache", ignore_cache); - - sendMessage(message); -} - -void LLPluginClassMedia::browse_forward() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward"); - sendMessage(message); -} - -void LLPluginClassMedia::browse_back() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back"); - sendMessage(message); -} - -void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent"); - - message.setValue("user_agent", user_agent); - - sendMessage(message); -} - -void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened"); - - message.setValue("target", target); - message.setValue("uuid", uuid); - - sendMessage(message); -} - -void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed"); - - message.setValue("uuid", uuid); - - sendMessage(message); -} - -void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors"); - message.setValueBoolean("ignore", ignore); - sendMessage(message); -} - -void LLPluginClassMedia::addCertificateFilePath(const std::string& path) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path"); - message.setValue("path", path); - sendMessage(message); -} - -void LLPluginClassMedia::crashPlugin() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); - - sendMessage(message); -} - -void LLPluginClassMedia::hangPlugin() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang"); - - sendMessage(message); -} - - -//////////////////////////////////////////////////////////// -// MARK: media_time class functions -bool LLPluginClassMedia::pluginSupportsMediaTime(void) -{ - std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME); - return !version.empty(); -} - -void LLPluginClassMedia::stop() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop"); - sendMessage(message); -} - -void LLPluginClassMedia::start(float rate) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start"); - - message.setValueReal("rate", rate); - - sendMessage(message); -} - -void LLPluginClassMedia::pause() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause"); - sendMessage(message); -} - -void LLPluginClassMedia::seek(float time) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek"); - - message.setValueReal("time", time); - - sendMessage(message); -} - -void LLPluginClassMedia::setLoop(bool loop) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop"); - - message.setValueBoolean("loop", loop); - - sendMessage(message); -} - -void LLPluginClassMedia::setVolume(float volume) -{ - if(volume != mRequestedVolume) - { - mRequestedVolume = volume; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume"); - - message.setValueReal("volume", volume); - - sendMessage(message); - } -} - -float LLPluginClassMedia::getVolume() -{ - return mRequestedVolume; -} - -void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history) -{ - // Send URL history to plugin - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history"); - message.setValueLLSD("history", url_history); - sendMessage(message); - - LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL; -} - +/**
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
+
+ return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+ mOwner = owner;
+ mPlugin = NULL;
+ reset();
+
+ //debug use
+ mDeleteOK = true ;
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+ llassert_always(mDeleteOK) ;
+ reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
+{
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+
+ mPlugin = new LLPluginProcessParent(this);
+ mPlugin->setSleepTime(mSleepTime);
+
+ // Queue up the media init message -- it will be sent after all the currently queued messages.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+ message.setValue("target", mTarget);
+ sendMessage(message);
+
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+
+ return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+ if(mPlugin != NULL)
+ {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mRequestedTextureWidth = 0;
+ mRequestedTextureHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 1.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickNavType.clear();
+ mClickTarget.clear();
+ mClickUUID.clear();
+ mStatusCode = 0;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ memset( addr, 0x00, newsize );
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+ return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+ return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
+
+ setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
+
+ if(mRequestedMediaWidth > 2048)
+ mRequestedMediaWidth = 2048;
+
+ if(mRequestedMediaHeight > 2048)
+ mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
+
+ return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+ bool result = !mDirtyRect.isEmpty();
+
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+ mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+ std::string result;
+
+
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
+
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
+
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
+
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
+/*
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
+*/
+ return result;
+}
+
+void LLPluginClassMedia::jsEnableObject( bool enable )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+ message.setValueReal( "angle", angle );
+
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+ message.setValue( "language", language );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+ message.setValue( "region", region );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+ message.setValue( "maturity", maturity );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+ {
+ // Don't queue up mouse move events that can't be delivered.
+ return;
+ }
+
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("button", button);
+
+ message.setValueS32("x", x);
+
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
+{
+ bool result = true;
+
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
+
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
+
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
+
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+
+ return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+ message.setValue("uri", uri);
+
+ sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+ F64 result = 0.0f;
+
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+ message.setValue("file", file);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::cut()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+ message.setValue("path", user_data_path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+ message.setValue("language", language_code);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+
+void LLPluginClassMedia::enableMediaPluginDebugging( bool enable )
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_media_plugin_debugging");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::setTarget(const std::string &target)
+{
+ mTarget = target;
+}
+
+/* virtual */
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else if(message_name == "pick_file")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+ }
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
+ else if(message_name == "debug_message")
+ {
+ mDebugMessageText = message.getValue("message_text");
+ mDebugMessageLevel = message.getValue("message_level");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+ mClickUUID = message.getValue("uuid");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickNavType = message.getValue("nav_type");
+ mClickTarget.clear();
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else if(message_name == "navigate_error_page")
+ {
+ mStatusCode = message.getValueS32("status_code");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+ }
+ else if(message_name == "cookie_set")
+ {
+ if(mOwner)
+ {
+ mOwner->handleCookieSet(this, message.getValue("cookie"));
+ }
+ }
+ else if(message_name == "close_request")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+ }
+ else if(message_name == "geometry_change")
+ {
+ mClickUUID = message.getValue("uuid");
+ mGeometryX = message.getValueS32("x");
+ mGeometryY = message.getValueS32("y");
+ mGeometryWidth = message.getValueS32("width");
+ mGeometryHeight = message.getValueS32("height");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+ }
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginDied()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+ message.setValueBoolean("focused", focused);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::set_cookies(const std::string &cookies)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
+ message.setValue("cookies", cookies);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+ message.setValueBoolean("enable", enable);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+ message.setValueBoolean("ignore_cache", ignore_cache);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+ message.setValue("user_agent", user_agent);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::showWebInspector( bool show )
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "show_web_inspector");
+ message.setValueBoolean("show", true); // only open for now - closed manually by user
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+
+ message.setValue("target", target);
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+ sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+ message.setValueReal("rate", rate);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+ message.setValueReal("time", time);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+ message.setValueBoolean("loop", loop);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+ message.setValueReal("volume", volume);
+
+ sendMessage(message);
+ }
+}
+
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
+
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index e7f303275e..1f548f8cc0 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -41,16 +41,16 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner LOG_CLASS(LLPluginClassMedia); public: LLPluginClassMedia(LLPluginClassMediaOwner *owner); - virtual ~LLPluginClassMedia(); + ~LLPluginClassMedia(); // local initialization, called by the media manager when creating a source - virtual bool init(const std::string &launcher_filename, + bool init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug); // undoes everything init() didm called by the media manager when destroying a source - virtual void reset(); + void reset(); void idle(void); @@ -118,6 +118,9 @@ public: void scrollEvent(int x, int y, MASK modifiers); + // enable/disable media plugin debugging messages and info spam + void enableMediaPluginDebugging( bool enable ); + // Javascript <-> viewer events void jsEnableObject( bool enable ); void jsAgentLocationEvent( double x, double y, double z ); @@ -209,6 +212,7 @@ public: void browse_forward(); void browse_back(); void setBrowserUserAgent(const std::string& user_agent); + void showWebInspector( bool show ); void proxyWindowOpened(const std::string &target, const std::string &uuid); void proxyWindowClosed(const std::string &uuid); void ignore_ssl_cert_errors(bool ignore); @@ -244,6 +248,10 @@ public: // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE + std::string getDebugMessageText() const { return mDebugMessageText; }; + std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; + // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE S32 getStatusCode() const { return mStatusCode; }; @@ -395,6 +403,8 @@ protected: std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + std::string mDebugMessageText; + std::string mDebugMessageLevel; S32 mGeometryX; S32 mGeometryY; S32 mGeometryWidth; diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 5a4fb1ce90..2f3edba7f3 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -64,6 +64,8 @@ public: MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process + MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin } EMediaEvent; diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index e6926c3e37..3643a15d8c 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -39,7 +39,7 @@ class LLPluginInstanceMessageListener { public: - virtual ~LLPluginInstanceMessageListener(); + ~LLPluginInstanceMessageListener(); /** Plugin receives message from plugin loader shell. */ virtual void receivePluginMessage(const std::string &message) = 0; }; diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h index 627577beb1..beb942c0fe 100644 --- a/indra/llplugin/llpluginmessagepipe.h +++ b/indra/llplugin/llpluginmessagepipe.h @@ -40,7 +40,8 @@ class LLPluginMessagePipeOwner LOG_CLASS(LLPluginMessagePipeOwner); public: LLPluginMessagePipeOwner(); - virtual ~LLPluginMessagePipeOwner(); + ~LLPluginMessagePipeOwner(); + // called with incoming messages virtual void receiveMessageRaw(const std::string &message) = 0; // called when the socket has an error diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index c66723f175..26c6b0c402 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -41,7 +41,7 @@ class LLPluginProcessParentOwner { public: - virtual ~LLPluginProcessParentOwner(); + ~LLPluginProcessParentOwner(); virtual void receivePluginMessage(const LLPluginMessage &message) = 0; virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;}; // This will only be called when the plugin has died unexpectedly diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 39f59c0bd8..4e3cfb9c8a 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -48,6 +48,7 @@ #include "llstacktrace.h" #include "llglheaders.h" +#include "llglslshader.h" #ifdef _DEBUG //#define GL_STATE_VERIFY @@ -1781,6 +1782,16 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { + if (LLGLSLShader::sNoFixedFunction) + { //always disable state that's deprecated post GL 3.0 + switch (state) + { + case GL_ALPHA_TEST: + enabled = 0; + break; + } + } + stop_glerror(); if (state) { diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 80c93bb0d2..f51d83abe4 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -49,6 +49,7 @@ using std::make_pair; using std::string; GLhandleARB LLGLSLShader::sCurBoundShader = 0; +LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; bool LLGLSLShader::sNoFixedFunction = false; //UI shader -- declared here so llui_libtest will link properly @@ -63,7 +64,8 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), -hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false) +hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false), +hasAlphaMask(false) { } @@ -386,6 +388,7 @@ void LLGLSLShader::bind() { glUseProgramObjectARB(mProgramObject); sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; if (mUniformsDirty) { LLShaderMgr::instance()->updateShaderUniforms(this); @@ -410,6 +413,7 @@ void LLGLSLShader::unbind() } glUseProgramObjectARB(0); sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; stop_glerror(); } } @@ -418,6 +422,7 @@ void LLGLSLShader::bindNoShader(void) { glUseProgramObjectARB(0); sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; } S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) @@ -979,3 +984,9 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) glVertexAttrib4fvARB(mAttribute[index], v); } } + +void LLGLSLShader::setAlphaRange(F32 minimum, F32 maximum) +{ + uniform1f("minimum_alpha", minimum); + uniform1f("maximum_alpha", maximum); +} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 621e0b82ee..558ea66b50 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -47,6 +47,7 @@ public: bool hasGamma; S32 mIndexedTextureChannels; bool disableTextureIndex; + bool hasAlphaMask; // char numLights; @@ -67,6 +68,8 @@ public: LLGLSLShader(); static GLhandleARB sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + static bool sNoFixedFunction; void unload(); @@ -105,6 +108,8 @@ public: void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void setAlphaRange(F32 minimum, F32 maximum); + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void vertexAttrib4fv(U32 index, GLfloat* v); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 9ca3a23d52..7188b0fa44 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1424,7 +1424,7 @@ void LLImageGL::deleteDeadTextures() { LLTexUnit* tex_unit = gGL.getTexUnit(i); - if (tex_unit->getCurrTexture() == tex) + if (tex_unit && tex_unit->getCurrTexture() == tex) { tex_unit->unbind(tex_unit->getCurrType()); stop_glerror(); @@ -1887,6 +1887,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) void LLImageGL::setCategory(S32 category) { +#if 0 //turn this off temporarily because it is not in use now. if(!gAuditTexture) { return ; @@ -1907,6 +1908,7 @@ void LLImageGL::setCategory(S32 category) mCategory = -1 ; } } +#endif } //for debug use diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 70df1dd1d1..d72918b15d 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1168,6 +1168,11 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { flush(); + if (LLGLSLShader::sNoFixedFunction) + { //glAlphaFunc is deprecated in OpenGL 3.3 + return; + } + if (mCurrAlphaFunc != func || mCurrAlphaFuncVal != value) { @@ -1182,6 +1187,30 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) glAlphaFunc(sGLCompareFunc[func], value); } } + + if (gDebugGL) + { //make sure cached state is correct + GLint cur_func = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); + + if (func == CF_DEFAULT) + { + func = CF_GREATER; + } + + if (cur_func != sGLCompareFunc[func]) + { + llerrs << "Alpha test function corrupted!" << llendl; + } + + F32 ref = 0.f; + glGetFloatv(GL_ALPHA_TEST_REF, &ref); + + if (ref != value) + { + llerrs << "Alpha test value corrupted!" << llendl; + } + } } void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 751b250d96..986c1f2774 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -206,21 +206,40 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasLighting) { - if (features->hasWaterFog) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightWaterF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -230,16 +249,36 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -272,14 +311,28 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) { return FALSE; } } else { - if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) { return FALSE; } @@ -310,16 +363,37 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { if (features->disableTextureIndex) { - if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + { + return FALSE; + } } } else { - if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + if (features->hasAlphaMask) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + { + return FALSE; + } } shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } @@ -406,7 +480,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) LL_DEBUGS("ShaderLoading") << log << LL_ENDL; } } -} + } GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels) { diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 6afe276379..4b0b7c561d 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -339,7 +339,7 @@ LLAccordionCtrlTab::Params::Params() ,fit_panel("fit_panel",true) ,selection_enabled("selection_enabled", false) { - mouse_opaque(false); + changeDefault(mouse_opaque, false); } LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp index ceeeb4d1f6..8ede4e3468 100644 --- a/indra/llui/llbadge.cpp +++ b/indra/llui/llbadge.cpp @@ -55,10 +55,7 @@ LLBadge::Params::Params() , location_percent_vcenter("location_percent_vcenter") , padding_horiz("padding_horiz") , padding_vert("padding_vert") -{ - // We set a name here so the name isn't necessary in any xml files that use badges - name = "badge"; -} +{} bool LLBadge::Params::equals(const Params& a) const { diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 7b015bd576..a12235c16f 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -104,8 +104,7 @@ LLButton::Params::Params() handle_right_mouse("handle_right_mouse") { addSynonym(is_toggle, "toggle"); - held_down_delay.seconds = 0.5f; - initial_value.set(LLSD(false), false); + changeDefault(initial_value, LLSD(false)); } diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index bb8ea50bed..f32f1dd74c 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -54,7 +54,7 @@ public: persist_time("persist_time", 0.f), // forever font_size_index("font_size_index") { - mouse_opaque(false); + changeDefault(mouse_opaque, false); } }; protected: diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index 7d3d5cf787..e81600fd6c 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -50,7 +50,7 @@ public: show_label("show_label", FALSE), display_children("display_children", TRUE) { - mouse_opaque(false); + changeDefault(mouse_opaque, false); } }; diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 7c56475e75..e095e577b1 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -51,8 +51,8 @@ public: drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark")) { - mouse_opaque(true); - follows.flags(FOLLOWS_ALL); + changeDefault(mouse_opaque, true); + changeDefault(follows.flags, FOLLOWS_ALL); } }; void initFromParams(const Params&); diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h index 710699fdc1..3a05bc05a1 100644 --- a/indra/llui/llfiltereditor.h +++ b/indra/llui/llfiltereditor.h @@ -42,12 +42,7 @@ class LLFilterEditor : public LLSearchEditor { public: struct Params : public LLInitParam::Block<Params, LLSearchEditor::Params> - { - Params() - { - name = "filter_editor"; - } - }; + {}; protected: LLFilterEditor(const Params&); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8917d5490c..bc494e97f5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -182,7 +182,7 @@ LLFloater::Params::Params() open_callback("open_callback"), close_callback("close_callback") { - visible = false; + changeDefault(visible, false); } diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h index 8d59380a00..36998eba2e 100644 --- a/indra/llui/llflyoutbutton.h +++ b/indra/llui/llflyoutbutton.h @@ -46,7 +46,7 @@ public: : action_button("action_button"), allow_text_entry("allow_text_entry") { - LLComboBox::Params::allow_text_entry = false; + changeDefault(LLComboBox::Params::allow_text_entry, false); } }; diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 752c7df7ee..899cc3a326 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -103,7 +103,7 @@ public: } else { - llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl; + lldebugs << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl; return mMap[LOGFUNCTOR]; } } @@ -115,7 +115,7 @@ private: static void log_functor(const LLSD& notification, const LLSD& payload) { - llwarns << "log_functor called with payload: " << payload << llendl; + lldebugs << "log_functor called with payload: " << payload << llendl; } static void do_nothing(const LLSD& notification, const LLSD& payload) diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 47f2cfaf89..30b79b4d20 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -43,10 +43,7 @@ LLIconCtrl::Params::Params() color("color"), use_draw_context_alpha("use_draw_context_alpha", true), scale_image("scale_image") -{ - tab_stop = false; - mouse_opaque = false; -} +{} LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) : LLUICtrl(p), diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index a59247ba09..a250404292 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -115,9 +115,7 @@ LLLayoutStack::Params::Params() open_time_constant("open_time_constant", 0.02f), close_time_constant("close_time_constant", 0.03f), border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) -{ - name="stack"; -} +{} LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) : LLView(p), diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 06fbc0f234..c2173fb89c 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -103,7 +103,7 @@ LLLineEditor::Params::Params() text_pad_right("text_pad_right"), default_text("default_text") { - mouse_opaque = true; + changeDefault(mouse_opaque, true); addSynonym(select_on_focus, "select_all_on_focus_received"); addSynonym(border, "border"); addSynonym(label, "watermark_text"); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 8de9c769e2..6cac841cde 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -90,7 +90,6 @@ const S32 TEAROFF_SEPARATOR_HEIGHT_PIXELS = 10; const S32 MENU_ITEM_PADDING = 4; const std::string SEPARATOR_NAME("separator"); -const std::string SEPARATOR_LABEL( "-----------" ); const std::string VERTICAL_SEPARATOR_LABEL( "|" ); const std::string LLMenuGL::BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK @@ -149,7 +148,7 @@ LLMenuItemGL::Params::Params() highlight_bg_color("highlight_bg_color"), highlight_fg_color("highlight_fg_color") { - mouse_opaque = true; + changeDefault(mouse_opaque, true); } // Default constructor @@ -566,8 +565,6 @@ void LLMenuItemGL::handleVisibilityChange(BOOL new_visibility) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LLMenuItemSeparatorGL::Params::Params() { - name = "separator"; - label = SEPARATOR_LABEL; } LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) : @@ -755,30 +752,6 @@ U32 LLMenuItemTearOffGL::getNominalHeight( void ) const return TEAROFF_SEPARATOR_HEIGHT_PIXELS; } - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLMenuItemBlankGL -// -// This class represents a blank, non-functioning item. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLMenuItemBlankGL : public LLMenuItemGL -{ -public: - struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> - { - Params() - { - name=""; - enabled = false; - } - }; - LLMenuItemBlankGL( const Params& p ) : LLMenuItemGL( p ) - {} - virtual void draw( void ) {} -}; - - ///============================================================================ /// Class LLMenuItemCallGL ///============================================================================ diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 7bde8e83ec..b5579a831a 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -381,8 +381,6 @@ public: { addSynonym(bg_visible, "opaque"); addSynonym(bg_color, "color"); - - name = "menu"; } }; @@ -650,7 +648,7 @@ public: { Params() { - visible = false; + changeDefault(visible, false); } }; @@ -698,16 +696,7 @@ class LLMenuBarGL : public LLMenuGL { public: struct Params : public LLInitParam::Block<Params, LLMenuGL::Params> - { - Params() - { - can_tear_off = false; - keep_fixed_size = true; - horizontal_layout = true; - visible = true; - drop_shadow = false; - } - }; + {}; LLMenuBarGL( const Params& p ); virtual ~LLMenuBarGL(); @@ -825,13 +814,7 @@ class LLMenuItemTearOffGL : public LLMenuItemGL { public: struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> - { - Params() - { - name = "tear off"; - label = "~~~~~~~~~~~"; - } - }; + {}; LLMenuItemTearOffGL( const Params& ); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 9052bc7d1d..70bcfb5b4f 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -66,11 +66,7 @@ LLMultiSlider::Params::Params() mouse_up_callback("mouse_up_callback"), thumb_width("thumb_width"), sliders("slider") -{ - name = "multi_slider_bar"; - mouse_opaque(true); - follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); -} +{} LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) : LLF32UICtrl(p), diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index e3193bc352..a45b617c2e 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -90,7 +90,6 @@ LLPanel::Params::Params() visible_callback("visible_callback"), accepts_badge("accepts_badge") { - name = "panel"; addSynonym(background_visible, "bg_visible"); addSynonym(has_border, "border_visible"); addSynonym(label, "title"); diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 3a12debf7e..95a7d09382 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -74,9 +74,6 @@ LLRadioGroup::Params::Params() { addSynonym(items, "radio_item"); - name = "radio_group"; - mouse_opaque = true; - follows.flags = FOLLOWS_LEFT | FOLLOWS_TOP; // radio items are not tabbable until they are selected tab_stop = false; } @@ -96,7 +93,10 @@ void LLRadioGroup::initFromParams(const Params& p) { LLRadioGroup::ItemParams item_params(*it); - item_params.font.setIfNotProvided(mFont); // apply radio group font by default + if (!item_params.font.isProvided()) + { + item_params.font = mFont; // apply radio group font by default + } item_params.commit_callback.function = boost::bind(&LLRadioGroup::onClickButton, this, _1); item_params.from_xui = p.from_xui; if (p.from_xui) diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 3a867a10a7..5d3bf7a670 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -63,9 +63,7 @@ LLScrollbar::Params::Params() right_button("right_button"), bg_visible("bg_visible", false), bg_color("bg_color", LLColor4::black) -{ - tab_stop = false; -} +{} LLScrollbar::LLScrollbar(const Params & p) : LLUICtrl(p), diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 112622d3f7..b44b4c36b6 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -74,8 +74,7 @@ LLScrollContainer::Params::Params() min_auto_scroll_rate("min_auto_scroll_rate", 100), max_auto_scroll_rate("max_auto_scroll_rate", 1000), reserve_scroll_corner("reserve_scroll_corner", false) -{ -} +{} // Default constructor diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h index 8f569c2a58..e8df176ec3 100644 --- a/indra/llui/llscrollingpanellist.h +++ b/indra/llui/llscrollingpanellist.h @@ -51,12 +51,7 @@ class LLScrollingPanelList : public LLUICtrl { public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> - { - Params() - { - name = "scrolling_panel_list"; - } - }; + {}; LLScrollingPanelList(const Params& p) : LLUICtrl(p) {} diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 696e4a2bb1..07a6dfaa10 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -46,10 +46,7 @@ static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid //--------------------------------------------------------------------------- LLScrollColumnHeader::Params::Params() : column("column") -{ - name = "column_header"; - tab_stop(false); -} +{} LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p) diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index e2711ac75a..12baea8e0c 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -135,7 +135,7 @@ public: halign("halign", LLFontGL::LEFT) { // default choice to "dynamic_width" - width.dynamic_width = true; + changeDefault(width.dynamic_width, true); addSynonym(sort_column, "sort"); } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index b7848ec37c..622f3e215c 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -147,12 +147,9 @@ LLScrollListCtrl::Params::Params() highlighted_color("highlighted_color"), contents(""), scroll_bar_bg_visible("scroll_bar_bg_visible"), - scroll_bar_bg_color("scroll_bar_bg_color") - , border("border") -{ - name = "scroll_list"; - mouse_opaque = true; -} + scroll_bar_bg_color("scroll_bar_bg_color"), + border("border") +{} LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) : LLUICtrl(p), @@ -2813,7 +2810,10 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS } S32 index = columnp->mIndex; - cell_p.width.setIfNotProvided(columnp->getWidth()); + if (!cell_p.width.isProvided()) + { + cell_p.width = columnp->getWidth(); + } LLScrollListCell* cell = LLScrollListCell::create(cell_p); diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index f5c3b532c4..c2d7916938 100644 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -55,9 +55,7 @@ public: search_button_visible("search_button_visible"), clear_button("clear_button"), clear_button_visible("clear_button_visible") - { - name = "search_editor"; - } + {} }; void setCommitOnFocusLost(BOOL b) { if (mSearchEditor) mSearchEditor->setCommitOnFocusLost(b); } diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 013950a5ad..db72234f94 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -54,9 +54,7 @@ LLSlider::Params::Params() track_highlight_vertical_image("track_highlight_vertical_image"), mouse_down_callback("mouse_down_callback"), mouse_up_callback("mouse_up_callback") -{ - follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); -} +{} LLSlider::LLSlider(const LLSlider::Params& p) : LLF32UICtrl(p), diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index d760178e35..583ed1ed2e 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -76,8 +76,14 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) } LLRect label_rect( left, top, label_width, bottom ); LLTextBox::Params params(p.slider_label); - params.rect.setIfNotProvided(label_rect); - params.font.setIfNotProvided(p.font); + if (!params.rect.isProvided()) + { + params.rect = label_rect; + } + if (!params.font.isProvided()) + { + params.font = p.font; + } params.initial_value(p.label()); mLabelBox = LLUICtrlFactory::create<LLTextBox> (params); addChild(mLabelBox); @@ -113,15 +119,33 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) S32 slider_left = label_width ? label_width + sliderctrl_spacing : 0; LLSlider::Params slider_p(p.slider_bar); slider_p.name("slider_bar"); - slider_p.rect.setIfNotProvided(LLRect(slider_left,top,slider_right,bottom)); - slider_p.initial_value.setIfNotProvided(p.initial_value().asReal()); - slider_p.min_value.setIfNotProvided(p.min_value); - slider_p.max_value.setIfNotProvided(p.max_value); - slider_p.increment.setIfNotProvided(p.increment); - slider_p.orientation.setIfNotProvided(p.orientation); + if (!slider_p.rect.isProvided()) + { + slider_p.rect = LLRect(slider_left,top,slider_right,bottom); + } + if (!slider_p.initial_value.isProvided()) + { + slider_p.initial_value = p.initial_value().asReal(); + } + if (!slider_p.min_value.isProvided()) + { + slider_p.min_value = p.min_value; + } + if (!slider_p.max_value.isProvided()) + { + slider_p.max_value = p.max_value; + } + if (!slider_p.increment.isProvided()) + { + slider_p.increment = p.increment; + } + if (!slider_p.orientation.isProvided()) + { + slider_p.orientation = p.orientation; + } - slider_p.commit_callback.function(&LLSliderCtrl::onSliderCommit); - slider_p.control_name(p.control_name); + slider_p.commit_callback.function = &LLSliderCtrl::onSliderCommit; + slider_p.control_name = p.control_name; slider_p.mouse_down_callback( p.mouse_down_callback ); slider_p.mouse_up_callback( p.mouse_up_callback ); mSlider = LLUICtrlFactory::create<LLSlider> (slider_p); @@ -134,8 +158,15 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) if( p.can_edit_text() ) { LLLineEditor::Params line_p(p.value_editor); - line_p.rect.setIfNotProvided(text_rect); - line_p.font.setIfNotProvided(p.font); + if (!line_p.rect.isProvided()) + { + line_p.rect = text_rect; + } + if (!line_p.font.isProvided()) + { + line_p.font = p.font; + } + line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit); line_p.prevalidate_callback(&LLTextValidate::validateFloat); mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p); @@ -149,8 +180,14 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) else { LLTextBox::Params text_p(p.value_text); - text_p.rect.setIfNotProvided(text_rect); - text_p.font.setIfNotProvided(p.font); + if (!text_p.rect.isProvided()) + { + text_p.rect = text_rect; + } + if (!text_p.font.isProvided()) + { + text_p.font = p.font; + } mTextBox = LLUICtrlFactory::create<LLTextBox>(text_p); addChild(mTextBox); } diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 62a9db82fe..513fff3234 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -65,7 +65,7 @@ public: show_mean("show_mean", TRUE), stat("stat") { - follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT); + changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT); } }; LLStatBar(const Params&); diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index 22a9fcd672..5abdc42448 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -46,7 +46,7 @@ public: Params() : setting("setting") { - follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT); + changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT); } }; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 7f0d650403..9c6a76822c 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -217,10 +217,7 @@ LLTabContainer::Params::Params() tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), use_ellipses("use_ellipses"), font_halign("halign") -{ - name(std::string("tab_container")); - mouse_opaque = false; -} +{} LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) : LLPanel(p), diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 6390039794..bc6461a0c2 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -55,7 +55,7 @@ static LLDefaultChildRegistry::Register<LLToolTipView> register_tooltip_view("to LLToolTipView::Params::Params() { - mouse_opaque = false; + changeDefault(mouse_opaque, false); } LLToolTipView::LLToolTipView(const LLToolTipView::Params& p) @@ -156,7 +156,7 @@ LLToolTip::Params::Params() web_based_media("web_based_media", false), media_playing("media_playing", false) { - chrome = true; + changeDefault(chrome, true); } LLToolTip::LLToolTip(const LLToolTip::Params& p) @@ -402,12 +402,12 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) LLToolTip::Params tooltip_params(params); // block mouse events if there is a click handler registered (specifically, hover) - if (params.click_callback.isProvided()) + if (params.click_callback.isProvided() && !params.mouse_opaque.isProvided()) { // set mouse_opaque to true if it wasn't already set to something else // this prevents mouse down from going "through" the tooltip and ultimately // causing the tooltip to disappear - tooltip_params.mouse_opaque.setIfNotProvided(true); + tooltip_params.mouse_opaque = true; } tooltip_params.rect = LLRect (0, 1, 1, 0); diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 499b97f52d..f0ba7fc7d7 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -104,14 +104,17 @@ private: public: ParamDefaults() { - // recursively initialize from base class param block - ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); - // after initializing base classes, look up template file for this param block + // look up template file for this param block... const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); if (param_block_tag) - { - LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype); + { // ...and if it exists, back fill values using the most specific template first + PARAM_BLOCK params; + LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params); + mPrototype.fillFrom(params); } + // recursively fill from base class param block + ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); + } const PARAM_BLOCK& get() { return mPrototype; } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 659a54cc6e..0616c2a0c0 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -2485,7 +2485,7 @@ void LLView::applyXUILayout(LLView::Params& p, LLView* parent) { LLRect parent_rect = parent->getLocalRect(); // overwrite uninitialized rect params, using context - LLRect last_rect = parent->getLocalRect(); + LLRect default_rect = parent->getLocalRect(); bool layout_topleft = (p.layout() == "topleft"); @@ -2509,15 +2509,13 @@ void LLView::applyXUILayout(LLView::Params& p, LLView* parent) p.rect.height = MIN_WIDGET_HEIGHT; } - last_rect.translate(0, last_rect.getHeight()); + default_rect.translate(0, default_rect.getHeight()); // If there was a recently constructed child, use its rectangle - get_last_child_rect(parent, &last_rect); + get_last_child_rect(parent, &default_rect); if (layout_topleft) { - p.bottom_delta.setIfNotProvided(0, false); - // Invert the sense of bottom_delta for topleft layout if (p.bottom_delta.isProvided()) { @@ -2530,33 +2528,44 @@ void LLView::applyXUILayout(LLView::Params& p, LLView* parent) else if (p.top_delta.isProvided()) { p.bottom_delta = - -(p.top_delta + p.rect.height - last_rect.getHeight()); + -(p.top_delta + p.rect.height - default_rect.getHeight()); } - else if (!p.bottom_delta.isProvided() - && !p.left_delta.isProvided() - && !p.top_pad.isProvided() + else if (!p.left_delta.isProvided() && !p.left_pad.isProvided()) { // set default position is just below last rect p.bottom_delta.set(-(p.rect.height + VPAD), false); } + else + { + p.bottom_delta.set(0, false); + } // default to same left edge - p.left_delta.setIfNotProvided(0, false); + if (!p.left_delta.isProvided()) + { + p.left_delta.set(0, false); + } if (p.left_pad.isProvided()) { // left_pad is based on prior widget's right edge - p.left_delta.set(p.left_pad + last_rect.getWidth(), false); + p.left_delta.set(p.left_pad + default_rect.getWidth(), false); } - last_rect.translate(p.left_delta, p.bottom_delta); + default_rect.translate(p.left_delta, p.bottom_delta); } else { // set default position is just below last rect - p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false); - p.left_delta.setIfNotProvided(0, false); - last_rect.translate(p.left_delta, p.bottom_delta); + if (!p.bottom_delta.isProvided()) + { + p.bottom_delta.set(-(p.rect.height + VPAD), false); + } + if (!p.left_delta.isProvided()) + { + p.left_delta.set(0, false); + } + default_rect.translate(p.left_delta, p.bottom_delta); } // this handles case where *both* x and x_delta are provided @@ -2567,12 +2576,30 @@ void LLView::applyXUILayout(LLView::Params& p, LLView* parent) // selectively apply rectangle defaults, making sure that // params are not flagged as having been "provided" // as rect params are overconstrained and rely on provided flags - p.rect.left.setIfNotProvided(last_rect.mLeft, false); - p.rect.bottom.setIfNotProvided(last_rect.mBottom, false); - p.rect.top.setIfNotProvided(last_rect.mTop, false); - p.rect.right.setIfNotProvided(last_rect.mRight, false); - p.rect.width.setIfNotProvided(last_rect.getWidth(), false); - p.rect.height.setIfNotProvided(last_rect.getHeight(), false); + if (!p.rect.left.isProvided()) + { + p.rect.left.set(default_rect.mLeft, false); + } + if (!p.rect.bottom.isProvided()) + { + p.rect.bottom.set(default_rect.mBottom, false); + } + if (!p.rect.top.isProvided()) + { + p.rect.top.set(default_rect.mTop, false); + } + if (!p.rect.right.isProvided()) + { + p.rect.right.set(default_rect.mRight, false); + } + if (!p.rect.width.isProvided()) + { + p.rect.width.set(default_rect.getWidth(), false); + } + if (!p.rect.height.isProvided()) + { + p.rect.height.set(default_rect.getHeight(), false); + } } } diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index 32d7ea7c25..919267dcc6 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -57,9 +57,6 @@ LLViewBorder::Params::Params() { addSynonym(border_thickness, "thickness"); addSynonym(render_style, "style"); - name = "view_border"; - mouse_opaque = false; - follows.flags = FOLLOWS_ALL; } diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index 77e94385d4..cf76202215 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -43,7 +43,7 @@ LLWindowShade::Params::Params() text_color("text_color"), can_close("can_close", true) { - mouse_opaque = false; + changeDefault(mouse_opaque, false); } LLWindowShade::LLWindowShade(const LLWindowShade::Params& params) diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 551d487cc8..1239e2d40b 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1172,8 +1172,39 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO // First we try and get a 32 bit depth pixel format BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); + + while(!result && mFSAASamples > 0) + { + llwarns << "FSAASamples: " << mFSAASamples << " not supported." << llendl ; + + mFSAASamples /= 2 ; //try to decrease sample pixel number until to disable anti-aliasing + if(mFSAASamples < 2) + { + mFSAASamples = 0 ; + } + + if (mFSAASamples > 0) + { + attrib_list[end_attrib + 3] = mFSAASamples; + } + else + { + cur_attrib = end_attrib ; + end_attrib = 0 ; + attrib_list[cur_attrib++] = 0 ; //end + } + result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); + + if(result) + { + llwarns << "Only support FSAASamples: " << mFSAASamples << llendl ; + } + } + if (!result) { + llwarns << "mFSAASamples: " << mFSAASamples << llendl ; + close(); show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit"); return FALSE; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 194ef8af6a..e40bdb4a3d 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -717,14 +717,6 @@ namespace LLInitParam Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) - { - if (!isProvided()) - { - set(val, flag_as_provided); - } - } - // implicit conversion operator value_assignment_t() const { return param_value_t::getValue(); } // explicit conversion @@ -869,14 +861,6 @@ namespace LLInitParam Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) - { - if (!isProvided()) - { - set(val, flag_as_provided); - } - } - // propagate changed status up to enclosing block /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { @@ -1033,15 +1017,6 @@ namespace LLInitParam Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - - void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) - { - if (!isProvided()) - { - set(val, flag_as_provided); - } - } - value_t& add() { mValues.push_back(param_value_t(value_t())); @@ -1232,14 +1207,6 @@ namespace LLInitParam Param::enclosingBlock().paramChanged(*this, flag_as_provided); } - void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) - { - if (!isProvided()) - { - set(val, flag_as_provided); - } - } - value_t& add() { mValues.push_back(value_t()); @@ -1719,6 +1686,17 @@ namespace LLInitParam static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } + + template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> + void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, + typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) + { + if (!param.isProvided()) + { + param.set(value, false); + } + } + }; template<typename T> diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 96f642f2a0..430ae9d4dc 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -1,1394 +1,1447 @@ -/** - * @file media_plugin_webkit.cpp - * @brief Webkit plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "llqtwebkit.h" - -#include "linden_common.h" -#include "indra_constants.h" // for indra keyboard codes - -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified -#if LL_LINUX -# define LL_QTWEBKIT_USES_PIXMAPS 0 -extern "C" { -# include <glib.h> -# include <glib-object.h> -} -#else -# define LL_QTWEBKIT_USES_PIXMAPS 0 -#endif // LL_LINUX - -# include "volume_catcher.h" - -#if LL_WINDOWS -# include <direct.h> -#else -# include <unistd.h> -# include <stdlib.h> -#endif - -#if LL_WINDOWS - // *NOTE:Mani - This captures the module handle for the dll. This is used below - // to get the path to this dll for webkit initialization. - // I don't know how/if this can be done with apr... - namespace { HMODULE gModuleHandle;}; - BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) - { - gModuleHandle = (HMODULE) hinstDLL; - return TRUE; - } -#endif - -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginWebKit : - public MediaPluginBase, - public LLEmbeddedBrowserWindowObserver -{ -public: - MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginWebKit(); - - /*virtual*/ void receiveMessage(const char *message_string); - -private: - - std::string mProfileDir; - std::string mHostLanguage; - std::string mUserAgent; - bool mCookiesEnabled; - bool mJavascriptEnabled; - bool mPluginsEnabled; - - enum - { - INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet - INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet. - INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued - INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed - INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws - INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event - INIT_STATE_RUNNING // All initialization gymnastics are complete. - }; - int mBrowserWindowId; - int mInitState; - std::string mInitialNavigateURL; - bool mNeedsUpdate; - - bool mCanCut; - bool mCanCopy; - bool mCanPaste; - int mLastMouseX; - int mLastMouseY; - bool mFirstFocus; - F32 mBackgroundR; - F32 mBackgroundG; - F32 mBackgroundB; - std::string mTarget; - - VolumeCatcher mVolumeCatcher; - - void setInitState(int state) - { -// std::cerr << "changing init state to " << state << std::endl; - mInitState = state; - } - - //////////////////////////////////////////////////////////////////////////////// - // - void update(int milliseconds) - { -#if LL_QTLINUX_DOESNT_HAVE_GLIB - // pump glib generously, as Linux browser plugins are on the - // glib main loop, even if the browser itself isn't - ugh - // This is NOT NEEDED if Qt itself was built with glib - // mainloop integration. - GMainContext *mainc = g_main_context_default(); - while(g_main_context_iteration(mainc, FALSE)); -#endif // LL_QTLINUX_DOESNT_HAVE_GLIB - - // pump qt - LLQtWebKit::getInstance()->pump( milliseconds ); - - mVolumeCatcher.pump(); - - checkEditState(); - - if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) - { - if(!mInitialNavigateURL.empty()) - { - // We already have the initial navigate URL -- kick off the navigate. - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL ); - mInitialNavigateURL.clear(); - } - } - - if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate ) - { - const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); - - unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ); - unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); -#if !LL_QTWEBKIT_USES_PIXMAPS - unsigned int buffer_size = rowspan * height; -#endif // !LL_QTWEBKIT_USES_PIXMAPS - -// std::cerr << "webkit plugin: updating" << std::endl; - - // TODO: should get rid of this memcpy if possible - if ( mPixels && browser_pixels ) - { -// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; - -#if LL_QTWEBKIT_USES_PIXMAPS - // copy the pixel data upside-down because of the co-ord system - for (int y=0; y<height; ++y) - { - memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan ); - } -#else - memcpy( mPixels, browser_pixels, buffer_size ); -#endif // LL_QTWEBKIT_USES_PIXMAPS - } - - if ( mWidth > 0 && mHeight > 0 ) - { -// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl; - setDirty( 0, 0, mWidth, mHeight ); - } - - mNeedsUpdate = false; - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - bool initBrowser() - { - // already initialized - if ( mInitState > INIT_STATE_UNINITIALIZED ) - return true; - - // set up directories - char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use - if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) - { - llwarns << "Couldn't get cwd - probably too long - failing to init." << llendl; - return false; - } - std::string application_dir = std::string( cwd ); - -#if LL_LINUX - // take care to initialize glib properly, because some - // versions of Qt don't, and we indirectly need it for (some - // versions of) Flash to not crash the browser. - if (!g_thread_supported ()) g_thread_init (NULL); - g_type_init(); -#endif - -#if LL_DARWIN - // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. - // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. - // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it - // which gets hit when the plugin is probed by webkit. - // Unsetting the environment variable here works around this issue. - unsetenv("USERBREAK"); -#endif - -#if LL_WINDOWS - //*NOTE:Mani - On windows, at least, the component path is the - // location of this dll's image file. - std::string component_dir; - char dll_path[_MAX_PATH]; - DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH); - while(len && dll_path[ len ] != ('\\') ) - { - len--; - } - if(len >= 0) - { - dll_path[len] = 0; - component_dir = dll_path; - } - else - { - // *NOTE:Mani - This case should be an rare exception. - // GetModuleFileNameA should always give you a full path, no? - component_dir = application_dir; - } -#else - std::string component_dir = application_dir; -#endif - - // window handle - needed on Windows and must be app window. -#if LL_WINDOWS - char window_title[ MAX_PATH ]; - GetConsoleTitleA( window_title, MAX_PATH ); - void* native_window_handle = (void*)FindWindowA( NULL, window_title ); -#else - void* native_window_handle = 0; -#endif - - // main browser initialization - bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle ); - if ( result ) - { - mInitState = INIT_STATE_INITIALIZED; - - return true; - }; - - return false; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - bool initBrowserWindow() - { - // already initialized - if ( mInitState > INIT_STATE_INITIALIZED ) - return true; - - // not enough information to initialize the browser yet. - if ( mWidth < 0 || mHeight < 0 || mDepth < 0 || - mTextureWidth < 0 || mTextureHeight < 0 ) - { - return false; - }; - - // Set up host language before creating browser window - if(!mHostLanguage.empty()) - { - LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage); - } - - // turn on/off cookies based on what host app tells us - LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); - - // turn on/off plugins based on what host app tells us - LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); - - // turn on/off Javascript based on what host app tells us - LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); - - // create single browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget); - - // tell LLQtWebKit about the size of the browser window - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - - // observer events that LLQtWebKit emits - LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); - - // append details to agent string - LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); - -#if !LL_QTWEBKIT_USES_PIXMAPS - // don't flip bitmap - LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); -#endif // !LL_QTWEBKIT_USES_PIXMAPS - - // set background color - // convert background color channels from [0.0, 1.0] to [0, 255]; - LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); - - // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. - setInitState(INIT_STATE_NAVIGATING); - - // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. - // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially - // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. - // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E" - // where RRGGBB is the background color in HTML style - std::stringstream url; - - url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#"; - // convert background color channels from [0.0, 1.0] to [0, 255]; - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); - url << "%22%3E%3C/body%3E%3C/html%3E"; - - //lldebugs << "data url is: " << url.str() << llendl; - - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); -// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); - - return true; - } - - void setVolume(F32 vol); - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onCursorChanged(const EventType& event) - { - LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue(); - std::string name; - - switch(llqt_cursor) - { - case LLQtWebKit::C_ARROW: - name = "arrow"; - break; - case LLQtWebKit::C_IBEAM: - name = "ibeam"; - break; - case LLQtWebKit::C_SPLITV: - name = "splitv"; - break; - case LLQtWebKit::C_SPLITH: - name = "splith"; - break; - case LLQtWebKit::C_POINTINGHAND: - name = "hand"; - break; - - default: - llwarns << "Unknown cursor ID: " << (int)llqt_cursor << llendl; - break; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); - message.setValue("name", name); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onPageChanged( const EventType& event ) - { - if(mInitState == INIT_STATE_WAIT_REDRAW) - { - setInitState(INIT_STATE_WAIT_COMPLETE); - } - - // flag that an update is required - mNeedsUpdate = true; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateBegin(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - message.setValue("uri", event.getEventUri()); - message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); - message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); - sendMessage(message); - - setStatus(STATUS_LOADING); - } - - if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) - { - // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary. -// setInitState(INIT_STATE_WAIT_REDRAW); - setInitState(INIT_STATE_WAIT_COMPLETE); - } - - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateComplete(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - if(mInitState < INIT_STATE_RUNNING) - { - setInitState(INIT_STATE_RUNNING); - - // Clear the history, so the "back" button doesn't take you back to "about:blank". - LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - message.setValue("uri", event.getEventUri()); - message.setValueS32("result_code", event.getIntValue()); - message.setValue("result_string", event.getStringValue()); - message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); - message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); - sendMessage(message); - - setStatus(STATUS_LOADED); - } - else if(mInitState == INIT_STATE_NAVIGATING) - { - setInitState(INIT_STATE_NAVIGATE_COMPLETE); - } - - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onUpdateProgress(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress"); - message.setValueS32("percent", event.getIntValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onStatusTextChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", event.getStringValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onTitleChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", event.getStringValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateErrorPage(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_error_page"); - message.setValueS32("status_code", event.getIntValue()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLocationChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", event.getEventUri()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onClickLinkHref(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); - message.setValue("uri", event.getEventUri()); - message.setValue("target", event.getStringValue()); - message.setValue("uuid", event.getStringValue2()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onClickLinkNoFollow(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", event.getEventUri()); -#if LLQTWEBKIT_API_VERSION >= 7 - message.setValue("nav_type", event.getNavigationType()); -#else - message.setValue("nav_type", "clicked"); -#endif - sendMessage(message); - } - - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onCookieChanged(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set"); - message.setValue("cookie", event.getStringValue()); - // These could be passed through as well, but aren't really needed. -// message.setValue("uri", event.getEventUri()); -// message.setValueBoolean("dead", (event.getIntValue() != 0)) - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowCloseRequested(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "close_request"); - message.setValue("uuid", event.getStringValue()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowGeometryChangeRequested(const EventType& event) - { - int x, y, width, height; - event.getRectValue(x, y, width, height); - - // This sometimes gets called with a zero-size request. Don't pass these along. - if(width > 0 && height > 0) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "geometry_change"); - message.setValue("uuid", event.getStringValue()); - message.setValueS32("x", x); - message.setValueS32("y", y); - message.setValueS32("width", width); - message.setValueS32("height", height); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - std::string onRequestFilePicker( const EventType& eventIn ) - { - return blockingPickFile(); - } - - std::string mAuthUsername; - std::string mAuthPassword; - bool mAuthOK; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) - { - mAuthOK = false; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); - message.setValue("url", in_url); - message.setValue("realm", in_realm); - message.setValueBoolean("blocking_request", true); - - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); - - if(mAuthOK) - { - out_username = mAuthUsername; - out_password = mAuthPassword; - } - - return mAuthOK; - } - - void authResponse(LLPluginMessage &message) - { - mAuthOK = message.getValueBoolean("ok"); - if(mAuthOK) - { - mAuthUsername = message.getValue("username"); - mAuthPassword = message.getValue("password"); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLinkHovered(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered"); - message.setValue("link", event.getEventUri()); - message.setValue("title", event.getStringValue()); - message.setValue("text", event.getStringValue2()); - sendMessage(message); - } - } - - LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) - { - int result = 0; - - if(modifiers.find("shift") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_SHIFT; - - if(modifiers.find("alt") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_ALT; - - if(modifiers.find("control") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_CONTROL; - - if(modifiers.find("meta") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_META; - - return (LLQtWebKit::EKeyboardModifier)result; - } - - //////////////////////////////////////////////////////////////////////////////// - // - void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers ) - { - native_scan_code = 0; - native_virtual_key = 0; - native_modifiers = 0; - - if( native_key_data.isMap() ) - { -#if LL_DARWIN - native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#elif LL_WINDOWS - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - // TODO: I don't think we need to do anything with native modifiers here -- please verify -#elif LL_LINUX - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#else - // Add other platforms here as needed -#endif - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) - { - // The incoming values for 'key' will be the ones from indra_constants.h - std::string utf8_text; - - if(key < KEY_SPECIAL) - { - // Low-ascii characters need to get passed through. - utf8_text = (char)key; - } - - // Any special-case handling we want to do for particular keys... - switch((KEY)key) - { - // ASCII codes for some standard keys - case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break; - case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break; - case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break; - case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break; - case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } - -// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl; - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); - - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - - checkEditState(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) - { - uint32_t key = LLQtWebKit::KEY_NONE; - -// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl; - - if(utf8str.size() == 1) - { - // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. - // In this case, use it as the key value. - key = utf8str[0]; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); - - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - - checkEditState(); - }; - - void checkEditState(void) - { - bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT); - bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY); - bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE); - - if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); - - if(can_cut != mCanCut) - { - mCanCut = can_cut; - message.setValueBoolean("cut", can_cut); - } - - if(can_copy != mCanCopy) - { - mCanCopy = can_copy; - message.setValueBoolean("copy", can_copy); - } - - if(can_paste != mCanPaste) - { - mCanPaste = can_paste; - message.setValueBoolean("paste", can_paste); - } - - sendMessage(message); - - } - } - - std::string mPickedFile; - - std::string blockingPickFile(void) - { - mPickedFile.clear(); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); - message.setValueBoolean("blocking_request", true); - - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); - - return mPickedFile; - } - - void onPickFileResponse(const std::string &file) - { - mPickedFile = file; - } - -}; - -MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : - MediaPluginBase(host_send_func, host_user_data) -{ -// std::cerr << "MediaPluginWebKit constructor" << std::endl; - - mBrowserWindowId = 0; - mInitState = INIT_STATE_UNINITIALIZED; - mNeedsUpdate = true; - mCanCut = false; - mCanCopy = false; - mCanPaste = false; - mLastMouseX = 0; - mLastMouseY = 0; - mFirstFocus = true; - mBackgroundR = 0.0f; - mBackgroundG = 0.0f; - mBackgroundB = 0.0f; - - mHostLanguage = "en"; // default to english - mJavascriptEnabled = true; // default to on - mPluginsEnabled = true; // default to on - mUserAgent = "LLPluginMedia Web Browser"; -} - -MediaPluginWebKit::~MediaPluginWebKit() -{ - // unhook observer - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - - // clean up - LLQtWebKit::getInstance()->reset(); - -// std::cerr << "MediaPluginWebKit destructor" << std::endl; -} - -void MediaPluginWebKit::receiveMessage(const char *message_string) -{ -// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "Webkit media plugin, Webkit version "; - plugin_version += LLQtWebKit::getInstance()->getVersion(); - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - // DTOR most likely won't be called but the recent change to the way this process - // is (not) killed means we see this message and can do what we need to here. - // Note: this cleanup is ultimately what writes cookies to the disk - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - LLQtWebKit::getInstance()->reset(); - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - -// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name -// << ", size: " << info.mSize -// << ", address: " << info.mAddress -// << std::endl; - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - -// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl; - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if(message_name == "set_volume") - { - F32 volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - mTarget = message_in.getValue("target"); - - // This is the media init message -- all necessary data for initialization should have been received. - if(initBrowser()) - { - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGBA); - #if LL_QTWEBKIT_USES_PIXMAPS - message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck. - #else - message.setValueU32("format", GL_RGBA); - #endif // LL_QTWEBKIT_USES_PIXMAPS - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else - { - // if initialization failed, we're done. - mDeleteMe = true; - } - - } - else if(message_name == "set_user_data_path") - { - std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter - mProfileDir = user_data_path + "browser_profile"; - - // FIXME: Should we do anything with this if it comes in after the browser has been initialized? - } - else if(message_name == "set_language_code") - { - mHostLanguage = message_in.getValue("language"); - - // FIXME: Should we do anything with this if it comes in after the browser has been initialized? - } - else if(message_name == "plugins_enabled") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - } - else if(message_name == "javascript_enabled") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - mBackgroundR = message_in.getValueReal("background_r"); - mBackgroundG = message_in.getValueReal("background_g"); - mBackgroundB = message_in.getValueReal("background_b"); -// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - if(initBrowserWindow()) - { - - // size changed so tell the browser - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - - // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight - // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; - - S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); - - // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. - if(real_width <= texture_width) - { - texture_width = real_width; - } - else - { - // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. - // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; - mDeleteMe = true; - return; - } - } - else - { - // Setting up the browser window failed. This is a fatal error. - mDeleteMe = true; - } - - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - - }; - }; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if(message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - -// std::cout << "loading URI: " << uri << std::endl; - - if(!uri.empty()) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri ); - } - else - { - mInitialNavigateURL = uri; - } - } - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - S32 button = message_in.getValueS32("button"); - mLastMouseX = message_in.getValueS32("x"); - mLastMouseY = message_in.getValueS32("y"); - std::string modifiers = message_in.getValue("modifiers"); - - // Treat unknown mouse events as mouse-moves. - LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE; - if(event == "down") - { - mouse_event = LLQtWebKit::ME_MOUSE_DOWN; - } - else if(event == "up") - { - mouse_event = LLQtWebKit::ME_MOUSE_UP; - } - else if(event == "double_click") - { - mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK; - } - - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers)); - checkEditState(); - } - else if(message_name == "scroll_event") - { - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - std::string modifiers = message_in.getValue("modifiers"); - - // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit. - // Qt expects 1 detent to be 120 units. - // It also seems that our y scroll direction is inverted vs. what Qt expects. - - x *= 120; - y *= -120; - - LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers)); - } - else if(message_name == "key_event") - { - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - // Treat unknown events as key-up for safety. - LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP; - if(event == "down") - { - key_event = LLQtWebKit::KE_KEY_DOWN; - } - else if(event == "repeat") - { - key_event = LLQtWebKit::KE_KEY_REPEAT; - } - - keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); - } - else if(message_name == "text_event") - { - std::string text = message_in.getValue("text"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - unicodeInput(text, decodeModifiers(modifiers), native_key_data); - } - if(message_name == "edit_cut") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT ); - checkEditState(); - } - if(message_name == "edit_copy") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY ); - checkEditState(); - } - if(message_name == "edit_paste") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE ); - checkEditState(); - } - if(message_name == "pick_file_response") - { - onPickFileResponse(message_in.getValue("file")); - } - if(message_name == "auth_response") - { - authResponse(message_in); - } - else - if(message_name == "js_enable_object") - { -#if LLQTWEBKIT_API_VERSION >= 9 - bool enable = message_in.getValueBoolean( "enable" ); - LLQtWebKit::getInstance()->setSLObjectEnabled( enable ); -#endif - } - else - if(message_name == "js_agent_location") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 x = message_in.getValueReal("x"); - F32 y = message_in.getValueReal("y"); - F32 z = message_in.getValueReal("z"); - LLQtWebKit::getInstance()->setAgentLocation( x, y, z ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_global_location") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 x = message_in.getValueReal("x"); - F32 y = message_in.getValueReal("y"); - F32 z = message_in.getValueReal("z"); - LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_orientation") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 angle = message_in.getValueReal("angle"); - LLQtWebKit::getInstance()->setAgentOrientation( angle ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_region") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& region = message_in.getValue("region"); - LLQtWebKit::getInstance()->setAgentRegion( region ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_maturity") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& maturity = message_in.getValue("maturity"); - LLQtWebKit::getInstance()->setAgentMaturity( maturity ); - LLQtWebKit::getInstance()->emitMaturity(); -#endif - } - else - if(message_name == "js_agent_language") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& language = message_in.getValue("language"); - LLQtWebKit::getInstance()->setAgentLanguage( language ); - LLQtWebKit::getInstance()->emitLanguage(); -#endif - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - if(message_name == "focus") - { - bool val = message_in.getValueBoolean("focused"); - LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val ); - - if(mFirstFocus && val) - { - // On the first focus, post a tab key event. This fixes a problem with initial focus. - std::string empty; - keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty)); - keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty)); - mFirstFocus = false; - } - } - else if(message_name == "clear_cache") - { - LLQtWebKit::getInstance()->clearCache(); - } - else if(message_name == "clear_cookies") - { - LLQtWebKit::getInstance()->clearAllCookies(); - } - else if(message_name == "enable_cookies") - { - mCookiesEnabled = message_in.getValueBoolean("enable"); - LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); - } - else if(message_name == "enable_plugins") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); - } - else if(message_name == "enable_javascript") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); - } - else if(message_name == "set_cookies") - { - LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies")); - } - else if(message_name == "proxy_setup") - { - bool val = message_in.getValueBoolean("enable"); - std::string host = message_in.getValue("host"); - int port = message_in.getValueS32("port"); - LLQtWebKit::getInstance()->enableProxy( val, host, port ); - } - else if(message_name == "browse_stop") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP ); - } - else if(message_name == "browse_reload") - { - // foo = message_in.getValueBoolean("ignore_cache"); - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD ); - } - else if(message_name == "browse_forward") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD ); - } - else if(message_name == "browse_back") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK ); - } - else if(message_name == "set_status_redirect") - { - int code = message_in.getValueS32("code"); - std::string url = message_in.getValue("url"); - if ( 404 == code ) // browser lib only supports 404 right now - { -#if LLQTWEBKIT_API_VERSION < 8 - LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url ); -#endif - }; - } - else if(message_name == "set_user_agent") - { - mUserAgent = message_in.getValue("user_agent"); - LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); - } - else if(message_name == "ignore_ssl_cert_errors") - { -#if LLQTWEBKIT_API_VERSION >= 3 - LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") ); -#else - llwarns << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << llendl; -#endif - } - else if(message_name == "add_certificate_file_path") - { -#if LLQTWEBKIT_API_VERSION >= 6 - LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") ); -#else - llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl; -#endif - } - else if(message_name == "init_history") - { - // Initialize browser history - LLSD history = message_in.getValueLLSD("history"); - // First, clear the URL history - LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); - // Then, add the history items in order - LLSD::array_iterator iter_history = history.beginArray(); - LLSD::array_iterator end_history = history.endArray(); - for(; iter_history != end_history; ++iter_history) - { - std::string url = (*iter_history).asString(); - if(! url.empty()) { - LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url); - } - } - } - else if(message_name == "proxy_window_opened") - { - std::string target = message_in.getValue("target"); - std::string uuid = message_in.getValue("uuid"); - LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid); - } - else if(message_name == "proxy_window_closed") - { - std::string uuid = message_in.getValue("uuid"); - LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl; - }; - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } -} - -void MediaPluginWebKit::setVolume(F32 volume) -{ - mVolumeCatcher.setVolume(volume); -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); - *plugin_send_func = MediaPluginWebKit::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} - - +/**
+ * @file media_plugin_webkit.cpp
+ * @brief Webkit plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "llqtwebkit.h"
+
+#include "linden_common.h"
+#include "indra_constants.h" // for indra keyboard codes
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified
+#if LL_LINUX
+# define LL_QTWEBKIT_USES_PIXMAPS 0
+extern "C" {
+# include <glib.h>
+# include <glib-object.h>
+}
+#else
+# define LL_QTWEBKIT_USES_PIXMAPS 0
+#endif // LL_LINUX
+
+# include "volume_catcher.h"
+
+#if LL_WINDOWS
+# include <direct.h>
+#else
+# include <unistd.h>
+# include <stdlib.h>
+#endif
+
+#if LL_WINDOWS
+ // *NOTE:Mani - This captures the module handle for the dll. This is used below
+ // to get the path to this dll for webkit initialization.
+ // I don't know how/if this can be done with apr...
+ namespace { HMODULE gModuleHandle;};
+ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+ {
+ gModuleHandle = (HMODULE) hinstDLL;
+ return TRUE;
+ }
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginWebKit :
+ public MediaPluginBase,
+ public LLEmbeddedBrowserWindowObserver
+{
+public:
+ MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginWebKit();
+
+ /*virtual*/ void receiveMessage(const char *message_string);
+
+private:
+
+ std::string mProfileDir;
+ std::string mHostLanguage;
+ std::string mUserAgent;
+ bool mCookiesEnabled;
+ bool mJavascriptEnabled;
+ bool mPluginsEnabled;
+ bool mEnableMediaPluginDebugging;
+
+ enum
+ {
+ INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet
+ INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet.
+ INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued
+ INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed
+ INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws
+ INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event
+ INIT_STATE_RUNNING // All initialization gymnastics are complete.
+ };
+ int mBrowserWindowId;
+ int mInitState;
+ std::string mInitialNavigateURL;
+ bool mNeedsUpdate;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+ int mLastMouseX;
+ int mLastMouseY;
+ bool mFirstFocus;
+ F32 mBackgroundR;
+ F32 mBackgroundG;
+ F32 mBackgroundB;
+ std::string mTarget;
+
+ VolumeCatcher mVolumeCatcher;
+
+ void postDebugMessage( const std::string& msg )
+ {
+ if ( mEnableMediaPluginDebugging )
+ {
+ LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message");
+ debug_message.setValue("message_text", "Media> " + msg);
+ debug_message.setValue("message_level", "info");
+ sendMessage(debug_message);
+ }
+ }
+
+ void setInitState(int state)
+ {
+// std::cerr << "changing init state to " << state << std::endl;
+ mInitState = state;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void update(int milliseconds)
+ {
+#if LL_QTLINUX_DOESNT_HAVE_GLIB
+ // pump glib generously, as Linux browser plugins are on the
+ // glib main loop, even if the browser itself isn't - ugh
+ // This is NOT NEEDED if Qt itself was built with glib
+ // mainloop integration.
+ GMainContext *mainc = g_main_context_default();
+ while(g_main_context_iteration(mainc, FALSE));
+#endif // LL_QTLINUX_DOESNT_HAVE_GLIB
+
+ // pump qt
+ LLQtWebKit::getInstance()->pump( milliseconds );
+
+ mVolumeCatcher.pump();
+
+ checkEditState();
+
+ if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ if(!mInitialNavigateURL.empty())
+ {
+ // We already have the initial navigate URL -- kick off the navigate.
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL );
+ mInitialNavigateURL.clear();
+ }
+ }
+
+ if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate )
+ {
+ const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
+
+ unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId );
+ unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
+#if !LL_QTWEBKIT_USES_PIXMAPS
+ unsigned int buffer_size = rowspan * height;
+#endif // !LL_QTWEBKIT_USES_PIXMAPS
+
+// std::cerr << "webkit plugin: updating" << std::endl;
+
+ // TODO: should get rid of this memcpy if possible
+ if ( mPixels && browser_pixels )
+ {
+// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl;
+
+#if LL_QTWEBKIT_USES_PIXMAPS
+ // copy the pixel data upside-down because of the co-ord system
+ for (int y=0; y<height; ++y)
+ {
+ memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan );
+ }
+#else
+ memcpy( mPixels, browser_pixels, buffer_size );
+#endif // LL_QTWEBKIT_USES_PIXMAPS
+ }
+
+ if ( mWidth > 0 && mHeight > 0 )
+ {
+// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl;
+ setDirty( 0, 0, mWidth, mHeight );
+ }
+
+ mNeedsUpdate = false;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ bool initBrowser()
+ {
+ // already initialized
+ if ( mInitState > INIT_STATE_UNINITIALIZED )
+ return true;
+
+ // set up directories
+ char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use
+ if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
+ {
+ llwarns << "Couldn't get cwd - probably too long - failing to init." << llendl;
+ return false;
+ }
+ std::string application_dir = std::string( cwd );
+
+#if LL_LINUX
+ // take care to initialize glib properly, because some
+ // versions of Qt don't, and we indirectly need it for (some
+ // versions of) Flash to not crash the browser.
+ if (!g_thread_supported ()) g_thread_init (NULL);
+ g_type_init();
+#endif
+
+#if LL_DARWIN
+ // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
+ // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
+ // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
+ // which gets hit when the plugin is probed by webkit.
+ // Unsetting the environment variable here works around this issue.
+ unsetenv("USERBREAK");
+#endif
+
+#if LL_WINDOWS
+ //*NOTE:Mani - On windows, at least, the component path is the
+ // location of this dll's image file.
+ std::string component_dir;
+ char dll_path[_MAX_PATH];
+ DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH);
+ while(len && dll_path[ len ] != ('\\') )
+ {
+ len--;
+ }
+ if(len >= 0)
+ {
+ dll_path[len] = 0;
+ component_dir = dll_path;
+ }
+ else
+ {
+ // *NOTE:Mani - This case should be an rare exception.
+ // GetModuleFileNameA should always give you a full path, no?
+ component_dir = application_dir;
+ }
+#else
+ std::string component_dir = application_dir;
+#endif
+
+ // debug spam sent to viewer and displayed in the log as usual
+ postDebugMessage( "Component dir set to: " + component_dir );
+
+ // window handle - needed on Windows and must be app window.
+#if LL_WINDOWS
+ char window_title[ MAX_PATH ];
+ GetConsoleTitleA( window_title, MAX_PATH );
+ void* native_window_handle = (void*)FindWindowA( NULL, window_title );
+#else
+ void* native_window_handle = 0;
+#endif
+
+ // main browser initialization
+ bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
+ if ( result )
+ {
+ mInitState = INIT_STATE_INITIALIZED;
+
+ // debug spam sent to viewer and displayed in the log as usual
+ postDebugMessage( "browser initialized okay" );
+
+ return true;
+ };
+
+ // debug spam sent to viewer and displayed in the log as usual
+ postDebugMessage( "browser nOT initialized." );
+
+ return false;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ bool initBrowserWindow()
+ {
+ // already initialized
+ if ( mInitState > INIT_STATE_INITIALIZED )
+ return true;
+
+ // not enough information to initialize the browser yet.
+ if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
+ mTextureWidth < 0 || mTextureHeight < 0 )
+ {
+ return false;
+ };
+
+ // Set up host language before creating browser window
+ if(!mHostLanguage.empty())
+ {
+ LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage);
+ postDebugMessage( "Setting language to " + mHostLanguage );
+ }
+
+ // turn on/off cookies based on what host app tells us
+ LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
+
+ // turn on/off plugins based on what host app tells us
+ LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
+
+ // turn on/off Javascript based on what host app tells us
+ LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
+
+ std::stringstream str;
+ str << "Cookies enabled = " << mCookiesEnabled << ", plugins enabled = " << mPluginsEnabled << ", Javascript enabled = " << mJavascriptEnabled;
+ postDebugMessage( str.str() );
+
+ // create single browser window
+ mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget);
+
+ str.str("");
+ str.clear();
+ str << "Setting browser window size to " << mWidth << " x " << mHeight;
+ postDebugMessage( str.str() );
+
+ // tell LLQtWebKit about the size of the browser window
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+ // observer events that LLQtWebKit emits
+ LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
+
+ // append details to agent string
+ LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
+ postDebugMessage( "Updating user agent with " + mUserAgent );
+
+#if !LL_QTWEBKIT_USES_PIXMAPS
+ // don't flip bitmap
+ LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
+#endif // !LL_QTWEBKIT_USES_PIXMAPS
+
+ // set background color
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
+
+ // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
+ setInitState(INIT_STATE_NAVIGATING);
+
+ // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
+ // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
+ // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
+ // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
+ // where RRGGBB is the background color in HTML style
+ std::stringstream url;
+
+ url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
+ url << "%22%3E%3C/body%3E%3C/html%3E";
+
+ //lldebugs << "data url is: " << url.str() << llendl;
+
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
+// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+
+ return true;
+ }
+
+ void setVolume(F32 vol);
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onCursorChanged(const EventType& event)
+ {
+ LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue();
+ std::string name;
+
+ switch(llqt_cursor)
+ {
+ case LLQtWebKit::C_ARROW:
+ name = "arrow";
+ break;
+ case LLQtWebKit::C_IBEAM:
+ name = "ibeam";
+ break;
+ case LLQtWebKit::C_SPLITV:
+ name = "splitv";
+ break;
+ case LLQtWebKit::C_SPLITH:
+ name = "splith";
+ break;
+ case LLQtWebKit::C_POINTINGHAND:
+ name = "hand";
+ break;
+
+ default:
+ llwarns << "Unknown cursor ID: " << (int)llqt_cursor << llendl;
+ break;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onPageChanged( const EventType& event )
+ {
+ if(mInitState == INIT_STATE_WAIT_REDRAW)
+ {
+ setInitState(INIT_STATE_WAIT_COMPLETE);
+ }
+
+ // flag that an update is required
+ mNeedsUpdate = true;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onNavigateBegin(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message.setValue("uri", event.getEventUri());
+ message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
+ message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
+ sendMessage(message);
+
+ // debug spam sent to viewer and displayed in the log as usual
+ postDebugMessage( "Navigate begin event at: " + event.getEventUri() );
+
+ setStatus(STATUS_LOADING);
+ }
+
+ if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary.
+// setInitState(INIT_STATE_WAIT_REDRAW);
+ setInitState(INIT_STATE_WAIT_COMPLETE);
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onNavigateComplete(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ if(mInitState < INIT_STATE_RUNNING)
+ {
+ setInitState(INIT_STATE_RUNNING);
+
+ // Clear the history, so the "back" button doesn't take you back to "about:blank".
+ LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message.setValue("uri", event.getEventUri());
+ message.setValueS32("result_code", event.getIntValue());
+ message.setValue("result_string", event.getStringValue());
+ message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
+ message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
+ sendMessage(message);
+
+ setStatus(STATUS_LOADED);
+ }
+ else if(mInitState == INIT_STATE_NAVIGATING)
+ {
+ setInitState(INIT_STATE_NAVIGATE_COMPLETE);
+ }
+
+ // debug spam sent to viewer and displayed in the log as usual
+ postDebugMessage( "Navigate complete event at: " + event.getEventUri() );
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onUpdateProgress(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress");
+ message.setValueS32("percent", event.getIntValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onStatusTextChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text");
+ message.setValue("status", event.getStringValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onTitleChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", event.getStringValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onNavigateErrorPage(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_error_page");
+ message.setValueS32("status_code", event.getIntValue());
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onLocationChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", event.getEventUri());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onClickLinkHref(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
+ message.setValue("uri", event.getEventUri());
+ message.setValue("target", event.getStringValue());
+ message.setValue("uuid", event.getStringValue2());
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onClickLinkNoFollow(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
+ message.setValue("uri", event.getEventUri());
+#if LLQTWEBKIT_API_VERSION >= 7
+ message.setValue("nav_type", event.getNavigationType());
+#else
+ message.setValue("nav_type", "clicked");
+#endif
+ sendMessage(message);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onCookieChanged(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set");
+ message.setValue("cookie", event.getStringValue());
+ // These could be passed through as well, but aren't really needed.
+// message.setValue("uri", event.getEventUri());
+// message.setValueBoolean("dead", (event.getIntValue() != 0))
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onWindowCloseRequested(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "close_request");
+ message.setValue("uuid", event.getStringValue());
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onWindowGeometryChangeRequested(const EventType& event)
+ {
+ int x, y, width, height;
+ event.getRectValue(x, y, width, height);
+
+ // This sometimes gets called with a zero-size request. Don't pass these along.
+ if(width > 0 && height > 0)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "geometry_change");
+ message.setValue("uuid", event.getStringValue());
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ std::string onRequestFilePicker( const EventType& eventIn )
+ {
+ return blockingPickFile();
+ }
+
+ std::string mAuthUsername;
+ std::string mAuthPassword;
+ bool mAuthOK;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password)
+ {
+ mAuthOK = false;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request");
+ message.setValue("url", in_url);
+ message.setValue("realm", in_realm);
+ message.setValueBoolean("blocking_request", true);
+
+ // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
+ sendMessage(message);
+
+ if(mAuthOK)
+ {
+ out_username = mAuthUsername;
+ out_password = mAuthPassword;
+ }
+
+ return mAuthOK;
+ }
+
+ void authResponse(LLPluginMessage &message)
+ {
+ mAuthOK = message.getValueBoolean("ok");
+ if(mAuthOK)
+ {
+ mAuthUsername = message.getValue("username");
+ mAuthPassword = message.getValue("password");
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onLinkHovered(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered");
+ message.setValue("link", event.getEventUri());
+ message.setValue("title", event.getStringValue());
+ message.setValue("text", event.getStringValue2());
+ sendMessage(message);
+ }
+ }
+
+ LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
+ {
+ int result = 0;
+
+ if(modifiers.find("shift") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_SHIFT;
+
+ if(modifiers.find("alt") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_ALT;
+
+ if(modifiers.find("control") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_CONTROL;
+
+ if(modifiers.find("meta") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_META;
+
+ return (LLQtWebKit::EKeyboardModifier)result;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers )
+ {
+ native_scan_code = 0;
+ native_virtual_key = 0;
+ native_modifiers = 0;
+
+ if( native_key_data.isMap() )
+ {
+#if LL_DARWIN
+ native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger());
+ native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+#elif LL_WINDOWS
+ native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+ // TODO: I don't think we need to do anything with native modifiers here -- please verify
+#elif LL_LINUX
+ native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
+ native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+ native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+#else
+ // Add other platforms here as needed
+#endif
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
+ {
+ // The incoming values for 'key' will be the ones from indra_constants.h
+ std::string utf8_text;
+
+ if(key < KEY_SPECIAL)
+ {
+ // Low-ascii characters need to get passed through.
+ utf8_text = (char)key;
+ }
+
+ // Any special-case handling we want to do for particular keys...
+ switch((KEY)key)
+ {
+ // ASCII codes for some standard keys
+ case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break;
+ case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break;
+ case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break;
+ case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break;
+ case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break;
+
+ default:
+ break;
+ }
+
+// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl;
+
+ uint32_t native_scan_code = 0;
+ uint32_t native_virtual_key = 0;
+ uint32_t native_modifiers = 0;
+ deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
+
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
+
+ checkEditState();
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
+ {
+ uint32_t key = LLQtWebKit::KEY_NONE;
+
+// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl;
+
+ if(utf8str.size() == 1)
+ {
+ // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character.
+ // In this case, use it as the key value.
+ key = utf8str[0];
+ }
+
+ uint32_t native_scan_code = 0;
+ uint32_t native_virtual_key = 0;
+ uint32_t native_modifiers = 0;
+ deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
+
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
+ LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
+
+ checkEditState();
+ };
+
+ void checkEditState(void)
+ {
+ bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT);
+ bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY);
+ bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE);
+
+ if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste))
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state");
+
+ if(can_cut != mCanCut)
+ {
+ mCanCut = can_cut;
+ message.setValueBoolean("cut", can_cut);
+ }
+
+ if(can_copy != mCanCopy)
+ {
+ mCanCopy = can_copy;
+ message.setValueBoolean("copy", can_copy);
+ }
+
+ if(can_paste != mCanPaste)
+ {
+ mCanPaste = can_paste;
+ message.setValueBoolean("paste", can_paste);
+ }
+
+ sendMessage(message);
+
+ }
+ }
+
+ std::string mPickedFile;
+
+ std::string blockingPickFile(void)
+ {
+ mPickedFile.clear();
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file");
+ message.setValueBoolean("blocking_request", true);
+
+ // The "blocking_request" key in the message means this sendMessage call will block until a response is received.
+ sendMessage(message);
+
+ return mPickedFile;
+ }
+
+ void onPickFileResponse(const std::string &file)
+ {
+ mPickedFile = file;
+ }
+
+};
+
+MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+ MediaPluginBase(host_send_func, host_user_data)
+{
+// std::cerr << "MediaPluginWebKit constructor" << std::endl;
+
+ mBrowserWindowId = 0;
+ mInitState = INIT_STATE_UNINITIALIZED;
+ mNeedsUpdate = true;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mFirstFocus = true;
+ mBackgroundR = 0.0f;
+ mBackgroundG = 0.0f;
+ mBackgroundB = 0.0f;
+
+ mHostLanguage = "en"; // default to english
+ mJavascriptEnabled = true; // default to on
+ mPluginsEnabled = true; // default to on
+ mEnableMediaPluginDebugging = false;
+ mUserAgent = "LLPluginMedia Web Browser";
+}
+
+MediaPluginWebKit::~MediaPluginWebKit()
+{
+ // unhook observer
+ LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
+
+ // clean up
+ LLQtWebKit::getInstance()->reset();
+
+// std::cerr << "MediaPluginWebKit destructor" << std::endl;
+}
+
+void MediaPluginWebKit::receiveMessage(const char *message_string)
+{
+// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+ LLPluginMessage message_in;
+
+ if(message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if(message_name == "init")
+ {
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::string plugin_version = "Webkit media plugin, Webkit version ";
+ plugin_version += LLQtWebKit::getInstance()->getVersion();
+ message.setValue("plugin_version", plugin_version);
+ sendMessage(message);
+ }
+ else if(message_name == "idle")
+ {
+ // no response is necessary here.
+ F64 time = message_in.getValueReal("time");
+
+ // Convert time to milliseconds for update()
+ update((int)(time * 1000.0f));
+ }
+ else if(message_name == "cleanup")
+ {
+ // DTOR most likely won't be called but the recent change to the way this process
+ // is (not) killed means we see this message and can do what we need to here.
+ // Note: this cleanup is ultimately what writes cookies to the disk
+ LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
+ LLQtWebKit::getInstance()->reset();
+ }
+ else if(message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name
+// << ", size: " << info.mSize
+// << ", address: " << info.mAddress
+// << std::endl;
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl;
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ if(mPixels == iter->second.mAddress)
+ {
+ // This is the currently active pixel buffer. Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if(message_name == "set_volume")
+ {
+ F32 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if(message_name == "init")
+ {
+ mTarget = message_in.getValue("target");
+
+ // This is the media init message -- all necessary data for initialization should have been received.
+ if(initBrowser())
+ {
+
+ // Plugin gets to decide the texture parameters to use.
+ mDepth = 4;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGBA);
+ #if LL_QTWEBKIT_USES_PIXMAPS
+ message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck.
+ #else
+ message.setValueU32("format", GL_RGBA);
+ #endif // LL_QTWEBKIT_USES_PIXMAPS
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else
+ {
+ // if initialization failed, we're done.
+ mDeleteMe = true;
+ }
+
+ }
+ else if(message_name == "set_user_data_path")
+ {
+ std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter
+ mProfileDir = user_data_path + "browser_profile";
+
+ // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
+ }
+ else if(message_name == "set_language_code")
+ {
+ mHostLanguage = message_in.getValue("language");
+
+ // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
+ }
+ else if(message_name == "plugins_enabled")
+ {
+ mPluginsEnabled = message_in.getValueBoolean("enable");
+ }
+ else if(message_name == "javascript_enabled")
+ {
+ mJavascriptEnabled = message_in.getValueBoolean("enable");
+ }
+ else if(message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+ mBackgroundR = message_in.getValueReal("background_r");
+ mBackgroundG = message_in.getValueReal("background_g");
+ mBackgroundB = message_in.getValueReal("background_b");
+// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha
+
+ if(!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+
+ if(initBrowserWindow())
+ {
+
+ // size changed so tell the browser
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+ // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
+ // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
+
+ S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
+
+ // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
+ if(real_width <= texture_width)
+ {
+ texture_width = real_width;
+ }
+ else
+ {
+ // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
+ // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
+ mDeleteMe = true;
+ return;
+ }
+ }
+ else
+ {
+ // Setting up the browser window failed. This is a fatal error.
+ mDeleteMe = true;
+ }
+
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ }
+ else if(message_name == "load_uri")
+ {
+ std::string uri = message_in.getValue("uri");
+
+// std::cout << "loading URI: " << uri << std::endl;
+
+ if(!uri.empty())
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri );
+ }
+ else
+ {
+ mInitialNavigateURL = uri;
+ }
+ }
+ }
+ else if(message_name == "mouse_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 button = message_in.getValueS32("button");
+ mLastMouseX = message_in.getValueS32("x");
+ mLastMouseY = message_in.getValueS32("y");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ // Treat unknown mouse events as mouse-moves.
+ LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE;
+ if(event == "down")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
+ }
+ else if(event == "up")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_UP;
+ }
+ else if(event == "double_click")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK;
+ }
+
+ LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers));
+ checkEditState();
+ }
+ else if(message_name == "scroll_event")
+ {
+ S32 x = message_in.getValueS32("x");
+ S32 y = message_in.getValueS32("y");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit.
+ // Qt expects 1 detent to be 120 units.
+ // It also seems that our y scroll direction is inverted vs. what Qt expects.
+
+ x *= 120;
+ y *= -120;
+
+ LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers));
+ }
+ else if(message_name == "key_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 key = message_in.getValueS32("key");
+ std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
+
+ // Treat unknown events as key-up for safety.
+ LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
+ if(event == "down")
+ {
+ key_event = LLQtWebKit::KE_KEY_DOWN;
+ }
+ else if(event == "repeat")
+ {
+ key_event = LLQtWebKit::KE_KEY_REPEAT;
+ }
+
+ keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
+ }
+ else if(message_name == "text_event")
+ {
+ std::string text = message_in.getValue("text");
+ std::string modifiers = message_in.getValue("modifiers");
+ LLSD native_key_data = message_in.getValueLLSD("native_key_data");
+
+ unicodeInput(text, decodeModifiers(modifiers), native_key_data);
+ }
+ if(message_name == "edit_cut")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT );
+ checkEditState();
+ }
+ if(message_name == "edit_copy")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY );
+ checkEditState();
+ }
+ if(message_name == "edit_paste")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE );
+ checkEditState();
+ }
+ if(message_name == "pick_file_response")
+ {
+ onPickFileResponse(message_in.getValue("file"));
+ }
+ if(message_name == "auth_response")
+ {
+ authResponse(message_in);
+ }
+ else
+ if(message_name == "enable_media_plugin_debugging")
+ {
+ mEnableMediaPluginDebugging = message_in.getValueBoolean( "enable" );
+ }
+
+ else
+ if(message_name == "js_enable_object")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ bool enable = message_in.getValueBoolean( "enable" );
+ LLQtWebKit::getInstance()->setSLObjectEnabled( enable );
+#endif
+ }
+ else
+ if(message_name == "js_agent_location")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 x = message_in.getValueReal("x");
+ F32 y = message_in.getValueReal("y");
+ F32 z = message_in.getValueReal("z");
+ LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_global_location")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 x = message_in.getValueReal("x");
+ F32 y = message_in.getValueReal("y");
+ F32 z = message_in.getValueReal("z");
+ LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_orientation")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 angle = message_in.getValueReal("angle");
+ LLQtWebKit::getInstance()->setAgentOrientation( angle );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_region")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& region = message_in.getValue("region");
+ LLQtWebKit::getInstance()->setAgentRegion( region );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_maturity")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& maturity = message_in.getValue("maturity");
+ LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+ LLQtWebKit::getInstance()->emitMaturity();
+#endif
+ }
+ else
+ if(message_name == "js_agent_language")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& language = message_in.getValue("language");
+ LLQtWebKit::getInstance()->setAgentLanguage( language );
+ LLQtWebKit::getInstance()->emitLanguage();
+#endif
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ if(message_name == "focus")
+ {
+ bool val = message_in.getValueBoolean("focused");
+ LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );
+
+ if(mFirstFocus && val)
+ {
+ // On the first focus, post a tab key event. This fixes a problem with initial focus.
+ std::string empty;
+ keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
+ keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
+ mFirstFocus = false;
+ }
+ }
+ else if(message_name == "clear_cache")
+ {
+ LLQtWebKit::getInstance()->clearCache();
+ }
+ else if(message_name == "clear_cookies")
+ {
+ LLQtWebKit::getInstance()->clearAllCookies();
+ }
+ else if(message_name == "enable_cookies")
+ {
+ mCookiesEnabled = message_in.getValueBoolean("enable");
+ LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
+ }
+ else if(message_name == "enable_plugins")
+ {
+ mPluginsEnabled = message_in.getValueBoolean("enable");
+ LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
+ }
+ else if(message_name == "enable_javascript")
+ {
+ mJavascriptEnabled = message_in.getValueBoolean("enable");
+ //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
+ }
+ else if(message_name == "set_cookies")
+ {
+ LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies"));
+ }
+ else if(message_name == "proxy_setup")
+ {
+ bool val = message_in.getValueBoolean("enable");
+ std::string host = message_in.getValue("host");
+ int port = message_in.getValueS32("port");
+ LLQtWebKit::getInstance()->enableProxy( val, host, port );
+ }
+ else if(message_name == "browse_stop")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP );
+ }
+ else if(message_name == "browse_reload")
+ {
+ // foo = message_in.getValueBoolean("ignore_cache");
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD );
+ }
+ else if(message_name == "browse_forward")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD );
+ }
+ else if(message_name == "browse_back")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK );
+ }
+ else if(message_name == "set_status_redirect")
+ {
+ int code = message_in.getValueS32("code");
+ std::string url = message_in.getValue("url");
+ if ( 404 == code ) // browser lib only supports 404 right now
+ {
+#if LLQTWEBKIT_API_VERSION < 8
+ LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url );
+#endif
+ };
+ }
+ else if(message_name == "set_user_agent")
+ {
+ mUserAgent = message_in.getValue("user_agent");
+ LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
+ }
+ else if(message_name == "show_web_inspector")
+ {
+#if LLQTWEBKIT_API_VERSION >= 10
+ bool val = message_in.getValueBoolean("show");
+ LLQtWebKit::getInstance()->showWebInspector( val );
+#else
+ llwarns << "Ignoring showWebInspector message (llqtwebkit version is too old)." << llendl;
+#endif
+ }
+ else if(message_name == "ignore_ssl_cert_errors")
+ {
+#if LLQTWEBKIT_API_VERSION >= 3
+ LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") );
+#else
+ llwarns << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << llendl;
+#endif
+ }
+ else if(message_name == "add_certificate_file_path")
+ {
+#if LLQTWEBKIT_API_VERSION >= 6
+ LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") );
+#else
+ llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl;
+#endif
+ }
+ else if(message_name == "init_history")
+ {
+ // Initialize browser history
+ LLSD history = message_in.getValueLLSD("history");
+ // First, clear the URL history
+ LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
+ // Then, add the history items in order
+ LLSD::array_iterator iter_history = history.beginArray();
+ LLSD::array_iterator end_history = history.endArray();
+ for(; iter_history != end_history; ++iter_history)
+ {
+ std::string url = (*iter_history).asString();
+ if(! url.empty()) {
+ LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url);
+ }
+ }
+ }
+ else if(message_name == "proxy_window_opened")
+ {
+ std::string target = message_in.getValue("target");
+ std::string uuid = message_in.getValue("uuid");
+ LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid);
+ }
+ else if(message_name == "proxy_window_closed")
+ {
+ std::string uuid = message_in.getValue("uuid");
+ LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl;
+ };
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl;
+ };
+ }
+}
+
+void MediaPluginWebKit::setVolume(F32 volume)
+{
+ mVolumeCatcher.setVolume(volume);
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginWebKit::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
+
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6fc7e51ca2..11b19ca4fe 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1798,7 +1798,7 @@ if (LINUX) set(product SecondLife-${ARCH}-${viewer_VERSION}) # These are the generated targets that are copied to package/ - set(COPY_INPUT_DEPENDENCIES + set(COPY_INPUT_DEPENDENCIES ${VIEWER_BINARY_NAME} linux-crash-logger linux-updater diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 781431d4de..e2f98c0bac 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -798,6 +798,61 @@ <key>Value</key> <integer>5</integer> </map> + <key>Socks5ProxyEnabled</key> + <map> + <key>Comment</key> + <string>Use Socks5 Proxy</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>HttpProxyType</key> + <map> + <key>Comment</key> + <string>Proxy type to use for HTTP operations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Socks</string> + </map> + <key>Socks5ProxyHost</key> + <map> + <key>Comment</key> + <string>Socks 5 Proxy Host</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string></string> + </map> + <key>Socks5ProxyPort</key> + <map> + <key>Comment</key> + <string>Socks 5 Proxy Port</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1080</integer> + </map> + <key>Socks5AuthType</key> + <map> + <key>Comment</key> + <string>Selected Auth mechanism for Socks5</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>None</string> + </map> <key>BuildAxisDeadZone0</key> <map> <key>Comment</key> @@ -1629,17 +1684,6 @@ <string /> </array> </map> - <key>CompressSnapshotsToDisk</key> - <map> - <key>Comment</key> - <string>Compress snapshots saved to disk (Using JPEG 2000)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>ConnectAsGod</key> <map> <key>Comment</key> @@ -1814,7 +1858,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>Cursor3D</key> <map> @@ -4004,7 +4048,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://search-beta.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string> + <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string> </map> <key>WebProfileURL</key> <map> @@ -5448,6 +5492,17 @@ <key>Value</key> <real>60.0</real> </map> + <key>MediaPluginDebugging</key> + <map> + <key>Comment</key> + <string>Turn on debugging messages that may help diagnosing media issues (WARNING: May reduce performance).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MediaControlFadeTime</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl new file mode 100644 index 0000000000..933e50fed1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -0,0 +1,48 @@ +/** + * @file diffuseF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } + + gl_FragData[0] = vec4(col.rgb, 0.0); + gl_FragData[1] = vec4(0,0,0,0); // spec + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl new file mode 100644 index 0000000000..f3ad6f92de --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -0,0 +1,44 @@ +/** + * @file diffuseAlphaMaskIndexedF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +varying vec3 vary_normal; + +uniform float minimum_alpha; +uniform float maximum_alpha; + +void main() +{ + vec4 col = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } + + gl_FragData[0] = vec4(col.rgb, 0.0); + gl_FragData[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index f1e9955bb6..7152e13946 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -1,7 +1,7 @@ /** * @file impostorF.glsl * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -23,6 +23,8 @@ * $/LicenseInfo$ */ +uniform float minimum_alpha; +uniform float maximum_alpha; uniform sampler2D diffuseMap; @@ -32,6 +34,12 @@ uniform sampler2D specularMap; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } + gl_FragData[0] = vec4(col.rgb, col.a * 0.005); gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl new file mode 100644 index 0000000000..615317febf --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -0,0 +1,45 @@ +/** + * @file shadowAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +varying vec4 post_pos; + +void main() +{ + float alpha = texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a; + + if (alpha < minimum_alpha || alpha > maximum_alpha) + { + discard; + } + + gl_FragColor = vec4(1,1,1,1); + + gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl new file mode 100644 index 0000000000..4be18a9c5e --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl @@ -0,0 +1,41 @@ +/** + * @file shadowAlphaMaskV.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + + +varying vec4 post_pos; + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index b687d97da0..541f08d5fe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -1,7 +1,7 @@ /** * @file shadowF.glsl * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -25,13 +25,11 @@ -uniform sampler2D diffuseMap; - varying vec4 post_pos; void main() { - gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); + gl_FragColor = vec4(1,1,1,1); gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index 394fedf28f..fc3ff45614 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -1,7 +1,7 @@ /** * @file shadowV.glsl * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -35,7 +35,4 @@ void main() post_pos = pos; gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); - - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl new file mode 100644 index 0000000000..92c09ce937 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl @@ -0,0 +1,44 @@ +/** + * @file impostorF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +uniform sampler2D diffuseMap; + +void main() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl b/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl new file mode 100644 index 0000000000..eea51eba45 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl @@ -0,0 +1,34 @@ +/** + * @file impostorV.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl new file mode 100644 index 0000000000..4c05329065 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl @@ -0,0 +1,48 @@ +/** + * @file lightAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +void default_lighting() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl new file mode 100644 index 0000000000..0de909353e --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl @@ -0,0 +1,51 @@ +/** + * @file lightAlphaMaskNonIndexedF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +void default_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl new file mode 100644 index 0000000000..8c7713c08d --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl @@ -0,0 +1,47 @@ +/** + * @file lightFullbrightAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +void fullbright_lighting() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl new file mode 100644 index 0000000000..89468b9665 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl @@ -0,0 +1,49 @@ +/** + * @file lightFullbrightNonIndexedAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +uniform sampler2D diffuseMap; + +void fullbright_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl new file mode 100644 index 0000000000..e5998b77a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -0,0 +1,47 @@ +/** + * @file lightFullbrightWaterAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec4 diffuseLookup(vec2 texcoord); + +vec3 fullbrightAtmosTransport(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_lighting_water() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl new file mode 100644 index 0000000000..3fdd110f7d --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl @@ -0,0 +1,47 @@ +/** + * @file lightFullbrightWaterNonIndexedAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +vec3 fullbrightAtmosTransport(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_lighting_water() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl new file mode 100644 index 0000000000..072dcaa6b6 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl @@ -0,0 +1,45 @@ +/** + * @file lightWaterAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void default_lighting_water() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl new file mode 100644 index 0000000000..2df34da4b4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl @@ -0,0 +1,49 @@ +/** + * @file lightWaterAlphaMaskNonIndexedF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void default_lighting_water() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color = applyWaterFog(color); + + gl_FragColor = color; +} + diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 36272f0c7c..b9125ec8d3 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1692,37 +1692,6 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty } } -// static -void LLAgentWearables::userRemoveAllClothes() -{ - // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty. - if (gAgentCamera.cameraCustomizeAvatar()) - { - // switching to outfit editor should automagically save any currently edited wearable - LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit")); - } - userRemoveAllClothesStep2(TRUE); -} - -// static -void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed) -{ - if (proceed) - { - gAgentWearables.removeWearable(LLWearableType::WT_SHIRT,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_PANTS,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_SHOES,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_SOCKS,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_JACKET,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_GLOVES,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_UNDERSHIRT,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_UNDERPANTS,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_SKIRT,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_ALPHA,true,0); - gAgentWearables.removeWearable(LLWearableType::WT_TATTOO,true,0); - } -} - // Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to // get attachments into desired state with minimal number of adds/removes. void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array) diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 3ef50f14da..252b812c27 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -165,7 +165,6 @@ private: void removeWearableFinal(const LLWearableType::EType type, bool do_remove_all /*= false*/, U32 index /*= 0*/); protected: static bool onRemoveWearableDialog(const LLSD& notification, const LLSD& response); - static void userRemoveAllClothesStep2(BOOL proceed); // userdata is NULL //-------------------------------------------------------------------- // Server Communication @@ -211,7 +210,6 @@ public: public: static void userRemoveWearable(const LLWearableType::EType &type, const U32 &index); static void userRemoveWearablesOfType(const LLWearableType::EType &type); - static void userRemoveAllClothes(); typedef std::vector<LLViewerObject*> llvo_vec_t; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 1388d9aee0..a0af94ba77 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2285,7 +2285,9 @@ void LLAppearanceMgr::autopopulateOutfits() void LLAppearanceMgr::onFirstFullyVisible() { gAgentAvatarp->debugAvatarVisible(); - autopopulateOutfits(); + // The auto-populate is failing at the point of generating outfits
+ // folders, so don't do the library copy until that is resolved.
+ // autopopulateOutfits(); } bool LLAppearanceMgr::updateBaseOutfit() diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d12b971bde..6a808b5daf 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -137,6 +137,7 @@ #include "lltoolmgr.h" #include "llassetstorage.h" #include "llpolymesh.h" +#include "llproxy.h" #include "llaudioengine.h" #include "llstreamingaudio.h" #include "llviewermenu.h" @@ -321,6 +322,41 @@ static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; +//-- LLDeferredTaskList ------------------------------------------------------ + +/** + * A list of deferred tasks. + * + * We sometimes need to defer execution of some code until the viewer gets idle, + * e.g. removing an inventory item from within notifyObservers() may not work out. + * + * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration. + * All tasks are executed only once. + */ +class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList> +{ + LOG_CLASS(LLDeferredTaskList); + + friend class LLAppViewer; + typedef boost::signals2::signal<void()> signal_t; + + void addTask(const signal_t::slot_type& cb) + { + mSignal.connect(cb); + } + + void run() + { + if (!mSignal.empty()) + { + mSignal(); + mSignal.disconnect_all_slots(); + } + } + + signal_t mSignal; +}; + //---------------------------------------------------------------------------- // List of entries from strings.xml to always replace @@ -731,6 +767,23 @@ bool LLAppViewer::init() initThreads(); LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; + // Initialize settings early so that the defaults for ignorable dialogs are + // picked up and then correctly re-saved after launching the updater (STORM-1268). + LLUI::settings_map_t settings_map; + settings_map["config"] = &gSavedSettings; + settings_map["ignores"] = &gWarningSettings; + settings_map["floater"] = &gSavedSettings; // *TODO: New settings file + settings_map["account"] = &gSavedPerAccountSettings; + + LLUI::initClass(settings_map, + LLUIImageList::getInstance(), + ui_audio_callback, + &LLUI::sGLScaleFactor); + LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + + LLNotifications::instance(); + LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; + writeSystemInfo(); // Initialize updater service (now that we have an io pump) @@ -772,19 +825,8 @@ bool LLAppViewer::init() { LLError::setPrintLocation(true); } - - // Widget construction depends on LLUI being initialized - LLUI::settings_map_t settings_map; - settings_map["config"] = &gSavedSettings; - settings_map["ignores"] = &gWarningSettings; - settings_map["floater"] = &gSavedSettings; // *TODO: New settings file - settings_map["account"] = &gSavedPerAccountSettings; - LLUI::initClass(settings_map, - LLUIImageList::getInstance(), - ui_audio_callback, - &LLUI::sGLScaleFactor); - + // Setup paths and LLTrans after LLUI::initClass has been called LLUI::setupPaths(); LLTransUtil::parseStrings("strings.xml", default_trans_args); @@ -1840,6 +1882,8 @@ bool LLAppViewer::cleanup() LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); llinfos << "File launched." << llendflush; } + llinfos << "Cleaning up LLProxy." << llendl; + LLProxy::cleanupClass(); LLMainLoopRepeater::instance().stop(); @@ -3820,6 +3864,11 @@ bool LLAppViewer::initCache() } } +void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) +{ + LLDeferredTaskList::instance().addTask(cb); +} + void LLAppViewer::purgeCache() { LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; @@ -4413,6 +4462,9 @@ void LLAppViewer::idle() gAudiop->idle(max_audio_decode_time); } } + + // Execute deferred tasks. + LLDeferredTaskList::instance().run(); // Handle shutdown process, for example, // wait for floaters to close, send quit message, diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 61ee6a7cf1..32115e0e7b 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -164,6 +164,8 @@ public: login_completed_signal_t mOnLoginCompleted; boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); } + void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle + void purgeCache(); // Clear the local cache. // mute/unmute the system's master audio diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index d0f4d19f56..42e7decec1 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -141,7 +141,6 @@ LLAvatarIconCtrl::Params::Params() draw_tooltip("draw_tooltip", true), default_icon_name("default_icon_name") { - name = "avatar_icon"; } diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index db936b28d9..1a0b98f6cf 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -43,7 +43,7 @@ namespace LLNotificationsUI */ class LLChannelManager : public LLSingleton<LLChannelManager> { -public: +public: struct Params { LLUUID id; @@ -51,7 +51,8 @@ public: EToastAlignment toast_align; EChannelAlignment channel_align; - Params(): id(LLUUID("")), display_toasts_always(false), toast_align(NA_BOTTOM), channel_align(CA_LEFT) + Params() + : id(LLUUID("")), display_toasts_always(false), toast_align(NA_BOTTOM), channel_align(CA_LEFT) {} }; diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp index 024ccbcd0b..aa6c9c094c 100644 --- a/indra/newview/llchatmsgbox.cpp +++ b/indra/newview/llchatmsgbox.cpp @@ -70,7 +70,7 @@ private: LLChatMsgBox::Params::Params() : block_spacing("block_spacing", 10) { - line_spacing.pixels = 4; + changeDefault(line_spacing.pixels, 4); } LLChatMsgBox::LLChatMsgBox(const Params& p) : diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 3000209aad..245157923d 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -126,9 +126,9 @@ LLSysWellChiclet::Params::Params() , unread_notifications("unread_notifications") , max_displayed_count("max_displayed_count", 99) { - button.name("button"); - button.tab_stop(FALSE); - button.label(LLStringUtil::null); + button.name = "button"; + button.tab_stop = FALSE; + button.label = LLStringUtil::null; } LLSysWellChiclet::LLSysWellChiclet(const Params& p) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index a6e12006a1..1f1069dcb4 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -107,9 +107,9 @@ public: { Params() { - draw_tooltip(FALSE); - mouse_opaque(FALSE); - default_icon_name("Generic_Person"); + changeDefault(draw_tooltip, FALSE); + changeDefault(mouse_opaque, FALSE); + changeDefault(default_icon_name, "Generic_Person"); }; }; @@ -131,9 +131,8 @@ public: Optional<std::string> default_icon; Params() - : default_icon("default_icon", "Generic_Group") - { - }; + : default_icon("default_icon", "Generic_Group") + {} }; /** @@ -162,9 +161,9 @@ public: Optional<std::string> default_icon; Params() - : default_icon("default_icon", "Generic_Object_Small") + : default_icon("default_icon", "Generic_Object_Small") { - avatar_id = LLUUID::null; + changeDefault(avatar_id, LLUUID::null); }; }; @@ -314,9 +313,7 @@ public: TYPE_AD_HOC }; struct Params : public LLInitParam::Block<Params, LLChiclet::Params> - { - Params(){} - }; + {}; virtual ~LLIMChiclet() {}; diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index d77ebc5367..5b942f283a 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -57,7 +57,6 @@ LLColorSwatchCtrl::Params::Params() caption_text("caption_text"), border("border") { - name = "colorswatch"; } LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p) diff --git a/indra/newview/lldebugview.h b/indra/newview/lldebugview.h index 5245f163c0..20262fc89e 100644 --- a/indra/newview/lldebugview.h +++ b/indra/newview/lldebugview.h @@ -48,7 +48,7 @@ public: { Params() { - mouse_opaque = false; + changeDefault(mouse_opaque, false); } }; LLDebugView(const Params&); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ddcf42e523..9719140a37 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -88,16 +88,13 @@ void LLDrawPoolAlpha::endDeferredPass(S32 pass) void LLDrawPoolAlpha::renderDeferred(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - { - LLFastTimer t(FTM_RENDER_GRASS); - gDeferredTreeProgram.bind(); - LLGLEnable test(GL_ALPHA_TEST); - //render alpha masked objects - LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); - gDeferredTreeProgram.unbind(); - } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + LLFastTimer t(FTM_RENDER_GRASS); + gDeferredDiffuseAlphaMaskProgram.bind(); + gDeferredDiffuseAlphaMaskProgram.setAlphaRange(0.33f, 1.f); + + //render alpha masked objects + LLRenderPass::pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + gDeferredDiffuseAlphaMaskProgram.unbind(); } @@ -124,7 +121,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) if (pass == 0) { simple_shader = &gDeferredAlphaProgram; - fullbright_shader = &gObjectFullbrightProgram; + fullbright_shader = &gObjectFullbrightAlphaMaskProgram; //prime simple shader (loads shadow relevant uniforms) gPipeline.bindDeferredShader(*simple_shader); @@ -138,7 +135,8 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) gPipeline.mDeferredDepth.bindTarget(); simple_shader = NULL; fullbright_shader = NULL; - gObjectFullbrightProgram.bind(); + gObjectFullbrightAlphaMaskProgram.bind(); + gObjectFullbrightAlphaMaskProgram.setAlphaRange(0.33f, 1.f); } deferred_render = TRUE; @@ -157,7 +155,7 @@ void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) { gPipeline.mDeferredDepth.flush(); gPipeline.mScreen.bindTarget(); - gObjectFullbrightProgram.unbind(); + gObjectFullbrightAlphaMaskProgram.unbind(); } deferred_render = FALSE; @@ -175,13 +173,13 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { - simple_shader = &gObjectSimpleWaterProgram; - fullbright_shader = &gObjectFullbrightWaterProgram; + simple_shader = &gObjectSimpleWaterAlphaMaskProgram; + fullbright_shader = &gObjectFullbrightWaterAlphaMaskProgram; } else { - simple_shader = &gObjectSimpleProgram; - fullbright_shader = &gObjectFullbrightProgram; + simple_shader = &gObjectSimpleAlphaMaskProgram; + fullbright_shader = &gObjectFullbrightAlphaMaskProgram; } if (mVertexShaderLevel > 0) @@ -227,29 +225,32 @@ void LLDrawPoolAlpha::render(S32 pass) mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); if (mVertexShaderLevel > 0) { - if (!LLPipeline::sRenderDeferred) + if (!LLPipeline::sRenderDeferred || !deferred_render) { simple_shader->bind(); + simple_shader->setAlphaRange(0.33f, 1.f); + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } if (fullbright_shader) { fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.33f, 1.f); } pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); //LLGLSLShader::bindNoShader(); } else { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); //OK gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); gPipeline.enableLightsDynamic(); pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy || @@ -257,7 +258,6 @@ void LLDrawPoolAlpha::render(S32 pass) if (deferred_render && pass == 1) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } else @@ -268,13 +268,33 @@ void LLDrawPoolAlpha::render(S32 pass) mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - if (LLPipeline::sImpostorRender) + if (mVertexShaderLevel > 0) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + if (LLPipeline::sImpostorRender) + { + fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.5f, 1.f); + simple_shader->bind(); + simple_shader->setAlphaRange(0.5f, 1.f); + } + else + { + fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.f, 1.f); + simple_shader->bind(); + simple_shader->setAlphaRange(0.f, 1.f); + } } else { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (LLPipeline::sImpostorRender) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK + } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK + } } } @@ -291,7 +311,6 @@ void LLDrawPoolAlpha::render(S32 pass) if (deferred_render && pass == 1) { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ALPHA); } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9f790d03fe..28e464b60d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -258,7 +258,6 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() sSkipOpaque = TRUE; sShaderLevel = mVertexShaderLevel; sVertexProgram = &gDeferredAvatarAlphaProgram; - sRenderingSkinned = TRUE; gPipeline.bindDeferredShader(*sVertexProgram); @@ -361,7 +360,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) { gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; } - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); + //gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); glColor4f(1,1,1,1); @@ -590,12 +589,22 @@ void LLDrawPoolAvatar::beginImpostor() LLVOAvatar::sNumVisibleAvatars = 0; } + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.bind(); + gImpostorProgram.setAlphaRange(0.01f, 1.f); + } + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); sDiffuseChannel = 0; } void LLDrawPoolAvatar::endImpostor() { + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.unbind(); + } gPipeline.enableLightsDynamic(); } @@ -605,16 +614,17 @@ void LLDrawPoolAvatar::beginRigid() { if (LLPipeline::sUnderWaterRender) { - sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - sVertexProgram = &gObjectSimpleNonIndexedProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedProgram; } if (sVertexProgram != NULL) { //eyeballs render with the specular shader sVertexProgram->bind(); + sVertexProgram->setAlphaRange(0.2f, 1.f); } } else @@ -647,6 +657,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); + sVertexProgram->setAlphaRange(0.01f, 1.f); } void LLDrawPoolAvatar::endDeferredImpostor() @@ -692,11 +703,11 @@ void LLDrawPoolAvatar::beginSkinned() { if (LLPipeline::sUnderWaterRender) { - sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - sVertexProgram = &gObjectSimpleNonIndexedProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedProgram; } } @@ -728,6 +739,11 @@ void LLDrawPoolAvatar::beginSkinned() sVertexProgram->bind(); } } + + if (LLGLSLShader::sNoFixedFunction) + { + sVertexProgram->setAlphaRange(0.2f, 1.f); + } } void LLDrawPoolAvatar::endSkinned() diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index d801f6df18..0742250b0b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -155,6 +155,7 @@ void LLStandardBumpmap::addstandard() LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ; LLStandardBumpmap::sStandardBumpmapCount++; } @@ -1073,11 +1074,12 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText if (!src_image->hasCallbacks()) { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again if (src_image->getWidth() != bump->getWidth() || - src_image->getHeight() != bump->getHeight() || - (LLPipeline::sRenderDeferred && bump->getComponents() != 4)) + src_image->getHeight() != bump->getHeight())// || + //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) { src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); + src_image->forceToSaveRawImage(0) ; } } } diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 224f149c6b..eec4ee6bac 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -182,7 +182,6 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) void LLDrawPoolSimple::render(S32 pass) { LLGLDisable blend(GL_BLEND); - LLGLDisable alpha_test(GL_ALPHA_TEST); { //render simple LLFastTimer t(FTM_RENDER_SIMPLE); @@ -202,6 +201,7 @@ void LLDrawPoolSimple::render(S32 pass) } else { + LLGLDisable alpha_test(GL_ALPHA_TEST); renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); } @@ -256,19 +256,21 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { - simple_shader = &gObjectSimpleNonIndexedWaterProgram; + simple_shader = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - simple_shader = &gObjectSimpleNonIndexedProgram; + simple_shader = &gObjectAlphaMaskNonIndexedProgram; } if (mVertexShaderLevel > 0) { simple_shader->bind(); + simple_shader->setAlphaRange(0.5f, 1.f); } else { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); // don't use shaders! if (gGLManager.mHasShaderObjects) { @@ -286,22 +288,23 @@ void LLDrawPoolGrass::endRenderPass(S32 pass) { simple_shader->unbind(); } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } void LLDrawPoolGrass::render(S32 pass) { LLGLDisable blend(GL_BLEND); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + { LLFastTimer t(FTM_RENDER_GRASS); LLGLEnable test(GL_ALPHA_TEST); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); - } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } void LLDrawPoolGrass::beginDeferredPass(S32 pass) @@ -316,17 +319,13 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass) void LLDrawPoolGrass::renderDeferred(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - { LLFastTimer t(FTM_RENDER_GRASS_DEFERRED); - gDeferredTreeProgram.bind(); - LLGLEnable test(GL_ALPHA_TEST); + gDeferredNonIndexedDiffuseAlphaMaskProgram.bind(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.setAlphaRange(0.5f, 1.f); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 429e06b227..a6e0151114 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -62,24 +62,25 @@ void LLDrawPoolTree::prerender() void LLDrawPoolTree::beginRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + if (LLPipeline::sUnderWaterRender) { - shader = &gObjectSimpleNonIndexedWaterProgram; + shader = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - shader = &gObjectSimpleNonIndexedProgram; + shader = &gObjectAlphaMaskNonIndexedProgram; } if (gPipeline.canUseVertexShaders()) { shader->bind(); + shader->setAlphaRange(0.5f, 1.f); } else { gPipeline.enableLightsDynamic(); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } } @@ -92,7 +93,7 @@ void LLDrawPoolTree::render(S32 pass) return; } - LLGLEnable test(GL_ALPHA_TEST); + LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); if (gSavedSettings.getBOOL("RenderAnimateTrees")) @@ -121,12 +122,16 @@ void LLDrawPoolTree::render(S32 pass) void LLDrawPoolTree::endRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + if (gPipeline.canUseWindLightShadersOnObjects()) { shader->unbind(); } + + if (mVertexShaderLevel <= 0) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } //============================================ @@ -135,10 +140,10 @@ void LLDrawPoolTree::endRenderPass(S32 pass) void LLDrawPoolTree::beginDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - shader = &gDeferredTreeProgram; + shader = &gDeferredNonIndexedDiffuseAlphaMaskProgram; shader->bind(); + shader->setAlphaRange(0.5f, 1.f); } void LLDrawPoolTree::renderDeferred(S32 pass) @@ -149,8 +154,7 @@ void LLDrawPoolTree::renderDeferred(S32 pass) void LLDrawPoolTree::endDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + shader->unbind(); } @@ -160,11 +164,12 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) void LLDrawPoolTree::beginShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_TREE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), gSavedSettings.getF32("RenderDeferredTreeShadowBias")); - gDeferredShadowProgram.bind(); + gDeferredShadowAlphaMaskProgram.bind(); + gDeferredShadowAlphaMaskProgram.setAlphaRange(0.5f, 1.f); } void LLDrawPoolTree::renderShadow(S32 pass) @@ -175,12 +180,9 @@ void LLDrawPoolTree::renderShadow(S32 pass) void LLDrawPoolTree::endShadowPass(S32 pass) { LLFastTimer t(FTM_SHADOW_TREE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), gSavedSettings.getF32("RenderDeferredSpotShadowBias")); - - //gDeferredShadowProgram.unbind(); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index a219386b53..79a835fd14 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -233,8 +233,7 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const { LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + gGL.getTexUnit(0)->bind(sCloudNoiseTexture); cloud_shader->bind(); diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index dd0b1d999c..3bcbb987f7 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -137,9 +137,9 @@ void LLFloaterPostcard::draw() // first set the max extents of our preview rect.translate(-rect.mLeft, -rect.mBottom); - rect.mLeft += 280; + rect.mLeft += 320; rect.mRight -= 10; - rect.mTop -= 20; + rect.mTop -= 27; rect.mBottom = rect.mTop - 130; // then fix the aspect ratio diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5fd262a720..d65928e385 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -105,6 +105,7 @@ #include "llviewermedia.h" #include "llpluginclassmedia.h" #include "llteleporthistorystorage.h" +#include "llproxy.h" #include "lllogininstance.h" // to check if logged in yet #include "llsdserialize.h" @@ -158,7 +159,7 @@ BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask) { BOOL result = TRUE; - if(key == 'Q' && mask == MASK_CONTROL) + if (key == 'Q' && mask == MASK_CONTROL) { result = FALSE; } @@ -333,16 +334,17 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this)); mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); - mCommitCallbackRegistrar.add("Pref.HardwareSettings", boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this)); - mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); - mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this)); - mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); - mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); - mCommitCallbackRegistrar.add("Pref.QualityPerformance", boost::bind(&LLFloaterPreference::onChangeQuality, this, _2)); + mCommitCallbackRegistrar.add("Pref.HardwareSettings", boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this)); + mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); + mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this)); + mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); + mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); + mCommitCallbackRegistrar.add("Pref.QualityPerformance", boost::bind(&LLFloaterPreference::onChangeQuality, this, _2)); mCommitCallbackRegistrar.add("Pref.applyUIColor", boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this)); mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); + mCommitCallbackRegistrar.add("Pref.Proxy", boost::bind(&LLFloaterPreference::onClickProxySettings, this)); sSkin = gSavedSettings.getString("SkinCurrent"); @@ -457,7 +459,7 @@ BOOL LLFloaterPreference::postBuild() void LLFloaterPreference::onBusyResponseChanged() { // set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise - if(LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) + if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) { gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); } @@ -539,7 +541,7 @@ void LLFloaterPreference::apply() LLViewerMedia::setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); - if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) + if (hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) { bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue(); std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue(); @@ -552,13 +554,13 @@ void LLFloaterPreference::apply() gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean()); - if(mGotPersonalInfo) + if (mGotPersonalInfo) { // gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response))); bool new_im_via_email = getChild<LLUICtrl>("send_im_to_email")->getValue().asBoolean(); bool new_hide_online = getChild<LLUICtrl>("online_visibility")->getValue().asBoolean(); - if((new_im_via_email != mOriginalIMViaEmail) + if ((new_im_via_email != mOriginalIMViaEmail) ||(new_hide_online != mOriginalHideOnlineStatus)) { // This hack is because we are representing several different @@ -566,13 +568,13 @@ void LLFloaterPreference::apply() // can only select between 2 values, we represent it as a // checkbox. This breaks down a little bit for liaisons, but // works out in the end. - if(new_hide_online != mOriginalHideOnlineStatus) - { - if(new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN; + if (new_hide_online != mOriginalHideOnlineStatus) + { + if (new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN; else mDirectoryVisibility = VISIBILITY_DEFAULT; //Update showonline value, otherwise multiple applys won't work mOriginalHideOnlineStatus = new_hide_online; - } + } gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility); } } @@ -616,6 +618,11 @@ void LLFloaterPreference::cancel() updateDoubleClickControls(); mDoubleClickActionDirty = false; } + LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy"); + if (advanced_proxy_settings) + { + advanced_proxy_settings->cancel(); + } } void LLFloaterPreference::onOpen(const LLSD& key) @@ -799,7 +806,7 @@ void LLFloaterPreference::onBtnCancel() void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if(instance) + if (instance) { instance->setPersonalInfo(visibility, im_via_email, email); } @@ -809,7 +816,7 @@ void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_ void LLFloaterPreference::refreshEnabledGraphics() { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if(instance) + if (instance) { instance->refresh(); //instance->refreshEnabledState(); @@ -1096,7 +1103,7 @@ void LLFloaterPreference::disableUnavailableSettings() LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); // if vertex shaders off, disable all shader related products - if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) { ctrl_shader_enable->setEnabled(FALSE); ctrl_shader_enable->setValue(FALSE); @@ -1127,7 +1134,7 @@ void LLFloaterPreference::disableUnavailableSettings() } // disabled windlight - if(!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) { ctrl_wind_light->setEnabled(FALSE); ctrl_wind_light->setValue(FALSE); @@ -1164,28 +1171,28 @@ void LLFloaterPreference::disableUnavailableSettings() } // disabled deferred SSAO - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) { ctrl_ssao->setEnabled(FALSE); ctrl_ssao->setValue(FALSE); } // disabled deferred shadows - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) { ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); } // disabled reflections - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) { ctrl_reflections->setEnabled(FALSE); ctrl_reflections->setValue(FALSE); } // disabled av - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) { ctrl_avatar_vp->setEnabled(FALSE); ctrl_avatar_vp->setValue(FALSE); @@ -1208,14 +1215,14 @@ void LLFloaterPreference::disableUnavailableSettings() } // disabled cloth - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) { ctrl_avatar_cloth->setEnabled(FALSE); ctrl_avatar_cloth->setValue(FALSE); } // disabled impostors - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) { ctrl_avatar_impostors->setEnabled(FALSE); ctrl_avatar_impostors->setValue(FALSE); @@ -1381,12 +1388,12 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im mOriginalIMViaEmail = im_via_email; mDirectoryVisibility = visibility; - if(visibility == VISIBILITY_DEFAULT) + if (visibility == VISIBILITY_DEFAULT) { mOriginalHideOnlineStatus = false; getChildView("online_visibility")->setEnabled(TRUE); } - else if(visibility == VISIBILITY_HIDDEN) + else if (visibility == VISIBILITY_HIDDEN) { mOriginalHideOnlineStatus = true; getChildView("online_visibility")->setEnabled(TRUE); @@ -1434,7 +1441,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) { std::string ctrl_name = name.asString(); - if((ctrl_name =="" )|| !hasChild(ctrl_name, true)) + if ((ctrl_name =="" )|| !hasChild(ctrl_name, true)) return; LLTextBox* text_box = getChild<LLTextBox>(name.asString()); @@ -1444,7 +1451,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box) { - if(text_box == NULL || ctrl== NULL) + if (text_box == NULL || ctrl== NULL) return; // get range and points when text should change @@ -1457,7 +1464,7 @@ void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_b F32 highPoint = min + (2.0f * range / 3.0f); // choose the right text - if(value < midPoint) + if (value < midPoint) { text_box->setText(LLTrans::getString("GraphicsQualityLow")); } @@ -1541,6 +1548,11 @@ void LLFloaterPreference::updateDoubleClickSettings() } } +void LLFloaterPreference::onClickProxySettings() +{ + LLFloaterReg::showInstance("prefs_proxy"); +} + void LLFloaterPreference::updateDoubleClickControls() { // check is one of double-click actions settings enabled @@ -1637,7 +1649,7 @@ BOOL LLPanelPreference::postBuild() { ////////////////////// PanelVoice /////////////////// - if(hasChild("voice_unavailable")) + if (hasChild("voice_unavailable")) { BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice"); getChildView("voice_unavailable")->setVisible( voice_disabled); @@ -1659,7 +1671,7 @@ BOOL LLPanelPreference::postBuild() } - if(hasChild("online_visibility") && hasChild("send_im_to_email")) + if (hasChild("online_visibility") && hasChild("send_im_to_email")) { getChild<LLUICtrl>("email_address")->setValue(getString("log_in_to_change") ); // getChild<LLUICtrl>("busy_response")->setValue(getString("log_in_to_change")); @@ -1788,7 +1800,7 @@ void LLPanelPreference::cancel() iter != mSavedColors.end(); ++iter) { LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>(iter->first); - if(color_swatch) + if (color_swatch) { color_swatch->set(iter->second); color_swatch->onCommit(); @@ -1832,7 +1844,7 @@ void LLPanelPreferenceGraphics::draw() LLButton* button_apply = findChild<LLButton>("Apply"); - if(button_apply && button_apply->getVisible()) + if (button_apply && button_apply->getVisible()) { bool enable = hasDirtyChilds(); @@ -1852,7 +1864,7 @@ bool LLPanelPreferenceGraphics::hasDirtyChilds() LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview); if (ctrl) { - if(ctrl->isDirty()) + if (ctrl->isDirty()) return true; } // Push children onto the end of the work stack @@ -1908,3 +1920,188 @@ void LLPanelPreferenceGraphics::setHardwareDefaults() resetDirtyChilds(); LLPanelPreference::setHardwareDefaults(); } + +LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) + : LLFloater(key), + mSocksSettingsDirty(false) +{ + mCommitCallbackRegistrar.add("Proxy.OK", boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this)); + mCommitCallbackRegistrar.add("Proxy.Cancel", boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this)); + mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); +} + +LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() +{ +} + +BOOL LLFloaterPreferenceProxy::postBuild() +{ + LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); + if (!socksAuth) + { + return FALSE; + } + if (socksAuth->getSelectedValue().asString() == "None") + { + getChild<LLLineEditor>("socks5_username")->setEnabled(false); + getChild<LLLineEditor>("socks5_password")->setEnabled(false); + } + else + { + // Populate the SOCKS 5 credential fields with protected values. + LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); + getChild<LLLineEditor>("socks5_username")->setValue(socks_cred->getIdentifier()["username"].asString()); + getChild<LLLineEditor>("socks5_password")->setValue(socks_cred->getAuthenticator()["creds"].asString()); + } + + center(); + return TRUE; +} + +void LLFloaterPreferenceProxy::onOpen(const LLSD& key) +{ + saveSettings(); +} + +void LLFloaterPreferenceProxy::onClose(bool app_quitting) +{ + if (mSocksSettingsDirty) + { + + // If the user plays with the Socks proxy settings after login, it's only fair we let them know + // it will not be updated until next restart. + if (LLStartUp::getStartupState()>STATE_LOGIN_WAIT) + { + LLNotifications::instance().add("ChangeProxySettings", LLSD(), LLSD()); + mSocksSettingsDirty = false; // we have notified the user now be quiet again + } + } +} + +void LLFloaterPreferenceProxy::saveSettings() +{ + // Save the value of all controls in the hierarchy + mSavedValues.clear(); + std::list<LLView*> view_stack; + view_stack.push_back(this); + while(!view_stack.empty()) + { + // Process view on top of the stack + LLView* curview = view_stack.front(); + view_stack.pop_front(); + + LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview); + if (ctrl) + { + LLControlVariable* control = ctrl->getControlVariable(); + if (control) + { + mSavedValues[control] = control->getValue(); + } + } + + // Push children onto the end of the work stack + for (child_list_t::const_iterator iter = curview->getChildList()->begin(); + iter != curview->getChildList()->end(); ++iter) + { + view_stack.push_back(*iter); + } + } +} + +void LLFloaterPreferenceProxy::onBtnOk() +{ + // commit any outstanding text entry + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + } + + // Save SOCKS proxy credentials securely if password auth is enabled + LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); + if (socksAuth->getSelectedValue().asString() == "UserPass") + { + LLSD socks_id = LLSD::emptyMap(); + socks_id["type"] = "SOCKS5"; + socks_id["username"] = getChild<LLLineEditor>("socks5_username")->getValue().asString(); + + LLSD socks_authenticator = LLSD::emptyMap(); + socks_authenticator["type"] = "SOCKS5"; + socks_authenticator["creds"] = getChild<LLLineEditor>("socks5_password")->getValue().asString(); + + // Using "SOCKS5" as the "grid" argument since the same proxy + // settings will be used for all grids and because there is no + // way to specify the type of credential. + LLPointer<LLCredential> socks_cred = gSecAPIHandler->createCredential("SOCKS5", socks_id, socks_authenticator); + gSecAPIHandler->saveCredential(socks_cred, true); + } + else + { + // Clear SOCKS5 credentials since they are no longer needed. + LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); + gSecAPIHandler->deleteCredential(socks_cred); + } + + closeFloater(false); +} + +void LLFloaterPreferenceProxy::onBtnCancel() +{ + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + refresh(); + } + + cancel(); +} + +void LLFloaterPreferenceProxy::cancel() +{ + + for (control_values_map_t::iterator iter = mSavedValues.begin(); + iter != mSavedValues.end(); ++iter) + { + LLControlVariable* control = iter->first; + LLSD ctrl_value = iter->second; + control->set(ctrl_value); + } + + closeFloater(); +} + +void LLFloaterPreferenceProxy::onChangeSocksSettings() +{ + mSocksSettingsDirty = true; + + LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); + if (socksAuth->getSelectedValue().asString() == "None") + { + getChild<LLLineEditor>("socks5_username")->setEnabled(false); + getChild<LLLineEditor>("socks5_password")->setEnabled(false); + } + else + { + getChild<LLLineEditor>("socks5_username")->setEnabled(true); + getChild<LLLineEditor>("socks5_password")->setEnabled(true); + } + + // Check for invalid states for the other HTTP proxy radio + LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_type"); + if ((otherHttpProxy->getSelectedValue().asString() == "Socks" && + getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == FALSE )||( + otherHttpProxy->getSelectedValue().asString() == "Web" && + getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == FALSE ) ) + { + otherHttpProxy->selectFirstItem(); + } + +}; diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 61f2c78640..ef9bc2dd53 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -156,6 +156,7 @@ public: void applyResolution(); void onChangeMaturity(); void onClickBlockList(); + void onClickProxySettings(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -229,4 +230,33 @@ protected: }; +class LLFloaterPreferenceProxy : public LLFloater +{ +public: + LLFloaterPreferenceProxy(const LLSD& key); + ~LLFloaterPreferenceProxy(); + + /// show off our menu + static void show(); + void cancel(); + +protected: + BOOL postBuild(); + void onOpen(const LLSD& key); + void onClose(bool app_quitting); + void saveSettings(); + void onBtnOk(); + void onBtnCancel(); + + void onChangeSocksSettings(); + +private: + + bool mSocksSettingsDirty; + typedef std::map<LLControlVariable*, LLSD> control_values_map_t; + control_values_map_t mSavedValues; + +}; + + #endif // LL_LLPREFERENCEFLOATER_H diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index cfd7d96eb0..8b72d83830 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1942,10 +1942,21 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // when drop is not handled by child, it should be handled // by the folder which is the hierarchy root. - if (!handled && getListener()->getUUID().notNull()) + if (!handled) + { + if (getListener()->getUUID().notNull()) { handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } + else + { + if (!mFolders.empty()) + { + // dispatch to last folder as a hack to support "Contents" folder in object inventory + handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + } + } + } if (handled) { diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 00bc63326b..2888f779f4 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -101,10 +101,7 @@ LLFolderViewItem::Params::Params() item_height("item_height"), item_top_pad("item_top_pad"), creation_date() -{ - mouse_opaque(true); - follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); -} +{} // Default constructor LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 842911ecc0..fa3f546157 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -620,7 +620,7 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV F32 pos_y = pos.mV[VY]; LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_TRUE); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); if (mCollisionBanned == BA_BANNED) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fb5d145637..b4dac28595 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5220,31 +5220,22 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, // static void LLWearableBridge::removeAllClothesFromAvatar() { - // Remove COF links. - for (S32 itype = LLWearableType::WT_SHAPE; itype < LLWearableType::WT_COUNT; ++itype) - { - if (itype == LLWearableType::WT_SHAPE || itype == LLWearableType::WT_SKIN || itype == LLWearableType::WT_HAIR || itype == LLWearableType::WT_EYES) - continue; - - for (S32 index = gAgentWearables.getWearableCount(itype)-1; index >= 0 ; --index) - { - LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>( - gAgentWearables.getWearableInventoryItem((LLWearableType::EType)itype, index)); - if (!item) - continue; - const LLUUID &item_id = item->getUUID(); - const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); - if (!wearable) - continue; - - // Find and remove this item from the COF. - LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); - } + // Fetch worn clothes (i.e. the ones in COF). + LLInventoryModel::item_array_t clothing_items; + LLInventoryModel::cat_array_t dummy; + LLIsType is_clothing(LLAssetType::AT_CLOTHING); + gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), + dummy, + clothing_items, + LLInventoryModel::EXCLUDE_TRASH, + is_clothing, + false); + + // Take them off by removing from COF. + for (LLInventoryModel::item_array_t::const_iterator it = clothing_items.begin(); it != clothing_items.end(); ++it) + { + LLAppearanceMgr::instance().removeItemFromAvatar((*it)->getUUID()); } - gInventory.notifyObservers(); - - // Remove wearables from gAgentWearables - LLAgentWearables::userRemoveAllClothes(); } // static diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index 93e2e7128b..8d76aa9531 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -57,7 +57,7 @@ public: Params() : quadrant("quadrant", JQ_ORIGIN) { - label = ""; + changeDefault(label, ""); } }; LLJoystick(const Params&); @@ -137,7 +137,7 @@ public: { Params() { - held_down_delay.seconds(0.0); + changeDefault(held_down_delay.seconds, 0.0); } }; diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 48be251611..9b4f146332 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -30,13 +30,13 @@ // viewer includes #include "llsecapi.h" -#include "lllogininstance.h" // to check if logged in yet -#include "llpanellogin.h" // save_password_to_disk() +#include "lllogininstance.h" // to check if logged in yet +#include "llpanellogin.h" #include "llstartup.h" // getStartupState() #include "llslurl.h" #include "llviewercontrol.h" // gSavedSettings #include "llviewernetwork.h" // EGridInfo -#include "llviewerwindow.h" // getWindow() +#include "llviewerwindow.h" // getWindow() // library includes #include "llmd5.h" diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index b20f89aa7c..f00d6087f9 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -568,7 +568,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia else { requested_options.append("basic-mode"); - requested_options.append("inventory-basic"); + //requested_options.append("inventory-basic"); } #endif diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 1eb786f433..0bdeb114f5 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -79,7 +79,6 @@ LLMediaCtrl::Params::Params() trusted_content("trusted_content", false), focus_on_click("focus_on_click", true) { - tab_stop(false); } LLMediaCtrl::LLMediaCtrl( const Params& p) : @@ -319,6 +318,11 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) if (mContextMenu) { + // hide/show debugging options + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + mContextMenu->show(x, y); LLMenuGL::showPopup(this, mContextMenu, x, y); } @@ -385,12 +389,22 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( "menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); + return TRUE; } +void LLMediaCtrl::onOpenWebInspector() +{ + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->showWebInspector( true ); +} + //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) @@ -1065,6 +1079,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) mHoverTextChanged = true; }; break; + + case MEDIA_EVENT_DEBUG_MESSAGE: + { + LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; + }; + break; }; // chain all events to any potential observers of this object. diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 0e4a5b1d65..3c0436e27a 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -166,6 +166,9 @@ public: // Incoming media event dispatcher virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + // right click debugging item + void onOpenWebInspector(); + LLUUID getTextureID() {return mMediaTextureID;} protected: diff --git a/indra/newview/llmemoryview.h b/indra/newview/llmemoryview.h index 9bdc59ab10..dc4849a9c4 100644 --- a/indra/newview/llmemoryview.h +++ b/indra/newview/llmemoryview.h @@ -38,8 +38,8 @@ public: { Params() { - mouse_opaque = true; - visible = false; + changeDefault(mouse_opaque, true); + changeDefault(visible, false); } }; LLMemoryView(const LLMemoryView::Params&); diff --git a/indra/newview/llmorphview.h b/indra/newview/llmorphview.h index 1d8ee8e944..318d49bba5 100644 --- a/indra/newview/llmorphview.h +++ b/indra/newview/llmorphview.h @@ -40,8 +40,8 @@ public: { Params() { - mouse_opaque(false); - follows.flags(FOLLOWS_ALL); + changeDefault(mouse_opaque, false); + changeDefault(follows.flags, FOLLOWS_ALL); } }; LLMorphView(const LLMorphView::Params&); diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index afceb58ccf..4e28d1f526 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -57,7 +57,6 @@ LLNameListCtrl::Params::Params() allow_calling_card_drop("allow_calling_card_drop", false), short_names("short_names", false) { - name = "name_list"; } LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index d58a1cb663..988e801b61 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -66,8 +66,8 @@ public: Params() : agent_id("agent_id") { - mouse_opaque(false); - follows.flags(FOLLOWS_ALL); + changeDefault(mouse_opaque, false); + changeDefault(follows.flags, FOLLOWS_ALL); } }; diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index e64192c2ae..31c0e3d01a 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -82,8 +82,8 @@ public: : panel("panel"), group_id("group_id") { - mouse_opaque(false); - follows.flags(FOLLOWS_ALL); + changeDefault(mouse_opaque, false); + changeDefault(follows.flags, FOLLOWS_ALL); } }; LLGroupDropTarget(const Params&); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index bef809f3a7..db7d836799 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -154,6 +154,10 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, } updateLocationCombo(false); + LLUICtrl& mode_combo = getChildRef<LLUICtrl>("mode_combo"); + mode_combo.setValue(gSavedSettings.getString("SessionSettingsFile")); + mode_combo.setCommitCallback(boost::bind(&LLPanelLogin::onModeChange, this, getChild<LLUICtrl>("mode_combo")->getValue(), _2)); + LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo"); server_choice_combo->setCommitCallback(onSelectServer, NULL); server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1)); @@ -1021,6 +1025,32 @@ void LLPanelLogin::updateLoginPanelLinks() sInstance->getChildView("forgot_password_text")->setVisible( system_grid); } +void LLPanelLogin::onModeChange(const LLSD& original_value, const LLSD& new_value) +{ + if (original_value.asString() != new_value.asString()) + { + LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&LLPanelLogin::onModeChangeConfirm, this, original_value, new_value, _1, _2)); + } +} + +void LLPanelLogin::onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch (option) + { + case 0: + gSavedSettings.getControl("SessionSettingsFile")->set(new_value); + LLAppViewer::instance()->requestQuit(); + break; + case 1: + // revert to original value + getChild<LLUICtrl>("mode_combo")->setValue(original_value); + break; + default: + break; + } +} + std::string canonicalize_username(const std::string& name) { std::string cname = name; diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index b29b3af7ca..be9de884d1 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -87,6 +87,8 @@ private: void reshapeBrowser(); void addFavoritesToStartLocation(); void addUsersWithFavoritesToUsername(); + void onModeChange(const LLSD& original_value, const LLSD& new_value); + void onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response); static void onClickConnect(void*); static void onClickNewAccount(void*); static void onClickVersion(void*); @@ -97,7 +99,6 @@ private: static void onServerComboLostFocus(LLFocusableElement*); static void updateServerCombo(); static void updateStartSLURL(); - static void updateLoginPanelLinks(); private: @@ -113,7 +114,4 @@ private: static BOOL sCapslockDidNotification; }; -std::string load_password_from_disk(void); -void save_password_to_disk(const char* hashed_password); - #endif diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h index 7b4ed137db..705a095cf0 100644 --- a/indra/newview/llpanelmarketplaceinbox.h +++ b/indra/newview/llpanelmarketplaceinbox.h @@ -37,9 +37,7 @@ class LLPanelMarketplaceInbox : public LLPanel, public LLSideTrayTabBadgeDriver public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> - { - Params() {} - }; + {}; LOG_CLASS(LLPanelMarketplaceInbox); diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index 089facf80c..46eeb9ea7f 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -41,9 +41,7 @@ class LLInboxInventoryPanel : public LLInventoryPanel { public: struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> - { - Params() {} - }; + {}; LLInboxInventoryPanel(const Params& p); ~LLInboxInventoryPanel(); diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h index 2cf5b77569..c6b4a5abe2 100644 --- a/indra/newview/llpanelmarketplaceoutbox.h +++ b/indra/newview/llpanelmarketplaceoutbox.h @@ -40,9 +40,7 @@ class LLPanelMarketplaceOutbox : public LLPanel public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> - { - Params() {} - }; + {}; LOG_CLASS(LLPanelMarketplaceOutbox); diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp index 6558c9a7fa..2824c70582 100644 --- a/indra/newview/llsearchcombobox.cpp +++ b/indra/newview/llsearchcombobox.cpp @@ -52,10 +52,9 @@ protected: }; LLSearchComboBox::Params::Params() -: search_button("search_button") -, dropdown_button_visible("dropdown_button_visible", false) -{ -} +: search_button("search_button"), + dropdown_button_visible("dropdown_button_visible", false) +{} LLSearchComboBox::LLSearchComboBox(const Params&p) : LLComboBox(p) diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 8e4c2c56c6..0935a0005b 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -286,8 +286,8 @@ bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVe #define CRED_AUTHENTICATOR_TYPE_HASH "hash" // // LLCredential - interface for credentials providing the following functionality: -// * persistance of credential information based on grid (for saving username/password) -// * serialization to an OGP identifier/authenticator pair +// * Persistence of credential information based on grid (for saving username/password) +// * Serialization to an OGP identifier/authenticator pair // class LLCredential : public LLRefCount { diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 904bb03270..8d64c8c04f 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1005,6 +1005,8 @@ void LLBasicCertificateStore::validate(int validation_policy, LLPointer<LLCertificateChain> cert_chain, const LLSD& validation_params) { + // If --no-verify-ssl-cert was passed on the command line, stop right now. + if (gSavedSettings.getBOOL("NoVerifySSLCert")) return; if(cert_chain->size() < 1) { diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 8fa4065fa6..26b2b0f5c3 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5123,7 +5123,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) gGL.getTexUnit(0)->bind(mSilhouetteImagep); LLGLSPipelineSelection gls_select; - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); LLGLEnable blend(GL_BLEND); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -5250,7 +5249,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 363c8543ed..f53b08a4bc 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -496,7 +496,7 @@ public: LLSideTray* side_tray = LLSideTray::getInstance(); // Check if the tab we are dragging is docked. - if (!side_tray->isTabAttached(getName())) return FALSE; + if (!side_tray->isTabAttached(mTabName)) return FALSE; // Same value is hardcoded in LLDragHandle::handleHover(). const S32 undock_threshold = 12; @@ -505,7 +505,7 @@ public: if (delta_x <= -undock_threshold || delta_x >= undock_threshold || delta_y <= -undock_threshold || delta_y >= undock_threshold) { - LLSideTrayTab* tab = side_tray->getTab(getName()); + LLSideTrayTab* tab = side_tray->getTab(mTabName); if (!tab) return FALSE; tab->setDocked(false); @@ -544,7 +544,12 @@ protected: , mDragLastScreenX(0) , mDragLastScreenY(0) , mBadgeDriver(NULL) - {} + { + // Find out the tab name to use in handleHover(). + size_t pos = getName().find("_button"); + llassert(pos != std::string::npos); + mTabName = getName().substr(0, pos); + } friend class LLUICtrlFactory; @@ -562,6 +567,7 @@ private: S32 mDragLastScreenX; S32 mDragLastScreenY; + std::string mTabName; LLSideTrayTabBadgeDriver* mBadgeDriver; }; @@ -679,6 +685,7 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name) bool LLSideTray::isTabAttached(const std::string& name) { LLSideTrayTab* tab = getTab(name); + llassert(tab); if (!tab) return false; return std::find(mTabs.begin(), mTabs.end(), tab) != mTabs.end(); diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp index 214f595772..95a12c7c23 100644 --- a/indra/newview/llsidetraypanelcontainer.cpp +++ b/indra/newview/llsidetraypanelcontainer.cpp @@ -32,10 +32,10 @@ static LLDefaultChildRegistry::Register<LLSideTrayPanelContainer> r2("panel_cont std::string LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME = "sub_panel_name"; LLSideTrayPanelContainer::Params::Params() - : default_panel_name("default_panel_name") +: default_panel_name("default_panel_name") { // Always hide tabs. - hide_tabs(true); + changeDefault(hide_tabs, true); } LLSideTrayPanelContainer::LLSideTrayPanelContainer(const Params& p) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e23b431457..fd17781a2e 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -523,6 +523,11 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } +BOOL LLSpatialGroup::isHUDGroup() +{ + return mSpatialPartition && mSpatialPartition->isHUDPartition() ; +} + BOOL LLSpatialGroup::isRecentlyVisible() const { return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; @@ -4155,6 +4160,10 @@ void LLSpatialGroup::drawObjectBox(LLColor4 col) drawBox(mObjectBounds[0], size); } +bool LLSpatialPartition::isHUDPartition() +{ + return mPartitionType == LLViewerRegion::PARTITION_HUD ; +} BOOL LLSpatialPartition::isVisible(const LLVector3& v) { diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 54d5d36f6e..11955540c6 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -282,6 +282,7 @@ public: LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); + BOOL isHUDGroup() ; BOOL isDead() { return isState(DEAD); } BOOL isState(U32 state) const; BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } @@ -470,6 +471,7 @@ public: S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); + bool isHUDPartition() ; virtual LLSpatialBridge* asBridge() { return NULL; } virtual BOOL isBridge() { return asBridge() != NULL; } diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index d3e96f8dfb..bbe573c546 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -47,12 +47,10 @@ static LLDefaultChildRegistry::Register<LLSpeakButton> t1("talk_button"); ////////////////////////////////////////////////////////////////////////// LLSpeakButton::Params::Params() - : speak_button("speak_button") - , show_button("show_button") - , monitor("monitor") -{ - // See widgets/talk_button.xml -} +: speak_button("speak_button"), + show_button("show_button"), + monitor("monitor") +{} LLSpeakButton::LLSpeakButton(const Params& p) : LLUICtrl(p) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7991233ace..749acea6c1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -126,6 +126,7 @@ #include "llpanelgroupnotices.h" #include "llpreview.h" #include "llpreviewscript.h" +#include "llproxy.h" #include "llproductinforequest.h" #include "llsecondlifeurls.h" #include "llselectmgr.h" @@ -386,6 +387,14 @@ bool idle_startup() LLNotificationsUtil::add(gViewerWindow->getInitAlert()); } + //------------------------------------------------- + // Init the SOCKS 5 proxy if the user has configured + // one. We need to do this early in case the user + // is using SOCKS for HTTP so we get the login + // screen and HTTP tables via SOCKS. + //------------------------------------------------- + LLStartUp::startLLProxy(); + gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass()); @@ -591,7 +600,7 @@ bool idle_startup() } LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; - + //------------------------------------------------- // Init audio, which may be needed for prefs dialog // or audio cues in connection UI. @@ -800,7 +809,21 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { - //reset the values that could have come in from a slurl + // Post login screen, we should see if any settings have changed that may + // require us to either start/stop or change the socks proxy. As various communications + // past this point may require the proxy to be up. + if (!LLStartUp::startLLProxy()) + { + // Proxy start up failed, we should now bail the state machine + // startLLProxy() will have reported an error to the user + // already, so we just go back to the login screen. The user + // could then change the preferences to fix the issue. + + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return FALSE; + } + + // reset the values that could have come in from a slurl // DEV-42215: Make sure they're not empty -- gUserCredential // might already have been set from gSavedSettings, and it's too bad // to overwrite valid values with empty strings. @@ -2556,22 +2579,32 @@ void init_start_screen(S32 location_id) else if(!start_image_bmp->load(temp_str) ) { LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL; - return; + gStartTexture = NULL; } + else + { + gStartImageWidth = start_image_bmp->getWidth(); + gStartImageHeight = start_image_bmp->getHeight(); - gStartImageWidth = start_image_bmp->getWidth(); - gStartImageHeight = start_image_bmp->getHeight(); + LLPointer<LLImageRaw> raw = new LLImageRaw; + if (!start_image_bmp->decode(raw, 0.0f)) + { + LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; + gStartTexture = NULL; + } + else + { + raw->expandToPowerOfTwo(); + gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ; + } + } - LLPointer<LLImageRaw> raw = new LLImageRaw; - if (!start_image_bmp->decode(raw, 0.0f)) + if(gStartTexture.isNull()) { - LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; - gStartTexture = NULL; - return; + gStartTexture = LLViewerTexture::sBlackImagep ; + gStartImageWidth = gStartTexture->getWidth() ; + gStartImageHeight = gStartTexture->getHeight() ; } - - raw->expandToPowerOfTwo(); - gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ; } @@ -2758,6 +2791,171 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl) } } +/** + * Read all proxy configuration settings and set up both the HTTP proxy and + * SOCKS proxy as needed. + * + * Any errors that are encountered will result in showing the user a notification. + * When an error is encountered, + * + * @return Returns true if setup was successful, false if an error was encountered. + */ +bool LLStartUp::startLLProxy() +{ + bool proxy_ok = true; + std::string httpProxyType = gSavedSettings.getString("HttpProxyType"); + + // Set up SOCKS proxy (if needed) + if (gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + // Determine and update LLProxy with the saved authentication system + std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + + if (auth_type.compare("UserPass") == 0) + { + LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); + std::string socks_user = socks_cred->getIdentifier()["username"].asString(); + std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); + + bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); + + if (!ok) + { + LLNotificationsUtil::add("SOCKS_BAD_CREDS"); + proxy_ok = false; + } + } + else if (auth_type.compare("None") == 0) + { + LLProxy::getInstance()->setAuthNone(); + } + else + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; + + // Unknown or missing setting. + gSavedSettings.setString("Socks5AuthType", "None"); + + // Clear the SOCKS credentials. + LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); + gSecAPIHandler->deleteCredential(socks_cred); + + LLProxy::getInstance()->setAuthNone(); + } + + if (proxy_ok) + { + // Start the proxy and check for errors + // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); + + if (status != SOCKS_OK) + { + LLSD subs; + subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); + subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + + std::string error_string; + + switch(status) + { + case SOCKS_CONNECT_ERROR: // TCP Fail + error_string = "SOCKS_CONNECT_ERROR"; + break; + + case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection + error_string = "SOCKS_NOT_PERMITTED"; + break; + + case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server + error_string = "SOCKS_NOT_ACCEPTABLE"; + break; + + case SOCKS_AUTH_FAIL: // Authentication failed + error_string = "SOCKS_AUTH_FAIL"; + break; + + case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed + error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; + break; + + case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server + error_string = "SOCKS_HOST_CONNECT_FAILED"; + break; + + case SOCKS_INVALID_HOST: // Improperly formatted host address or port. + error_string = "SOCKS_INVALID_HOST"; + break; + + default: + error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, + LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; + break; + } + + LLNotificationsUtil::add(error_string, subs); + proxy_ok = false; + } + } + } + else + { + LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up + } + + if (proxy_ok) + { + // Determine the HTTP proxy type (if any) + if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) + { + LLHost http_host; + http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); + http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) + { + LLSD subs; + subs["HOST"] = http_host.getIPString(); + subs["PORT"] = (S32)http_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); + proxy_ok = false; + } + } + else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + LLHost socks_host; + socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) + { + LLSD subs; + subs["HOST"] = socks_host.getIPString(); + subs["PORT"] = (S32)socks_host.getPort(); + LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); + proxy_ok = false; + } + } + else if (httpProxyType.compare("None") == 0) + { + LLProxy::getInstance()->disableHTTPProxy(); + } + else + { + LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration."<< LL_ENDL; + + // Set the missing or wrong configuration back to something valid. + gSavedSettings.setString("HttpProxyType", "None"); + LLProxy::getInstance()->disableHTTPProxy(); + + // Leave proxy_ok alone, since this isn't necessarily fatal. + } + } + + return proxy_ok; +} + bool login_alert_done(const LLSD& notification, const LLSD& response) { LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index b3d9ef1dcc..99a644eb9c 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -113,6 +113,8 @@ public: static void setStartSLURL(const LLSLURL& slurl); static LLSLURL& getStartSLURL() { return sStartSLURL; } + static bool startLLProxy(); // Initialize the SOCKS 5 proxy + private: static LLSLURL sStartSLURL; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 1b8be7a5b2..0a00885843 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -162,6 +162,8 @@ BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL LLStatusBar::postBuild() { + LLControlVariablePtr mode_control = gSavedSettings.getControl("SessionSettingsFile"); + gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3)); mTextTime = getChild<LLTextBox>("TimeText" ); @@ -233,9 +235,40 @@ BOOL LLStatusBar::postBuild() mScriptOut = getChildView("scriptout"); + LLUICtrl& mode_combo = getChildRef<LLUICtrl>("mode_combo"); + mode_combo.setValue(gSavedSettings.getString("SessionSettingsFile")); + mode_combo.setCommitCallback(boost::bind(&LLStatusBar::onModeChange, this, getChild<LLUICtrl>("mode_combo")->getValue(), _2)); + + return TRUE; } +void LLStatusBar::onModeChange(const LLSD& original_value, const LLSD& new_value) +{ + if (original_value.asString() != new_value.asString()) + { + LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&LLStatusBar::onModeChangeConfirm, this, original_value, new_value, _1, _2)); + } +} + +void LLStatusBar::onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch (option) + { + case 0: + gSavedSettings.getControl("SessionSettingsFile")->set(new_value); + LLAppViewer::instance()->requestQuit(); + break; + case 1: + // revert to original value + getChild<LLUICtrl>("mode_combo")->setValue(original_value); + break; + default: + break; + } +} + // Per-frame updates of visibility void LLStatusBar::refresh() { diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 4ea3183d18..e1e1f5459b 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -92,6 +92,8 @@ private: void onMouseEnterVolume(); void onMouseEnterNearbyMedia(); void onClickScreen(S32 x, S32 y); + void onModeChange(const LLSD& original_value, const LLSD& new_value);
+ void onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response);
static void onClickMediaToggle(void* data); static void onClickBalance(void* data); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index fdfbee400e..b1312d641f 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -92,11 +92,7 @@ public: multiselect_text("multiselect_text"), caption_text("caption_text"), border("border") - { - name = "texture picker"; - mouse_opaque(true); - follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); - } + {} }; protected: LLTextureCtrl(const Params&); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 0115115a23..6547154bc4 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -94,7 +94,7 @@ public: Params() : texture_view("texture_view") { - mouse_opaque(false); + changeDefault(mouse_opaque, false); } }; LLTextureBar(const Params& p) @@ -387,7 +387,7 @@ public: : texture_view("texture_view") { S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - rect(LLRect(0,0,100,line_height * 4)); + changeDefault(rect, LLRect(0,0,100,line_height * 4)); } }; @@ -486,7 +486,7 @@ public: : texture_view("texture_view") { S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - rect(LLRect(0,0,100,line_height * 4)); + changeDefault(rect, LLRect(0,0,100,line_height * 4)); } }; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index fa91f129b8..6873cf058a 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -307,8 +307,14 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair S32 bottom_offset = mIsScriptDialog ? (BTN_HEIGHT + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD) : BOTTOM_PAD; S32 max_width = mControlPanel->getRect().getWidth(); LLButton* ignore_btn = NULL; + LLButton* mute_btn = NULL; for (std::vector<index_button_pair_t>::const_iterator it = buttons.begin(); it != buttons.end(); it++) { + if (-2 == it->first) + { + mute_btn = it->second; + continue; + } if (it->first == -1) { ignore_btn = it->second; @@ -328,6 +334,8 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair left = btn_rect.mLeft + btn_rect.getWidth() + h_pad; mControlPanel->addChild(btn, -1); } + + U32 ignore_btn_width = 0; if (mIsScriptDialog && ignore_btn != NULL) { LLRect ignore_btn_rect(ignore_btn->getRect()); @@ -340,8 +348,25 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair ignore_btn_rect.setOriginAndSize(ignore_btn_left, BOTTOM_PAD,// always move ignore button at the bottom ignore_btn_rect.getWidth(), ignore_btn_rect.getHeight()); ignore_btn->setRect(ignore_btn_rect); + ignore_btn_width = ignore_btn_rect.getWidth(); mControlPanel->addChild(ignore_btn, -1); } + + if (mIsScriptDialog && mute_btn != NULL) + { + LLRect mute_btn_rect(mute_btn->getRect()); + S32 buttons_per_row = max_width / BUTTON_WIDTH; //assume that h_pad far less than BUTTON_WIDTH + // Place mute (Block) button to the left of the ignore button. + S32 mute_btn_left = buttons_per_row * BUTTON_WIDTH + (buttons_per_row - 1) * h_pad - mute_btn_rect.getWidth() - ignore_btn_width - (h_pad / 2); + if (mute_btn_left + mute_btn_rect.getWidth() > max_width) // make sure that the mute button is in panel + { + mute_btn_left = max_width - mute_btn_rect.getWidth() - 2 * HPAD; + } + mute_btn_rect.setOriginAndSize(mute_btn_left, BOTTOM_PAD,// always move mute button at the bottom + mute_btn_rect.getWidth(), mute_btn_rect.getHeight()); + mute_btn->setRect(mute_btn_rect); + mControlPanel->addChild(mute_btn); + } } void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 button_panel_height) diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dd0989d608..fecc6d91bd 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -232,6 +232,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); + LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b22c6d2fd4..ad65a8846c 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -141,7 +141,7 @@ public: mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); //common - mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); + mInventoryItemsDict["/bow1"] = LLTrans::getString("/bow1"); mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); mInventoryItemsDict["/count"] = LLTrans::getString("/count"); mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 06104bc457..56ef31fb0b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1806,6 +1806,7 @@ void LLViewerMediaImpl::createMediaSource() LL_WARNS("Media") << "Failed to initialize media for mime type " << mMimeType << LL_ENDL; } } + } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1910,7 +1911,10 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); media_source->setJavascriptEnabled( javascript_enabled ); - + + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); + media_source->setTarget(target); const std::string plugin_dir = gDirUtilp->getLLPluginDir(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b29821479b..26599f557e 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -116,6 +116,8 @@ using namespace LLVOAvatarDefines; +typedef LLPointer<LLViewerObject> LLViewerObjectPtr; + static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels; BOOL enable_land_build(void*); @@ -4010,23 +4012,21 @@ void handle_god_request_avatar_geometry(void *) } } - -void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) +static bool get_derezzable_objects( + EDeRezDestination dest, + std::string& error, + LLViewerRegion*& first_region, + LLDynamicArray<LLViewerObjectPtr>* derez_objectsp, + bool only_check = false) { - if(gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - //gInventoryView->setPanelOpen(TRUE); + bool found = false; - std::string error; - LLDynamicArray<LLViewerObject*> derez_objects; + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); // Check conditions that we can't deal with, building a list of // everything that we'll actually be derezzing. - LLViewerRegion* first_region = NULL; - for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) + for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin(); + iter != selection->valid_root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); @@ -4093,8 +4093,53 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) } if(can_derez_current) { - derez_objects.put(object); + found = true; + + if (only_check) + // one found, no need to traverse to the end + break; + + if (derez_objectsp) + derez_objectsp->put(object); + + } + } + + return found; +} + +static bool can_derez(EDeRezDestination dest) +{ + LLViewerRegion* first_region = NULL; + std::string error; + return get_derezzable_objects(dest, error, first_region, NULL, true); +} + +static void derez_objects( + EDeRezDestination dest, + const LLUUID& dest_id, + LLViewerRegion*& first_region, + std::string& error, + LLDynamicArray<LLViewerObjectPtr>* objectsp) +{ + LLDynamicArray<LLViewerObjectPtr> derez_objects; + + if (!objectsp) // if objects to derez not specified + { + // get them from selection + if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false)) + { + llwarns << "No objects to derez" << llendl; + return; } + + objectsp = &derez_objects; + } + + + if(gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); } // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per @@ -4104,13 +4149,13 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) // satisfy anybody. const S32 MAX_ROOTS_PER_PACKET = 250; const S32 MAX_PACKET_COUNT = 254; - F32 packets = ceil((F32)derez_objects.count() / (F32)MAX_ROOTS_PER_PACKET); + F32 packets = ceil((F32)objectsp->count() / (F32)MAX_ROOTS_PER_PACKET); if(packets > (F32)MAX_PACKET_COUNT) { error = "AcquireErrorTooManyObjects"; } - if(error.empty() && derez_objects.count() > 0) + if(error.empty() && objectsp->count() > 0) { U8 d = (U8)dest; LLUUID tid; @@ -4135,11 +4180,11 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) msg->addU8Fast(_PREHASH_PacketCount, packet_count); msg->addU8Fast(_PREHASH_PacketNumber, packet_number); objects_in_packet = 0; - while((object_index < derez_objects.count()) + while((object_index < objectsp->count()) && (objects_in_packet++ < MAX_ROOTS_PER_PACKET)) { - LLViewerObject* object = derez_objects.get(object_index++); + LLViewerObject* object = objectsp->get(object_index++); msg->nextBlockFast(_PREHASH_ObjectData); msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); // VEFFECT: DerezObject @@ -4164,6 +4209,13 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) } } +static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) +{ + LLViewerRegion* first_region = NULL; + std::string error; + derez_objects(dest, dest_id, first_region, error, NULL); +} + void handle_take_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; @@ -4175,12 +4227,19 @@ void handle_take_copy() // You can return an object to its owner if it is on your land. class LLObjectReturn : public view_listener_t { +public: + LLObjectReturn() : mFirstRegion(NULL) {} + +private: bool handleEvent(const LLSD& userdata) { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. + get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects); + LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); return true; } @@ -4191,16 +4250,23 @@ class LLObjectReturn : public view_listener_t if (0 == option) { // Ignore category ID for this derez destination. - derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null); + derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects); } + mReturnableObjects.clear(); + mError.clear(); + mFirstRegion = NULL; + // drop reference to current selection mObjectSelection = NULL; return false; } -protected: LLObjectSelectionHandle mObjectSelection; + + LLDynamicArray<LLViewerObjectPtr> mReturnableObjects; + std::string mError; + LLViewerRegion* mFirstRegion; }; @@ -4225,29 +4291,7 @@ class LLObjectEnableReturn : public view_listener_t } else { - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - // Estate owners and managers can always return objects. - if (region->canManageEstate()) - { - new_value = true; - } - else - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* obj) - { - return - obj->permModify() || - obj->isReturnable(); - } - } func; - const bool firstonly = true; - new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); - } - } + new_value = can_derez(DRD_RETURN_TO_OWNER); } #endif return new_value; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 321d02aaf1..68745d5aeb 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1049,48 +1049,26 @@ void start_new_inventory_observer() class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver { LOG_CLASS(LLDiscardAgentOffer); + public: LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : LLInventoryFetchItemsObserver(object_id), mFolderID(folder_id), mObjectID(object_id) {} - virtual ~LLDiscardAgentOffer() {} + virtual void done() { LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - bool notify = false; - if(trash_id.notNull() && mObjectID.notNull()) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - gInventory.moveObject(mObjectID, trash_id); - LLInventoryObject* obj = gInventory.getObject(mObjectID); - if(obj) - { - // no need to restamp since this is already a freshly - // stamped item. - obj->updateParentOnServer(FALSE); - notify = true; - } - } - else - { - LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: " - << (trash_id.isNull() ? "trash " : "") - << (mObjectID.isNull() ? "object" : "") << LL_ENDL; - } + + // We're invoked from LLInventoryModel::notifyObservers(). + // If we now try to remove the inventory item, it will cause a nested + // notifyObservers() call, which won't work. + // So defer moving the item to trash until viewer gets idle (in a moment). + LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID)); gInventory.removeObserver(this); - if(notify) - { - gInventory.notifyObservers(); - } delete this; } + protected: LLUUID mFolderID; LLUUID mObjectID; @@ -1495,7 +1473,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LLChat chat; std::string log_message; S32 button = LLNotificationsUtil::getSelectedOption(notification, response); - + LLInventoryObserver* opener = NULL; LLViewerInventoryCategory* catp = NULL; catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); @@ -1527,7 +1505,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here: from_string = chatHistory_string = mFromName; - bool busy=FALSE; + bool busy = gAgent.getBusy(); switch(button) { @@ -1586,9 +1564,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& } break; - case IOR_BUSY: - //Busy falls through to decline. Says to make busy message. - busy=TRUE; case IOR_MUTE: // MUTE falls through to decline case IOR_DECLINE: @@ -1734,7 +1709,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const from_string = chatHistory_string = mFromName; } - bool busy=FALSE; + bool busy = gAgent.getBusy(); switch(button) { @@ -1780,9 +1755,6 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const } // end switch (mIM) break; - case IOR_BUSY: - //Busy falls through to decline. Says to make busy message. - busy=TRUE; case IOR_MUTE: // MUTE falls through to decline case IOR_DECLINE: @@ -2667,7 +2639,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { // Until throttling is implemented, busy mode should reject inventory instead of silently // accepting it. SEE SL-39554 - info->forceResponse(IOR_BUSY); + info->forceResponse(IOR_DECLINE); } else { @@ -6544,8 +6516,24 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response) rtn_text = LLNotification::getSelectedOptionName(response); } - // Didn't click "Ignore" - if (button_idx != -1) + // Button -2 = Mute + // Button -1 = Ignore - no processing needed for this button + // Buttons 0 and above = dialog choices + + if (-2 == button_idx) + { + std::string object_name = notification["payload"]["object_name"].asString(); + LLUUID object_id = notification["payload"]["object_id"].asUUID(); + LLMute mute(object_id, object_name, LLMute::OBJECT); + if (LLMuteList::getInstance()->add(mute)) + { + // This call opens the sidebar, displays the block list, and highlights the newly blocked + // object in the list so the user can see that their block click has taken effect. + LLPanelBlockedList::showPanelAndSelect(object_id); + } + } + + if (0 <= button_idx) { LLMessageSystem* msg = gMessageSystem; msg->newMessage("ScriptDialogReply"); @@ -6588,12 +6576,12 @@ void process_script_dialog(LLMessageSystem* msg, void**) std::string message; std::string first_name; std::string last_name; - std::string title; + std::string object_name; S32 chat_channel; msg->getString("Data", "FirstName", first_name); msg->getString("Data", "LastName", last_name); - msg->getString("Data", "ObjectName", title); + msg->getString("Data", "ObjectName", object_name); msg->getString("Data", "Message", message); msg->getS32("Data", "ChatChannel", chat_channel); @@ -6604,6 +6592,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) payload["sender"] = msg->getSender().getIPandPort(); payload["object_id"] = object_id; payload["chat_channel"] = chat_channel; + payload["object_name"] = object_name; // build up custom form S32 button_count = msg->getNumberOfBlocks("Buttons"); @@ -6622,7 +6611,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) } LLSD args; - args["TITLE"] = title; + args["TITLE"] = object_name; args["MESSAGE"] = message; LLNotificationPtr notification; if (!first_name.empty()) diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 9d09d9c01a..d8acd99953 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -57,7 +57,6 @@ enum InventoryOfferResponse IOR_ACCEPT, IOR_DECLINE, IOR_MUTE, - IOR_BUSY, IOR_SHOW }; diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index dfa35edef4..90fbc41daa 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -485,6 +485,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent { switch(event) { + case MEDIA_EVENT_DEBUG_MESSAGE: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_DEBUG_MESSAGE " << LL_ENDL; + }; + break; + case MEDIA_EVENT_CONTENT_UPDATED: { // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index db2dc531db..17f908d73f 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1193,6 +1193,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec eCacheUpdateResult result = CACHE_UPDATE_ADDED; if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) { + delete mImpl->mCacheMap.begin()->second ; mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); result = CACHE_UPDATE_REPLACED; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 62d83b516f..36106752a2 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -70,8 +70,12 @@ LLGLSLShader gTwoTextureAddProgram; //object shaders LLGLSLShader gObjectSimpleProgram; LLGLSLShader gObjectSimpleWaterProgram; +LLGLSLShader gObjectSimpleAlphaMaskProgram; +LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; LLGLSLShader gObjectFullbrightProgram; LLGLSLShader gObjectFullbrightWaterProgram; +LLGLSLShader gObjectFullbrightAlphaMaskProgram; +LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; LLGLSLShader gObjectFullbrightShinyProgram; LLGLSLShader gObjectFullbrightShinyWaterProgram; LLGLSLShader gObjectShinyProgram; @@ -80,6 +84,8 @@ LLGLSLShader gObjectBumpProgram; LLGLSLShader gObjectSimpleNonIndexedProgram; LLGLSLShader gObjectSimpleNonIndexedWaterProgram; +LLGLSLShader gObjectAlphaMaskNonIndexedProgram; +LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; LLGLSLShader gObjectFullbrightNonIndexedProgram; LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; @@ -112,6 +118,7 @@ LLGLSLShader gAvatarProgram; LLGLSLShader gAvatarWaterProgram; LLGLSLShader gAvatarEyeballProgram; LLGLSLShader gAvatarPickProgram; +LLGLSLShader gImpostorProgram; // WindLight shader handles LLGLSLShader gWLSkyProgram; @@ -128,7 +135,9 @@ LLGLSLShader gDeferredImpostorProgram; LLGLSLShader gDeferredEdgeProgram; LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredDiffuseAlphaMaskProgram; LLGLSLShader gDeferredNonIndexedDiffuseProgram; +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; LLGLSLShader gDeferredSkinnedDiffuseProgram; LLGLSLShader gDeferredSkinnedBumpProgram; LLGLSLShader gDeferredSkinnedAlphaProgram; @@ -145,6 +154,7 @@ LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredShadowAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAttachmentShadowProgram; LLGLSLShader gDeferredAlphaProgram; @@ -177,6 +187,8 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gWaterProgram); mShaderList.push_back(&gAvatarEyeballProgram); mShaderList.push_back(&gObjectSimpleProgram); + mShaderList.push_back(&gImpostorProgram); + mShaderList.push_back(&gObjectSimpleAlphaMaskProgram); mShaderList.push_back(&gObjectBumpProgram); mShaderList.push_back(&gUIProgram); mShaderList.push_back(&gCustomAlphaProgram); @@ -185,10 +197,13 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gSolidColorProgram); mShaderList.push_back(&gOcclusionProgram); mShaderList.push_back(&gObjectFullbrightProgram); + mShaderList.push_back(&gObjectFullbrightAlphaMaskProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gObjectFullbrightShinyWaterProgram); mShaderList.push_back(&gObjectSimpleNonIndexedProgram); mShaderList.push_back(&gObjectSimpleNonIndexedWaterProgram); + mShaderList.push_back(&gObjectAlphaMaskNonIndexedProgram); + mShaderList.push_back(&gObjectAlphaMaskNonIndexedWaterProgram); mShaderList.push_back(&gObjectFullbrightNonIndexedProgram); mShaderList.push_back(&gObjectFullbrightNonIndexedWaterProgram); mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram); @@ -205,6 +220,8 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gTerrainWaterProgram); mShaderList.push_back(&gObjectSimpleWaterProgram); mShaderList.push_back(&gObjectFullbrightWaterProgram); + mShaderList.push_back(&gObjectSimpleWaterAlphaMaskProgram); + mShaderList.push_back(&gObjectFullbrightWaterAlphaMaskProgram); mShaderList.push_back(&gAvatarWaterProgram); mShaderList.push_back(&gObjectShinyWaterProgram); mShaderList.push_back(&gObjectShinyNonIndexedWaterProgram); @@ -623,10 +640,15 @@ void LLViewerShaderMgr::unloadShaders() gSolidColorProgram.unload(); gObjectSimpleProgram.unload(); + gImpostorProgram.unload(); + gObjectSimpleAlphaMaskProgram.unload(); gObjectBumpProgram.unload(); gObjectSimpleWaterProgram.unload(); + gObjectSimpleWaterAlphaMaskProgram.unload(); gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); + gObjectFullbrightAlphaMaskProgram.unload(); + gObjectFullbrightWaterAlphaMaskProgram.unload(); gObjectShinyProgram.unload(); gObjectFullbrightShinyProgram.unload(); @@ -635,6 +657,8 @@ void LLViewerShaderMgr::unloadShaders() gObjectSimpleNonIndexedProgram.unload(); gObjectSimpleNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNonIndexedProgram.unload(); + gObjectAlphaMaskNonIndexedWaterProgram.unload(); gObjectFullbrightNonIndexedProgram.unload(); gObjectFullbrightNonIndexedWaterProgram.unload(); @@ -673,6 +697,8 @@ void LLViewerShaderMgr::unloadShaders() gPostNightVisionProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); gDeferredSkinnedBumpProgram.unload(); @@ -766,17 +792,25 @@ BOOL LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); @@ -1022,6 +1056,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); gDeferredSkinnedBumpProgram.unload(); @@ -1037,6 +1073,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); gDeferredShadowProgram.unload(); + gDeferredShadowAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAttachmentShadowProgram.unload(); gDeferredAvatarProgram.unload(); @@ -1077,6 +1114,27 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits; + gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader"; gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); @@ -1401,6 +1459,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; + gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; gDeferredAvatarShadowProgram.mShaderFiles.clear(); @@ -1613,16 +1681,23 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyWaterProgram.unload(); gObjectShinyWaterProgram.unload(); gObjectSimpleProgram.unload(); + gImpostorProgram.unload(); + gObjectSimpleAlphaMaskProgram.unload(); gObjectBumpProgram.unload(); gObjectSimpleWaterProgram.unload(); + gObjectSimpleWaterAlphaMaskProgram.unload(); gObjectFullbrightProgram.unload(); + gObjectFullbrightAlphaMaskProgram.unload(); gObjectFullbrightWaterProgram.unload(); + gObjectFullbrightWaterAlphaMaskProgram.unload(); gObjectShinyNonIndexedProgram.unload(); gObjectFullbrightShinyNonIndexedProgram.unload(); gObjectFullbrightShinyNonIndexedWaterProgram.unload(); gObjectShinyNonIndexedWaterProgram.unload(); gObjectSimpleNonIndexedProgram.unload(); gObjectSimpleNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNonIndexedProgram.unload(); + gObjectAlphaMaskNonIndexedWaterProgram.unload(); gObjectFullbrightNonIndexedProgram.unload(); gObjectFullbrightNonIndexedWaterProgram.unload(); gSkinnedObjectSimpleProgram.unload(); @@ -1672,6 +1747,41 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { + gObjectAlphaMaskNonIndexedProgram.mName = "Non indexed alpha mask Shader"; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasGamma = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNonIndexedWaterProgram.mName = "Non indexed alpha mask Water Shader"; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader"; gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true; gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true; @@ -1770,6 +1880,17 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { + gImpostorProgram.mName = "Impostor Shader"; + gImpostorProgram.mFeatures.disableTextureIndex = true; + gImpostorProgram.mShaderFiles.clear(); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { gObjectSimpleProgram.mName = "Simple Shader"; gObjectSimpleProgram.mFeatures.calculatesLighting = true; gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; @@ -1783,6 +1904,23 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; success = gObjectSimpleProgram.createShader(NULL, NULL); } + + if (success) + { + gObjectSimpleAlphaMaskProgram.mName = "Simple Alpha Mask Shader"; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); + } if (success) { @@ -1819,6 +1957,24 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { + gObjectSimpleWaterAlphaMaskProgram.mName = "Simple Water Alpha Mask Shader"; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { gObjectFullbrightProgram.mName = "Fullbright Shader"; gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; gObjectFullbrightProgram.mFeatures.hasGamma = true; @@ -1850,6 +2006,39 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { + gObjectFullbrightAlphaMaskProgram.mName = "Fullbright Alpha Mask Shader"; + gObjectFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader"; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { gObjectShinyProgram.mName = "Shiny Shader"; gObjectShinyProgram.mFeatures.calculatesAtmospherics = true; gObjectShinyProgram.mFeatures.calculatesLighting = true; @@ -2092,6 +2281,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarProgram.mFeatures.hasGamma = true; gAvatarProgram.mFeatures.hasAtmospherics = true; gAvatarProgram.mFeatures.hasLighting = true; + gAvatarProgram.mFeatures.hasAlphaMask = true; gAvatarProgram.mFeatures.disableTextureIndex = true; gAvatarProgram.mShaderFiles.clear(); gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2108,6 +2298,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.mFeatures.hasWaterFog = true; gAvatarWaterProgram.mFeatures.hasAtmospherics = true; gAvatarWaterProgram.mFeatures.hasLighting = true; + gAvatarWaterProgram.mFeatures.hasAlphaMask = true; gAvatarWaterProgram.mFeatures.disableTextureIndex = true; gAvatarWaterProgram.mShaderFiles.clear(); gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2146,6 +2337,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarEyeballProgram.mFeatures.hasGamma = true; gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; gAvatarEyeballProgram.mFeatures.hasLighting = true; + gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; gAvatarEyeballProgram.mShaderFiles.clear(); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 93a0ecc4f0..d4040f11e1 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -297,11 +297,17 @@ extern LLGLSLShader gTwoTextureAddProgram; //object shaders extern LLGLSLShader gObjectSimpleProgram; +extern LLGLSLShader gObjectSimpleAlphaMaskProgram; extern LLGLSLShader gObjectSimpleWaterProgram; +extern LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; extern LLGLSLShader gObjectSimpleNonIndexedProgram; extern LLGLSLShader gObjectSimpleNonIndexedWaterProgram; +extern LLGLSLShader gObjectAlphaMaskNonIndexedProgram; +extern LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; extern LLGLSLShader gObjectFullbrightProgram; extern LLGLSLShader gObjectFullbrightWaterProgram; +extern LLGLSLShader gObjectFullbrightAlphaMaskProgram; +extern LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; extern LLGLSLShader gObjectFullbrightNonIndexedProgram; extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; extern LLGLSLShader gObjectBumpProgram; @@ -345,6 +351,7 @@ extern LLGLSLShader gAvatarProgram; extern LLGLSLShader gAvatarWaterProgram; extern LLGLSLShader gAvatarEyeballProgram; extern LLGLSLShader gAvatarPickProgram; +extern LLGLSLShader gImpostorProgram; // WindLight shader handles extern LLGLSLShader gWLSkyProgram; @@ -359,6 +366,8 @@ extern LLGLSLShader gDeferredImpostorProgram; extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; extern LLGLSLShader gDeferredSkinnedDiffuseProgram; extern LLGLSLShader gDeferredSkinnedBumpProgram; @@ -377,6 +386,7 @@ extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredShadowAlphaMaskProgram; extern LLGLSLShader gDeferredPostGIProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredPostNoDoFProgram; diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h index 0861dfcb20..fb428d0dc1 100644 --- a/indra/newview/llviewertexteditor.h +++ b/indra/newview/llviewertexteditor.h @@ -36,12 +36,7 @@ class LLViewerTextEditor : public LLTextEditor { public: struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> - { - Params() - { - name = "text_editor"; - } - }; + {}; protected: LLViewerTextEditor(const Params&); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5fcc57bc91..70509f9a9f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -66,6 +66,7 @@ // statics LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL; +LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL; @@ -295,17 +296,23 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const void LLViewerTextureManager::init() { - LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); - raw->clear(0x77, 0x77, 0x77, 0xFF); - LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ; - -#if 1 - LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); - LLViewerFetchedTexture::sDefaultImagep = imagep; + { + LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); + raw->clear(0x77, 0x77, 0x77, 0xFF); + LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ; + } const S32 dim = 128; LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); U8* data = image_raw->getData(); + + memset(data, 0, dim * dim * 3) ; + LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ; + +#if 1 + LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); + LLViewerFetchedTexture::sDefaultImagep = imagep; + for (S32 i = 0; i<dim; i++) { for (S32 j = 0; j<dim; j++) @@ -359,6 +366,7 @@ void LLViewerTextureManager::cleanup() LLImageGL::sDefaultGLTexture = NULL ; LLViewerTexture::sNullImagep = NULL; + LLViewerTexture::sBlackImagep = NULL; LLViewerFetchedTexture::sDefaultImagep = NULL; LLViewerFetchedTexture::sSmokeImagep = NULL; LLViewerFetchedTexture::sMissingAssetImagep = NULL; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index c5b8c8923a..de528927b4 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -330,6 +330,7 @@ public: static BOOL sUseTextureAtlas ; static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. + static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black) }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b5be3cd552..7946846222 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4225,7 +4225,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask) + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } @@ -4254,7 +4254,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) } } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { @@ -4337,7 +4340,7 @@ U32 LLVOAvatar::renderRigid() bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask) + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } @@ -4348,7 +4351,10 @@ U32 LLVOAvatar::renderRigid() num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy); } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } return num_indices; } diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index f0b5b50feb..6d457434b5 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -621,16 +621,20 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca S32 num_entries; success = check_read(&apr_file, &num_entries, sizeof(S32)) ; - for (S32 i = 0; success && i < num_entries; i++) + if(success) { - LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); - if (!entry->getLocalID()) + for (S32 i = 0; i < num_entries; i++) { - llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; - delete entry ; - success = false ; + LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); + if (!entry->getLocalID()) + { + llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; + delete entry ; + success = false ; + break ; + } + cache_entry_map[entry->getLocalID()] = entry; } - cache_entry_map[entry->getLocalID()] = entry; } } } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 30216f02db..528c7acbc8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -704,19 +704,22 @@ BOOL LLVOVolume::isVisible() const return FALSE ; } -void LLVOVolume::updateTextureVirtualSize() +void LLVOVolume::updateTextureVirtualSize(bool forced) { LLFastTimer ftm(FTM_VOLUME_TEXTURES); // Update the pixel area of all faces - if(!isVisible()) + if(!forced) { - return ; - } + if(!isVisible()) + { + return ; + } - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } } static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); @@ -3998,7 +4001,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } llassert_always(vobj); - vobj->updateTextureVirtualSize(); + vobj->updateTextureVirtualSize(true); vobj->preRebuild(); drawablep->clearState(LLDrawable::HAS_ALPHA); @@ -4487,6 +4490,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); } + bool hud_group = group->isHUDGroup() ; std::vector<LLFace*>::iterator face_iter = faces.begin(); LLSpatialGroup::buffer_map_t buffer_map; @@ -4757,7 +4761,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } - else if (LLPipeline::sRenderDeferred) + else if (LLPipeline::sRenderDeferred && !hud_group) { //deferred rendering if (te->getFullbright()) { //register in post deferred fullbright shiny pass @@ -4795,7 +4799,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: else if (fullbright || bake_sunlight) { //fullbright registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap()) { //if this is the deferred render and a bump map is present, register in post deferred bump registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); } @@ -4821,7 +4825,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && !LLPipeline::sRenderDeferred) + if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index fc00f0c0d0..13565cb27c 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -206,7 +206,7 @@ public: /*virtual*/ BOOL updateLOD(); void updateRadius(); /*virtual*/ void updateTextures(); - void updateTextureVirtualSize(); + void updateTextureVirtualSize(bool forced = false); void updateFaceFlags(); void regenFaces(); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index bd1d2ed7a7..f483ba5af8 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -306,19 +306,8 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) mCurlRequest = new LLCurlEasyRequest(); } mErrorCert = NULL; - - if (gSavedSettings.getBOOL("BrowserProxyEnabled")) - { - mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); - S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); - - // tell curl about the settings - mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress); - mCurlRequest->setopt(CURLOPT_PROXYPORT, port); - mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - } -// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging +// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this); BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert"); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4899df13e5..7a26404138 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3340,13 +3340,15 @@ void render_hud_elements() glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); gGL.color4f(1,1,1,1); - if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + + if (LLGLSLShader::sNoFixedFunction) { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); + } + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { LLGLEnable multisample(gSavedSettings.getU32("RenderFSAASamples") > 0 ? GL_MULTISAMPLE_ARB : 0); gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() @@ -3360,10 +3362,6 @@ void render_hud_elements() // Render name tags. LLHUDObject::renderAll(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } } else if (gForceRenderLandFence) { @@ -3374,6 +3372,11 @@ void render_hud_elements() { LLHUDText::renderAllHUD(); } + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } gGL.flush(); } @@ -3669,6 +3672,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); } @@ -3734,6 +3738,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); } } @@ -3934,6 +3939,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); gGL.setColorMask(true, false); } @@ -3999,6 +4005,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); @@ -6182,7 +6189,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGlowExtractProgram.uniform1f("warmthAmount", warmthAmount); LLGLEnable blend_on(GL_BLEND); LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); mScreen.bindTexture(0, 0); @@ -8252,7 +8259,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gOcclusionProgram.bind(); } LLFastTimer ftm(FTM_SHADOW_SIMPLE); - LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) { @@ -8278,12 +8284,11 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { LLFastTimer ftm(FTM_SHADOW_ALPHA); - LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + gDeferredShadowAlphaMaskProgram.bind(); + gDeferredShadowAlphaMaskProgram.setAlphaRange(0.6f, 1.f); renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); glColor4f(1,1,1,1); renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } //glCullFace(GL_BACK); @@ -8768,6 +8773,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SIMPLE, LLPipeline::RENDER_TYPE_PASS_BUMP, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml index d352312d15..c2f7d26dc9 100644 --- a/indra/newview/skins/default/xui/da/menu_viewer.xml +++ b/indra/newview/skins/default/xui/da/menu_viewer.xml @@ -140,7 +140,6 @@ <menu_item_check label="Fjern kamerabegrænsninger" name="Disable Camera Distance"/> <menu_item_check label="Højopløsningsfoto" name="HighResSnapshot"/> <menu_item_check label="Lydløse fotos til disk" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Komprimér fotos til disk" name="CompressSnapshotsToDisk"/> <menu label="Værktøjer til ydelse" name="Performance Tools"> <menu_item_call label="Lag meter" name="Lag Meter"/> <menu_item_check label="Statistik bjælke" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index c3999501eb..3ccdfc036a 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1335,7 +1335,7 @@ Prøv igen om lidt. </notification> <notification name="ObjectGiveItem"> Et object med navnet <nolink>[OBJECTFROMNAME]</nolink> ejet af [NAME_SLURL] har givet dig denne [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Behold"/> <button name="Discard" text="Smid væk"/> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index de4c269be6..e010844206 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="Kamerabeschränkungen deaktivieren" name="Disable Camera Distance"/> <menu_item_check label="Foto (hohe Auflösung)" name="HighResSnapshot"/> <menu_item_check label="Fotos auf Festplatte leise speichern" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Fotos auf Festplatte komprimieren" name="CompressSnapshotsToDisk"/> <menu label="Performance Tools" name="Performance Tools"> <menu_item_call label="Lag-Anzeige" name="Lag Meter"/> <menu_item_check label="Statistikleiste" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index abea3442fa..1971061096 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2432,7 +2432,7 @@ Versuchen Sie es in einigen Minuten erneut. </notification> <notification name="ObjectGiveItem"> Ein Objekt namens <nolink>[OBJECTFROMNAME]</nolink>, das [NAME_SLURL] gehört, hat Ihnen folgende/n/s [OBJECTTYPE] übergeben: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Behalten"/> <button name="Discard" text="Verwerfen"/> diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml index 8da35e9d7f..c756661ffc 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/floater_postcard.xml @@ -7,11 +7,11 @@ height="380" layout="topleft" min_height="380" - min_width="450" + min_width="490" name="Postcard" help_topic="postcard" title="EMAIL SNAPSHOT" - width="450"> + width="490"> <floater.string name="default_subject"> Postcard from [SECOND_LIFE]. @@ -40,7 +40,7 @@ follows="left|top" height="20" layout="topleft" - left_delta="108" + left_delta="148" name="to_form" top_delta="-4" width="150" /> @@ -59,7 +59,7 @@ follows="left|top" height="20" layout="topleft" - left_delta="108" + left_delta="148" name="from_form" top_delta="-4" width="150" /> @@ -78,7 +78,7 @@ follows="left|top" height="20" layout="topleft" - left_delta="108" + left_delta="148" max_length_bytes="100" name="name_form" top_delta="-4" @@ -99,7 +99,7 @@ height="20" label="Type your subject here." layout="topleft" - left_delta="108" + left_delta="148" max_length_bytes="100" name="subject_form" top_delta="-4" diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml new file mode 100644 index 0000000000..449731ab89 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="500" + layout="topleft" + name="Proxy Settings Floater" + help_topic="proxysettings" + title="Proxy Settings" + width="500"> + <check_box + control_name="BrowserProxyEnabled" + top="38" + enabled="true" + follows="left|top" + height="14" + initial_value="false" + commit_callback.function="Proxy.Change" + label="Use HTTP Proxy for Web pages" + left="22" + mouse_opaque="true" + name="web_proxy_enabled" + radio_style="false" + width="400" + top_pad="5" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + left_delta="23" + layout="topleft" + name="Proxy location" + top_pad="10" + width="300"> + HTTP Proxy: + </text> + <line_editor + control_name="BrowserProxyAddress" + enabled_control="BrowserProxyEnabled" + follows="left|top" + font="SansSerif" + height="23" + layout="topleft" + left_delta="0" + name="web_proxy_editor" + tool_tip="The DNS name or IP address of the HTTP proxy you would like to use." + top_pad="4" + width="200" /> + <spinner + control_name="BrowserProxyPort" + enabled_control="BrowserProxyEnabled" + decimal_digits="0" + follows="left|top" + height="23" + increment="1" + initial_value="80" + label="Port number:" + label_width="95" + layout="topleft" + left_delta="210" + max_val="12000" + min_val="10" + name="web_proxy_port" + top_delta="0" + tool_tip="The port of the HTTP proxy you would like to use." + width="145" /> + <check_box + control_name="Socks5ProxyEnabled" + height="16" + label="Use SOCKS 5 Proxy for UDP traffic" + layout="topleft" + left="22" + name="socks_proxy_enabled" + top_pad="32" + width="256" + commit_callback.function="Proxy.Change" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="23" + name="Proxy location" + top_pad="10" + width="300"> + SOCKS 5 Proxy: + </text> + <line_editor + control_name="Socks5ProxyHost" + enabled_control="Socks5ProxyEnabled" + follows="left|top" + font="SansSerif" + height="23" + layout="topleft" + left_delta="0" + name="socks_proxy_editor" + tool_tip="The DNS name or IP address of the SOCKS 5 proxy you would like to use." + top_pad="4" + width="200" + commit_callback.function="Proxy.Change" /> + <spinner + control_name="Socks5ProxyPort" + enabled_control="Socks5ProxyEnabled" + decimal_digits="0" + follows="left|top" + height="23" + increment="1" + initial_value="80" + label="Port number:" + label_width="95" + layout="topleft" + left_delta="210" + max_val="12000" + min_val="10" + name="socks_proxy_port" + top_delta="0" + width="145" + tool_tip="The port of the SOCKS 5 proxy you would like to use." + commit_callback.function="Proxy.Change" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="40" + name="Proxy location" + top_pad="15" + width="300"> + SOCKS Authentication: + </text> + <radio_group + control_name="Socks5AuthType" + enabled_control="Socks5ProxyEnabled" + height="50" + layout="topleft" + name="socks5_auth_type" + top_pad="10" + width="120" + commit_callback.function="Proxy.Change" > + <radio_item + height="16" + label="No Authentication" + layout="topleft" + name="Socks5NoAuth" + value="None" + tool_tip="Socks5 proxy requires no authentication." + width="120" /> + <radio_item + height="16" + label="Username/Password" + layout="topleft" + name="Socks5UserPass" + value="UserPass" + tool_tip="Socks5 proxy requires username/password authentication." + width="120" /> + </radio_group> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_delta="20" + top_delta="50" + width="200"> + Username: + </text> + <text + type="string" + length="1" + follows="left|top" + height="10" + left_pad="15" + layout="topleft" + width="200"> + Password: + </text> + <line_editor + follows="left|top" + font="SansSerif" + height="23" + layout="topleft" + left="60" + name="socks5_username" + tool_tip="The username used to authenticate with your SOCKS 5 server" + top_pad="4" + width="200" + commit_callback.function="Proxy.Change" /> + <line_editor + follows="left|top" + font="SansSerif" + height="23" + layout="topleft" + left_pad="15" + name="socks5_password" + tool_tip="The password used to authenticate with your SOCKS 5 server" + top_delta="0" + width="200" + is_password="true" + commit_callback.function="Proxy.Change" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="25" + name="Proxy location" + top_pad="18" + width="300"> + Other HTTP traffic proxy: + </text> + <radio_group + control_name="HttpProxyType" + name="other_http_proxy_type" + height="60" + layout="topleft" + top_pad="9" + width="120" + left_delta="15" + commit_callback.function="Proxy.Change" > + <radio_item + height="16" + label="Do not proxy" + layout="topleft" + name="OtherNoProxy" + value="None" + width="120" + tool_tip="Non-web HTTP traffic will NOT be sent to any proxy."/> + <radio_item + height="16" + label="Use HTTP Proxy" + layout="topleft" + name="OtherHTTPProxy" + value="Web" + width="120" + enabled_control="BrowserProxyEnabled" + tool_tip="Non-web HTTP will be sent through the configured Web proxy." /> + <radio_item + height="16" + label="Use SOCKS 5 Proxy" + layout="topleft" + name="OtherSocksProxy" + value="Socks" + width="120" + enabled_control="Socks5ProxyEnabled" + tool_tip="Non-web HTTP traffic will be sent through the configured Socks 5 proxy."/> + </radio_group> + <button + follows="left|top" + height="22" + label="OK" + label_selected="OK" + layout="topleft" + left="282" + name="OK" + top_pad="36" + width="90" + commit_callback.function="Proxy.OK" /> + <button + follows="left|top" + height="22" + label="Cancel" + label_selected="Cancel" + layout="topleft" + left_pad="10" + name="Cancel" + top_delta="0" + width="90" + commit_callback.function="Proxy.Cancel" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_media_ctrl.xml b/indra/newview/skins/default/xui/en/menu_media_ctrl.xml index c39c26f25f..960da4bd7a 100644 --- a/indra/newview/skins/default/xui/en/menu_media_ctrl.xml +++ b/indra/newview/skins/default/xui/en/menu_media_ctrl.xml @@ -28,4 +28,16 @@ <menu_item_call.on_enable function="Edit.EnablePaste" /> </menu_item_call> + <menu_item_separator + layout="topleft" + name="debug_separator" + visible="false" /> + <menu_item_call + label="Open Web Inspector" + layout="topleft" + name="open_webinspector" + visible="false"> + <menu_item_call.on_click + function="Open.WebInspector" /> + </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 01699955a6..b08e3abb71 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1250,16 +1250,6 @@ function="ToggleControl" parameter="QuietSnapshotsToDisk" /> </menu_item_check> - <menu_item_check - label="Compress Snapshots to Disk" - name="CompressSnapshotsToDisk"> - <menu_item_check.on_check - function="CheckControl" - parameter="CompressSnapshotsToDisk" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="CompressSnapshotsToDisk" /> - </menu_item_check> <menu_item_separator/> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1dda0b3235..02b61546e7 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5937,7 +5937,7 @@ No valid parcel could be found. name="ObjectGiveItem" type="offer"> An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLURL] has given you this [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button index="0" @@ -6295,6 +6295,10 @@ Grant this request? [MESSAGE] <form name="form"> <button + index="-2" + name="Mute" + text="Block"/> + <button index="-1" name="Ignore" text="Ignore"/> @@ -6310,6 +6314,10 @@ Grant this request? [MESSAGE] <form name="form"> <button + index="-2" + name="Mute" + text="Block"/> + <button index="-1" name="Ignore" text="Ignore"/> @@ -7191,6 +7199,138 @@ Click and drag anywhere on the world to rotate your view </notification> <notification + icon="alertmodal.tga" + name="SOCKS_NOT_PERMITTED" + type="alertmodal"> + The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, not allowed by rule set. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_CONNECT_ERROR" + type="alertmodal"> + The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, could not open TCP channel. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_NOT_ACCEPTABLE" + type="alertmodal"> + The SOCKS 5 proxy "[HOST]:[PORT]" refused the selected authentication system. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_AUTH_FAIL" + type="alertmodal"> + The SOCKS 5 proxy "[HOST]:[PORT]" reported your credentials are invalid. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_UDP_FWD_NOT_GRANTED" + type="alertmodal"> + The SOCKS 5 proxy "[HOST]:[PORT]" refused the UDP associate request. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_HOST_CONNECT_FAILED" + type="alertmodal"> + Could not connect to SOCKS 5 proxy server "[HOST]:[PORT]". + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_UNKNOWN_STATUS" + type="alertmodal"> + Unknown proxy error with server "[HOST]:[PORT]". + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_INVALID_HOST" + type="alertmodal"> + Invalid SOCKS proxy address or port "[HOST]:[PORT]". + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="SOCKS_BAD_CREDS" + type="alertmodal"> + Invalid SOCKS 5 username or password. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="PROXY_INVALID_HTTP_HOST" + type="alertmodal"> + Invalid HTTP proxy address or port "[HOST]:[PORT]". + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="PROXY_INVALID_SOCKS_HOST" + type="alertmodal"> + Invalid SOCKS proxy address or port "[HOST]:[PORT]". + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ChangeProxySettings" + type="alert"> + Proxy settings take effect after you restart [APP_NAME]. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification name="AuthRequest" type="browser"> The site at '<nolink>[HOST_NAME]</nolink>' in realm '[REALM]' requires a user name and password. diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 9e70706603..beea53437a 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -52,7 +52,7 @@ multi_select="true" name="list_attachments" top="0" - width="311"/> + width="311" /> </accordion_tab> <accordion_tab layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 0bc1be666e..983f93cb03 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -117,16 +117,33 @@ label="Remember password" name="connect_btn" top="35" width="90" /> - <menu_button - left_pad="5" - top="35" - width="80" + <text + follows="left|bottom" + font="SansSerifSmall" + height="15" + left_pad="10" + name="mode_selection_text" + top="20" + width="130"> + Mode: + </text> + <combo_box + follows="left|bottom" height="23" - label="Mode ▲" - name="mode_menu" + max_chars="128" tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." - menu_filename="menu_mode_change.xml" - /> + top_pad="0" + name="mode_combo" + width="110"> + <combo_box.item + label="Basic" + name="Basic" + value="settings_minimal.xml" /> + <combo_box.item + label="Advanced" + name="Advanced" + value="" /> + </combo_box> <text follows="left|bottom" font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 8a7bd53054..34237c2503 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -97,7 +97,7 @@ mouse_opaque="false" name="location_combo" top_delta="0" - width="266"> + width="246"> <combo_list mouse_wheel_opaque="true"/> <!-- *TODO: Delete. Let the location_input use the correct art sizes. @@ -137,7 +137,7 @@ name="search_combo_box" tool_tip="Search" top_delta="0" - width="200" > + width="220" > <combo_editor label="Search [SECOND_LIFE]" name="search_combo_editor"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 30be5bc853..47236c1a48 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -139,7 +139,7 @@ height="16" label="Add datestamp to log file name." layout="topleft" - left_detla="5" + left_delta="5" name="logfile_name_datestamp" top_pad="10" width="350"/> 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 e639f0dc9d..a7078ce2e1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -70,7 +70,7 @@ layout="topleft" left="77" name="connection_port_enabled" - top_pad="20" + top_pad="10" width="256"> <check_box.commit_callback function="Notification.Show" @@ -79,7 +79,7 @@ <spinner control_name="ConnectionPort" enabled_control="ConnectionPortEnabled" - decimal_digits="0" + decimal_digits="0" follows="left|top" height="23" increment="1" @@ -195,60 +195,6 @@ name="media_popup_enabled" width="400" top_pad="5"/> - <check_box - top_delta="4" - enabled="true" - follows="left|top" - height="14" - initial_value="false" - control_name="BrowserProxyEnabled" - label="Enable Web Proxy" - left_delta="0" - mouse_opaque="true" - name="web_proxy_enabled" - radio_style="false" - width="400" top_pad="5"/> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="20" - name="Proxy location" - top_delta="16" - width="300"> - Proxy location: - </text> - <line_editor - control_name="BrowserProxyAddress" - enabled_control="BrowserProxyEnabled" - follows="left|top" - font="SansSerif" - height="23" - layout="topleft" - left_delta="0" - name="web_proxy_editor" - tool_tip="The name or IP address of the proxy you would like to use" - top_pad="4" - width="200" /> - <spinner - control_name="BrowserProxyPort" - enabled_control="BrowserProxyEnabled" - decimal_digits="0" - follows="left|top" - height="23" - increment="1" - initial_value="80" - label="Port number:" - label_width="95" - layout="topleft" - left_delta="210" - max_val="12000" - min_val="10" - name="web_proxy_port" - top_delta="0" - width="145" /> <text type="string" length="1" @@ -286,4 +232,31 @@ name="Install_manual" value="0" /> </combo_box> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="30" + name="Proxy Settings:" + mouse_opaque="false" + top_pad="5" + width="300"> + Proxy Settings: + </text> + <button + label="Adjust proxy settings" + follows="left|top" + height="23" + width="140" + label_selected="Browse" + layout="topleft" + left_delta="50" + name="set_proxy" + top_pad="5" + > + <button.commit_callback + function="Pref.Proxy" /> + </button> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index bbb8b40594..5d060c0a0d 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -193,7 +193,7 @@ </text> <text follows="left|top" - height="20" + height="60" layout="topleft" left_delta="0" name="height_text_lbl11" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 23ad0e9528..095f661462 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -35,7 +35,7 @@ </panel.string> <panel height="18" - left="-315" + left="-335" width="95" top="1" follows="right|top" @@ -77,18 +77,24 @@ top="0" width="55" /> </panel> - <menu_button + <combo_box follows="right|top" - image_color="0 0 0 0" - hover_glow_amount="0" left_pad="5" top="0" - width="55" - height="18" - label="Mode ▼" + width="100" + height="20" + name="mode_combo" tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." - menu_filename="menu_mode_change.xml" - /> + > + <combo_box.item + label="Basic Mode" + name="Basic" + value="settings_minimal.xml" /> + <combo_box.item + label="Advanced Mode" + name="Advanced" + value="" /> + </combo_box> <text type="string" font="SansSerifSmall" @@ -101,7 +107,7 @@ left_pad="5" name="TimeText" tool_tip="Current time (Pacific)" - width="90"> + width="75"> 24:00 AM PST </text> <button diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 1351ad6e52..c0154ae9b3 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3439,7 +3439,7 @@ Abuse Report</string> <string name="Female - Stick tougue out">Female - Stick tougue out</string> <string name="Female - Wow">Female - Wow</string> - <string name="/bow">/bow</string> + <string name="/bow1">/bow1</string> <string name="/clap">/clap</string> <string name="/count">/count</string> <string name="/extinguish">/extinguish</string> diff --git a/indra/newview/skins/default/xui/en/widgets/badge.xml b/indra/newview/skins/default/xui/en/widgets/badge.xml index 2d4c02b092..738d150f64 100644 --- a/indra/newview/skins/default/xui/en/widgets/badge.xml +++ b/indra/newview/skins/default/xui/en/widgets/badge.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!-- Additional attributes: --> -<badge border_image="Badge_Border" +<badge name="badge" + border_image="Badge_Border" border_color="BadgeBorderColor" font="SansSerifSmall" image="Badge_Background" diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml index 302014eb24..61d36468d7 100644 --- a/indra/newview/skins/default/xui/en/widgets/button.xml +++ b/indra/newview/skins/default/xui/en/widgets/button.xml @@ -26,5 +26,6 @@ height="23" scale_image="true" handle_right_mouse="true" - use_draw_context_alpha="true"> + use_draw_context_alpha="true" + held_down_delay.seconds="0.5"> </button> diff --git a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml index 48b987d7e8..ab3de1eaab 100644 --- a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml +++ b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <color_swatch alpha_background_image="color_swatch_alpha.tga" border_color="ColorSwatchBorderColor" - name="color_swatch"> + name="colorswatch"> <color_swatch.caption_text name="caption" halign="center" follows="left|right|bottom" diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml index 0720621f0b..2cc4abdd30 100644 --- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <filter_editor + name="filter_editor" clear_button_visible="true" search_button_visible="false" text_pad_left="7" diff --git a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml index e6bdcccfdf..6fa74f403d 100644 --- a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml @@ -5,4 +5,6 @@ item_height="20" item_top_pad="4" selection_image="Rounded_Square" + mouse_opaque="true" + follows="left|top|right" /> diff --git a/indra/newview/skins/default/xui/en/widgets/layout_stack.xml b/indra/newview/skins/default/xui/en/widgets/layout_stack.xml new file mode 100644 index 0000000000..48bcb46533 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/layout_stack.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Global settings for all widgets ("UI Controls") --> +<!-- The params in this file aren't currently getting loaded in OSX --> +<layout_stack name="stack"/> diff --git a/indra/newview/skins/default/xui/en/widgets/menu.xml b/indra/newview/skins/default/xui/en/widgets/menu.xml index 58543338f6..13ac84beb2 100644 --- a/indra/newview/skins/default/xui/en/widgets/menu.xml +++ b/indra/newview/skins/default/xui/en/widgets/menu.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu bg_color="MenuDefaultBgColor" +<menu name="menu" + bg_color="MenuDefaultBgColor" bg_visible="true" drop_shadow="true" tear_off="false" diff --git a/indra/newview/skins/default/xui/en/widgets/menu_bar.xml b/indra/newview/skins/default/xui/en/widgets/menu_bar.xml new file mode 100644 index 0000000000..ee3ef0cd7a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu_bar.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu_bar + can_tear_off = "false" + keep_fixed_size = "true" + horizontal_layout = "true" + visible = "true" + drop_shadow = "false"/> diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml index e5cea476da..7452d685eb 100644 --- a/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml +++ b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <menu_item_separator enabled_color="MenuItemEnabledColor" - disabled_color="MenuItemDisabledColor" - highlight_bg_color="MenuItemHighlightBgColor" - highlight_fg_color="MenuItemHighlightFgColor"> + name="separator" + disabled_color="MenuItemDisabledColor" + highlight_bg_color="MenuItemHighlightBgColor" + highlight_fg_color="MenuItemHighlightFgColor" + label="-----------"> </menu_item_separator> diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml index 185ed6ee3e..72af3924c1 100644 --- a/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml +++ b/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!-- Use "disabled color" to make it look like menu separators --> <menu_item_tear_off enabled_color="MenuItemDisabledColor" - disabled_color="MenuItemDisabledColor" - highlight_bg_color="MenuItemHighlightBgColor" - highlight_fg_color="MenuItemHighlightFgColor"> -</menu_item_tear_off> + name="tear_off" + label = "~~~~~~~~~~~" + disabled_color="MenuItemDisabledColor" + highlight_bg_color="MenuItemHighlightBgColor" + highlight_fg_color="MenuItemHighlightFgColor"/> diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml index e0900b48f3..90b0625982 100644 --- a/indra/newview/skins/default/xui/en/widgets/multi_slider.xml +++ b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_slider text_color="LabelTextColor" - text_disabled_color="LabelDisabledColor" - draw_track="true" - use_triangle="false" - font="SansSerifSmall"/> + mouse_opaque="true" + text_disabled_color="LabelDisabledColor" + draw_track="true" + use_triangle="false" + font="SansSerifSmall"/> diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml index 04a2cd635c..bbcb008df4 100644 --- a/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml +++ b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<multi_slider_bar track_color="MultiSliderTrackColor" +<multi_slider_bar name="multi_slider_bar" + track_color="MultiSliderTrackColor" thumb_disabled_color="MultiSliderDisabledThumbColor" thumb_outline_color="MultiSliderThumbOutlineColor" thumb_center_color="MultiSliderThumbCenterColor" @@ -7,4 +8,6 @@ triangle_color="MultiSliderTriangleColor" draw_track="true" use_triangle="false" - thumb_width="8"/> + thumb_width="8" + mouse_opaque="true" + follows="left|top"/> diff --git a/indra/newview/skins/default/xui/en/widgets/name_list.xml b/indra/newview/skins/default/xui/en/widgets/name_list.xml new file mode 100644 index 0000000000..3ae0f68227 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/name_list.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<name_list name="name_list" + /> diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml index 47a210d9b7..b36f723831 100644 --- a/indra/newview/skins/default/xui/en/widgets/panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/panel.xml @@ -4,7 +4,8 @@ bg_opaque_image - image name for "in-front" panel look bg_alpha_image - image name for "in-back" or transparent panel look --> -<panel bg_opaque_color="PanelFocusBackgroundColor" +<panel name="panel" + bg_opaque_color="PanelFocusBackgroundColor" bg_alpha_color="PanelDefaultBackgroundColor" bg_opaque_image_overlay="White" bg_alpha_image_overlay="White" diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml index e6d4bff8b5..682dcf40d8 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml @@ -5,7 +5,8 @@ track_image_horizontal ="ScrollTrack_Horiz" track_color="ScrollbarTrackColor" thumb_color="ScrollbarThumbColor" - thickness="15"> + thickness="15" + tab_stop="false"> <up_button name="up_button" image_unselected="ScrollArrow_Up" image_selected="ScrollArrow_Up" diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml b/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml index f936a1e208..8a48fcb32d 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<scroll_column_header - image_unselected="SegmentedBtn_Middle_Selected" +<scroll_column_header name="column_header" + image_unselected="SegmentedBtn_Middle_Selected" image_selected="SegmentedBtn_Middle_Selected" - image_pressed="SegmentedBtn_Middle_Selected_Press" + image_pressed="SegmentedBtn_Middle_Selected_Press" image_disabled="SegmentedBtn_Middle_Disabled" image_disabled_selected="SegmentedBtn_Middle_Selected_Disabled" image_overlay="DisclosureArrow_Opened_Off" image_overlay_alignment="right" halign="left" + tab_stop="false" scale_image="true" /> diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml index 85fc64c8b4..a6d096a964 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<scroll_container color="black" +<scroll_container name="scroll_container" + color="black" opaque="false" min_auto_scroll_rate="120" max_auto_scroll_rate="500" tab_stop="false" - name="scroll_container" mouse_opaque="true" /> diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml index dd93675807..e43989c6c7 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<scroll_list fg_unselected_color="ScrollUnselectedColor" +<scroll_list name="scroll_list" + fg_unselected_color="ScrollUnselectedColor" fg_selected_color="ScrollSelectedFGColor" bg_selected_color="ScrollSelectedBGColor" fg_disable_color="ScrollDisabledColor" @@ -13,6 +14,7 @@ scroll_bar_bg_visible="false" scroll_bar_bg_color="black" mouse_wheel_opaque="false" + mouse_opaque="true" background_visible="true" heading_height="23" draw_border="false" diff --git a/indra/newview/skins/default/xui/en/widgets/scrolling_panel_list.xml b/indra/newview/skins/default/xui/en/widgets/scrolling_panel_list.xml new file mode 100644 index 0000000000..40cbf5977a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/scrolling_panel_list.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<scrolling_panel_list name="scrolling_panel_list"/>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml index 32e443a058..faa0404b35 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <search_editor + name="search_editor" clear_button_visible="false" search_button_visible="true" text_pad_left="6" diff --git a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml index ea63cac790..0335213ed6 100644 --- a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml +++ b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!--All horizontal sliders are configured to have no highlighted track. See EXT-5939. --> -<slider_bar track_color="SliderTrackColor" +<slider_bar follows="left|top" + track_color="SliderTrackColor" thumb_outline_color="SliderThumbOutlineColor" thumb_center_color="SliderThumbCenterColor" thumb_image="SliderThumb_Off" diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index c37ead0be2..3e2202b20f 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -3,7 +3,9 @@ label_pad_bottom - vertical padding under tab button labels label_pad_left - padding to the left of tab button labels --> -<tab_container tab_min_width="60" +<tab_container name="tab_container" + mouse_opaque="false" + tab_min_width="60" tab_max_width="150" use_custom_icon_ctrl="false" halign="center" diff --git a/indra/newview/skins/default/xui/en/widgets/text_editor.xml b/indra/newview/skins/default/xui/en/widgets/text_editor.xml index 0f7f50b312..100571cc01 100644 --- a/indra/newview/skins/default/xui/en/widgets/text_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/text_editor.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!-- Core parameters are in simple_text_editor.xml --> <text_editor + name="text_editor" parse_urls="false" show_context_menu="true"/> diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml index 757f0f49d1..ba2fdf4f1f 100644 --- a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml +++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<texture_picker border_color="DefaultHighlightLight"> +<texture_picker border_color="DefaultHighlightLight" + name="texture picker" + mouse_opaque="true" + follows="left|top" + > <multiselect_text font="SansSerifSmall"/> <caption_text text="Multiple" halign="center" diff --git a/indra/newview/skins/default/xui/en/widgets/view_border.xml b/indra/newview/skins/default/xui/en/widgets/view_border.xml index 0b0a9beb95..bf40e3086b 100644 --- a/indra/newview/skins/default/xui/en/widgets/view_border.xml +++ b/indra/newview/skins/default/xui/en/widgets/view_border.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<view_border highlight_light_color="DefaultHighlightLight" +<view_border name="view_border" + highlight_light_color="DefaultHighlightLight" highlight_dark_color="DefaultHighlightDark" shadow_light_color="DefaultShadowLight" shadow_dark_color="DefaultShadowDark" border_thickness="1" border_style="line" - bevel_style="out"/>
\ No newline at end of file + bevel_style="out" + mouse_opaque="false" + follows="all"/>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/web_browser.xml b/indra/newview/skins/default/xui/en/widgets/web_browser.xml index 118d63bbf0..676fafd828 100644 --- a/indra/newview/skins/default/xui/en/widgets/web_browser.xml +++ b/indra/newview/skins/default/xui/en/widgets/web_browser.xml @@ -1,2 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<web_browser border_visible="true"/> +<web_browser border_visible="true" + tab_stop="false" + /> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 049a89aa06..b0d16d1ca4 100644 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="Desactivar los límites de la cámara" name="Disable Camera Distance"/> <menu_item_check label="Foto en Alta Resolución" name="HighResSnapshot"/> <menu_item_check label="Silenciar el Guardar una foto" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Comprimir las fotos para el disco duro" name="CompressSnapshotsToDisk"/> <menu label="Herramientas de rendimiento" name="Performance Tools"> <menu_item_call label="Medidor de lag" name="Lag Meter"/> <menu_item_check label="Estadísticas" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 1a75beed3f..2ec1b333a9 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2426,7 +2426,7 @@ Por favor, vuelve a intentarlo en unos momentos. </notification> <notification name="ObjectGiveItem"> Un objeto de nombre <nolink>[OBJECTFROMNAME]</nolink>, propiedad de [NAME_SLURL], te ha dado este [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Guardar"/> <button name="Discard" text="Descartar"/> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index ccea1e4570..46adc79a00 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="Désactiver les contraintes de la caméra" name="Disable Camera Distance"/> <menu_item_check label="Photo haute résolution" name="HighResSnapshot"/> <menu_item_check label="Photos discrètes sur disque" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Compresser les photos sur disque" name="CompressSnapshotsToDisk"/> <menu label="Outils de performance" name="Performance Tools"> <menu_item_call label="Mesure du lag" name="Lag Meter"/> <menu_item_check label="Barre de statistiques" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index dd8fdaf50e..ef95a1a389 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2418,7 +2418,7 @@ Veuillez réessayer dans quelques minutes. </notification> <notification name="ObjectGiveItem"> Un objet nommé <nolink>[OBJECTFROMNAME]</nolink> appartenant à [NAME_SLURL] vous a donné un objet de type [OBJECTTYPE] : -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Garder"/> <button name="Discard" text="Jeter"/> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index daeda576cc..ef40cbda7c 100644 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="Disabilita vincoli fotocamera" name="Disable Camera Distance"/> <menu_item_check label="Foto ad alta risoluzione" name="HighResSnapshot"/> <menu_item_check label="Manda foto su disco senza avvisi" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Comprimi le foto su disco" name="CompressSnapshotsToDisk"/> <menu label="Strumenti di performance" name="Performance Tools"> <menu_item_call label="Misuratore lag" name="Lag Meter"/> <menu_item_check label="Barra statistiche" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 88625ef4b7..d09f207af2 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2420,7 +2420,7 @@ Riprova tra qualche istante. </notification> <notification name="ObjectGiveItem"> Un oggetto denominato <nolink>[OBJECTFROMNAME]</nolink> di proprietà di [NAME_SLURL] ti ha dato questo [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Prendi"/> <button name="Discard" text="Rifiuta"/> diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml index 09b315b026..223c1e1f11 100644 --- a/indra/newview/skins/default/xui/ja/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="カメラの距離移動を制限しない" name="Disable Camera Distance"/> <menu_item_check label="高解像度スナップショット" name="HighResSnapshot"/> <menu_item_check label="シャッター音とアニメーションなしでスナップショットをディスクに保存する" name="QuietSnapshotsToDisk"/> - <menu_item_check label="圧縮してスナップショットをディスクに保存する" name="CompressSnapshotsToDisk"/> <menu label="パフォーマンスツール" name="Performance Tools"> <menu_item_call label="ラグ計測器" name="Lag Meter"/> <menu_item_check label="統計バー" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 5f5dad0d3e..6bff82bec4 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2467,7 +2467,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ </notification> <notification name="ObjectGiveItem"> [NAME_SLURL] が所有する <nolink>[OBJECTFROMNAME]</nolink> という名前のオブジェクトが、あなたに [OBJECTTYPE] を渡しました: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="受け取る"/> <button name="Discard" text="破棄"/> diff --git a/indra/newview/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml index f27b83d3f9..06e6d8ae7a 100644 --- a/indra/newview/skins/default/xui/nl/notifications.xml +++ b/indra/newview/skins/default/xui/nl/notifications.xml @@ -2698,7 +2698,7 @@ Probeer het alstublieft opnieuw over enkele ogenblikken. Geen geldig perceel kon gevonden worden. </notification> <notification name="ObjectGiveItem"> - Een object genaamd <nolink>[OBJECTFROMNAME]</nolink>, eigendom van [NAME_SLURL], heeft u een [OBJECTTYPE] genaamd [ITEM_SLURL] gegeven. + Een object genaamd <nolink>[OBJECTFROMNAME]</nolink>, eigendom van [NAME_SLURL], heeft u een [OBJECTTYPE] genaamd <nolink>[ITEM_SLURL]</nolink> gegeven. <form name="form"> <button name="Keep" text="Behouden"/> <button name="Discard" text="Afwijzen"/> diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml index e869806d04..fe4662c5a2 100644 --- a/indra/newview/skins/default/xui/pl/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml @@ -138,7 +138,6 @@ <menu_item_check label="Wyłącz ograniczenia zasięgu kamery" name="Disable Camera Distance"/> <menu_item_check label="Wysoka rozdzielczość zdjęć" name="HighResSnapshot"/> <menu_item_check label="Zapisuj zdjęcia na dysk twardy bez efektu dźwiękowego" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Skompresuj zdjęcie na dysk twardy" name="CompressSnapshotsToDisk"/> <menu label="Narzędzia" name="Performance Tools"> <menu_item_call label="Pomiar lagów" name="Lag Meter"/> <menu_item_check label="Statystyki" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 63f976a314..7d3225ea31 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2385,7 +2385,7 @@ Spróbuj ponowanie za kilka minut. </notification> <notification name="ObjectGiveItem"> Obiekt o nazwie <nolink>[OBJECTFROMNAME]</nolink>, należący do [NAME_SLURL] dał Tobie [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Zachowaj"/> <button name="Discard" text="Wyrzuć"/> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index c184fb0af3..ea54afed5e 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -159,7 +159,6 @@ <menu_item_check label="Disable Camera Constraints" name="Disable Camera Distance"/> <menu_item_check label="Foto de alta resolução" name="HighResSnapshot"/> <menu_item_check label="Compactar fotos para HD" name="QuietSnapshotsToDisk"/> - <menu_item_check label="Compactar fotos para HD" name="CompressSnapshotsToDisk"/> <menu label="Ferramentas de desempenho" name="Performance Tools"> <menu_item_call label="Medidor de lag" name="Lag Meter"/> <menu_item_check label="Barra de estatísticas" name="Statistics Bar"/> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 0bb02a7199..22de7edfdd 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2401,7 +2401,7 @@ Por favor, tente novamente em alguns instantes. </notification> <notification name="ObjectGiveItem"> Um objeto chamado <nolink>[OBJECTFROMNAME]</nolink>, de [NAME_SLURL], lhe deu este(a) [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Segure"/> <button name="Discard" text="Descarte"/> diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index bee940ddc1..0ac85d399e 100644 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -35,7 +35,7 @@ Qt Webkit 版本: [QT_WEBKIT_VERSION] (無) </floater.string> <floater.string name="AboutTraffic"> - Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) + 封包損失:[PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) </floater.string> <tab_container name="about_tab"> <panel label="資訊" name="support_panel"> @@ -77,7 +77,7 @@ google-perftools Copyright (c) 2005, Google Inc. All rights reserved. See licenses.txt for details. -Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) +語音聊天音頻編碼:Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) </text_editor> </panel> </tab_container> diff --git a/indra/newview/skins/default/xui/zh/floater_about_land.xml b/indra/newview/skins/default/xui/zh/floater_about_land.xml index efd8909e67..e59a23fda0 100644 --- a/indra/newview/skins/default/xui/zh/floater_about_land.xml +++ b/indra/newview/skins/default/xui/zh/floater_about_land.xml @@ -30,7 +30,7 @@ Anyone </panel.string> <panel.string name="area_text"> - Area + 區域 </panel.string> <panel.string name="area_size_text"> [AREA] m² @@ -42,7 +42,7 @@ You must approve your purchase to modify this land. </panel.string> <panel.string name="group_owned_text"> - (社團所擁有) + (群組所擁有) </panel.string> <panel.string name="profile_text"> 檔案 @@ -81,13 +81,13 @@ 分級: </text> <text name="ContentRatingText"> - 成人 + 完全成人 </text> <text name="Owner:"> 擁有者: </text> <text name="Group:"> - 社團: + 群組: </text> <button label="設定" name="Set..."/> <check_box label="Allow Deed to Group" name="check deed" tool_tip="A group officer can deed this land to the group, so it will be supported by the group's land allocation."/> @@ -133,7 +133,7 @@ </text> <button label="購買土地" name="Buy Land..."/> <button label="腳本資訊" name="Scripts..."/> - <button label="Buy For Group" name="Buy For Group..."/> + <button label="為群組購買" name="Buy For Group..."/> <button label="購買通行權" name="Buy Pass..." tool_tip="A pass gives you temporary access to this land."/> <button label="放棄土地" name="Abandon Land..."/> <button label="Reclaim Land" name="Reclaim Land..."/> @@ -186,7 +186,7 @@ 分級: </text> <text name="region_maturity_text"> - 成人 + 完全成人 </text> <text name="resellable_lbl"> Resale: @@ -238,7 +238,7 @@ <button label="顯示" label_selected="顯示" name="ShowOwner"/> <button label="退回" name="ReturnOwner..." tool_tip="Return objects to their owners."/> <text name="Set to group:"> - Set to group: + 設定群組: </text> <text name="group_objects_text"> [COUNT] @@ -286,10 +286,10 @@ Only large parcels can be listed in search. This option is disabled because you cannot modify this parcel's options. </panel.string> <panel.string name="mature_check_mature"> - Moderate Content + 適度成人內容 </panel.string> <panel.string name="mature_check_adult"> - 成人內容 + 完全成人內容 </panel.string> <panel.string name="mature_check_mature_tooltip"> Your parcel information or content is considered moderate. @@ -315,17 +315,17 @@ Only large parcels can be listed in search. 建造: </text> <check_box label="任何人" name="edit objects check"/> - <check_box label="社團" name="edit group objects check"/> + <check_box label="群組" name="edit group objects check"/> <text name="allow_label3"> 物件進入: </text> <check_box label="任何人" name="all object entry check"/> - <check_box label="社團" name="group object entry check"/> + <check_box label="群組" name="group object entry check"/> <text name="allow_label4"> 執行腳本: </text> <check_box label="任何人" name="check other scripts"/> - <check_box label="社團" name="check group scripts"/> + <check_box label="群組" name="check group scripts"/> <text name="land_options_label"> 土地選項: </text> @@ -335,7 +335,7 @@ Only large parcels can be listed in search. <combo_box name="land category with adult"> <combo_box.item label="任何類別" name="item0"/> <combo_box.item label="Linden Location" name="item1"/> - <combo_box.item label="成人" name="item2"/> + <combo_box.item label="完全成人" name="item2"/> <combo_box.item label="Arts & Culture" name="item3"/> <combo_box.item label="Business" name="item4"/> <combo_box.item label="Educational" name="item5"/> @@ -363,7 +363,7 @@ Only large parcels can be listed in search. <combo_box.item label="Rental" name="item13"/> <combo_box.item label="Other" name="item12"/> </combo_box> - <check_box label="Moderate Content" name="MatureCheck" tool_tip=" "/> + <check_box label="適度成人內容" name="MatureCheck" tool_tip=" "/> <text name="Snapshot:"> 快照: </text> @@ -416,12 +416,12 @@ Only large parcels can be listed in search. </text> <check_box label="Loop" name="media_loop" tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning."/> </panel> - <panel label="SOUND" name="land_audio_panel"> + <panel label="聲音" name="land_audio_panel"> <text name="MusicURL:"> - Music URL: + 音樂 URL: </text> <text name="Sound:"> - Sound: + 聲音: </text> <check_box label="Restrict gesture and object sounds to this parcel" name="check sound local"/> <text name="Voice settings:"> @@ -449,11 +449,11 @@ Only large parcels can be listed in search. </text> <check_box label="Payment Information on File [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Ban unidentified Residents."/> <check_box label="年齡驗證 [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information."/> - <check_box label="Allow Group Access: [GROUP]" name="GroupCheck" tool_tip="Set group in the General tab."/> - <check_box label="Sell passes to:" name="PassCheck" tool_tip="Allows temporary access to this parcel"/> + <check_box label="允許出入的群組:[GROUP]" name="GroupCheck" tool_tip="Set group in the General tab."/> + <check_box label="出售通行權給:" name="PassCheck" tool_tip="允許暫時出入這個地段"/> <combo_box name="pass_combo"> <combo_box.item label="Anyone" name="Anyone"/> - <combo_box.item label="社團" name="Group"/> + <combo_box.item label="群組" name="Group"/> </combo_box> <spinner label="Price in L$:" name="PriceSpin"/> <spinner label="Hours of access:" name="HoursSpin"/> @@ -462,11 +462,11 @@ Only large parcels can be listed in search. Allowed Residents </text> <name_list name="AccessList" tool_tip="([LISTED] listed, [MAX] max)"/> - <button label="Add" name="add_allowed"/> - <button label="Remove" label_selected="Remove" name="remove_allowed"/> + <button label="添加" name="add_allowed"/> + <button label="移除" label_selected="移除" name="remove_allowed"/> </panel> <panel name="Banned_layout_panel"> - <text label="Ban" name="BanCheck"> + <text label="禁止" name="BanCheck"> 被封鎖的居民 </text> <name_list name="BannedList" tool_tip="([LISTED] listed, [MAX] max)"/> diff --git a/indra/newview/skins/default/xui/zh/floater_animation_preview.xml b/indra/newview/skins/default/xui/zh/floater_animation_preview.xml index b5d65119f7..baf68ffce6 100644 --- a/indra/newview/skins/default/xui/zh/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/zh/floater_animation_preview.xml @@ -35,7 +35,7 @@ Maximum animation length is [MAX_LENGTH] seconds. Cannot get JOINT name. </floater.string> <floater.string name="E_ST_NO_OFFSET"> - Cannot find OFFSET. + 無法尋找位移。 </floater.string> <floater.string name="E_ST_NO_CHANNELS"> Cannot find CHANNELS. diff --git a/indra/newview/skins/default/xui/zh/floater_auction.xml b/indra/newview/skins/default/xui/zh/floater_auction.xml index eb1c9e55dc..b1862bc582 100644 --- a/indra/newview/skins/default/xui/zh/floater_auction.xml +++ b/indra/newview/skins/default/xui/zh/floater_auction.xml @@ -6,6 +6,6 @@ <check_box initial_value="true" label="Include yellow selection fence" name="fence_check"/> <button label="Snapshot" label_selected="Snapshot" name="snapshot_btn"/> <button label="Sell to Anyone" label_selected="Sell to Anyone" name="sell_to_anyone_btn"/> - <button label="Clear Settings" label_selected="Clear Settings" name="reset_parcel_btn"/> + <button label="清除設定" label_selected="清除設定" name="reset_parcel_btn"/> <button label="Start Auction" label_selected="Start Auction" name="start_auction_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_avatar_picker.xml b/indra/newview/skins/default/xui/zh/floater_avatar_picker.xml index 27a4199f8c..7e2d74c728 100644 --- a/indra/newview/skins/default/xui/zh/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/zh/floater_avatar_picker.xml @@ -36,7 +36,7 @@ </panel> <panel label="接近我" name="NearMePanel"> <text name="InstructSelectResident"> - 選擇一位附近的人: + 選擇一個附近的人: </text> <slider label="範圍" name="near_me_range"/> <text name="meters"> diff --git a/indra/newview/skins/default/xui/zh/floater_avatar_textures.xml b/indra/newview/skins/default/xui/zh/floater_avatar_textures.xml index b1dc081f04..36dae7c798 100644 --- a/indra/newview/skins/default/xui/zh/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/zh/floater_avatar_textures.xml @@ -17,31 +17,31 @@ Textures <panel name="scroll_content_panel"> <texture_picker label="頭髮" name="hair-baked"/> <texture_picker label="頭髮" name="hair_grain"/> - <texture_picker label="Hair Alpha" name="hair_alpha"/> + <texture_picker label="頭髮半透明" name="hair_alpha"/> <texture_picker label="頭部" name="head-baked"/> - <texture_picker label="Makeup" name="head_bodypaint"/> - <texture_picker label="Head Alpha" name="head_alpha"/> + <texture_picker label="化妝" name="head_bodypaint"/> + <texture_picker label="頭部半透明" name="head_alpha"/> <texture_picker label="頭部刺青" name="head_tattoo"/> <texture_picker label="眼睛" name="eyes-baked"/> <texture_picker label="眼睛" name="eyes_iris"/> - <texture_picker label="Eyes Alpha" name="eyes_alpha"/> - <texture_picker label="Upper Body" name="upper-baked"/> - <texture_picker label="Upper BodyPaint" name="upper_bodypaint"/> + <texture_picker label="眼睛半透明" name="eyes_alpha"/> + <texture_picker label="上半身半透明" name="upper-baked"/> + <texture_picker label="上半身身體部位" name="upper_bodypaint"/> <texture_picker label="內衣" name="upper_undershirt"/> <texture_picker label="手套" name="upper_gloves"/> <texture_picker label="襯衫" name="upper_shirt"/> - <texture_picker label="Upper Jacket" name="upper_jacket"/> - <texture_picker label="Upper Alpha" name="upper_alpha"/> - <texture_picker label="Upper Tattoo" name="upper_tattoo"/> - <texture_picker label="Lower Body" name="lower-baked"/> - <texture_picker label="Lower BodyPaint" name="lower_bodypaint"/> + <texture_picker label="上半身夾克" name="upper_jacket"/> + <texture_picker label="上半身半透明" name="upper_alpha"/> + <texture_picker label="上半身刺青" name="upper_tattoo"/> + <texture_picker label="下半身" name="lower-baked"/> + <texture_picker label="下半身身體部位" name="lower_bodypaint"/> <texture_picker label="內褲" name="lower_underpants"/> <texture_picker label="襪子" name="lower_socks"/> <texture_picker label="鞋子" name="lower_shoes"/> <texture_picker label="褲子" name="lower_pants"/> <texture_picker label="夾克" name="lower_jacket"/> - <texture_picker label="Lower Alpha" name="lower_alpha"/> - <texture_picker label="Lower Tattoo" name="lower_tattoo"/> + <texture_picker label="下半身半透明" name="lower_alpha"/> + <texture_picker label="下半身刺青" name="lower_tattoo"/> <texture_picker label="裙子" name="skirt-baked"/> <texture_picker label="裙子" name="skirt"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml b/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml index 629b0d17d5..660710fb7b 100644 --- a/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="EDIT CONTENT PERMISSIONS"> +<floater name="floaterbulkperms" title="編輯內容物權限"> <floater.string name="nothing_to_modify_text"> - Selection contains no editable contents. + 選擇未包含可編輯的內容物。 </floater.string> <floater.string name="status_text"> - Setting permissions on [NAME] + 設定權限於 [NAME] </floater.string> <floater.string name="start_text"> - Starting permission change requests... + 開始進行權限變更要求... </floater.string> <floater.string name="done_text"> - Finished permission change requests. + 權限變更要求已完成。 </floater.string> <icon name="icon_animation" tool_tip="動作"/> <icon name="icon_bodypart" tool_tip="身體部位"/> @@ -24,10 +24,10 @@ <button label="√ 全部" name="check_all"/> <button label="清除" label_selected="無" name="check_none"/> <text name="newperms"> - New Content Permissions + 新內容物權限 </text> <text name="GroupLabel"> - 社團: + 群組: </text> <check_box label="分享" name="share_with_group"/> <text name="AnyoneLabel"> @@ -39,7 +39,7 @@ </text> <check_box label="修改" name="next_owner_modify"/> <check_box label="覆製" name="next_owner_copy"/> - <check_box initial_value="true" label="轉移" name="next_owner_transfer" tool_tip="Next owner can give away or resell this object"/> + <check_box initial_value="true" label="轉移" name="next_owner_transfer" tool_tip="下一個擁有者能送出或轉售這個物件"/> <button label="確定" name="apply"/> <button label="取消" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_bumps.xml b/indra/newview/skins/default/xui/zh/floater_bumps.xml index d2b7494b08..64c11af953 100644 --- a/indra/newview/skins/default/xui/zh/floater_bumps.xml +++ b/indra/newview/skins/default/xui/zh/floater_bumps.xml @@ -1,22 +1,22 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_bumps" title="BUMPS, PUSHES & HITS"> <floater.string name="none_detected"> - None detected + 未偵測到 </floater.string> <floater.string name="bump"> - [TIME] [NAME] bumped you + [TIME] [NAME] 碰撞你 </floater.string> <floater.string name="llpushobject"> - [TIME] [NAME] pushed you with a script + [TIME] [NAME] 以腳本推撞你 </floater.string> <floater.string name="selected_object_collide"> - [TIME] [NAME] hit you with an object + [TIME] [NAME] 以物件擊中你 </floater.string> <floater.string name="scripted_object_collide"> - [TIME] [NAME] hit you with a scripted object + [TIME] [NAME] 以腳本物件擊中你 </floater.string> <floater.string name="physical_object_collide"> - [TIME] [NAME] hit you with a physical object + [TIME] [NAME] 以物理物件擊中你 </floater.string> <floater.string name="timeStr"> [[hour,datetime,slt]:[min,datetime,slt]] diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml index d8e9fb0ecc..f187a1ab40 100644 --- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml @@ -7,7 +7,7 @@ 你需要更多 L$ </text> <text name="contacting"> - Contacting LindeX... + 聯接到 LindeX 中... </text> <text name="info_buying"> 購買 L$ @@ -28,7 +28,7 @@ 1234 </line_editor> <text name="buying_label"> - For the price + 以此價格 </text> <text name="currency_est"> approx. [LOCALAMOUNT] @@ -60,7 +60,7 @@ <button label="立即購買" name="buy_btn"/> <button label="取消" name="cancel_btn"/> <text name="info_cannot_buy"> - Unable to Buy + 無法購買 </text> - <button label="Continue to the Web" name="error_web"/> + <button label="繼續到網頁" name="error_web"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_buy_land.xml b/indra/newview/skins/default/xui/zh/floater_buy_land.xml index 34401c11d0..c4a5d174ef 100644 --- a/indra/newview/skins/default/xui/zh/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/zh/floater_buy_land.xml @@ -16,7 +16,7 @@ You do not have permission to buy land for your active group. </floater.string> <floater.string name="no_land_selected"> - No land selected. + 無土地被選擇。 </floater.string> <floater.string name="multiple_parcels_selected"> Multiple different parcels selected. @@ -32,7 +32,7 @@ Try selecting a smaller area. The group already owns the parcel. </floater.string> <floater.string name="you_already_own"> - You already own the parcel. + 你已經擁有這個地段。 </floater.string> <floater.string name="set_to_sell_to_other"> The selected parcel is set to sell to another party. @@ -47,7 +47,7 @@ Try selecting a smaller area. <floater.string name="processing"> Processing your purchase... -(This may take a minute or two.) +(過程這將會花費一到兩分鐘) </floater.string> <floater.string name="fetching_error"> There has been an error while fetching land buying information. diff --git a/indra/newview/skins/default/xui/zh/floater_buy_object.xml b/indra/newview/skins/default/xui/zh/floater_buy_object.xml index ef8bc183a4..507e482766 100644 --- a/indra/newview/skins/default/xui/zh/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/zh/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="BUY COPY OF OBJECT"> +<floater name="contents" title="購買物件副本"> <floater.string name="title_buy_text"> 購買 </floater.string> diff --git a/indra/newview/skins/default/xui/zh/floater_camera.xml b/indra/newview/skins/default/xui/zh/floater_camera.xml index 65d04583f5..f4db20684c 100644 --- a/indra/newview/skins/default/xui/zh/floater_camera.xml +++ b/indra/newview/skins/default/xui/zh/floater_camera.xml @@ -10,56 +10,56 @@ Move Camera Up and Down, Left and Right </floater.string> <floater.string name="camera_modes_title"> - Camera modes + 攝影機模式 </floater.string> <floater.string name="pan_mode_title"> - Orbit Zoom Pan + 環繞縮放平移 </floater.string> <floater.string name="presets_mode_title"> - Preset Views + 預設視角 </floater.string> <floater.string name="free_mode_title"> - View Object + 視角物件 </floater.string> <panel name="controls"> <panel name="preset_views_list"> <panel_camera_item name="front_view"> <panel_camera_item.text name="front_view_text"> - Front View + 前視視角 </panel_camera_item.text> </panel_camera_item> <panel_camera_item name="group_view"> <panel_camera_item.text name="side_view_text"> - Side View + 側視視角 </panel_camera_item.text> </panel_camera_item> <panel_camera_item name="rear_view"> <panel_camera_item.text name="rear_view_text"> - Rear View + 後視視角 </panel_camera_item.text> </panel_camera_item> </panel> <panel name="camera_modes_list"> <panel_camera_item name="object_view"> <panel_camera_item.text name="object_view_text"> - Object View + 物件視角 </panel_camera_item.text> </panel_camera_item> <panel_camera_item name="mouselook_view"> <panel_camera_item.text name="mouselook_view_text"> - Mouselook View + 第一人稱視角 </panel_camera_item.text> </panel_camera_item> </panel> <panel name="zoom"> <joystick_rotate name="cam_rotate_stick" tool_tip="Orbit camera around focus"/> <slider_bar name="zoom_slider" tool_tip="Zoom camera toward focus"/> - <joystick_track name="cam_track_stick" tool_tip="Move camera up and down, left and right"/> + <joystick_track name="cam_track_stick" tool_tip="移動攝影機上下左右"/> </panel> </panel> <panel name="buttons"> - <button label="" name="presets_btn" tool_tip="Preset Views"/> + <button label="" name="presets_btn" tool_tip="預設視角"/> <button label="" name="pan_btn" tool_tip="Orbit Zoom Pan"/> - <button label="" name="avatarview_btn" tool_tip="Camera modes"/> + <button label="" name="avatarview_btn" tool_tip="攝影機模式"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_choose_group.xml b/indra/newview/skins/default/xui/zh/floater_choose_group.xml index 9968565bf2..9977bfc828 100644 --- a/indra/newview/skins/default/xui/zh/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/zh/floater_choose_group.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="groups" title="社團"> +<floater name="groups" title="群組"> <text name="groupdesc"> - 選擇一個社團: + 選擇一個群組: </text> <button label="確定" label_selected="確定" name="OK"/> <button label="取消" label_selected="取消" name="Cancel"/> diff --git a/indra/newview/skins/default/xui/zh/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/zh/floater_day_cycle_options.xml new file mode 100644 index 0000000000..28d2ba6ed4 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_day_cycle_options.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Day Cycle Floater" title="日循環編輯器"> + <tab_container name="Day Cycle Tabs"> + <panel label="日循環" name="Day Cycle"> + <multi_slider initial_value="0" name="WLTimeSlider"/> + <multi_slider initial_value="0" name="WLDayCycleKeys"/> + <text name="WL12am"> + 12am + </text> + <text name="WL3am"> + 3am + </text> + <text name="WL6am"> + 6am + </text> + <text name="WL9amHash"> + 9am + </text> + <text name="WL12pmHash"> + 12pm + </text> + <text name="WL3pm"> + 3pm + </text> + <text name="WL6pm"> + 6pm + </text> + <text name="WL9pm"> + 9pm + </text> + <text name="WL12am2"> + 12am + </text> + <text name="WL12amHash"> + | + </text> + <text name="WL3amHash"> + I + </text> + <text name="WL6amHash"> + | + </text> + <text name="WL9amHash2"> + I + </text> + <text name="WL12pmHash2"> + | + </text> + <text name="WL3pmHash"> + I + </text> + <text name="WL6pmHash"> + | + </text> + <text name="WL9pmHash"> + I + </text> + <text name="WL12amHash2"> + | + </text> + <button label="Add Key" label_selected="Add Key" name="WLAddKey"/> + <button label="Delete Key" label_selected="Delete Key" name="WLDeleteKey"/> + <text name="WLCurKeyFrameText"> + Key Frame Settings: + </text> + <text name="WLCurKeyTimeText"> + Key Time: + </text> + <spinner label="Hour" name="WLCurKeyHour"/> + <spinner label="Min" name="WLCurKeyMin"/> + <text name="WLCurKeyTimeText2"> + Key Preset: + </text> + <combo_box label="Preset" name="WLKeyPresets"/> + <text name="DayCycleText"> + Snap: + </text> + <combo_box label="五分鐘" name="WLSnapOptions"/> + <text name="DayCycleText2"> + Length of Cycle: + </text> + <spinner label="小時" name="WLLengthOfDayHour"/> + <spinner label="分" name="WLLengthOfDayMin"/> + <spinner label="秒" name="WLLengthOfDaySec"/> + <text name="DayCycleText3"> + 預覽: + </text> + <button label="Play" label_selected="Play" name="WLAnimSky"/> + <button label="停止!" label_selected="停止" name="WLStopAnimSky"/> + <button label="Use Estate Time" label_selected="Go to Estate Time" name="WLUseLindenTime"/> + <button label="Save Test Day" label_selected="Save Test Day" name="WLSaveDayCycle"/> + <button label="Load Test Day" label_selected="Load Test Day" name="WLLoadDayCycle"/> + </panel> + </tab_container> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_display_name.xml b/indra/newview/skins/default/xui/zh/floater_display_name.xml index e12fc21166..39abfe0b8b 100644 --- a/indra/newview/skins/default/xui/zh/floater_display_name.xml +++ b/indra/newview/skins/default/xui/zh/floater_display_name.xml @@ -13,6 +13,6 @@ Type your new name again to confirm: </text> <button label="儲存" name="save_btn" tool_tip="Save your new Display Name"/> - <button label="Reset" name="reset_btn" tool_tip="Make Display Name the same as Username"/> + <button label="重設" name="reset_btn" tool_tip="Make Display Name the same as Username"/> <button label="取消" name="cancel_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_env_settings.xml b/indra/newview/skins/default/xui/zh/floater_env_settings.xml new file mode 100644 index 0000000000..534ee7f0d0 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_env_settings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Environment Editor Floater" title="ENVIRONMENT EDITOR"> + <floater.string name="timeStr"> + [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc] + </floater.string> + <text name="EnvTimeText"> + Time of Day + </text> + <text name="EnvTimeText2"> + 12:00 PM + </text> + <text name="EnvCloudText"> + Cloud Cover + </text> + <text name="EnvWaterColorText"> + 水色 + </text> + <color_swatch name="EnvWaterColor" tool_tip="Click to open color picker"/> + <text name="EnvWaterFogText"> + 水霧 + </text> + <button label="Use Estate Time" name="EnvUseEstateTimeButton"/> + <button label="進階天空" name="EnvAdvancedSkyButton"/> + <button label="進階水文" name="EnvAdvancedWaterButton"/> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_gesture.xml b/indra/newview/skins/default/xui/zh/floater_gesture.xml index 651a976774..a809cf085c 100644 --- a/indra/newview/skins/default/xui/zh/floater_gesture.xml +++ b/indra/newview/skins/default/xui/zh/floater_gesture.xml @@ -4,7 +4,7 @@ 載入中... </floater.string> <floater.string name="playing"> - (Playing) + (播放中) </floater.string> <floater.string name="copy_name"> Copy of [COPY_NAME] diff --git a/indra/newview/skins/default/xui/zh/floater_god_tools.xml b/indra/newview/skins/default/xui/zh/floater_god_tools.xml index fbe89ab2a6..448113bf74 100644 --- a/indra/newview/skins/default/xui/zh/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/zh/floater_god_tools.xml @@ -2,25 +2,25 @@ <floater name="godtools floater" title="神之工具"> <tab_container name="GodTools Tabs"> <panel label="網格" name="grid"> - <button label="Flush This Region's Map Visibility Caches" label_selected="Flush This Region's Map Visibility Caches" name="Flush This Region's Map Visibility Caches"/> + <button label="刷新這個地區的地圖可視快取" label_selected="刷新這個地區的地圖可視快取" name="Flush This Region's Map Visibility Caches"/> </panel> <panel label="地區" name="region"> <text name="Region Name:"> 地區名稱: </text> <check_box label="Prelude" name="check prelude" tool_tip="Set this to make the region a prelude"/> - <check_box label="Fixed Sun" name="check fixed sun" tool_tip="Fix the sun position (like in Region/Estate > Terrain"/> + <check_box label="固定太陽" name="check fixed sun" tool_tip="Fix the sun position (like in Region/Estate > Terrain"/> <check_box label="Reset Home On Teleport" name="check reset home" tool_tip="When Resident teleports out, reset their home to the destination position."/> <check_box label="Visible" name="check visible" tool_tip="Set this to make the region visible to non-gods"/> - <check_box label="Damage" name="check damage" tool_tip="Set this to enable damage in this region"/> - <check_box label="Block Traffic Tracking" name="block dwell" tool_tip="Set this to make the region not compute traffic"/> - <check_box label="Block Terraform" name="block terraform" tool_tip="Set this to disallow people terraforming their land"/> - <check_box label="Sandbox" name="is sandbox" tool_tip="Toggle whether this is a sandbox region"/> - <button label="Bake Terrain" label_selected="Bake Terrain" name="Bake Terrain" tool_tip="Save the current terrain as default"/> + <check_box label="傷害" name="check damage" tool_tip="Set this to enable damage in this region"/> + <check_box label="阻止流量追蹤" name="block dwell" tool_tip="Set this to make the region not compute traffic"/> + <check_box label="阻止變形" name="block terraform" tool_tip="Set this to disallow people terraforming their land"/> + <check_box label="沙盒" name="is sandbox" tool_tip="Toggle whether this is a sandbox region"/> + <button label="Bake Terrain" label_selected="Bake Terrain" name="Bake Terrain" tool_tip="儲存目前的地形為預設"/> <button label="Revert Terrain" label_selected="Revert Terrain" name="Revert Terrain" tool_tip="Replace the current terrain with default"/> <button label="Swap Terrain" label_selected="Swap Terrain" name="Swap Terrain" tool_tip="Swap current terrain with default"/> <text name="estate id"> - Estate ID: + 領地 ID: </text> <text name="parent id"> Parent ID: @@ -40,14 +40,14 @@ <text name="land cost text"> L$ per m²: </text> - <button label="Refresh" label_selected="Refresh" name="Refresh" tool_tip="Click here to refresh the above information"/> - <button label="套用" label_selected="套用" name="Apply" tool_tip="Click here to apply any changes from above"/> + <button label="重新整理" label_selected="重新整理" name="Refresh" tool_tip="Click here to refresh the above information"/> + <button label="套用" label_selected="套用" name="Apply" tool_tip="點擊此處以接受套用上述變更"/> <button label="選擇地區" label_selected="選擇地區" name="Select Region" tool_tip="Select the whole region with the land tool"/> <button label="立即自動儲存" label_selected="立即自動儲存" name="Autosave now" tool_tip="Save gzipped state to autosave directory"/> </panel> <panel label="物件" name="objects"> <panel.string name="no_target"> - (no target) + (無目標) </panel.string> <text name="Region Name:"> 地區名稱: @@ -61,7 +61,7 @@ <button label="套用" label_selected="套用" name="Apply" tool_tip="Click here to apply any changes from above"/> <button label="Set Target" label_selected="Set Target" name="Set Target" tool_tip="Set the target avatar for object deletion"/> <text name="target_avatar_name"> - (no target) + (無目標) </text> <button label="Delete Target's Scripted Objects On Others Land" label_selected="Delete Target's Scripted Objects On Others Land" name="Delete Target's Scripted Objects On Others Land" tool_tip="Delete all scripted objects owned by the target on land not owned by the target. (no copy) objects will be returned."/> <button label="Delete Target's Scripted Objects On *Any* Land" label_selected="Delete Target's Scripted Objects On *Any* Land" name="Delete Target's Scripted Objects On *Any* Land" tool_tip="Delete all scripted objects owned by the target in this region. (no copy) objects will be returned."/> 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 fcd702b16d..a41be7ef9a 100644 --- a/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/zh/floater_inventory_item_properties.xml @@ -46,7 +46,7 @@ </text> <check_box label="覆製" name="CheckEveryoneCopy"/> <text name="GroupLabel"> - 社團: + 群組: </text> <check_box label="分享" name="CheckShareWithGroup"/> <text name="NextOwnerLabel"> diff --git a/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml index a4ede92ab1..370ab32b9f 100644 --- a/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Inventory Finder" title="最近_收納區_物品"> <check_box label="動作" name="check_animation"/> - <check_box label="Calling Cards" name="check_calling_card"/> + <check_box label="名片" name="check_calling_card"/> <check_box label="服裝" name="check_clothing"/> <check_box label="姿勢" name="check_gesture"/> <check_box label="地標" name="check_landmark"/> diff --git a/indra/newview/skins/default/xui/zh/floater_land_holdings.xml b/indra/newview/skins/default/xui/zh/floater_land_holdings.xml index 3d9d391a21..1d172f63e1 100644 --- a/indra/newview/skins/default/xui/zh/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/zh/floater_land_holdings.xml @@ -1,22 +1,22 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="MY LAND"> +<floater name="land holdings floater" title="我的土地"> <floater.string name="area_string"> [AREA] m² </floater.string> <scroll_list name="parcel list"> <scroll_list.columns label="地段" name="name"/> <scroll_list.columns label="地區" name="location"/> - <scroll_list.columns label="Type" name="type"/> - <scroll_list.columns label="Area" name="area"/> + <scroll_list.columns label="類型" name="type"/> + <scroll_list.columns label="區域" name="area"/> </scroll_list> - <button label="瞬間傳送" label_selected="瞬間傳送" name="Teleport" tool_tip="Teleport to the center of this land."/> - <button label="地圖" label_selected="地圖" name="Show on Map" tool_tip="Show this land on the world map"/> + <button label="瞬間傳送" label_selected="瞬間傳送" name="Teleport" tool_tip="瞬間傳送到這土地的中央。"/> + <button label="地圖" label_selected="地圖" name="Show on Map" tool_tip="將這塊土地顯示在世界地圖上。"/> <text name="contrib_label"> Contributions to your groups: </text> <scroll_list name="grant list"> - <scroll_list.columns label="社團" name="group"/> - <scroll_list.columns label="Area" name="area"/> + <scroll_list.columns label="群組" name="group"/> + <scroll_list.columns label="區域" name="area"/> </scroll_list> <text name="allowed_label"> Allowed land holdings at current payment plan: diff --git a/indra/newview/skins/default/xui/zh/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/zh/floater_live_lsleditor.xml index e6f6e32352..fe61c312ed 100644 --- a/indra/newview/skins/default/xui/zh/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/zh/floater_live_lsleditor.xml @@ -9,7 +9,7 @@ <floater.string name="Title"> 腳本:[NAME] </floater.string> - <button label="Reset" label_selected="Reset" name="Reset"/> - <check_box initial_value="true" label="Running" name="running"/> + <button label="重設" label_selected="重設" name="Reset"/> + <check_box initial_value="true" label="執行中" name="running"/> <check_box initial_value="true" label="Mono" name="mono"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_moveview.xml b/indra/newview/skins/default/xui/zh/floater_moveview.xml index 3e44f458e7..e1155bdf34 100644 --- a/indra/newview/skins/default/xui/zh/floater_moveview.xml +++ b/indra/newview/skins/default/xui/zh/floater_moveview.xml @@ -43,33 +43,33 @@ 向下飛(按下 C 鍵) </string> <string name="jump_tooltip"> - Jump (press E) + 跳躍(按下 E 鍵) </string> <string name="crouch_tooltip"> - Crouch (press C) + 蹲下(按下 C 鍵) </string> <string name="walk_title"> - Walk + 行走 </string> <string name="run_title"> - Run + 跑步 </string> <string name="fly_title"> 飛行 </string> <panel name="panel_actions"> - <button name="turn left btn" tool_tip="Turn left (press Left Arrow or A)"/> - <joystick_slide name="move left btn" tool_tip="Walk left (press Shift + Left Arrow or A)"/> - <button name="turn right btn" tool_tip="Turn right (press Right Arrow or D)"/> - <joystick_slide name="move right btn" tool_tip="Walk right (press Shift + Right Arrow or D)"/> - <joystick_turn name="forward btn" tool_tip="Walk forward (press up arrow or W)"/> - <joystick_turn name="backward btn" tool_tip="Walk backward (press down arrow or S)"/> + <button name="turn left btn" tool_tip="左轉(按下左方向鍵或按 A 鍵)"/> + <joystick_slide name="move left btn" tool_tip="向左走(按下 Shift 加左方向鍵或按 A 鍵)"/> + <button name="turn right btn" tool_tip="右轉(按下右方向鍵或按 D 鍵)"/> + <joystick_slide name="move right btn" tool_tip="向右走(按下 Shift 加右方向鍵或按 D 鍵)"/> + <joystick_turn name="forward btn" tool_tip="向前走(按向上方向鍵或按 W 鍵)"/> + <joystick_turn name="backward btn" tool_tip="向後退(按向下方向鍵或按 S 鍵)"/> <button name="move up btn" tool_tip="向上飛(按下 E 鍵)"/> <button name="move down btn" tool_tip="向下飛(按下 C 建)"/> </panel> <panel name="panel_modes"> - <button label="" name="mode_walk_btn" tool_tip="Walking mode"/> - <button label="" name="mode_run_btn" tool_tip="Running mode"/> + <button label="" name="mode_walk_btn" tool_tip="行走模式"/> + <button label="" name="mode_run_btn" tool_tip="跑步模式"/> <button label="" name="mode_fly_btn" tool_tip="飛行模式"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_mute_object.xml b/indra/newview/skins/default/xui/zh/floater_mute_object.xml index 7d76f4de08..606e061395 100644 --- a/indra/newview/skins/default/xui/zh/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/zh/floater_mute_object.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="block by name" title="BLOCK OBJECT BY NAME"> +<floater name="block by name" title="依名稱封鎖物件"> <text name="message"> Block an object: </text> <line_editor name="object_name"> - Object name + 物件名稱 </line_editor> <text name="note"> * Only blocks object text, not sounds diff --git a/indra/newview/skins/default/xui/zh/floater_outfit_save_as.xml b/indra/newview/skins/default/xui/zh/floater_outfit_save_as.xml index e33183a0dc..a557e1c2e3 100644 --- a/indra/newview/skins/default/xui/zh/floater_outfit_save_as.xml +++ b/indra/newview/skins/default/xui/zh/floater_outfit_save_as.xml @@ -6,6 +6,6 @@ 儲存我正在穿的為新裝扮: </text> <line_editor name="name ed"> - [DESC] (new) + [DESC] (新) </line_editor> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_pay.xml b/indra/newview/skins/default/xui/zh/floater_pay.xml index b4841df0ff..0a823cd82e 100644 --- a/indra/newview/skins/default/xui/zh/floater_pay.xml +++ b/indra/newview/skins/default/xui/zh/floater_pay.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> <string name="payee_group"> - 支付社團 + 支付群組 </string> <string name="payee_resident"> 支付居民 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 2a2aec93b9..39259524d7 100644 --- a/indra/newview/skins/default/xui/zh/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/zh/floater_pay_object.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="Give Money"> <string name="payee_group"> - 支付社團 + 支付群組 </string> <string name="payee_resident"> 支付居民 diff --git a/indra/newview/skins/default/xui/zh/floater_perm_prefs.xml b/indra/newview/skins/default/xui/zh/floater_perm_prefs.xml index 31b8133a18..498848ee56 100644 --- a/indra/newview/skins/default/xui/zh/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/zh/floater_perm_prefs.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="perm prefs" title="預設上傳權限"> <panel label="權限" name="permissions"> - <check_box label="與社團分享" name="share_with_group"/> + <check_box label="與群組分享" name="share_with_group"/> <check_box label="允許任何人覆製" name="everyone_copy"/> <text name="NextOwnerLabel"> 下一個擁有者可以: diff --git a/indra/newview/skins/default/xui/zh/floater_preview_gesture.xml b/indra/newview/skins/default/xui/zh/floater_preview_gesture.xml index 0649ecb791..ad49370423 100644 --- a/indra/newview/skins/default/xui/zh/floater_preview_gesture.xml +++ b/indra/newview/skins/default/xui/zh/floater_preview_gesture.xml @@ -40,7 +40,7 @@ <combo_box label="無" name="modifier_combo"/> <combo_box label="無" name="key_combo"/> <text name="library_label"> - Library: + 資源庫: </text> <scroll_list name="library_list"> <scroll_list.rows name="action_animation" value="動作"/> @@ -48,7 +48,7 @@ <scroll_list.rows name="action_chat" value="聊天"/> <scroll_list.rows name="action_wait" value="等待"/> </scroll_list> - <button label="Add >>" name="add_btn"/> + <button label="添加 >>" name="add_btn"/> <text name="steps_label"> Steps: </text> diff --git a/indra/newview/skins/default/xui/zh/floater_preview_notecard.xml b/indra/newview/skins/default/xui/zh/floater_preview_notecard.xml index 3c2f913a6d..9447939801 100644 --- a/indra/newview/skins/default/xui/zh/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/zh/floater_preview_notecard.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="preview notecard" title="記事卡:"> <floater.string name="no_object"> - Unable to find object containing this notecard. + 未發現物件包含此記事卡。 </floater.string> <floater.string name="not_allowed"> - You do not have permission to view this notecard. + 你並沒有權限去察看此記事卡。 </floater.string> <floater.string name="Title"> 記事卡: [NAME] diff --git a/indra/newview/skins/default/xui/zh/floater_preview_sound.xml b/indra/newview/skins/default/xui/zh/floater_preview_sound.xml index d9854a85b6..d99d13669f 100644 --- a/indra/newview/skins/default/xui/zh/floater_preview_sound.xml +++ b/indra/newview/skins/default/xui/zh/floater_preview_sound.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="preview_sound"> <floater.string name="Title"> - Sound: [NAME] + 聲音: [NAME] </floater.string> <text name="desc txt"> 描述: diff --git a/indra/newview/skins/default/xui/zh/floater_publish_classified.xml b/indra/newview/skins/default/xui/zh/floater_publish_classified.xml index acec1efcb0..5f0ffea182 100644 --- a/indra/newview/skins/default/xui/zh/floater_publish_classified.xml +++ b/indra/newview/skins/default/xui/zh/floater_publish_classified.xml @@ -5,7 +5,7 @@ Remember, Classified fees are non-refundable. </text> - <spinner label="價格: L$" name="price_for_listing" tool_tip="Price for listing." value="50"/> - <button label="Publish" name="publish_btn"/> + <spinner label="價格: L$" name="price_for_listing" tool_tip="刊登費用。" value="50"/> + <button label="發布" name="publish_btn"/> <button label="取消" name="cancel_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_region_debug_console.xml b/indra/newview/skins/default/xui/zh/floater_region_debug_console.xml index b16a3bd9cc..4ff2a3fc79 100644 --- a/indra/newview/skins/default/xui/zh/floater_region_debug_console.xml +++ b/indra/newview/skins/default/xui/zh/floater_region_debug_console.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="region_debug_console" title="Region Debug"/> +<floater name="region_debug_console" title="地區除錯"/> diff --git a/indra/newview/skins/default/xui/zh/floater_script_preview.xml b/indra/newview/skins/default/xui/zh/floater_script_preview.xml index 75ef4ebe73..c3d05402c0 100644 --- a/indra/newview/skins/default/xui/zh/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/zh/floater_script_preview.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT"> <floater.string name="Title"> - SCRIPT: [NAME] + 腳本:[NAME] </floater.string> <text name="desc txt"> 描述: diff --git a/indra/newview/skins/default/xui/zh/floater_script_queue.xml b/indra/newview/skins/default/xui/zh/floater_script_queue.xml index 4062db5014..ff02946d86 100644 --- a/indra/newview/skins/default/xui/zh/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/zh/floater_script_queue.xml @@ -7,13 +7,13 @@ Done. </floater.string> <floater.string name="Resetting"> - Resetting + 重設中 </floater.string> <floater.string name="Running"> - Running + 執行中 </floater.string> <floater.string name="NotRunning"> - Not running + 非執行中 </floater.string> <button label="關閉" label_selected="關閉" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_search.xml b/indra/newview/skins/default/xui/zh/floater_search.xml index 5b247350b8..bb693b7a70 100644 --- a/indra/newview/skins/default/xui/zh/floater_search.xml +++ b/indra/newview/skins/default/xui/zh/floater_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_search" title="FIND"> +<floater name="floater_search" title="尋找"> <floater.string name="loading_text"> 載入中... </floater.string> diff --git a/indra/newview/skins/default/xui/zh/floater_settings_debug.xml b/indra/newview/skins/default/xui/zh/floater_settings_debug.xml index bba075cf08..56a31bc292 100644 --- a/indra/newview/skins/default/xui/zh/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/zh/floater_settings_debug.xml @@ -4,10 +4,10 @@ <radio_item label="TRUE" name="TRUE" value="true"/> <radio_item label="FALSE" name="FALSE" value=""/> </radio_group> - <color_swatch label="Color" name="val_color_swatch"/> + <color_swatch label="顏色" name="val_color_swatch"/> <spinner label="x" name="val_spinner_1"/> <spinner label="x" name="val_spinner_2"/> <spinner label="x" name="val_spinner_3"/> <spinner label="x" name="val_spinner_4"/> - <button label="Reset to default" name="default_btn"/> + <button label="回復至預設值" name="default_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_stats.xml b/indra/newview/skins/default/xui/zh/floater_stats.xml index eebd5df3f7..582572d0e2 100644 --- a/indra/newview/skins/default/xui/zh/floater_stats.xml +++ b/indra/newview/skins/default/xui/zh/floater_stats.xml @@ -50,9 +50,9 @@ <stat_bar label="物件" name="simobjects"/> <stat_bar label="Active Objects" name="simactiveobjects"/> <stat_bar label="Active Scripts" name="simactivescripts"/> - <stat_bar label="Script Events" name="simscripteps"/> - <stat_bar label="Packets In" name="siminpps"/> - <stat_bar label="Packets Out" name="simoutpps"/> + <stat_bar label="腳本事件" name="simscripteps"/> + <stat_bar label="進入封包" name="siminpps"/> + <stat_bar label="出去封包" name="simoutpps"/> <stat_bar label="擱置下載" name="simpendingdownloads"/> <stat_bar label="擱置上傳" name="simpendinguploads"/> <stat_bar label="Total Unacked Bytes" name="simtotalunackedbytes"/> diff --git a/indra/newview/skins/default/xui/zh/floater_tools.xml b/indra/newview/skins/default/xui/zh/floater_tools.xml index 300d7ee63b..c70e70451e 100644 --- a/indra/newview/skins/default/xui/zh/floater_tools.xml +++ b/indra/newview/skins/default/xui/zh/floater_tools.xml @@ -49,13 +49,13 @@ </text> <radio_group name="focus_radio_group"> <radio_item label="Zoom" name="radio zoom"/> - <radio_item label="Orbit (Ctrl)" name="radio orbit"/> - <radio_item label="Pan (Ctrl+Shift)" name="radio pan"/> + <radio_item label="環繞(Ctrl)" name="radio orbit"/> + <radio_item label="平移(Ctrl+Shift)" name="radio pan"/> </radio_group> <slider_bar initial_value="0.125" name="slider zoom"/> <radio_group name="move_radio_group"> <radio_item label="移動" name="radio move"/> - <radio_item label="Lift (Ctrl)" name="radio lift"/> + <radio_item label="舉起(Ctrl)" name="radio lift"/> <radio_item label="Spin (Ctrl+Shift)" name="radio spin"/> </radio_group> <radio_group name="edit_radio_group"> @@ -178,10 +178,10 @@ 擁有者: </text> <text name="Group:"> - 社團: + 群組: </text> <name_box initial_value="載入中..." name="Group Name Proxy"/> - <button name="button set group" tool_tip="選擇一個社團以分享這物件權限"/> + <button name="button set group" tool_tip="選擇一個群組以分享這物件權限"/> <check_box label="分享" name="checkbox share with group" tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."/> <button label="Deed" label_selected="Deed" name="button deed" tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."/> <text name="label click action"> @@ -480,7 +480,7 @@ <check_box label="顯示擁有者" name="checkbox show owners" tool_tip="Colorize the parcels according to the type of owner: 綠色 = 你的土地 -水藍 = 你社團的土地 +水藍 = 你群組的土地 紅色 = 其他人所有 黃色 = 出售 紫色 = 拍賣 diff --git a/indra/newview/skins/default/xui/zh/floater_top_objects.xml b/indra/newview/skins/default/xui/zh/floater_top_objects.xml index 074a4a1881..0e7e0c5b1a 100644 --- a/indra/newview/skins/default/xui/zh/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/zh/floater_top_objects.xml @@ -22,7 +22,7 @@ 積分 </floater.string> <floater.string name="none_descriptor"> - None found. + 未發現。 </floater.string> <text name="title_text"> 載入中... @@ -39,7 +39,7 @@ <text name="id_text"> 物件 ID: </text> - <button label="Show Beacon" name="show_beacon_btn"/> + <button label="顯示指標" name="show_beacon_btn"/> <text name="obj_name_text"> 物件名稱: </text> diff --git a/indra/newview/skins/default/xui/zh/floater_voice_controls.xml b/indra/newview/skins/default/xui/zh/floater_voice_controls.xml index 4d650eaaee..c27b80e9c5 100644 --- a/indra/newview/skins/default/xui/zh/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/zh/floater_voice_controls.xml @@ -4,13 +4,13 @@ NEARBY VOICE </string> <string name="title_group"> - Group Call with [GROUP] + 與 [GROUP] 進行群組通話 </string> <string name="title_adhoc"> - Conference Call + 會議通話 </string> <string name="title_peer_2_peer"> - Call with [NAME] + 與 [NAME] 進行通話 </string> <string name="no_one_near"> No one near has voice enabled @@ -22,7 +22,7 @@ <layout_panel name="leave_call_panel"> <layout_stack name="voice_effect_and_leave_call_stack"> <layout_panel name="leave_call_btn_panel"> - <button label="Leave Call" name="leave_call_btn"/> + <button label="結束通話" name="leave_call_btn"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/zh/floater_water.xml b/indra/newview/skins/default/xui/zh/floater_water.xml new file mode 100644 index 0000000000..5fb57272af --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_water.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Water Floater" title="進階水文編輯器"> + <floater.string name="WLDefaultWaterNames"> + Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez + </floater.string> + <text name="KeyFramePresetsText"> + Water Presets: + </text> + <button label="新增" label_selected="新增" name="WaterNewPreset"/> + <button label="儲存" label_selected="儲存" name="WaterSavePreset"/> + <button label="刪除" label_selected="刪除" name="WaterDeletePreset"/> + <tab_container name="Water Tabs"> + <panel label="設定" name="Settings"> + <text name="BHText"> + Water Fog Color + </text> + <color_swatch name="WaterFogColor" tool_tip="點擊以開啟顏色挑選器"/> + <text name="WaterFogDensText"> + Fog Density Exponent + </text> + <text name="WaterUnderWaterFogModText"> + Underwater Fog Modifier + </text> + <text name="BDensText"> + Reflection Wavelet Scale + </text> + <slider label="1" name="WaterNormalScaleX"/> + <slider label="2" name="WaterNormalScaleY"/> + <slider label="3" name="WaterNormalScaleZ"/> + <text name="HDText"> + Fresnel Scale + </text> + <text name="FresnelOffsetText"> + Fresnel Offset + </text> + <text name="DensMultText"> + Refract Scale Above + </text> + <text name="WaterScaleBelowText"> + Refract Scale Below + </text> + <text name="MaxAltText"> + Blur Multiplier + </text> + </panel> + <panel label="圖像" name="Waves"> + <text name="BHText"> + Big Wave Direction + </text> + <text name="WaterWave1DirXText"> + X + </text> + <text name="WaterWave1DirYText"> + Y + </text> + <text name="BHText2"> + Little Wave Direction + </text> + <text name="WaterWave2DirXText"> + X + </text> + <text name="WaterWave2DirYText"> + Y + </text> + <text name="BHText3"> + 正常地圖 + </text> + </panel> + </tab_container> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_web_content.xml b/indra/newview/skins/default/xui/zh/floater_web_content.xml index a756498b81..be6bf8bb27 100644 --- a/indra/newview/skins/default/xui/zh/floater_web_content.xml +++ b/indra/newview/skins/default/xui/zh/floater_web_content.xml @@ -2,13 +2,13 @@ <floater name="floater_web_content" title=""> <layout_stack name="stack1"> <layout_panel name="nav_controls"> - <button name="back" tool_tip="Navigate back"/> - <button name="forward" tool_tip="Navigate forward"/> + <button name="back" tool_tip="向後導覽"/> + <button name="forward" tool_tip="向前導覽"/> <button name="stop" tool_tip="停止導覽"/> <button name="reload" tool_tip="重載頁面"/> <combo_box name="address" tool_tip="在此輸入 URL 位置"/> - <icon name="media_secure_lock_flag" tool_tip="Secured Browsing"/> - <button name="popexternal" tool_tip="Open current URL in your desktop browser"/> + <icon name="media_secure_lock_flag" tool_tip="加密的瀏覽"/> + <button name="popexternal" tool_tip="在你的桌面瀏覽器中開啟目前的 URL 位址"/> </layout_panel> </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/zh/floater_whitelist_entry.xml index 36e00049f0..967e36ead7 100644 --- a/indra/newview/skins/default/xui/zh/floater_whitelist_entry.xml +++ b/indra/newview/skins/default/xui/zh/floater_whitelist_entry.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="whitelist_entry" title="WHITELIST ENTRY"> +<floater name="whitelist_entry" title="許可的項目清單"> <text name="media_label"> - Enter a URL or URL pattern to add to the list of allowed domains + 輸入一個 URL 位址或 URL 格式以添加到允許的網域清單中 </text> - <line_editor name="whitelist_entry" tool_tip="Enter a URL or URL pattern to White List"/> + <line_editor name="whitelist_entry" tool_tip="輸入一個 URL 位址或 URL 格式到白名單"/> <button label="確定" name="ok_btn"/> <button label="取消" name="cancel_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_windlight_options.xml b/indra/newview/skins/default/xui/zh/floater_windlight_options.xml new file mode 100644 index 0000000000..383e35d50d --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_windlight_options.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="WindLight floater" title="進階天空編輯器"> + <floater.string name="WLDefaultSkyNames"> + A-12AM:A-12PM:A-3AM:A-3PM:A-4.30PM:A-6AM:A-6PM:A-9AM:A-9PM:Barcelona:Blizzard:Blue Midday:Coastal Afternoon:Coastal Sunset:Default:Desert Sunset:Fine Day:Fluffy Big Clouds:Foggy:Funky Funky:Funky Funky Funky:Gelatto:Ghost:Incongruent Truths:Midday 1:Midday 2:Midday 3:Midday 4:Night:Pirate:Purple:Sailor's Delight:Sheer Sensuality + </floater.string> + <text name="KeyFramePresetsText"> + 天空預設值: + </text> + <button label="新增" label_selected="新增" name="WLNewPreset"/> + <button label="儲存" label_selected="儲存" name="WLSavePreset"/> + <button label="刪除" label_selected="刪除" name="WLDeletePreset"/> + <button label="日循環編輯器" label_selected="日循環編輯器" name="WLDayCycleMenuButton"/> + <tab_container name="WindLight Tabs"> + <panel label="大氣" name="Atmosphere"> + <text name="BHText"> + 藍天水平線 + </text> + <text name="BHText2"> + R + </text> + <text name="BHText3"> + G + </text> + <text name="BHText4"> + B + </text> + <text name="BHText5"> + I + </text> + <text name="BDensText"> + 陰霾水平線 + </text> + <text name="BDensText2"> + 藍天密度 + </text> + <text name="BHText6"> + R + </text> + <text name="BHText7"> + G + </text> + <text name="BHText8"> + B + </text> + <text name="BHText9"> + I + </text> + <text name="HDText"> + 陰霾密度 + </text> + <text name="DensMultText"> + 密度倍增 + </text> + <text name="WLDistanceMultText"> + 距離倍增 + </text> + <text name="MaxAltText"> + 最大高度 + </text> + </panel> + <panel label="照明" name="Lighting"> + <text name="SLCText"> + 日/月 顏色 + </text> + <text name="BHText"> + R + </text> + <text name="BHText2"> + G + </text> + <text name="BHText3"> + B + </text> + <text name="BHText4"> + I + </text> + <text name="TODText"> + 日/月 位置 + </text> + <text name="WLAmbientText"> + 環境 + </text> + <text name="BHText5"> + R + </text> + <text name="BHText6"> + G + </text> + <text name="BHText7"> + B + </text> + <text name="BHText8"> + I + </text> + <text name="WLEastAngleText"> + 東升角度 + </text> + <text name="SunGlowText"> + 太陽光輝 + </text> + <slider label="焦點" name="WLGlowB"/> + <slider label="尺寸" name="WLGlowR"/> + <text name="SceneGammaText"> + 場景 Gamma 值 + </text> + <text name="WLStarText"> + 星空量度 + </text> + </panel> + <panel label="雲彩" name="Clouds"> + <text name="WLCloudColorText"> + 雲彩顏色 + </text> + <text name="BHText"> + R + </text> + <text name="BHText2"> + G + </text> + <text name="BHText3"> + B + </text> + <text name="BHText4"> + I + </text> + <text name="WLCloudColorText2"> + 雲彩 XY 軸 / 密度 + </text> + <text name="BHText5"> + X + </text> + <text name="BHText6"> + Y + </text> + <text name="BHText7"> + D + </text> + <text name="WLCloudCoverageText"> + 雲彩覆蓋 + </text> + <text name="WLCloudScaleText"> + 雲彩規模 + </text> + <text name="WLCloudDetailText"> + 雲彩細節(XY 軸 / 密度) + </text> + <text name="BHText8"> + X + </text> + <text name="BHText9"> + Y + </text> + <text name="BHText10"> + D + </text> + <text name="WLCloudScrollXText"> + 雲彩 X 滾軸 + </text> + <check_box label="鎖定" name="WLCloudLockX"/> + <text name="WLCloudScrollYText"> + 雲彩 Y 滾軸 + </text> + <check_box label="鎖定" name="WLCloudLockY"/> + <check_box label="描繪傳統雲彩" name="DrawClassicClouds"/> + </panel> + </tab_container> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_world_map.xml b/indra/newview/skins/default/xui/zh/floater_world_map.xml index 552bb02582..6ac6fb76b7 100644 --- a/indra/newview/skins/default/xui/zh/floater_world_map.xml +++ b/indra/newview/skins/default/xui/zh/floater_world_map.xml @@ -2,45 +2,45 @@ <floater name="worldmap" title="世界地圖"> <panel name="layout_panel_1"> <text name="events_label"> - Legend + 圖例 </text> </panel> <panel name="layout_panel_2"> - <button name="Show My Location" tool_tip="Center map on my avatar's location"/> + <button name="Show My Location" tool_tip="以我的化身所在位置居中地圖"/> <text name="me_label"> - Me + 自己 </text> <text name="person_label"> 人 </text> <text name="infohub_label"> - Infohub + 資訊中心 </text> <text name="land_sale_label"> - Land Sale + 土地出售 </text> <text name="auction_label"> - land auction + 土地拍賣 </text> <text name="by_owner_label"> - by owner + 依擁有者 </text> <button name="Go Home" tool_tip="瞬間傳送到我的家位置"/> <text name="Home_label"> 家 </text> <text name="events_label"> - Events: + 事件: </text> <text name="pg_label"> - 一般 + 一般普級 </text> <check_box initial_value="true" name="events_mature_chk"/> <text name="events_mature_label"> - Moderate + 適度成人 </text> <text name="events_adult_label"> - 成人 + 完全成人 </text> </panel> <panel name="layout_panel_3"> @@ -55,8 +55,8 @@ <combo_box label="我的地標" name="landmark combo" tool_tip="將地標位置顯示在地圖上"> <combo_box.item label="我的地標" name="item1"/> </combo_box> - <search_editor label="Regions by Name" name="location" tool_tip="輸入一個地區的名稱"/> - <button label="Find" name="DoSearch" tool_tip="Search for region"/> + <search_editor label="地區依名稱" name="location" tool_tip="輸入一個地區的名稱"/> + <button label="尋找" name="DoSearch" tool_tip="搜尋地區"/> <button name="Clear" tool_tip="Clear tracking lines and reset map"/> <text name="events_label"> 位置: diff --git a/indra/newview/skins/default/xui/zh/inspect_group.xml b/indra/newview/skins/default/xui/zh/inspect_group.xml index 3583976646..ac331be203 100644 --- a/indra/newview/skins/default/xui/zh/inspect_group.xml +++ b/indra/newview/skins/default/xui/zh/inspect_group.xml @@ -5,16 +5,16 @@ --> <floater name="inspect_group"> <string name="PrivateGroup"> - 私人社團 + 私人群組 </string> <string name="FreeToJoin"> 免費加入 </string> <string name="CostToJoin"> - L$[AMOUNT] to join + 花費 L$[AMOUNT] 加入 </string> <string name="YouAreMember"> - You are a member + 你是成員 </string> <text name="group_subtitle"> 123 members diff --git a/indra/newview/skins/default/xui/zh/inspect_remote_object.xml b/indra/newview/skins/default/xui/zh/inspect_remote_object.xml index 26f49ce69a..bed19d6d78 100644 --- a/indra/newview/skins/default/xui/zh/inspect_remote_object.xml +++ b/indra/newview/skins/default/xui/zh/inspect_remote_object.xml @@ -17,6 +17,6 @@ http://slurl.com/Ahern/50/50/50 </text> <button label="地圖" name="map_btn"/> - <button label="Block" name="block_btn"/> + <button label="封鎖" name="block_btn"/> <button label="關閉" name="close_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/zh/menu_attachment_other.xml b/indra/newview/skins/default/xui/zh/menu_attachment_other.xml index a04d59bc81..885c4b9add 100644 --- a/indra/newview/skins/default/xui/zh/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/zh/menu_attachment_other.xml @@ -5,13 +5,13 @@ <menu_item_call label="加為朋友" name="Add Friend"/> <menu_item_call label="IM" name="Send IM..."/> <menu_item_call label="通話" name="Call"/> - <menu_item_call label="邀請加入社團" name="Invite..."/> + <menu_item_call label="邀請加入群組" name="Invite..."/> <menu_item_call label="封鎖" name="Avatar Mute"/> <menu_item_call label="回報" name="abuse"/> <menu_item_call label="凍結" name="Freeze..."/> <menu_item_call label="踢出" name="Eject..."/> <menu_item_call label="材質除錯" name="Debug..."/> - <menu_item_call label="Zoom In" name="Zoom In"/> + <menu_item_call label="放大" name="Zoom In"/> <menu_item_call label="支付" name="Pay..."/> <menu_item_call label="物件檔案" name="Object Inspect"/> </context_menu> 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 e3a791cde5..1911a1aeff 100644 --- a/indra/newview/skins/default/xui/zh/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/zh/menu_attachment_self.xml @@ -9,7 +9,7 @@ <menu_item_call label="編輯我的裝扮" name="Edit Outfit"/> <menu_item_call label="編輯我的體形" name="Edit My Shape"/> <menu_item_call label="我的朋友" name="Friends..."/> - <menu_item_call label="我的社團" name="Groups..."/> + <menu_item_call label="我的群組" name="Groups..."/> <menu_item_call label="我的檔案" name="Profile..."/> <menu_item_call label="材質除錯" name="Debug..."/> <menu_item_call label="丟棄" name="Drop"/> diff --git a/indra/newview/skins/default/xui/zh/menu_avatar_other.xml b/indra/newview/skins/default/xui/zh/menu_avatar_other.xml index acf98dfdfa..260571eb54 100644 --- a/indra/newview/skins/default/xui/zh/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/zh/menu_avatar_other.xml @@ -5,7 +5,7 @@ <menu_item_call label="加為朋友" name="Add Friend"/> <menu_item_call label="IM" name="Send IM..."/> <menu_item_call label="通話" name="Call"/> - <menu_item_call label="邀請加入社團" name="Invite..."/> + <menu_item_call label="邀請加入群組" name="Invite..."/> <menu_item_call label="Block" name="Avatar Mute"/> <menu_item_call label="回報" name="abuse"/> <menu_item_call label="凍結" name="Freeze..."/> 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 646edcf563..d516e3ab58 100644 --- a/indra/newview/skins/default/xui/zh/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/zh/menu_avatar_self.xml @@ -15,7 +15,7 @@ <menu_item_call label="內褲" name="Self Underpants"/> <menu_item_call label="刺青" name="Self Tattoo"/> <menu_item_call label="Physics" name="Self Physics"/> - <menu_item_call label="Alpha" name="Self Alpha"/> + <menu_item_call label="半透明" name="Self Alpha"/> <menu_item_call label="全部衣服" name="All Clothes"/> </context_menu> <context_menu label="HUD" name="Object Detach HUD"/> @@ -26,7 +26,7 @@ <menu_item_call label="編輯我裝扮" name="Edit Outfit"/> <menu_item_call label="編輯我的體形" name="Edit My Shape"/> <menu_item_call label="我的朋友" name="Friends..."/> - <menu_item_call label="我的社團" name="Groups..."/> + <menu_item_call label="我的群組" name="Groups..."/> <menu_item_call label="我的檔案" name="Profile..."/> <menu_item_call label="材質除錯" name="Debug..."/> </context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml b/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml index e053eb2388..a331c47a6e 100644 --- a/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml +++ b/indra/newview/skins/default/xui/zh/menu_gesture_gear.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_gesture_gear"> - <menu_item_call label="Add/Remove from Favorites" name="activate"/> + <menu_item_call label="由我的最愛中 添加/移除" name="activate"/> <menu_item_call label="覆製" name="copy_gesture"/> <menu_item_call label="貼上" name="paste"/> <menu_item_call label="覆製 UUID" name="copy_uuid"/> diff --git a/indra/newview/skins/default/xui/zh/menu_group_plus.xml b/indra/newview/skins/default/xui/zh/menu_group_plus.xml index 77c2c92491..d4a5a69104 100644 --- a/indra/newview/skins/default/xui/zh/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/zh/menu_group_plus.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="menu_group_plus"> - <menu_item_call label="Join Group..." name="item_join"/> - <menu_item_call label="New Group..." name="item_new"/> + <menu_item_call label="加入群組..." name="item_join"/> + <menu_item_call label="新群組..." name="item_new"/> </menu> diff --git a/indra/newview/skins/default/xui/zh/menu_imchiclet_group.xml b/indra/newview/skins/default/xui/zh/menu_imchiclet_group.xml index 2577c582a7..4664fcb027 100644 --- a/indra/newview/skins/default/xui/zh/menu_imchiclet_group.xml +++ b/indra/newview/skins/default/xui/zh/menu_imchiclet_group.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="IMChiclet Group Menu"> - <menu_item_call label="社團資訊" name="Show Profile"/> + <menu_item_call label="群組資訊" name="Show Profile"/> <menu_item_call label="顯示會話" name="Chat"/> <menu_item_call label="結束會話" name="End Session"/> </menu> diff --git a/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml index 0f14057c07..7385764e4c 100644 --- a/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/zh/menu_inspect_avatar_gear.xml @@ -5,7 +5,7 @@ <menu_item_call label="IM" name="im"/> <menu_item_call label="通話" name="call"/> <menu_item_call label="瞬間傳送" name="teleport"/> - <menu_item_call label="Invite to Group" name="invite_to_group"/> + <menu_item_call label="邀請加入群組" name="invite_to_group"/> <menu_item_call label="Block" name="block"/> <menu_item_call label="Unblock" name="unblock"/> <menu_item_call label="回報" name="report"/> @@ -14,7 +14,7 @@ <menu_item_call label="踢出" name="kick"/> <menu_item_call label="CSR" name="csr"/> <menu_item_call label="材質除錯" name="debug"/> - <menu_item_call label="Find On Map" name="find_on_map"/> + <menu_item_call label="在地圖上尋找" name="find_on_map"/> <menu_item_call label="Zoom In" name="zoom_in"/> <menu_item_call label="支付" name="pay"/> <menu_item_call label="分享" name="share"/> diff --git a/indra/newview/skins/default/xui/zh/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/zh/menu_inspect_self_gear.xml index 2d7da70bfc..1c75705743 100644 --- a/indra/newview/skins/default/xui/zh/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/zh/menu_inspect_self_gear.xml @@ -14,7 +14,7 @@ <menu_item_call label="內衣" name="Self Undershirt"/> <menu_item_call label="內褲" name="Self Underpants"/> <menu_item_call label="刺青" name="Self Tattoo"/> - <menu_item_call label="Alpha" name="Self Alpha"/> + <menu_item_call label="半透明" name="Self Alpha"/> <menu_item_call label="全部衣服" name="All Clothes"/> </context_menu> <context_menu label="HUD" name="Object Detach HUD"/> @@ -25,7 +25,7 @@ <menu_item_call label="編輯我的裝扮" name="Edit Outfit"/> <menu_item_call label="編輯我的體形" name="Edit My Shape"/> <menu_item_call label="我的朋友" name="Friends..."/> - <menu_item_call label="我的社團" name="Groups..."/> + <menu_item_call label="我的群組" name="Groups..."/> <menu_item_call label="我的檔案" name="Profile..."/> <menu_item_call label="材質除錯" name="Debug..."/> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_inventory.xml b/indra/newview/skins/default/xui/zh/menu_inventory.xml index a93e8be149..49a50c97c6 100644 --- a/indra/newview/skins/default/xui/zh/menu_inventory.xml +++ b/indra/newview/skins/default/xui/zh/menu_inventory.xml @@ -23,9 +23,9 @@ <menu_item_call label="新手套" name="New Gloves"/> <menu_item_call label="新內衣" name="New Undershirt"/> <menu_item_call label="新內褲" name="New Underpants"/> - <menu_item_call label="New Alpha Mask" name="New Alpha Mask"/> + <menu_item_call label="新半透明遮罩" name="New Alpha Mask"/> <menu_item_call label="新刺青" name="New Tattoo"/> - <menu_item_call label="New Physics" name="New Physics"/> + <menu_item_call label="新身體物理" name="New Physics"/> </menu> <menu label="新身體部位" name="New Body Parts"> <menu_item_call label="新體形" name="New Shape"/> @@ -51,7 +51,7 @@ <menu_item_call label="取代目前的裝扮" name="Replace Outfit"/> <menu_item_call label="添加到目前裝扮" name="Add To Outfit"/> <menu_item_call label="由目前的裝扮移除" name="Remove From Outfit"/> - <menu_item_call label="Find Original" name="Find Original"/> + <menu_item_call label="尋找原件" name="Find Original"/> <menu_item_call label="Purge Item" name="Purge Item"/> <menu_item_call label="Restore Item" name="Restore Item"/> <menu_item_call label="開啟" name="Open"/> @@ -71,7 +71,7 @@ <menu_item_call label="Play Inworld" name="Animation Play"/> <menu_item_call label="Play Locally" name="Animation Audition"/> <menu_item_call label="送出即時訊息" name="Send Instant Message"/> - <menu_item_call label="Offer Teleport..." name="Offer Teleport..."/> + <menu_item_call label="發給瞬間傳送請求..." name="Offer Teleport..."/> <menu_item_call label="Start Conference Chat" name="Conference Chat"/> <menu_item_call label="Activate" name="Activate"/> <menu_item_call label="Deactivate" name="Deactivate"/> @@ -81,7 +81,7 @@ <menu label="Attach To" name="Attach To"/> <menu label="Attach To HUD" name="Attach To HUD"/> <menu_item_call label="編輯" name="Wearable Edit"/> - <menu_item_call label="Add" name="Wearable Add"/> + <menu_item_call label="添加" name="Wearable Add"/> <menu_item_call label="脫下" name="Take Off"/> <menu_item_call label="-- 無選項 --" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/zh/menu_inventory_add.xml b/indra/newview/skins/default/xui/zh/menu_inventory_add.xml index 9199608200..a0fc060e27 100644 --- a/indra/newview/skins/default/xui/zh/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/zh/menu_inventory_add.xml @@ -21,9 +21,9 @@ <menu_item_call label="新手套" name="New Gloves"/> <menu_item_call label="新內衣" name="New Undershirt"/> <menu_item_call label="新內褲" name="New Underpants"/> - <menu_item_call label="New Alpha" name="New Alpha"/> + <menu_item_call label="新半透明" name="New Alpha"/> <menu_item_call label="新刺青" name="New Tattoo"/> - <menu_item_call label="New Physics" name="New Physics"/> + <menu_item_call label="新身體物理" name="New Physics"/> </menu> <menu label="新身體部位" name="New Body Parts"> <menu_item_call label="新體形" name="New Shape"/> diff --git a/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml index f51b27d9ce..74b90ada5e 100644 --- a/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/zh/menu_inventory_gear_default.xml @@ -11,7 +11,7 @@ <menu_item_call label="清空 Lost and Found" name="empty_lostnfound"/> <menu_item_call label="儲存材質為" name="Save Texture As"/> <menu_item_call label="分享" name="Share"/> - <menu_item_call label="Find Original" name="Find Original"/> - <menu_item_call label="Find All Links" name="Find All Links"/> + <menu_item_call label="尋找原件" name="Find Original"/> + <menu_item_call label="尋找全部聯結" name="Find All Links"/> <menu_item_call label="清空垃圾筒" name="empty_trash"/> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml index cf47020bd9..90704fee65 100644 --- a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml @@ -13,8 +13,8 @@ <menu_item_call label="新手套" name="New Gloves"/> <menu_item_call label="新內衣" name="New Undershirt"/> <menu_item_call label="新內褲" name="New Underpants"/> - <menu_item_call label="New Alpha" name="New Alpha"/> - <menu_item_call label="New Physics" name="New Physics"/> + <menu_item_call label="新半透明" name="New Alpha"/> + <menu_item_call label="新身體物理" name="New Physics"/> <menu_item_call label="新刺青" name="New Tattoo"/> </menu> <menu label="新身體部位" name="New Body Parts"> diff --git a/indra/newview/skins/default/xui/zh/menu_participant_list.xml b/indra/newview/skins/default/xui/zh/menu_participant_list.xml index 3737e3d041..81ae6e4e85 100644 --- a/indra/newview/skins/default/xui/zh/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/zh/menu_participant_list.xml @@ -8,7 +8,7 @@ <menu_item_call label="通話" name="Call"/> <menu_item_call label="分享" name="Share"/> <menu_item_call label="支付" name="Pay"/> - <menu_item_check label="View People Icons" name="View Icons"/> + <menu_item_check label="察看人群圖示" name="View Icons"/> <menu_item_check label="Block Voice" name="Block/Unblock"/> <menu_item_check label="Block Text" name="MuteText"/> <context_menu label="Moderator Options" name="Moderator Options"> diff --git a/indra/newview/skins/default/xui/zh/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/zh/menu_people_friends_view_sort.xml index 2b0c461312..59854faeec 100644 --- a/indra/newview/skins/default/xui/zh/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/zh/menu_people_friends_view_sort.xml @@ -2,7 +2,7 @@ <toggleable_menu name="menu_group_plus"> <menu_item_check label="依名稱排序" name="sort_name"/> <menu_item_check label="依狀態排序" name="sort_status"/> - <menu_item_check label="View People Icons" name="view_icons"/> - <menu_item_check label="View Permissions Granted" name="view_permissions"/> - <menu_item_call label="Show Blocked Residents & Objects" name="show_blocked_list"/> + <menu_item_check label="察看人群圖示" name="view_icons"/> + <menu_item_check label="察看許可權限" name="view_permissions"/> + <menu_item_call label="顯示被封鎖的居民與物件" name="show_blocked_list"/> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml index cf36507d74..1be5c69b94 100644 --- a/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/zh/menu_people_groups_view_sort.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_group_plus"> - <menu_item_check label="顯示社團圖示" name="Display Group Icons"/> - <menu_item_call label="脫離所選擇的社團" name="Leave Selected Group"/> + <menu_item_check label="顯示群組圖示" name="Display Group Icons"/> + <menu_item_call label="脫離所選擇的群組" name="Leave Selected Group"/> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_people_nearby.xml b/indra/newview/skins/default/xui/zh/menu_people_nearby.xml index 49fa775424..9faa35001c 100644 --- a/indra/newview/skins/default/xui/zh/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/zh/menu_people_nearby.xml @@ -9,5 +9,5 @@ <menu_item_call label="分享" name="Share"/> <menu_item_call label="支付" name="Pay"/> <menu_item_check label="Block/Unblock" name="Block/Unblock"/> - <menu_item_call label="Offer Teleport" name="teleport"/> + <menu_item_call label="發給瞬間傳送請求" name="teleport"/> </context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml index c7aff48df4..1380e0b307 100644 --- a/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml +++ b/indra/newview/skins/default/xui/zh/menu_people_nearby_multiselect.xml @@ -6,5 +6,5 @@ <menu_item_call label="通話" name="Call"/> <menu_item_call label="分享" name="Share"/> <menu_item_call label="支付" name="Pay"/> - <menu_item_call label="Offer Teleport" name="teleport"/> + <menu_item_call label="發給瞬間傳送請求" name="teleport"/> </context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/zh/menu_people_nearby_view_sort.xml index 5cf54b117b..a7f5c74b82 100644 --- a/indra/newview/skins/default/xui/zh/menu_people_nearby_view_sort.xml +++ b/indra/newview/skins/default/xui/zh/menu_people_nearby_view_sort.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_group_plus"> - <menu_item_check label="Sort by Recent Speakers" name="sort_by_recent_speakers"/> + <menu_item_check label="依最近說話者排序" name="sort_by_recent_speakers"/> <menu_item_check label="依名稱排序" name="sort_name"/> <menu_item_check label="依距離排序" name="sort_distance"/> - <menu_item_check label="View People Icons" name="view_icons"/> - <menu_item_call label="Show Blocked Residents & Objects" name="show_blocked_list"/> + <menu_item_check label="察看人群圖示" name="view_icons"/> + <menu_item_call label="顯示笨封鎖的居民與物件" name="show_blocked_list"/> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_place_add_button.xml b/indra/newview/skins/default/xui/zh/menu_place_add_button.xml index d0b9438cfc..95f8917234 100644 --- a/indra/newview/skins/default/xui/zh/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/zh/menu_place_add_button.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <menu name="menu_folder_gear"> - <menu_item_call label="Add Folder" name="add_folder"/> + <menu_item_call label="添加資料夾" name="add_folder"/> <menu_item_call label="添加地標" name="add_landmark"/> </menu> diff --git a/indra/newview/skins/default/xui/zh/menu_url_group.xml b/indra/newview/skins/default/xui/zh/menu_url_group.xml index 2cbdd602cb..de97bb731f 100644 --- a/indra/newview/skins/default/xui/zh/menu_url_group.xml +++ b/indra/newview/skins/default/xui/zh/menu_url_group.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <context_menu name="Url Popup"> - <menu_item_call label="顯示社團資訊" name="show_group"/> - <menu_item_call label="覆製社團到剪貼簿" name="url_copy_label"/> + <menu_item_call label="顯示群組資訊" name="show_group"/> + <menu_item_call label="覆製群組到剪貼簿" name="url_copy_label"/> <menu_item_call label="覆製 SLurl 到剪貼簿" name="url_copy"/> </context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml index 6d70ac4c1f..a51e26c3f4 100644 --- a/indra/newview/skins/default/xui/zh/menu_viewer.xml +++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml @@ -26,7 +26,7 @@ </menu> <menu label="溝通" name="Communicate"> <menu_item_call label="我的朋友" name="My Friends"/> - <menu_item_call label="我的社團" name="My Groups"/> + <menu_item_call label="我的群組" name="My Groups"/> <menu_item_check label="附近的聊天" name="Nearby Chat"/> <menu_item_call label="附近的人群" name="Active Speakers"/> </menu> @@ -96,7 +96,7 @@ <menu label="腳本" name="Scripts"> <menu_item_call label="重新編譯腳本(Mono)" name="Mono"/> <menu_item_call label="重新編譯腳本(LSL)" name="LSL"/> - <menu_item_call label="Reset Scripts" name="Reset Scripts"/> + <menu_item_call label="重設腳本" name="Reset Scripts"/> <menu_item_call label="設定腳本為執行中" name="Set Scripts to Running"/> <menu_item_call label="設定腳本為非執行中" name="Set Scripts to Not Running"/> </menu> @@ -139,7 +139,6 @@ <menu_item_check label="Disable Camera Constraints" name="Disable Camera Distance"/> <menu_item_check label="高解析度快照" name="HighResSnapshot"/> <menu_item_check label="靜音拍攝快照到硬碟" name="QuietSnapshotsToDisk"/> - <menu_item_check label="壓縮快照存到硬碟" name="CompressSnapshotsToDisk"/> <menu label="效能工具" name="Performance Tools"> <menu_item_call label="Lag Meter" name="Lag Meter"/> <menu_item_check label="統計列" name="Statistics Bar"/> @@ -155,7 +154,7 @@ </menu> <menu label="Rendering Types" name="Rendering Types"> <menu_item_check label="Simple" name="Simple"/> - <menu_item_check label="Alpha" name="Alpha"/> + <menu_item_check label="半透明" name="Alpha"/> <menu_item_check label="Tree" name="Tree"/> <menu_item_check label="Avatars" name="Character"/> <menu_item_check label="SurfacePath" name="SurfacePath"/> @@ -179,21 +178,21 @@ <menu_item_check label="Flexible Objects" name="Flexible Objects"/> </menu> <menu_item_check label="Use Plugin Read Thread" name="Use Plugin Read Thread"/> - <menu_item_call label="Clear Group Cache" name="ClearGroupCache"/> - <menu_item_check label="Mouse Smoothing" name="Mouse Smoothing"/> + <menu_item_call label="清除群組快取資料" name="ClearGroupCache"/> + <menu_item_check label="滑鼠平滑移動" name="Mouse Smoothing"/> <menu label="快速鍵" name="Shortcuts"> <menu_item_call label="圖像(L$[COST])..." name="Upload Image"/> <menu_item_check label="搜尋" name="Search"/> <menu_item_call label="釋出按鍵" name="Release Keys"/> <menu_item_call label="設定使用者界面大小至預設值" name="Set UI Size to Default"/> - <menu_item_check label="Show Advanced Menu - legacy shortcut" name="Show Advanced Menu - legacy shortcut"/> + <menu_item_check label="顯示進階選單 - 舊版捷徑" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="關閉視窗" name="Close Window"/> <menu_item_call label="關閉全部視窗" name="Close All Windows"/> - <menu_item_call label="Snapshot to Disk" name="Snapshot to Disk"/> + <menu_item_call label="拍攝快照到硬碟" name="Snapshot to Disk"/> <menu_item_call label="第一人稱視角" name="Mouselook"/> <menu_item_check label="Joystick Flycam" name="Joystick Flycam"/> - <menu_item_call label="Reset View" name="Reset View"/> - <menu_item_call label="Look at Last Chatter" name="Look at Last Chatter"/> + <menu_item_call label="重設視角" name="Reset View"/> + <menu_item_call label="注視上一位聊天者" name="Look at Last Chatter"/> <menu label="選擇建造工具" name="Select Tool"> <menu_item_call label="聚焦工具" name="Focus"/> <menu_item_call label="移動工具" name="Move"/> @@ -218,10 +217,10 @@ <menu_item_check label="Fast Timers" name="Fast Timers"/> <menu_item_check label="記憶體" name="Memory"/> <menu_item_call label="Region Info to Debug Console" name="Region Info to Debug Console"/> - <menu_item_call label="Group Info to Debug Console" name="Group Info to Debug Console"/> + <menu_item_call label="群組資訊至除錯控制台" name="Group Info to Debug Console"/> <menu_item_call label="Capabilities Info to Debug Console" name="Capabilities Info to Debug Console"/> <menu_item_check label="Camera" name="Camera"/> - <menu_item_check label="Wind" name="Wind"/> + <menu_item_check label="風力" name="Wind"/> <menu_item_check label="FOV" name="FOV"/> <menu_item_check label="Badge" name="Badge"/> </menu> @@ -232,17 +231,17 @@ <menu_item_check label="Show Matrices" name="Show Matrices"/> <menu_item_check label="Show Color Under Cursor" name="Show Color Under Cursor"/> <menu_item_check label="顯示記憶體" name="Show Memory"/> - <menu_item_check label="Show Updates to Objects" name="Show Updates"/> - </menu> - <menu label="Force an Error" name="Force Errors"> - <menu_item_call label="Force Breakpoint" name="Force Breakpoint"/> - <menu_item_call label="Force LLError And Crash" name="Force LLError And Crash"/> - <menu_item_call label="Force Bad Memory Access" name="Force Bad Memory Access"/> - <menu_item_call label="Force Infinite Loop" name="Force Infinite Loop"/> - <menu_item_call label="Force Driver Crash" name="Force Driver Carsh"/> - <menu_item_call label="Force Software Exception" name="Force Software Exception"/> - <menu_item_call label="Force Disconnect Viewer" name="Force Disconnect Viewer"/> - <menu_item_call label="Simulate a Memory Leak" name="Memory Leaking Simulation"/> + <menu_item_check label="顯示更新到物件" name="Show Updates"/> + </menu> + <menu label="強制錯誤" name="Force Errors"> + <menu_item_call label="強制中斷點" name="Force Breakpoint"/> + <menu_item_call label="強制腳本錯誤並崩潰" name="Force LLError And Crash"/> + <menu_item_call label="強制不良的記憶體存取" name="Force Bad Memory Access"/> + <menu_item_call label="強制無限迴圈" name="Force Infinite Loop"/> + <menu_item_call label="強制驅動程式崩潰" name="Force Driver Carsh"/> + <menu_item_call label="強制軟體例外異常" name="Force Software Exception"/> + <menu_item_call label="強制瀏覽器斷線" name="Force Disconnect Viewer"/> + <menu_item_call label="模擬記憶體不足" name="Memory Leaking Simulation"/> </menu> <menu label="Render Tests" name="Render Tests"> <menu_item_check label="Camera Offset" name="Camera Offset"/> @@ -278,8 +277,8 @@ <menu_item_check label="Global Illumination (experimental)" name="Global Illumination"/> <menu_item_check label="Debug GL" name="Debug GL"/> <menu_item_check label="Debug Pipeline" name="Debug Pipeline"/> - <menu_item_check label="Automatic Alpha Masks (deferred)" name="Automatic Alpha Masks (deferred)"/> - <menu_item_check label="Automatic Alpha Masks (non-deferred)" name="Automatic Alpha Masks (non-deferred)"/> + <menu_item_check label="自動半透明遮罩(遞延)" name="Automatic Alpha Masks (deferred)"/> + <menu_item_check label="自動半透明遮罩(非遞延)" name="Automatic Alpha Masks (non-deferred)"/> <menu_item_check label="Animation Textures" name="Animation Textures"/> <menu_item_check label="Disable Textures" name="Disable Textures"/> <menu_item_check label="Full Res Textures" name="Rull Res Textures"/> @@ -310,7 +309,7 @@ <menu_item_check label="Sim Sun Override" name="Sim Sun Override"/> <menu_item_check label="Cheesy Beacon" name="Cheesy Beacon"/> <menu_item_check label="Fixed Weather" name="Fixed Weather"/> - <menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/> + <menu_item_call label="傾印地區物件快取" name="Dump Region Object Cache"/> </menu> <menu label="UI" name="UI"> <menu_item_call label="Media Browser Test" name="Web Browser Test"/> @@ -325,10 +324,10 @@ <menu_item_check label="Region Debug Console" name="Region Debug Console"/> <menu_item_check label="Debug SelectMgr" name="Debug SelectMgr"/> <menu_item_check label="Debug Clicks" name="Debug Clicks"/> - <menu_item_check label="Debug Views" name="Debug Views"/> + <menu_item_check label="視角除錯" name="Debug Views"/> <menu_item_check label="Debug Name Tooltips" name="Debug Name Tooltips"/> - <menu_item_check label="Debug Mouse Events" name="Debug Mouse Events"/> - <menu_item_check label="Debug Keys" name="Debug Keys"/> + <menu_item_check label="滑鼠事件除錯" name="Debug Mouse Events"/> + <menu_item_check label="按鍵除錯" name="Debug Keys"/> <menu_item_check label="Debug WindowProc" name="Debug WindowProc"/> </menu> <menu label="XUI" name="XUI"> @@ -336,7 +335,7 @@ <menu_item_call label="Show Font Test" name="Show Font Test"/> <menu_item_check label="Show XUI Names" name="Show XUI Names"/> <menu_item_call label="送出測試 IMs" name="Send Test IMs"/> - <menu_item_call label="Flush Names Caches" name="Flush Names Caches"/> + <menu_item_call label="沖洗名稱快取資料" name="Flush Names Caches"/> </menu> <menu label="化身" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> @@ -380,14 +379,14 @@ <menu label="Admin" name="Admin"> <menu label="Object"> <menu_item_call label="取得副本" name="Take Copy"/> - <menu_item_call label="Force Owner To Me" name="Force Owner To Me"/> + <menu_item_call label="強制擁有者為我" name="Force Owner To Me"/> <menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/> <menu_item_call label="刪除" name="Delete"/> <menu_item_call label="Lock" name="Lock"/> <menu_item_call label="Get Assets IDs" name="Get Assets IDs"/> </menu> <menu label="地段" name="Parcel"> - <menu_item_call label="Force Owner To Me" name="Owner To Me"/> + <menu_item_call label="強制擁有者為我" name="Owner To Me"/> <menu_item_call label="Set to Linden Content" name="Set to Linden Content"/> <menu_item_call label="Claim Public Land" name="Claim Public Land"/> </menu> @@ -410,9 +409,9 @@ <menu_item_call label="內衣" name="Menu Undershirt"/> <menu_item_call label="內褲" name="Menu Underpants"/> <menu_item_call label="裙子" name="Skirt"/> - <menu_item_call label="Alpha" name="Alpha"/> - <menu_item_call label="Tattoo" name="Tattoo"/> - <menu_item_call label="Physics" name="Physics"/> + <menu_item_call label="半透明" name="Alpha"/> + <menu_item_call label="刺青" name="Tattoo"/> + <menu_item_call label="身體物理" name="Physics"/> <menu_item_call label="全部衣服" name="All Clothes"/> </menu> <menu label="幫助" name="Help"> diff --git a/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml index c5c1f661fb..2eea314dd8 100644 --- a/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml @@ -2,7 +2,7 @@ <context_menu name="Outfit Wearable Context Menu"> <menu_item_call label="取代" name="wear_replace"/> <menu_item_call label="Wear" name="wear_wear"/> - <menu_item_call label="Add" name="wear_add"/> + <menu_item_call label="添加" name="wear_add"/> <menu_item_call label="Take Off / Detach" name="take_off_or_detach"/> <menu_item_call label="卸下" name="detach"/> <context_menu label="Attach to" name="wearable_attach_to"/> diff --git a/indra/newview/skins/default/xui/zh/mime_types.xml b/indra/newview/skins/default/xui/zh/mime_types.xml index 3498942f9b..89fe92fabc 100644 --- a/indra/newview/skins/default/xui/zh/mime_types.xml +++ b/indra/newview/skins/default/xui/zh/mime_types.xml @@ -5,7 +5,7 @@ 網頁內容 </label> <tooltip name="web_tooltip"> - This location has Web content + 這位置有網頁內容 </tooltip> <playtip name="web_playtip"> 顯示網頁內容 @@ -35,7 +35,7 @@ </widgetset> <widgetset name="audio"> <label name="audio_label"> - Audio + 音頻 </label> <tooltip name="audio_tooltip"> There is audio at this location @@ -61,12 +61,12 @@ </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> - Audio + 音頻 </label> </mimetype> <mimetype name="video/*"> <label name="video2_label"> - Video + 視頻 </label> </mimetype> <mimetype name="image/*"> @@ -76,7 +76,7 @@ </mimetype> <mimetype name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - 影片(QuickTime) + 視頻(QuickTime) </label> </mimetype> <mimetype name="application/javascript"> @@ -86,7 +86,7 @@ </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> - Ogg Audio/Video + Ogg 音頻/視頻 </label> </mimetype> <mimetype name="application/pdf"> @@ -106,7 +106,7 @@ </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) + 同步多媒體整合語言(SMIL) </label> </mimetype> <mimetype name="application/xhtml+xml"> @@ -121,22 +121,22 @@ </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> - Audio (MIDI) + 音頻(MIDI) </label> </mimetype> <mimetype name="audio/mpeg"> <label name="audio/mpeg_label"> - Audio (MP3) + 音頻(MP3) </label> </mimetype> <mimetype name="audio/x-aiff"> <label name="audio/x-aiff_label"> - Audio (AIFF) + 音頻(AIFF) </label> </mimetype> <mimetype name="audio/x-wav"> <label name="audio/x-wav_label"> - Audio (WAV) + 音頻(WAV) </label> </mimetype> <mimetype name="image/bmp"> @@ -186,32 +186,32 @@ </mimetype> <mimetype name="video/mpeg"> <label name="video/mpeg_label"> - 影片(MPEG) + 視頻(MPEG) </label> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> - 影片(MP4) + 視頻(MP4) </label> </mimetype> <mimetype name="video/quicktime"> <label name="video/quicktime_label"> - 影片(QuickTime) + 視頻(QuickTime) </label> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> - 影片(Windows Media ASF) + 視頻(Windows Media ASF) </label> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> - 影片(Windows Media WMV) + 視頻(Windows Media WMV) </label> </mimetype> <mimetype name="video/x-msvideo"> <label name="video/x-msvideo_label"> - 影片(AVI) + 視頻(AVI) </label> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/zh/mime_types_linux.xml b/indra/newview/skins/default/xui/zh/mime_types_linux.xml index 3498942f9b..08839abe6a 100644 --- a/indra/newview/skins/default/xui/zh/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/zh/mime_types_linux.xml @@ -35,7 +35,7 @@ </widgetset> <widgetset name="audio"> <label name="audio_label"> - Audio + 音頻 </label> <tooltip name="audio_tooltip"> There is audio at this location @@ -61,7 +61,7 @@ </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> - Audio + 音頻 </label> </mimetype> <mimetype name="video/*"> @@ -76,7 +76,7 @@ </mimetype> <mimetype name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - 影片(QuickTime) + 視頻(QuickTime) </label> </mimetype> <mimetype name="application/javascript"> @@ -86,7 +86,7 @@ </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> - Ogg Audio/Video + Ogg 音頻/視頻 </label> </mimetype> <mimetype name="application/pdf"> @@ -121,22 +121,22 @@ </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> - Audio (MIDI) + 音頻(MIDI) </label> </mimetype> <mimetype name="audio/mpeg"> <label name="audio/mpeg_label"> - Audio (MP3) + 音頻(MP3) </label> </mimetype> <mimetype name="audio/x-aiff"> <label name="audio/x-aiff_label"> - Audio (AIFF) + 音頻(AIFF) </label> </mimetype> <mimetype name="audio/x-wav"> <label name="audio/x-wav_label"> - Audio (WAV) + 音頻(WAV) </label> </mimetype> <mimetype name="image/bmp"> @@ -186,32 +186,32 @@ </mimetype> <mimetype name="video/mpeg"> <label name="video/mpeg_label"> - 影片(MPEG) + 視頻(MPEG) </label> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> - 影片(MP4) + 視頻(MP4) </label> </mimetype> <mimetype name="video/quicktime"> <label name="video/quicktime_label"> - 影片(QuickTime) + 視頻(QuickTime) </label> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> - 影片(Windows Media ASF) + 視頻(Windows Media ASF) </label> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> - 影片(Windows Media WMV) + 視頻(Windows Media WMV) </label> </mimetype> <mimetype name="video/x-msvideo"> <label name="video/x-msvideo_label"> - 影片(AVI) + 視頻(AVI) </label> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/zh/mime_types_mac.xml b/indra/newview/skins/default/xui/zh/mime_types_mac.xml index 3f38c528a6..7958f64219 100644 --- a/indra/newview/skins/default/xui/zh/mime_types_mac.xml +++ b/indra/newview/skins/default/xui/zh/mime_types_mac.xml @@ -27,21 +27,21 @@ 圖像 </label> <tooltip name="image_tooltip"> - There is an image at this location + 有一個影像在此位置 </tooltip> <playtip name="image_playtip"> - View this location's image + 察看在此位置的影像 </playtip> </widgetset> <widgetset name="audio"> <label name="audio_label"> - Audio + 音頻 </label> <tooltip name="audio_tooltip"> - There is audio at this location + 有一個音頻在此位置 </tooltip> <playtip name="audio_playtip"> - Play this location's audio + 播放在此位置的音頻 </playtip> </widgetset> <scheme name="rtsp"> @@ -61,12 +61,12 @@ </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> - Audio + 音頻 </label> </mimetype> <mimetype name="video/*"> <label name="video2_label"> - Video + 視頻 </label> </mimetype> <mimetype name="image/*"> @@ -76,7 +76,7 @@ </mimetype> <mimetype name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - 影片 (QuickTime) + 視頻 (QuickTime) </label> </mimetype> <mimetype name="application/javascript"> @@ -86,7 +86,7 @@ </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> - Ogg Audio/Video + OGG 音頻/視頻 </label> </mimetype> <mimetype name="application/pdf"> @@ -106,7 +106,7 @@ </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) + 同步多媒體整合語言(SMIL) </label> </mimetype> <mimetype name="application/xhtml+xml"> @@ -121,22 +121,22 @@ </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> - Audio (MIDI) + 音頻 (MIDI) </label> </mimetype> <mimetype name="audio/mpeg"> <label name="audio/mpeg_label"> - Audio (MP3) + 音頻(MP3) </label> </mimetype> <mimetype name="audio/x-aiff"> <label name="audio/x-aiff_label"> - Audio (AIFF) + 音頻(AIFF) </label> </mimetype> <mimetype name="audio/x-wav"> <label name="audio/x-wav_label"> - Audio (WAV) + 音頻(WAV) </label> </mimetype> <mimetype name="image/bmp"> @@ -186,32 +186,32 @@ </mimetype> <mimetype name="video/mpeg"> <label name="video/mpeg_label"> - 影片(MPEG) + 視頻(MPEG) </label> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> - 影片(MP4) + 視頻(MP4) </label> </mimetype> <mimetype name="video/quicktime"> <label name="video/quicktime_label"> - 影片(QuickTime) + 視頻(QuickTime) </label> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> - 影片(Windows Media ASF) + 視頻(Windows Media ASF) </label> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> - 影片(Windows Media WMV) + 視頻(Windows Media WMV) </label> </mimetype> <mimetype name="video/x-msvideo"> <label name="video/x-msvideo_label"> - 影片(AVI) + 視頻(AVI) </label> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index 65bb8ce517..1c89e9b522 100644 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <notifications> <global name="skipnexttime"> - Don't show me this again + 不再顯示此提醒 </global> <global name="alwayschoose"> - Always choose this option + 總是選取這個選項 </global> <global name="implicitclosebutton"> 關閉 @@ -44,7 +44,7 @@ <button name="Cancel_yesnocancelbuttons" text="$canceltext"/> </form> </template> - <notification label="Unknown Notification Message" name="MissingAlert"> + <notification label="未知的通知訊息" name="MissingAlert"> Your version of [APP_NAME] does not know how to display the notification it just received. Please verify that you have the latest Viewer installed. Error details: The notification called '[_NAME]' was not found in notifications.xml. @@ -72,9 +72,9 @@ Error details: The notification called '[_NAME]' was not found in noti <usetemplate name="okbutton" yestext="確定"/> </notification> <notification name="LoginFailedNoNetwork"> - Could not connect to the [SECOND_LIFE_GRID]. + 無法連接到[SECOND_LIFE_GRID]. '[DIAGNOSTIC]' -Make sure your Internet connection is working properly. +請確定你的網際網路是正常運作的。 <usetemplate name="okbutton" yestext="確定"/> </notification> <notification name="MessageTemplateNotFound"> @@ -82,7 +82,7 @@ Make sure your Internet connection is working properly. <usetemplate name="okbutton" yestext="確定"/> </notification> <notification name="WearableSave"> - Save changes to current clothing/body part? + 除存變更到目前的衣服/身體部位? <usetemplate canceltext="取消" name="yesnocancelbuttons" notext="不要儲存" yestext="儲存"/> </notification> <notification name="CompileQueueSaveText"> @@ -132,7 +132,7 @@ Do you want to grant modify rights for the selected Residents? <usetemplate name="okcancelbuttons" notext="否" yestext="是"/> </notification> <notification name="UnableToCreateGroup"> - Unable to create group. + 無法建立新群組。 [MESSAGE] <usetemplate name="okbutton" yestext="確定"/> </notification> @@ -142,7 +142,7 @@ Do you want to grant modify rights for the selected Residents? <usetemplate canceltext="取消" name="yesnocancelbuttons" notext="忽視變更" yestext="套用變更"/> </notification> <notification name="MustSpecifyGroupNoticeSubject"> - You must specify a subject to send a group notice. + 你必須指定一個主旨以送出群組通知。 <usetemplate name="okbutton" yestext="確定"/> </notification> <notification name="AddGroupOwnerWarning"> @@ -150,7 +150,7 @@ Do you want to grant modify rights for the selected Residents? Members cannot be removed from that role. The members must resign from the role themselves. Are you sure you want to continue? - <usetemplate ignoretext="Confirm before I add a new group Owner" name="okcancelignore" notext="否" yestext="是"/> + <usetemplate ignoretext="在我添加一個新的群組擁有者前確認" name="okcancelignore" notext="否" yestext="是"/> </notification> <notification name="AssignDangerousActionWarning"> You are about to add the Ability '[ACTION_NAME]' to the Role '[ROLE_NAME]'. @@ -173,17 +173,17 @@ Add this Ability to '[ROLE_NAME]'? <notification name="AttachmentDrop"> You are about to drop your attachment. Are you sure you want to continue? - <usetemplate ignoretext="Confirm before dropping attachments" name="okcancelignore" notext="否" yestext="是"/> + <usetemplate ignoretext="在丟下附件前確認" name="okcancelignore" notext="否" yestext="是"/> </notification> <notification name="JoinGroupCanAfford"> - Joining this group costs L$[COST]. -Do you wish to proceed? - <usetemplate name="okcancelbuttons" notext="取消" yestext="Join"/> + 加入此群組須花費 L$[COST]。 +你確定要繼續嗎? + <usetemplate name="okcancelbuttons" notext="取消" yestext="加入"/> </notification> <notification name="JoinGroupNoCost"> You are joining group [NAME]. Do you wish to proceed? - <usetemplate name="okcancelbuttons" notext="取消" yestext="Join"/> + <usetemplate name="okcancelbuttons" notext="取消" yestext="加入"/> </notification> <notification name="JoinGroupCannotAfford"> Joining this group costs L$[COST]. @@ -193,7 +193,7 @@ You do not have enough L$ to join this group. Creating this group will cost L$100. Groups need more than one member, or they are deleted forever. Please invite members within 48 hours. - <usetemplate canceltext="取消" name="okcancelbuttons" notext="取消" yestext="Create group for L$100"/> + <usetemplate canceltext="取消" name="okcancelbuttons" notext="取消" yestext="花費 L$100 建立群組"/> </notification> <notification name="LandBuyPass"> For L$[COST] you can enter this land ('[PARCEL_NAME]') for [TIME] hours. Buy a pass? @@ -341,7 +341,7 @@ There is no reimbursement for fees paid. <notification name="DeleteMedia"> You have selected to delete the media associated with this face. Are you sure you want to continue? - <usetemplate ignoretext="Confirm before I delete media from an object" name="okcancelignore" notext="否" yestext="是"/> + <usetemplate ignoretext="在我由一個部件中刪除媒體前確認" name="okcancelignore" notext="否" yestext="是"/> </notification> <notification name="ClassifiedSave"> Save changes to classified [NAME]? @@ -370,14 +370,14 @@ Are you sure you want to continue? Please select a proposal to view. </notification> <notification name="SelectHistoryItemToView"> - Please select a history item to view. + 請選擇一個歷史紀錄物品去察看。 </notification> <notification name="CacheWillClear"> - Cache will be cleared after you restart [APP_NAME]. + 當你重新啟動 [APP_NAME] 後快取資料將會被清除。 </notification> <notification name="CacheWillBeMoved"> - Cache will be moved after you restart [APP_NAME]. -Note: This will clear the cache. + 當你重新啟動 [APP_NAME] 後快取資料將被移動。 +注意:這將會清除快取資料。 </notification> <notification name="ChangeConnectionPort"> Port settings take effect after you restart [APP_NAME]. @@ -519,7 +519,7 @@ Do you really want to give these items? <usetemplate canceltext="取消" name="yesnocancelbuttons" notext="踢出並封鎖" yestext="踢出"/> </notification> <notification name="EjectAvatarNoBan"> - 將這一位化身由你的土地踢出? + 將這一個化身由你的土地踢出? <usetemplate name="okcancelbuttons" notext="取消" yestext="踢出"/> </notification> <notification name="EjectAvatarFullnameNoBan"> @@ -527,10 +527,10 @@ Do you really want to give these items? <usetemplate name="okcancelbuttons" notext="取消" yestext="踢出"/> </notification> <notification name="EjectAvatarFromGroup"> - 你已將 [AVATAR_NAME] 由社團 [GROUP_NAME] 中踢出 + 你已將 [AVATAR_NAME] 由群組 [GROUP_NAME] 中踢出 </notification> <notification name="AcquireErrorTooManyObjects"> - ACQUIRE ERROR: Too many objects selected. + 取得錯誤:太多物件被選取。 </notification> <notification name="AcquireErrorObjectSpan"> ACQUIRE ERROR: Objects span more than one region. @@ -605,7 +605,7 @@ Expected [VALIDS] [FILE] </notification> <notification name="SoundFileInvalidTooLong"> - Audio file is too long (10 second maximum): + 音頻檔太長(最大值 10 秒): [FILE] </notification> <notification name="ProblemWithFile"> @@ -738,8 +738,8 @@ If you continue to get this message, please check the [SUPPORT_SITE]. 收納區功能目前無法使用。 </notification> <notification name="CannotSetLandOwnerNothingSelected"> - Unable to set land owner: -No parcel selected. + 無法設定土地擁有者: +無地段被選取。 </notification> <notification name="CannotSetLandOwnerMultipleRegions"> Unable to force land ownership because selection spans multiple regions. Please select a smaller area and try again. @@ -762,8 +762,8 @@ No region selected. No parcel selected. </notification> <notification name="CannotReleaseLandNoRegion"> - Unable to abandon land: -Cannot find region. + 無法放棄土地: +無法尋找地區。 </notification> <notification name="CannotBuyLandNothingSelected"> Unable to buy land: @@ -778,11 +778,11 @@ Cannot find the region this land is in. </notification> <notification name="CannotDeedLandNothingSelected"> Unable to deed land: -No parcel selected. +無地段被選取。 </notification> <notification name="CannotDeedLandNoGroup"> Unable to deed land: -No Group selected. +無群組被選取。 </notification> <notification name="CannotDeedLandNoRegion"> Unable to deed land: @@ -1377,11 +1377,11 @@ We must restart [APP_NAME] to install the update. <notification name="DeedObjectToGroup"> Deeding this object will cause the group to: * Receive L$ paid into the object - <usetemplate ignoretext="Confirm before I deed an object to a group" name="okcancelignore" notext="取消" yestext="Deed"/> + <usetemplate ignoretext="在我讓渡一個物件給群組前確認" name="okcancelignore" notext="取消" yestext="Deed"/> </notification> <notification name="WebLaunchExternalTarget"> - Do you want to open your Web browser to view this content? - <usetemplate ignoretext="Launch my browser to view a web page" name="okcancelignore" notext="取消" yestext="確定"/> + 你確定要開啟網頁瀏覽器去察看這個內容? + <usetemplate ignoretext="啟動我的網頁瀏覽器去察看網頁" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="WebLaunchJoinNow"> 前往你的[http://secondlife.com/account/ 塗鴉牆]以進行管理你的帳戶? @@ -1389,37 +1389,37 @@ We must restart [APP_NAME] to install the update. </notification> <notification name="WebLaunchSecurityIssues"> Visit the [SECOND_LIFE] Wiki for details of how to report a security issue. - <usetemplate ignoretext="Launch my browser to learn how to report a Security Issue" name="okcancelignore" notext="取消" yestext="確定"/> + <usetemplate ignoretext="開啟我的網頁瀏覽器以學習如何回報一個安全性的議題" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="WebLaunchQAWiki"> - Visit the [SECOND_LIFE] QA Wiki. - <usetemplate ignoretext="Launch my browser to view the QA Wiki" name="okcancelignore" notext="取消" yestext="確定"/> + 拜訪 [SECOND_LIFE] 問與答維基。 + <usetemplate ignoretext="開啟我的網頁瀏覽器去察看問與答維基" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="WebLaunchPublicIssue"> - Visit the [SECOND_LIFE] Public Issue Tracker, where you can report bugs and other issues. - <usetemplate ignoretext="Launch my browser to use the Public Issue Tracker" name="okcancelignore" notext="取消" yestext="前往頁面"/> + 拜訪 [SECOND_LIFE] 公共議題追蹤,那裡你將可以回報臭蟲與其他議題。 + <usetemplate ignoretext="開啟我的網頁瀏覽器以使用公共議題追蹤。" name="okcancelignore" notext="取消" yestext="前往頁面"/> </notification> <notification name="WebLaunchSupportWiki"> 前往林登官方部落格,以取得最新的新聞與資訊。 - <usetemplate ignoretext="Launch my browser to view the blog" name="okcancelignore" notext="取消" yestext="確定"/> + <usetemplate ignoretext="開啟我的網頁瀏覽器以察看部落格" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="WebLaunchLSLGuide"> - Do you want to open the Scripting Guide for help with scripting? - <usetemplate ignoretext="Launch my browser to view the Scripting Guide" name="okcancelignore" notext="取消" yestext="確定"/> + 你要開啟腳本撰寫指引以幫助你開發腳本嗎? + <usetemplate ignoretext="開啟我的網頁瀏覽器以察看腳本撰寫指引" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="WebLaunchLSLWiki"> - Do you want to visit the LSL Portal for help with scripting? - <usetemplate ignoretext="Launch my browser to view the LSL Portal" name="okcancelignore" notext="取消" yestext="前往頁面"/> + 你要拜訪 LSL 入口以取得腳本設計的幫助嗎? + <usetemplate ignoretext="開啟我的網頁瀏覽器以察看 LSL 入口" name="okcancelignore" notext="取消" yestext="前往頁面"/> </notification> <notification name="ReturnToOwner"> - Are you sure you want to return the selected objects to their owners? Transferable deeded objects will be returned to their previous owners. + 你確定要退回所選擇的物件給它們的擁有者嗎? 可轉移並讓渡的物件將會退回給它們的前一位擁有者。 -*WARNING* No-transfer deeded objects will be deleted! - <usetemplate ignoretext="Confirm before I return objects to their owners" name="okcancelignore" notext="取消" yestext="確定"/> +*警告* 非可轉移並讓渡的物件將會被刪除! + <usetemplate ignoretext="在我退回物件給它們的擁有者前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="GroupLeaveConfirmMember"> - You are currently a member of the group [GROUP]. -Leave Group? + 你目前是 [GROUP] 群組的成員。 +是否要離開群組? <usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/> </notification> <notification name="ConfirmKick"> @@ -1452,12 +1452,12 @@ Leave Group? <notification name="BusyModeSet"> Busy mode is set. Chat and instant messages will be hidden. Instant messages will get your Busy mode response. All teleportation offers will be declined. All inventory offers will go to your Trash. - <usetemplate ignoretext="I change my status to Busy mode" name="okignore" yestext="確定"/> + <usetemplate ignoretext="我變更我的狀態為忙碌模式" name="okignore" yestext="確定"/> </notification> <notification name="JoinedTooManyGroupsMember"> You have reached your maximum number of groups. Please leave another group before joining this one, or decline the offer. [NAME] has invited you to join a group as a member. - <usetemplate name="okcancelbuttons" notext="Decline" yestext="Join"/> + <usetemplate name="okcancelbuttons" notext="Decline" yestext="加入"/> </notification> <notification name="JoinedTooManyGroups"> You have reached your maximum number of groups. Please leave some group before joining or creating a new one. @@ -1757,7 +1757,7 @@ Publish this classified now for L$[AMOUNT]? <usetemplate canceltext="取消" name="yesnocancelbuttons" notext="否" yestext="是"/> </notification> <notification name="SetGroupMature"> - Does this group contain Moderate content? + 這個群組將包含適度成人內容? <usetemplate canceltext="取消" name="yesnocancelbuttons" notext="否" yestext="是"/> </notification> <notification label="Confirm restart" name="ConfirmRestart"> @@ -1894,7 +1894,7 @@ Move the inventory item(s)? </notification> <notification name="DeleteItems"> [QUESTION] - <usetemplate ignoretext="Confirm before deleting items" name="okcancelignore" notext="取消" yestext="確定"/> + <usetemplate ignoretext="刪除物品前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="HelpReportAbuseEmailLL"> 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]. @@ -1955,37 +1955,37 @@ Do you want to replace it with the selected object? Would you like to leave Busy Mode before completing this transaction? <form name="form"> - <ignore name="ignore" text="I am about to pay a person or object while I am in Busy mode"/> - <button ignore="Always leave Busy Mode" name="Yes" text="確定"/> - <button ignore="Never leave Busy Mode" name="No" text="取消"/> + <ignore name="ignore" text="當我在忙碌模式時,將要支付金錢或給他人物件"/> + <button ignore="總是離開忙碌模式" name="Yes" text="確定"/> + <button ignore="絕不離開忙碌模式" name="No" text="取消"/> </form> </notification> <notification name="ConfirmDeleteProtectedCategory"> - The folder '[FOLDERNAME]' is a system folder. Deleting system folders can cause instability. Are you sure you want to delete it? - <usetemplate ignoretext="Confirm before I delete a system folder" name="okcancelignore" notext="取消" yestext="確定"/> + 資料夾 '[FOLDERNAME]' 是系統資料夾。刪除系統資料夾將導致不穩定。你確定你要刪除它? + <usetemplate ignoretext="在我刪除系統資料夾前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="ConfirmEmptyTrash"> - Are you sure you want to permanently delete the contents of your Trash? - <usetemplate ignoretext="Confirm before I empty the inventory Trash folder" name="okcancelignore" notext="取消" yestext="確定"/> + 你確定你要對你垃圾筒中的內容進行刪除? + <usetemplate ignoretext="在我清空收納區垃圾筒資料夾前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="ConfirmClearBrowserCache"> - Are you sure you want to delete your travel, web, and search history? + 你確定要刪除你的旅行、網頁及搜尋歷史紀錄嗎? <usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/> </notification> <notification name="ConfirmClearCookies"> - Are you sure you want to clear your cookies? + 你確定要清除你的 cookies 嗎? <usetemplate name="okcancelbuttons" notext="取消" yestext="是"/> </notification> <notification name="ConfirmClearMediaUrlList"> - Are you sure you want to clear your list of saved URLs? + 你確定要清除你所儲存的 Url 清單嗎? <usetemplate name="okcancelbuttons" notext="取消" yestext="是"/> </notification> <notification name="ConfirmEmptyLostAndFound"> - Are you sure you want to permanently delete the contents of your Lost And Found? - <usetemplate ignoretext="Confirm before I empty the inventory Lost And Found folder" name="okcancelignore" notext="否" yestext="是"/> + 你確定你要進行刪除所有 Lost And Found 資料夾中的內容? + <usetemplate ignoretext="在我清空收納區中的 Lost And Found 資料夾前進行確認" name="okcancelignore" notext="否" yestext="是"/> </notification> <notification name="CopySLURL"> - The following SLurl has been copied to your clipboard: + 下列的 SLurl 位置已經覆製到你的剪貼簿上: [SLURL] Link to this from a web page to give others easy access to this location, or try it out yourself by pasting it into the address bar of any web browser. @@ -1994,11 +1994,11 @@ Link to this from a web page to give others easy access to this location, or try </form> </notification> <notification name="WLSavePresetAlert"> - Do you wish to overwrite the saved preset? - <usetemplate name="okcancelbuttons" notext="No" yestext="是"/> + 你要覆寫已儲存的預設配置嗎? + <usetemplate name="okcancelbuttons" notext="否" yestext="是"/> </notification> <notification name="WLDeletePresetAlert"> - Do you wish to delete [SKY]? + 你要刪除 [SKY]? <usetemplate name="okcancelbuttons" notext="否" yestext="是"/> </notification> <notification name="WLNoEditDefault"> @@ -2015,7 +2015,7 @@ Link to this from a web page to give others easy access to this location, or try Give me a name for the new sky. <form name="form"> <input name="message"> - New Preset + 新預設配配置 </input> <button name="OK" text="確定"/> <button name="Cancel" text="取消"/> @@ -2094,13 +2094,13 @@ Link to this from a web page to give others easy access to this location, or try [MESSAGE] </notification> <notification name="Cancelled"> - Cancelled + 已取消 </notification> <notification name="CancelledSit"> - Cancelled Sit + 取消坐下 </notification> <notification name="CancelledAttach"> - Cancelled Attach + 取消貼上 </notification> <notification name="ReplacedMissingWearable"> Replaced missing clothing/body part with default. @@ -2131,13 +2131,13 @@ Link to this from a web page to give others easy access to this location, or try In-world snapshot upload done </notification> <notification name="TerrainDownloaded"> - Terrain.raw downloaded + 地形 .raw 檔已下載 </notification> <notification name="GestureMissing"> - Hmm. Gesture [NAME] is missing from the database. + 嗯,姿勢 [NAME] 在資料庫中遺失。 </notification> <notification name="UnableToLoadGesture"> - Unable to load gesture [NAME]. + 無法載入姿勢 [NAME]。 </notification> <notification name="LandmarkMissing"> 資料庫中的地標遺失。 @@ -2146,30 +2146,30 @@ Link to this from a web page to give others easy access to this location, or try 無法載入地標,請再試一次。 </notification> <notification name="CapsKeyOn"> - Your Caps Lock key is on. -This might affect your password. + 你的大寫鍵已啟用。 +這將可能會影響到你輸入的密碼。 </notification> <notification name="NotecardMissing"> - Notecard is missing from database. + 記事卡在資料庫中遺失。 </notification> <notification name="NotecardNoPermissions"> - You don't have permission to view this notecard. + 你並沒有權限去察看這個記事卡。 </notification> <notification name="RezItemNoPermissions"> - Insufficient permissions to rez object. + 產生物件時發生權限衝突。 </notification> <notification name="UnableToLoadNotecard"> - Unable to load notecard. -Please try again. + 無法載入記事卡。 +請再試一次。 </notification> <notification name="ScriptMissing"> - Script is missing from database. + 腳本在資料庫中遺失。 </notification> <notification name="ScriptNoPermissions"> - Insufficient permissions to view script. + 察看腳本時發生權限衝突。 </notification> <notification name="UnableToLoadScript"> - Unable to load script. Please try again. + 無法載入腳本。請再試一次。 </notification> <notification name="IncompleteInventory"> The complete contents you are offering are not yet locally available. Please try offering those items again in a minute. @@ -2193,31 +2193,31 @@ Please try again. Please select a single object. </notification> <notification name="ObjectNotForSale"> - This object is not for sale. + 這物件不出售。 </notification> <notification name="EnteringGodMode"> - Entering god mode, level [LEVEL] + 進入神之模式中,等級 [LEVEL] </notification> <notification name="LeavingGodMode"> - Now leaving god mode, level [LEVEL] + 現在離開神之模式,等級 [LEVEL] </notification> <notification name="CopyFailed"> - You don't have permission to copy this. + 你並沒有權限去覆製這個。 </notification> <notification name="InventoryAccepted"> - [NAME] received your inventory offer. + [NAME] 接收到你提供的收納區物品。 </notification> <notification name="InventoryDeclined"> - [NAME] declined your inventory offer. + [NAME] 拒絕你提供的收納區物品。 </notification> <notification name="ObjectMessage"> [NAME]: [MESSAGE] </notification> <notification name="CallingCardAccepted"> - Your calling card was accepted. + 你的名片已被接受。 </notification> <notification name="CallingCardDeclined"> - Your calling card was declined. + 你的名片已被拒絕。 </notification> <notification name="TeleportToLandmark"> You can teleport to locations like '[NAME]' by opening the Places panel on the right side of your screen, and then select the Landmarks tab. @@ -2249,12 +2249,12 @@ Try selecting a smaller piece of land. [MESSAGE] </notification> <notification name="EventNotification"> - Event Notification: + 活動通知: [NAME] [DATE] <form name="form"> - <button name="Details" text="Details"/> + <button name="Details" text="細節"/> <button name="Cancel" text="取消"/> </form> </notification> @@ -2312,8 +2312,8 @@ Non-transferable objects that are deeded to the group have been deleted. You can be hurt here. If you die, you will be teleported to your home location. </notification> <notification name="NoFly"> - This area has flying disabled. -You can't fly here. + 這區域關閉並禁止飛行。 +你不能在此處飛行。 </notification> <notification name="PushRestricted"> This area does not allow pushing. You can't push others here unless you own the land. @@ -2353,13 +2353,13 @@ Please go to the Knowledge Base for details on accessing areas with this maturit You do not have proper payment status to enter this region. </notification> <notification name="MustGetAgeRgion"> - You must be age-verified to enter this region. + 你必須通過年齡認證以進入這地區。 </notification> <notification name="MustGetAgeParcel"> - You must be age-verified to enter this parcel. + 你必須通過年齡驗證以進入這地段。 </notification> <notification name="NoDestRegion"> - No destination region found. + 無目的地地區發現。 </notification> <notification name="NotAllowedInDest"> You are not allowed into the destination. @@ -2381,10 +2381,10 @@ Please go to the Knowledge Base for details on accessing areas with this maturit Please try again in a few moments. </notification> <notification name="GeneralFailure"> - General failure. + 一般故障。 </notification> <notification name="RoutedWrongRegion"> - Routed to wrong region. Please try again. + 路由導向到錯誤地區。請再試一次。 </notification> <notification name="NoValidAgentID"> No valid agent id. @@ -2418,7 +2418,7 @@ Please try again in a few moments. </notification> <notification name="ObjectGiveItem"> An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLURL] has given you this [OBJECTTYPE]: -[ITEM_SLURL] +<nolink>[ITEM_SLURL]</nolink> <form name="form"> <button name="Keep" text="Keep"/> <button name="Discard" text="Discard"/> @@ -2442,7 +2442,7 @@ Please try again in a few moments. <notification name="JoinGroup"> [MESSAGE] <form name="form"> - <button name="Join" text="Join"/> + <button name="Join" text="加入"/> <button name="Decline" text="Decline"/> <button name="Info" text="資訊"/> </form> @@ -2709,15 +2709,15 @@ They will be blocked for a few seconds for your security. <notification name="IMToast"> [MESSAGE] <form name="form"> - <button name="respondbutton" text="Respond"/> + <button name="respondbutton" text="回應"/> </form> </notification> <notification name="ConfirmCloseAll"> - Are you sure you want to close all IMs? - <usetemplate ignoretext="Confirm before I close all IMs" name="okcancelignore" notext="取消" yestext="確定"/> + 你確定要關閉全部 IMs 對話視窗? + <usetemplate ignoretext="在我關閉全部的 IMs 對話視窗前確認。" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="AttachmentSaved"> - Attachment has been saved. + 附件已儲存。 </notification> <notification name="UnableToFindHelpTopic"> Unable to find the help topic for this element. @@ -2831,7 +2831,7 @@ This will also cause all residents that later join the call to be muted, even after you have left the call. Mute everyone? - <usetemplate ignoretext="Confirm before I mute all participants in a group call" name="okcancelignore" notext="取消" yestext="確定"/> + <usetemplate ignoretext="在我對所有群組通話的參與者予以靜音前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification label="聊天" name="HintChat"> To join the conversation, type into the chat field below. @@ -2875,10 +2875,10 @@ Click and drag anywhere on the world to rotate your view Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars. </notification> <notification name="PopupAttempt"> - A pop-up was prevented from opening. + 一個突顯式視窗開啟時被阻擋。 <form name="form"> - <ignore name="ignore" text="Enable all pop-ups"/> - <button name="open" text="Open pop-up window"/> + <ignore name="ignore" text="啟用全部的突顯式視窗"/> + <button name="open" text="開啟突顯式視窗"/> </form> </notification> <notification name="AuthRequest"> @@ -2943,10 +2943,10 @@ If you continue to have problems, please visit the [SUPPORT_SITE]. - Your system memory does not meet the minimum requirements. </global> <global name="You can only set your 'Home Location' on your land or at a mainland Infohub."> - If you own a piece of land, you can make it your home location. -Otherwise, you can look at the Map and find places marked "Infohub". + 若你擁有一塊土地,你可以標記它成為你的家的位置。 +或者,你可以察看地圖尋找標記為 "資訊中心" 的地方。 </global> <global name="You died and have been teleported to your home location"> - You died and have been teleported to your home location. + 你已經死亡並且被瞬間傳送回你的家的位置。 </global> </notifications> diff --git a/indra/newview/skins/default/xui/zh/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/zh/panel_block_list_sidetray.xml index 9ef4258f0b..1dfa024138 100644 --- a/indra/newview/skins/default/xui/zh/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/zh/panel_block_list_sidetray.xml @@ -3,8 +3,8 @@ <text name="title_text"> 封鎖清單 </text> - <scroll_list name="blocked" tool_tip="List of currently blocked Residents"/> - <button label="Block person" name="Block resident..." tool_tip="Pick a Resident to block"/> - <button label="Block object by name" name="Block object by name..." tool_tip="Pick an object to block by name"/> - <button label="Unblock" name="Unblock" tool_tip="Remove Resident or object from blocked list"/> + <scroll_list name="blocked" tool_tip="目前封鎖的居民清單"/> + <button label="封鎖他人" name="Block resident..." tool_tip="挑選一位居民以進行封鎖"/> + <button label="依名稱封鎖物件" name="Block object by name..." tool_tip="依名稱挑選一個物件進行封鎖"/> + <button label="解除封鎖" name="Unblock" tool_tip="將居民或物件由封鎖清單中移除"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_classified_info.xml b/indra/newview/skins/default/xui/zh/panel_classified_info.xml index 94edb7ab71..cf3113ef1c 100644 --- a/indra/newview/skins/default/xui/zh/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/zh/panel_classified_info.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="panel_classified_info"> <panel.string name="type_mature"> - Moderate + 適度成人 </panel.string> <panel.string name="type_pg"> - General Content + 一般普級內容 </panel.string> <panel.string name="l$_price"> L$[PRICE] diff --git a/indra/newview/skins/default/xui/zh/panel_edit_alpha.xml b/indra/newview/skins/default/xui/zh/panel_edit_alpha.xml index 73c59d9ae3..6b17302bf1 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_alpha.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_alpha.xml @@ -2,11 +2,11 @@ <panel name="edit_alpha_panel"> <scroll_container name="avatar_alpha_color_panel_scroll"> <panel name="avatar_alpha_color_panel"> - <texture_picker label="Lower Alpha" name="Lower Alpha" tool_tip="點擊以挑選圖片"/> - <texture_picker label="Upper Alpha" name="Upper Alpha" tool_tip="點擊以挑選圖片"/> - <texture_picker label="Head Alpha" name="Head Alpha" tool_tip="點擊以挑選圖片"/> - <texture_picker label="Eye Alpha" name="Eye Alpha" tool_tip="點擊以挑選圖片"/> - <texture_picker label="Hair Alpha" name="Hair Alpha" tool_tip="點擊以挑選圖片"/> + <texture_picker label="下半身半透明" name="Lower Alpha" tool_tip="點擊以挑選圖片"/> + <texture_picker label="上半身半透明" name="Upper Alpha" tool_tip="點擊以挑選圖片"/> + <texture_picker label="頭部半透明" name="Head Alpha" tool_tip="點擊以挑選圖片"/> + <texture_picker label="眼睛半透明" name="Eye Alpha" tool_tip="點擊以挑選圖片"/> + <texture_picker label="頭髮半透明" name="Hair Alpha" tool_tip="點擊以挑選圖片"/> </panel> </scroll_container> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml index e749d9e3e7..f12701c981 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml @@ -32,9 +32,9 @@ <button label="Set to Current Location" name="set_to_curr_location_btn"/> <text name="category_label" value="Category:"/> <text name="content_type_label" value="Content type:"/> - <icons_combo_box label="General Content" name="content_type"> - <icons_combo_box.item label="Moderate Content" name="mature_ci" value="Mature"/> - <icons_combo_box.item label="General Content" name="pg_ci" value="PG"/> + <icons_combo_box label="一般普級內容" name="content_type"> + <icons_combo_box.item label="適度成人內容" name="mature_ci" value="Mature"/> + <icons_combo_box.item label="一般普級內容" name="pg_ci" value="PG"/> </icons_combo_box> <check_box label="Auto renew each week" name="auto_renew"/> <text name="price_for_listing_label" value="Price for listing:"/> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_physics.xml b/indra/newview/skins/default/xui/zh/panel_edit_physics.xml index 77ee4fd36d..26fedb59be 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_physics.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_physics.xml @@ -2,12 +2,12 @@ <panel name="edit_physics_panel"> <panel label="" name="accordion_panel"> <accordion name="physics_accordion"> - <accordion_tab name="physics_breasts_updown_tab" title="Breasts Bounce"/> - <accordion_tab name="physics_breasts_inout_tab" title="Breasts Cleavage"/> - <accordion_tab name="physics_breasts_leftright_tab" title="Breasts Sway"/> - <accordion_tab name="physics_belly_tab" title="Belly Bounce"/> - <accordion_tab name="physics_butt_tab" title="Butt Bounce"/> - <accordion_tab name="physics_butt_leftright_tab" title="Butt Sway"/> + <accordion_tab name="physics_breasts_updown_tab" title="乳房彈性"/> + <accordion_tab name="physics_breasts_inout_tab" title="乳溝深淺"/> + <accordion_tab name="physics_breasts_leftright_tab" title="乳房搖擺"/> + <accordion_tab name="physics_belly_tab" title="腹部彈性"/> + <accordion_tab name="physics_butt_tab" title="臀部彈性"/> + <accordion_tab name="physics_butt_leftright_tab" title="臀部搖擺"/> <accordion_tab name="physics_advanced_tab" title="進階參數"/> </accordion> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_pick.xml b/indra/newview/skins/default/xui/zh/panel_edit_pick.xml index a624877ab3..6ac7226185 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_pick.xml @@ -29,7 +29,7 @@ <layout_panel name="layout_panel1"> <button label="儲存精選地點" name="save_changes_btn"/> </layout_panel> - <layout_panel name="layout_panel2"> + <layout_panel name="layout_panel1"> <button label="取消" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_shoes.xml b/indra/newview/skins/default/xui/zh/panel_edit_shoes.xml index 7bf923b4ca..675caf9e2e 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_shoes.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_shoes.xml @@ -2,7 +2,7 @@ <panel name="edit_shoes_panel"> <panel name="avatar_shoes_color_panel"> <texture_picker label="材質" name="Fabric" tool_tip="點擊以挑選圖片"/> - <color_swatch label="Color/Tint" name="Color/Tint" tool_tip="Click to open color picker"/> + <color_swatch label="顏色/色調" name="Color/Tint" tool_tip="點擊以開啟顏色挑選器"/> </panel> <panel name="accordion_panel"> <accordion name="wearable_accordion"> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml index 936a2651ab..066b1fd389 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml @@ -40,13 +40,13 @@ Editing Underpants </string> <string name="edit_alpha_title"> - Editing Alpha Mask + 半透明遮罩編輯中 </string> <string name="edit_tattoo_title"> - Editing Tattoo + 刺青編輯中 </string> <string name="edit_physics_title"> - Editing Physics + 身體物理編輯中 </string> <string name="shape_desc_text"> 體形: @@ -88,13 +88,13 @@ 內褲: </string> <string name="alpha_desc_text"> - Alpha Mask: + 半透明遮罩: </string> <string name="tattoo_desc_text"> 刺青: </string> <string name="physics_desc_text"> - Physics: + 身體物理: </string> <labeled_back_button label="儲存" name="back_btn" tool_tip="回到編輯裝扮"/> <text name="edit_wearable_title" value="體形編輯中"/> diff --git a/indra/newview/skins/default/xui/zh/panel_group_control_panel.xml b/indra/newview/skins/default/xui/zh/panel_group_control_panel.xml index 1e3c18f522..3915e80d43 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_control_panel.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_control_panel.xml @@ -2,16 +2,16 @@ <panel name="panel_im_control_panel"> <layout_stack name="vertical_stack"> <layout_panel name="group_info_btn_panel"> - <button label="社團檔案" name="group_info_btn"/> + <button label="群組檔案" name="group_info_btn"/> </layout_panel> <layout_panel name="call_btn_panel"> - <button label="Call Group" name="call_btn"/> + <button label="群組通話" name="call_btn"/> </layout_panel> <layout_panel name="end_call_btn_panel"> - <button label="Leave Call" name="end_call_btn"/> + <button label="結束通話" name="end_call_btn"/> </layout_panel> <layout_panel name="voice_ctrls_btn_panel"> - <button label="Open Voice Controls" name="voice_ctrls_btn"/> + <button label="開啟語音控制" name="voice_ctrls_btn"/> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_group_general.xml b/indra/newview/skins/default/xui/zh/panel_group_general.xml index a97a35056b..f70fbf22a8 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_general.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_general.xml @@ -6,7 +6,7 @@ Hover your mouse over the options for more help. </panel.string> <panel.string name="group_info_unchanged"> - 一般社團資訊已經被變更 + 一般群組資訊已經被變更 </panel.string> <panel.string name="incomplete_member_data_str"> Retrieving member data @@ -22,7 +22,7 @@ Hover your mouse over the options for more help. <button label="現在就加入!!" name="btn_join"/> </panel> <text_editor name="charter"> - Group Charter + 群組規章 </text_editor> <name_list name="visible_members"> <name_list.columns label="成員" name="name"/> @@ -36,11 +36,11 @@ Hover your mouse over the options for more help. 我的頭銜: </text> <combo_box name="active_title" tool_tip="Sets the title that appears in your avatar's name tag when this group is active."/> - <check_box label="接受社團通知" name="receive_notices" tool_tip="Sets whether you want to receive Notices from this group. Uncheck this box if this group is spamming you."/> + <check_box label="接受群組通知" name="receive_notices" tool_tip="Sets whether you want to receive Notices from this group. Uncheck this box if this group is spamming you."/> <check_box label="顯示在我的檔案中" name="list_groups_in_profile" tool_tip="Sets whether you want to show this group in your profile"/> <panel name="preferences_container"> <text name="group_settngs_label"> - 社團 + 群組 </text> <check_box label="任何人都可以加入" name="open_enrollement" tool_tip="Sets whether this group allows new members to join without being invited."/> <check_box label="加入費用" name="check_enrollment_fee" tool_tip="Sets whether to require an enrollment fee to join the group"/> @@ -49,8 +49,8 @@ Hover your mouse over the options for more help. <combo_item name="select_mature"> - 選擇內容分級 - </combo_item> - <combo_box.item label="Moderate Content" name="mature"/> - <combo_box.item label="一般內容" name="pg"/> + <combo_box.item label="適度成人內容" name="mature"/> + <combo_box.item label="一般普級內容" name="pg"/> </combo_box> <check_box initial_value="true" label="顯示在搜尋中" name="show_in_group_list" tool_tip="Let people see this group in search results"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/zh/panel_group_info_sidetray.xml index 320645ea5e..db01edcdb3 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_info_sidetray.xml @@ -1,20 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="社團檔案" name="GroupInfo"> +<panel label="群組檔案" name="GroupInfo"> <panel.string name="default_needs_apply_text"> - There are unsaved changes + 變更未儲存 </panel.string> <panel.string name="want_apply_text"> - Do you want to save these changes? + 你要儲存這些變更嗎? </panel.string> <panel.string name="group_join_btn"> - Join (L$[AMOUNT]) + 加入(L$[AMOUNT]) </panel.string> <panel.string name="group_join_free"> - Free + 免費 </panel.string> <panel name="group_info_top"> <text_editor name="group_name" value="(載入中...)"/> - <line_editor label="Type your new group name here" name="group_name_editor"/> + <line_editor label="在此輸入你的新群組名稱" name="group_name_editor"/> </panel> <layout_stack name="layout"> <layout_panel name="group_accordions"> @@ -31,11 +31,11 @@ <button label="聊天" name="btn_chat"/> </layout_panel> <layout_panel name="call_btn_lp"> - <button label="Group Call" name="btn_call" tool_tip="Call this group"/> + <button label="群組通話" name="btn_call" tool_tip="與此群組進行通話"/> </layout_panel> <layout_panel name="btn_apply_lp"> <button label="儲存" label_selected="儲存" name="btn_apply"/> - <button label="創造社團" name="btn_create" tool_tip="創造一個新社團"/> + <button label="創造群組" name="btn_create" tool_tip="創造一個新群組"/> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_group_invite.xml b/indra/newview/skins/default/xui/zh/panel_group_invite.xml index a1395f454b..07dcb2303e 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_invite.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_invite.xml @@ -12,7 +12,7 @@ <text name="help_text"> You can select multiple Residents to invite to your group. Click 'Open Resident Chooser' to start. </text> - <button label="Open Resident Chooser" name="add_button"/> + <button label="開啟居民選擇視窗" name="add_button"/> <name_list name="invitee_list" tool_tip="Hold the Ctrl key and click Resident names to multi-select"/> <button label="Remove Selected from List" name="remove_button" tool_tip="Removes the Residents selected above from the invite list"/> <text name="role_text"> @@ -22,6 +22,6 @@ <button label="送出邀請" name="ok_button"/> <button label="取消" name="cancel_button"/> <string name="GroupInvitation"> - 社團邀請 + 群組邀請 </string> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_group_land_money.xml b/indra/newview/skins/default/xui/zh/panel_group_land_money.xml index 58022c2279..1bf3929683 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_land_money.xml @@ -7,7 +7,7 @@ You don't have permission to view group owned land </panel.string> <panel.string name="epmty_view_group_land_text"> - No entries + 沒有項目 </panel.string> <panel.string name="cant_view_group_accounting_text"> You don't have permission to view the group's accounting information. @@ -16,7 +16,7 @@ 載入中... </panel.string> <panel.string name="land_contrib_error"> - Unable to set your land contribution + 無法設定你的土地捐獻 </panel.string> <panel name="layout_panel_landmoney"> <scroll_list name="group_parcel_list"> @@ -46,7 +46,7 @@ [AREA] m² </text> <text name="your_contribution_label"> - Your contribution: + 你的捐獻: </text> <text name="your_contribution_units"> m² @@ -58,7 +58,7 @@ More land credits are needed to support land in use </text> <text name="group_money_heading"> - 社團 L$ + 群組 L$ </text> </panel> <tab_container name="group_money_tab_container"> diff --git a/indra/newview/skins/default/xui/zh/panel_group_notices.xml b/indra/newview/skins/default/xui/zh/panel_group_notices.xml index 65c07e7137..26273dd9ce 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_notices.xml @@ -10,7 +10,7 @@ You can turn off Notices on the General tab. </panel.string> <text name="lbl2"> 通知保留 14 天。 -每個社團一天最多 200 則 +每個群組一天最多 200 則 </text> <scroll_list name="notice_list"> <scroll_list.columns label="主旨" name="subject"/> diff --git a/indra/newview/skins/default/xui/zh/panel_group_notify.xml b/indra/newview/skins/default/xui/zh/panel_group_notify.xml index 803f34d5a7..00462d8b0b 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_notify.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_notify.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="instant_message" name="panel_group_notify"> +<panel label="即時訊息" name="panel_group_notify"> <string name="message_max_lines_count" value="7"/> <string name="subject_font" value="SANSSERIF_BIG"/> <string name="date_font" value="SANSSERIF"/> <panel label="header" name="header"> <text name="title" value="Sender Name / Group Name"/> </panel> - <text_editor name="message" value="message"/> + <text_editor name="message" value="訊息"/> <text name="attachment" value="Attachment"/> <button label="確定" name="btn_ok"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_group_roles.xml b/indra/newview/skins/default/xui/zh/panel_group_roles.xml index fff4383893..cf5fc26d14 100644 --- a/indra/newview/skins/default/xui/zh/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/zh/panel_group_roles.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="成員與角色" name="roles_tab"> <panel.string name="default_needs_apply_text"> - There are unsaved changes + 未儲存的設定 </panel.string> <panel.string name="want_apply_text"> - Do you want to save your changes? + 你要儲存你的變更嗎? </panel.string> <tab_container name="roles_tab_container"> <panel label="成員" name="members_sub_tab" tool_tip="成員"> <panel.string name="help_text"> - You can add or remove Roles assigned to Members. -Select multiple Members by holding the Ctrl key and -clicking on their names. + 你可以添加或移除一個角色指派給成員。 +選責多個成員時同時按著 Ctrl 鍵且 +使用滑鼠左鍵點擊他們的名字。 </panel.string> <panel.string name="donation_area"> [AREA] m² @@ -55,12 +55,12 @@ things in this group. There's a broad variety of Abilities. </tab_container> <panel name="members_footer"> <text name="static"> - Assigned Roles + 指派角色 </text> <text name="static2"> - Allowed Abilities + 允許的能力 </text> - <scroll_list name="member_allowed_actions" tool_tip="For details of each allowed ability see the abilities tab"/> + <scroll_list name="member_allowed_actions" tool_tip="想瞭解有關於允許的能力的細節請查閱能力頁籤"/> </panel> <panel name="roles_footer"> <text name="static"> @@ -73,23 +73,23 @@ things in this group. There's a broad variety of Abilities. 描述 </text> <text name="static4"> - Assigned Members + 指派角色 </text> <check_box label="Reveal members" name="role_visible_in_list" tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."/> <text name="static5"> - Allowed Abilities + 允許的能力 </text> - <scroll_list name="role_allowed_actions" tool_tip="For details of each allowed ability see the abilities tab"/> + <scroll_list name="role_allowed_actions" tool_tip="想瞭解有關於每一項允許的能力的細節請查閱能力頁籤"/> </panel> <panel name="actions_footer"> <text_editor name="action_description"> This Ability is 'Eject Members from this Group'. Only an Owner can eject another Owner. </text_editor> <text name="static2"> - Roles with this ability + 有此能力的角色 </text> <text name="static3"> - Members with this ability + 有此能力的成員 </text> </panel> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_landmarks.xml b/indra/newview/skins/default/xui/zh/panel_landmarks.xml index fa907e3d90..eea406170a 100644 --- a/indra/newview/skins/default/xui/zh/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/zh/panel_landmarks.xml @@ -4,12 +4,12 @@ <accordion_tab name="tab_favorites" title="最愛列"/> <accordion_tab name="tab_landmarks" title="我的地標"/> <accordion_tab name="tab_inventory" title="我的收納區"/> - <accordion_tab name="tab_library" title="Library"/> + <accordion_tab name="tab_library" title="資源庫"/> </accordion> <panel name="bottom_panel"> <layout_stack name="bottom_panel"> <layout_panel name="options_gear_btn_panel"> - <menu_button name="options_gear_btn" tool_tip="Show additional options"/> + <menu_button name="options_gear_btn" tool_tip="顯示額外選項"/> </layout_panel> <layout_panel name="add_btn_panel"> <button name="add_btn" tool_tip="添加新地標"/> diff --git a/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml b/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml index 059a78cf7d..3e44f2a584 100644 --- a/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/zh/panel_media_settings_general.xml @@ -14,7 +14,7 @@ 目前頁面: </text> <text name="current_url" tool_tip="The current page for this media source" value=""/> - <button label="Reset" name="current_url_reset_btn"/> + <button label="重設" name="current_url_reset_btn"/> <check_box initial_value="false" label="Auto Loop" name="auto_loop"/> <check_box initial_value="false" label="First Click Interacts" name="first_click_interact"/> <check_box initial_value="false" label="Auto Zoom" name="auto_zoom"/> diff --git a/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml index 3645f471ce..ec62b61c54 100644 --- a/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml +++ b/indra/newview/skins/default/xui/zh/panel_media_settings_permissions.xml @@ -17,7 +17,7 @@ <check_box initial_value="false" label="Allow Navigation & Interactivity" name="perms_owner_interact"/> <check_box initial_value="false" label="顯示控制列" name="perms_owner_control"/> <text name="group_label"> - 社團: + 群組: </text> <check_box initial_value="false" label="Allow Navigation & Interactivity" name="perms_group_interact"/> <check_box initial_value="false" label="顯示控制列" name="perms_group_control"/> diff --git a/indra/newview/skins/default/xui/zh/panel_media_settings_security.xml b/indra/newview/skins/default/xui/zh/panel_media_settings_security.xml index ef56c34b5c..aaaf6bfb94 100644 --- a/indra/newview/skins/default/xui/zh/panel_media_settings_security.xml +++ b/indra/newview/skins/default/xui/zh/panel_media_settings_security.xml @@ -4,7 +4,7 @@ <text name="home_url_fails_some_items_in_whitelist"> Entries that the home page fails against are marked: </text> - <button label="Add" name="whitelist_add"/> + <button label="添加" name="whitelist_add"/> <button label="刪除" name="whitelist_del"/> <text name="home_url_fails_whitelist"> Warning: the home page specified in the General tab fails to pass this whitelist. It has been disabled until a valid entry has been added. diff --git a/indra/newview/skins/default/xui/zh/panel_navigation_bar.xml b/indra/newview/skins/default/xui/zh/panel_navigation_bar.xml index 1748d117f4..60a5767d09 100644 --- a/indra/newview/skins/default/xui/zh/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/zh/panel_navigation_bar.xml @@ -9,8 +9,8 @@ <combo_editor label="搜尋 [SECOND_LIFE]" name="search_combo_editor"/> </search_combo_box> </panel> - <favorites_bar name="favorite" tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"> - <label name="favorites_bar_label" tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"> + <favorites_bar name="favorite" tool_tip="拖曳傳送地標到此以便讓你在第二人生中能快速傳送到你最愛的地點!!"> + <label name="favorites_bar_label" tool_tip="拖曳傳送地標到此以便讓你在第二人生中能快速傳送到你最愛的地點!!"> 最愛列 </label> <chevron_button name=">>" tool_tip="顯示更多我的最愛"/> diff --git a/indra/newview/skins/default/xui/zh/panel_nearby_media.xml b/indra/newview/skins/default/xui/zh/panel_nearby_media.xml index 5ab6837569..6a4b5fcf35 100644 --- a/indra/newview/skins/default/xui/zh/panel_nearby_media.xml +++ b/indra/newview/skins/default/xui/zh/panel_nearby_media.xml @@ -30,9 +30,9 @@ </text> <combo_box name="show_combo"> <combo_box.item label="全部" name="All"/> - <combo_box.item label="In this Parcel" name="WithinParcel"/> - <combo_box.item label="Outside this Parcel" name="OutsideParcel"/> - <combo_box.item label="On other Avatars" name="OnOthers"/> + <combo_box.item label="在此地段內" name="WithinParcel"/> + <combo_box.item label="在此地段外部" name="OutsideParcel"/> + <combo_box.item label="在其他化身身上" name="OnOthers"/> </combo_box> <scroll_list name="media_list"> <scroll_list.columns label="Proximity" name="media_proximity"/> @@ -53,10 +53,10 @@ <button name="pause_btn" tool_tip="暫停所選擇的媒體"/> </layout_panel> <layout_panel name="volume_slider_ctrl"> - <slider_bar initial_value="0.5" name="volume_slider" tool_tip="Audio volume for selected media"/> + <slider_bar initial_value="0.5" name="volume_slider" tool_tip="所選擇的媒體之音頻音量"/> </layout_panel> <layout_panel name="mute"> - <button name="mute_btn" tool_tip="Mute audio on selected media"/> + <button name="mute_btn" tool_tip="靜音所選擇的媒體音頻"/> </layout_panel> <layout_panel name="zoom"> <button name="zoom_btn" tool_tip="Zoom into selected media"/> diff --git a/indra/newview/skins/default/xui/zh/panel_notes.xml b/indra/newview/skins/default/xui/zh/panel_notes.xml index f68fd74d1f..5d0e6760ff 100644 --- a/indra/newview/skins/default/xui/zh/panel_notes.xml +++ b/indra/newview/skins/default/xui/zh/panel_notes.xml @@ -27,7 +27,7 @@ <button label="地圖" name="show_on_map_btn" tool_tip="Show the Resident on the map"/> </layout_panel> <layout_panel name="teleport_btn_lp"> - <button label="瞬間傳送" name="teleport" tool_tip="Offer teleport"/> + <button label="瞬間傳送" name="teleport" tool_tip="發給瞬間傳送請求"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/zh/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/zh/panel_outfits_wearing.xml index 39a9bcb848..693cdcdeca 100644 --- a/indra/newview/skins/default/xui/zh/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/zh/panel_outfits_wearing.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="Wearing"> <panel name="bottom_panel"> - <menu_button name="options_gear_btn" tool_tip="Show additional options"/> + <menu_button name="options_gear_btn" tool_tip="顯示額外選項"/> </panel> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_people.xml b/indra/newview/skins/default/xui/zh/panel_people.xml index 4c6d6c76be..c97ff2ae96 100644 --- a/indra/newview/skins/default/xui/zh/panel_people.xml +++ b/indra/newview/skins/default/xui/zh/panel_people.xml @@ -14,18 +14,18 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <string name="no_filtered_friends_msg"> Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]. </string> - <string name="people_filter_label" value="Filter People"/> - <string name="groups_filter_label" value="Filter Groups"/> - <string name="no_filtered_groups_msg" value="Didn't find what you're looking for? Try [secondlife:///app/search/groups/[SEARCH_TERM] Search]."/> - <string name="no_groups_msg" value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]."/> - <string name="MiniMapToolTipMsg" value="[REGION](Double-click to open Map, shift-drag to pan)"/> - <string name="AltMiniMapToolTipMsg" value="[REGION](Double-click to teleport, shift-drag to pan)"/> - <filter_editor label="Filter" name="filter_input"/> + <string name="people_filter_label" value="人員過濾器"/> + <string name="groups_filter_label" value="群組過濾器"/> + <string name="no_filtered_groups_msg" value="沒有發現你要找的嗎?何不試試 [secondlife:///app/search/groups/[SEARCH_TERM] 搜尋]。"/> + <string name="no_groups_msg" value="想找尋群組加入嗎?何不試試 [secondlife:///app/search/groups 搜尋]。"/> + <string name="MiniMapToolTipMsg" value="[REGION](雙擊以開啟地圖,按下 shift 鍵拖曳來平移)"/> + <string name="AltMiniMapToolTipMsg" value="[REGION](雙擊以瞬間傳送,按下 shift 鍵拖曳來平移)"/> + <filter_editor label="過濾器" name="filter_input"/> <tab_container name="tabs"> <panel label="附近" name="nearby_panel"> <panel label="bottom_panel" name="bottom_panel"> <menu_button name="nearby_view_sort_btn" tool_tip="選項"/> - <button name="add_friend_btn" tool_tip="Add selected Resident to your friends List"/> + <button name="add_friend_btn" tool_tip="添加已選擇的居民到Ad你的朋友清單"/> </panel> </panel> <panel label="我的朋友" name="friends_panel"> @@ -39,55 +39,55 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <menu_button name="friends_viewsort_btn" tool_tip="顯示額外選項"/> </layout_panel> <layout_panel name="add_btn_panel"> - <button name="add_btn" tool_tip="Offer friendship to a Resident"/> + <button name="add_btn" tool_tip="向居民提出加為好友邀請"/> </layout_panel> <layout_panel name="trash_btn_panel"> - <dnd_button name="del_btn" tool_tip="Remove selected person from your Friends list"/> + <dnd_button name="del_btn" tool_tip="由你的朋友清單移除所選擇的人"/> </layout_panel> </layout_stack> </panel> </panel> - <panel label="我的社團" name="groups_panel"> + <panel label="我的群組" name="groups_panel"> <panel label="bottom_panel" name="bottom_panel"> <menu_button name="groups_viewsort_btn" tool_tip="選項"/> - <button name="plus_btn" tool_tip="Join group/Create new group"/> - <button name="activate_btn" tool_tip="Activate selected group"/> + <button name="plus_btn" tool_tip="加入群組/創立新群組"/> + <button name="activate_btn" tool_tip="啟用所選擇的群組"/> </panel> </panel> - <panel label="RECENT" name="recent_panel"> + <panel label="最近" name="recent_panel"> <panel label="bottom_panel" name="bottom_panel"> <menu_button name="recent_viewsort_btn" tool_tip="選項"/> - <button name="add_friend_btn" tool_tip="Add selected Resident to your friends List"/> + <button name="add_friend_btn" tool_tip="添加所選的居民到你的朋友清單"/> </panel> </panel> </tab_container> <panel name="button_bar"> <layout_stack name="bottom_bar_ls"> <layout_panel name="view_profile_btn_lp"> - <button label="檔案" name="view_profile_btn" tool_tip="Show picture, groups, and other Residents information"/> + <button label="檔案" name="view_profile_btn" tool_tip="顯示圖片、群組與其他居民資訊"/> </layout_panel> - <layout_panel name="im_btn_lp"> + <layout_panel name="chat_btn_lp"> <button label="IM" name="im_btn" tool_tip="開啟即時訊息會話"/> </layout_panel> - <layout_panel name="call_btn_lp"> - <button label="通話" name="call_btn" tool_tip="Call this Resident"/> + <layout_panel name="chat_btn_lp"> + <button label="通話" name="call_btn" tool_tip="與此居民進行通話"/> </layout_panel> - <layout_panel name="share_btn_lp"> + <layout_panel name="chat_btn_lp"> <button label="分享" name="share_btn" tool_tip="分享一個收納區物品"/> </layout_panel> - <layout_panel name="teleport_btn_lp"> - <button label="瞬間傳送" name="teleport_btn" tool_tip="Offer teleport"/> + <layout_panel name="chat_btn_lp"> + <button label="瞬間傳送" name="teleport_btn" tool_tip="發給瞬間傳送請求"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls1"> <layout_panel name="group_info_btn_lp"> - <button label="社團檔案" name="group_info_btn" tool_tip="顯示社團資訊"/> + <button label="群組檔案" name="group_info_btn" tool_tip="顯示群組資訊"/> </layout_panel> <layout_panel name="chat_btn_lp"> - <button label="Group Chat" name="chat_btn" tool_tip="開啟聊天會話"/> + <button label="群組聊天" name="chat_btn" tool_tip="開啟聊天會話"/> </layout_panel> <layout_panel name="group_call_btn_lp"> - <button label="Group Call" name="group_call_btn" tool_tip="Call this group"/> + <button label="群組通話" name="group_call_btn" tool_tip="與此群組進行通話"/> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_picks.xml b/indra/newview/skins/default/xui/zh/panel_picks.xml index a233092dc2..15733b71b0 100644 --- a/indra/newview/skins/default/xui/zh/panel_picks.xml +++ b/indra/newview/skins/default/xui/zh/panel_picks.xml @@ -19,7 +19,7 @@ <button label="資訊" name="info_btn" tool_tip="顯示精選地點資訊"/> </layout_panel> <layout_panel name="teleport_btn_lp"> - <button label="瞬間傳送" name="teleport_btn" tool_tip="瞬間傳送到相對應的區域"/> + <button label="瞬間傳送" name="teleport_btn" tool_tip="瞬間傳送到的區域"/> </layout_panel> <layout_panel name="show_on_map_btn_lp"> <button label="地圖" name="show_on_map_btn" tool_tip="在世界地圖上顯示相對應的區域"/> diff --git a/indra/newview/skins/default/xui/zh/panel_place_profile.xml b/indra/newview/skins/default/xui/zh/panel_place_profile.xml index aa7b036398..d7bcb0d027 100644 --- a/indra/newview/skins/default/xui/zh/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/zh/panel_place_profile.xml @@ -4,33 +4,33 @@ <string name="off" value="Off"/> <string name="anyone" value="Anyone"/> <string name="available" value="available"/> - <string name="allocated" value="allocated"/> + <string name="allocated" value="已分配"/> <string name="title_place" value="地點檔案"/> <string name="title_teleport_history" value="瞬間傳送歷史紀錄"/> - <string name="not_available" value="(N\A)"/> + <string name="not_available" value="(N\A)"/> <string name="unknown" value="(未知)"/> <string name="public" value="(公開)"/> <string name="none_text" value="(無)"/> <string name="sale_pending_text" value="(擱置銷售)"/> - <string name="group_owned_text" value="(社團所擁有)"/> + <string name="group_owned_text" value="(群組所擁有)"/> <string name="price_text" value="L$"/> <string name="area_text" value="m²"/> <string name="all_residents_text" value="全部居民"/> - <string name="group_text" value="社團"/> + <string name="group_text" value="群組"/> <string name="can_resell"> - Purchased land in this region may be resold. + 購買這地區的土地允許轉售。 </string> <string name="can_not_resell"> - Purchased land in this region may not be resold. + 購買這地區的土地不允許轉售。 </string> <string name="can_change"> - Purchased land in this region may be joined or subdivided. + 購買這地區的土地允許進行合併或分割。 </string> <string name="can_not_change"> - Purchased land in this region may not be joined or subdivided. + 購買這地區的土地不允許進行合併或分割。 </string> <string name="server_update_text"> - Place information not available without server update. + 地點資訊因無伺服器更新故無法提供。 </string> <string name="server_error_text"> Information about this location is unavailable at this time, please try again later. @@ -41,7 +41,7 @@ <string name="acquired_date"> [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] </string> - <button name="back_btn" tool_tip="Back"/> + <button name="back_btn" tool_tip="返回"/> <text name="title" value="地點檔案"/> <scroll_container name="place_scroll"> <panel name="scrolling_panel"> @@ -56,7 +56,7 @@ <panel name="parcel_characteristics_panel"> <text name="rating_label" value="分級:"/> <text name="rating_value" value="未知"/> - <text name="voice_label" value="Voice:"/> + <text name="voice_label" value="語音:"/> <text name="voice_value" value="On"/> <text name="fly_label" value="飛行:"/> <text name="fly_value" value="On"/> @@ -66,7 +66,7 @@ <text name="build_value" value="On"/> <text name="scripts_label" value="腳本:"/> <text name="scripts_value" value="On"/> - <text name="damage_label" value="Damage:"/> + <text name="damage_label" value="商害:"/> <text name="damage_value" value="Off"/> <button label="關於土地" name="about_land_btn"/> </panel> @@ -78,10 +78,10 @@ <text name="region_type_label" value="類型:"/> <text name="region_type" value="Moose"/> <text name="region_rating_label" value="分級:"/> - <text name="region_rating" value="成人"/> + <text name="region_rating" value="完全成人"/> <text name="region_owner_label" value="擁有者:"/> <text name="region_owner" value="moose Van Moose extra long name moose"/> - <text name="region_group_label" value="社團:"/> + <text name="region_group_label" value="群組:"/> <text name="region_group"> The Mighty Moose of mooseville soundvillemoose </text> @@ -104,8 +104,8 @@ <text name="traffic_label" value="流量:"/> <text name="primitives_label" value="Primitives:"/> <text name="parcel_scripts_label" value="腳本:"/> - <text name="terraform_limits_label" value="Terraform limits:"/> - <text name="subdivide_label" value="Subdivide/Join ability:"/> + <text name="terraform_limits_label" value="土地變形限制:"/> + <text name="subdivide_label" value="分割土地/合併土地能力:"/> <text name="resale_label" value="ReSale ability:"/> <text name="sale_to_label" value="出售給:"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_places.xml b/indra/newview/skins/default/xui/zh/panel_places.xml index 6434a7279c..8ac464271e 100644 --- a/indra/newview/skins/default/xui/zh/panel_places.xml +++ b/indra/newview/skins/default/xui/zh/panel_places.xml @@ -11,7 +11,7 @@ <button label="瞬間傳送" name="teleport_btn" tool_tip="瞬間傳送到所選擇的區域"/> </layout_panel> <layout_panel name="chat_btn_lp"> - <button label="地圖" name="map_btn" tool_tip="Show the corresponding area on the World Map"/> + <button label="地圖" name="map_btn" tool_tip="在世界地圖上顯示相對應的區域"/> </layout_panel> </layout_stack> </layout_panel> @@ -24,7 +24,7 @@ <menu_button name="overflow_btn" tool_tip="顯示額外選項"/> </layout_panel> </layout_stack> - <layout_stack name="bottom_bar_profile_ls"> + <layout_stack name="bottom_bar_ls3"> <layout_panel name="profile_btn_lp"> <button label="檔案" name="profile_btn" tool_tip="顯示地點檔案"/> </layout_panel> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml b/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml index c691edb11c..c083d40a82 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_chat.xml @@ -10,7 +10,7 @@ </radio_group> <check_box initial_value="true" label="聊天時播放打字動作" name="play_typing_animation"/> <check_box label="當我離線時將收到的 IM 訊息郵寄給我" name="send_im_to_email"/> - <check_box label="Enable plain text IM and chat history" name="plain_text_chat_history"/> + <check_box label="啟用純本文 IM 與聊天歷史紀錄" name="plain_text_chat_history"/> <check_box label="聊天泡泡" name="bubble_text_chat"/> <text name="show_ims_in_label"> 顯示 IMs 於: @@ -23,14 +23,14 @@ <radio_item label="頁籤" name="radio2" value="1"/> </radio_group> <text name="disable_toast_label"> - Enable incoming chat popups: + 啟用傳入聊天的突顯示視窗: </text> - <check_box label="Group Chats" name="EnableGroupChatPopups" tool_tip="Check to see popups when a Group Chat message arrives"/> - <check_box label="IM 聊天" name="EnableIMChatPopups" tool_tip="Check to see popups when an instant message arrives"/> + <check_box label="群組聊天" name="EnableGroupChatPopups" tool_tip="當群組聊天訊息抵達時查看突顯式視窗"/> + <check_box label="IM 聊天" name="EnableIMChatPopups" tool_tip="當即時訊息抵達時查看突顯式視窗"/> <spinner label="Nearby chat toasts life time:" name="nearby_toasts_lifetime"/> <spinner label="Nearby chat toasts fading time:" name="nearby_toasts_fadingtime"/> <text name="translate_chb_label"> - Use machine translation while chatting (powered by Google) + 聊天時使用機器自動進行翻譯(由 Google 所提供) </text> <text name="translate_language_text"> 聊天翻譯為: diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_general.xml b/indra/newview/skins/default/xui/zh/panel_preferences_general.xml index b7449dad10..cabe13adb8 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_general.xml @@ -23,9 +23,9 @@ 我想要能進出內容分級的地區為: </text> <combo_box name="maturity_desired_combobox"> - <combo_box.item label="General, Moderate, Adult" name="Desired_Adult"/> - <combo_box.item label="General and Moderate" name="Desired_Mature"/> - <combo_box.item label="一般" name="Desired_PG"/> + <combo_box.item label="一般普級,適度成人,完全成人" name="Desired_Adult"/> + <combo_box.item label="一般普級與適度成人" name="Desired_Mature"/> + <combo_box.item label="一般普級" name="Desired_PG"/> </combo_box> <text name="start_location_textbox"> 開始位置: @@ -45,9 +45,9 @@ </radio_group> <check_box label="我的名字" name="show_my_name_checkbox1"/> <check_box label="使用者名稱" name="show_slids" tool_tip="顯示使用者名稱,就像 bobsmith123 這類的"/> - <check_box label="社團頭銜" name="show_all_title_checkbox1" tool_tip="顯示社團頭銜,像是 Officer 或成員"/> - <check_box label="高亮顯示朋友" name="show_friends" tool_tip="高亮顯示你朋友的名稱標籤"/> - <check_box label="View Display Names" name="display_names_check" tool_tip="Check to use display names in chat, IM, name tags, etc."/> + <check_box label="群組頭銜" name="show_all_title_checkbox1" tool_tip="顯示群組頭銜,像是 Officer 或成員"/> + <check_box label="高亮標示朋友" name="show_friends" tool_tip="高亮顯示你朋友的名稱標籤"/> + <check_box label="察看顯示名稱" name="display_names_check" tool_tip="Check to use display names in chat, IM, name tags, etc."/> <text name="inworld_typing_rg_label"> 按下字母鍵: </text> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/zh/panel_preferences_graphics1.xml index 8c728bf779..ee8cd9794a 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_graphics1.xml @@ -1,47 +1,47 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="圖形" name="Display panel"> <text name="QualitySpeed"> - Quality and speed: + 品質與速度: </text> <text name="FasterText"> - Faster + 最快 </text> <text name="BetterText"> - Better + 最佳 </text> <text name="ShadersPrefText"> - Low + 低 </text> <text name="ShadersPrefText2"> - Mid + 中 </text> <text name="ShadersPrefText3"> - High + 高 </text> <text name="ShadersPrefText4"> - Ultra + 超高 </text> <panel label="自訂圖形" name="CustomGraphics Panel"> <text name="ShadersText"> - Shaders: + 著色器: </text> - <check_box initial_value="true" label="Transparent Water" name="TransparentWater"/> - <check_box initial_value="true" label="Bump mapping and shiny" name="BumpShiny"/> - <check_box initial_value="true" label="Basic shaders" name="BasicShaders" tool_tip="Disabling this option may prevent some graphics card drivers from crashing"/> - <check_box initial_value="true" label="Atmospheric shaders" name="WindLightUseAtmosShaders"/> + <check_box initial_value="true" label="清澈透明的水" name="TransparentWater"/> + <check_box initial_value="true" label="凹凸映射與光澤效果" name="BumpShiny"/> + <check_box initial_value="true" label="基本著色" name="BasicShaders" tool_tip="關閉此一選項可能避免部分顯示卡驅動程式損毀當機"/> + <check_box initial_value="true" label="大氣著色" name="WindLightUseAtmosShaders"/> <text name="reflection_label"> - Water Reflections: + 水文反射: </text> <combo_box name="Reflections"> - <combo_box.item label="Minimal" name="0"/> - <combo_box.item label="Terrain and trees" name="1"/> + <combo_box.item label="最小" name="0"/> + <combo_box.item label="地形與樹木" name="1"/> <combo_box.item label="全部靜態物件" name="2"/> <combo_box.item label="全部化身與物件" name="3"/> - <combo_box.item label="Everything" name="4"/> + <combo_box.item label="一切" name="4"/> </combo_box> - <slider label="Avatar Physics:" name="AvatarPhysicsDetail"/> + <slider label="化身物理:" name="AvatarPhysicsDetail"/> <text name="AvatarPhysicsDetailText"> - Low + 低 </text> <slider label="描繪距離:" name="DrawDistance"/> <text name="DrawDistanceMeterText2"> @@ -49,54 +49,54 @@ </text> <slider label="Max. particle count:" name="MaxParticleCount"/> <slider label="Max. # of non-impostor avatars:" name="MaxNumberAvatarDrawn"/> - <slider label="Post process quality:" name="RenderPostProcess"/> + <slider label="後製品質:" name="RenderPostProcess"/> <text name="MeshDetailText"> - Mesh detail: + 網面細節: </text> - <slider label="Objects:" name="ObjectMeshDetail"/> + <slider label="物件:" name="ObjectMeshDetail"/> <slider label="Flexiprims:" name="FlexibleMeshDetail"/> - <slider label="Trees:" name="TreeMeshDetail"/> - <slider label="Avatars:" name="AvatarMeshDetail"/> - <slider label="Terrain:" name="TerrainMeshDetail"/> - <slider label="Sky:" name="SkyMeshDetail"/> + <slider label="樹木:" name="TreeMeshDetail"/> + <slider label="化身:" name="AvatarMeshDetail"/> + <slider label="地形:" name="TerrainMeshDetail"/> + <slider label="天空:" name="SkyMeshDetail"/> <text name="PostProcessText"> - Low + 低 </text> <text name="ObjectMeshDetailText"> - Low + 低 </text> <text name="FlexibleMeshDetailText"> - Low + 低 </text> <text name="TreeMeshDetailText"> - Low + 低 </text> <text name="AvatarMeshDetailText"> - Low + 低 </text> <text name="TerrainMeshDetailText"> - Low + 低 </text> <text name="SkyMeshDetailText"> - Low + 低 </text> <text name="AvatarRenderingText"> Avatar Rendering: </text> <check_box initial_value="true" label="Avatar impostors" name="AvatarImpostors"/> <check_box initial_value="true" label="Hardware skinning" name="AvatarVertexProgram"/> - <check_box initial_value="true" label="Avatar cloth" name="AvatarCloth"/> + <check_box initial_value="true" label="化身衣服" name="AvatarCloth"/> <text name="TerrainDetailText"> - Terrain detail: + 地形細節: </text> <radio_group name="TerrainDetailRadio"> - <radio_item label="Low" name="0"/> - <radio_item label="High" name="2"/> + <radio_item label="低" name="0"/> + <radio_item label="高" name="2"/> </radio_group> --> </panel> <button label="套用" label_selected="套用" name="Apply"/> - <button label="Reset" name="Defaults"/> + <button label="重設" name="Defaults"/> <button label="進階" name="Advanced"/> <button label="硬體" label_selected="硬體" name="GraphicsHardwareButton"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_move.xml b/indra/newview/skins/default/xui/zh/panel_preferences_move.xml index de296f72f3..57e3540b3d 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_move.xml @@ -5,20 +5,20 @@ <text name="heading2"> 自動位移: </text> - <check_box label="建造 / 編輯" name="edit_camera_movement" tool_tip="Use automatic camera positioning when entering and exiting edit mode"/> - <check_box label="編輯外觀" name="appearance_camera_movement" tool_tip="Use automatic camera positioning while in edit mode"/> - <check_box initial_value="true" label="側邊欄" name="appearance_sidebar_positioning" tool_tip="Use automatic camera positioning for sidebar"/> + <check_box label="建造 / 編輯" name="edit_camera_movement" tool_tip="使用進入或離開編輯模式時自動調整攝影機位置功能"/> + <check_box label="編輯外觀" name="appearance_camera_movement" tool_tip="使用編輯模式時自動調整攝影機位置功能"/> + <check_box initial_value="true" label="側邊欄" name="appearance_sidebar_positioning" tool_tip="使用開啟側邊欄時自動調整攝影機位置功能"/> <check_box label="將我顯示於第一人稱視角中" name="first_person_avatar_visible"/> <text name=" Mouse Sensitivity"> - Mouselook mouse sensitivity: + 第一人稱視角滑鼠敏感度: </text> <check_box label="反轉" name="invert_mouse"/> <check_box label="總是使用方向鍵移動" name="arrow_keys_move_avatar_check"/> - <check_box label="Tap-tap-hold to run" name="tap_tap_hold_to_run"/> + <check_box label="連點按住後跑步" name="tap_tap_hold_to_run"/> <check_box label="雙擊以D:" name="double_click_chkbox"/> <radio_group name="double_click_action"> <radio_item label="瞬間傳送" name="radio_teleport"/> - <radio_item label="Auto-pilot" name="radio_autopilot"/> + <radio_item label="自動導航駕駛" name="radio_autopilot"/> </radio_group> <button label="其他設備" name="joystick_setup_button"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml index 89a1a48abf..bd6d465572 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml @@ -8,8 +8,8 @@ (位置、圖像、網頁、搜尋的歷史紀錄) </text> <check_box label="將我顯示在搜尋的結果中" name="online_searchresults"/> - <check_box label="只有我的朋友和社團知道我在線上" name="online_visibility"/> - <check_box label="只有我的朋友和社團可以 IM 或與我通話。" name="voice_call_friends_only_check"/> + <check_box label="只有我的朋友和群組知道我在線上" name="online_visibility"/> + <check_box label="只有我的朋友和群組可以 IM 或與我通話。" name="voice_call_friends_only_check"/> <check_box label="當通話結束時關閉麥克風" name="auto_disengage_mic_check"/> <check_box label="登入時顯示我最愛的地標位置(經由 '開始於' 的下拉式選單)" name="favorites_on_login_check"/> <text name="Logs:"> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml b/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml index e7a934c5cc..efefb92df6 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_setup.xml @@ -21,7 +21,7 @@ 快取位置: </text> <button label="瀏覽" label_selected="瀏覽" name="set_cache"/> - <button label="重設" label_selected="重設" name="reset_cache"/> + <button label="" label_selected="重設" name="reset_cache"/> <text name="Web:"> 網頁: </text> diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml b/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml index 305d1e2ac9..3280b9357b 100644 --- a/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_sound.xml @@ -9,7 +9,7 @@ 最小化時靜音 </text> <slider label="按鍵音" name="UI Volume"/> - <slider label="Ambient" name="Wind Volume"/> + <slider label="環境音" name="Wind Volume"/> <slider label="音效" name="SFX Volume"/> <slider label="串流音樂" name="Music Volume"/> <check_box label="已啟用" name="enable_music"/> @@ -33,7 +33,7 @@ <check_box label="Toggle speak on/off when I press:" name="push_to_talk_toggle_check" tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."/> <line_editor label="Push-to-Speak trigger" name="modifier_combo"/> <button label="設定按鍵" name="set_voice_hotkey_button"/> - <button name="set_voice_middlemouse_button" tool_tip="Reset to Middle Mouse Button"/> + <button name="set_voice_middlemouse_button" tool_tip="重設滑鼠中鍵按鈕"/> <button label="輸入 / 輸出設備" name="device_settings_btn"/> <panel label="設備設定" name="device_settings_panel"> <panel.string name="default_text"> diff --git a/indra/newview/skins/default/xui/zh/panel_profile.xml b/indra/newview/skins/default/xui/zh/panel_profile.xml index fcf7bb64db..502449ac3a 100644 --- a/indra/newview/skins/default/xui/zh/panel_profile.xml +++ b/indra/newview/skins/default/xui/zh/panel_profile.xml @@ -36,9 +36,9 @@ <text name="title_acc_status_text" value="帳戶狀態:"/> <text name="title_partner_text" value="配偶:"/> <panel name="partner_data_panel"> - <text initial_value="(retrieving)" name="partner_text"/> + <text initial_value="(檢索中)" name="partner_text"/> </panel> - <text name="title_groups_text" value="社團:"/> + <text name="title_groups_text" value="群組:"/> </panel> </scroll_container> </layout_panel> @@ -47,7 +47,7 @@ <layout_panel name="profile_buttons_panel"> <layout_stack name="bottom_bar_ls"> <layout_panel name="add_friend_btn_lp"> - <button label="加為朋友" name="add_friend" tool_tip="Offer friendship to the Resident"/> + <button label="加為朋友" name="add_friend" tool_tip="發出交友邀請給這居民"/> </layout_panel> <layout_panel name="im_btn_lp"> <button label="IM" name="im" tool_tip="開啟即時訊息會話"/> @@ -56,7 +56,7 @@ <button label="通話" name="call" tool_tip="與這位居民通話"/> </layout_panel> <layout_panel name="chat_btn_lp"> - <button label="瞬間傳送" name="teleport" tool_tip="Offer teleport"/> + <button label="瞬間傳送" name="teleport" tool_tip="發給瞬間傳送請求"/> </layout_panel> <layout_panel name="overflow_btn_lp"> <menu_button label="▼" name="overflow_btn" tool_tip="支付金錢,或分享收納區給居民"/> diff --git a/indra/newview/skins/default/xui/zh/panel_region_covenant.xml b/indra/newview/skins/default/xui/zh/panel_region_covenant.xml index 315bc0ac8e..ad94c4c7e9 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_covenant.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_covenant.xml @@ -36,7 +36,7 @@ <text_editor name="covenant_editor"> There is no Covenant provided for this Estate. </text_editor> - <button label="Reset" name="reset_covenant"/> + <button label="重設" name="reset_covenant"/> <text name="covenant_help_text"> Changes to the covenant will show on all parcels in the estate. </text> @@ -62,7 +62,7 @@ 分級: </text> <text name="region_maturity_text"> - 成人 + 完全成人 </text> <text name="resellable_lbl"> 轉售: diff --git a/indra/newview/skins/default/xui/zh/panel_region_debug.xml b/indra/newview/skins/default/xui/zh/panel_region_debug.xml index 1ffbcbf8fd..ed5e6e9d2c 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_debug.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_debug.xml @@ -7,8 +7,8 @@ 未知 </text> <check_box label="關閉腳本" name="disable_scripts_check" tool_tip="關閉這個地區現在的全部腳本"/> - <check_box label="Disable Collisions" name="disable_collisions_check" tool_tip="Disable non-avatar collisions in this region"/> - <check_box label="Disable Physics" name="disable_physics_check" tool_tip="Disable all physics in this region"/> + <check_box label="關閉碰撞" name="disable_collisions_check" tool_tip="關閉這個地區現在的非化身碰撞"/> + <check_box label="關閉物理" name="disable_physics_check" tool_tip="關閉這個地區現在的全部物理"/> <button label="套用" name="apply_btn"/> <text name="objret_text_lbl"> 物件退回 @@ -23,12 +23,12 @@ <text name="options_text_lbl"> 選項: </text> - <check_box label="With scripts" name="return_scripts" tool_tip="只退回R包含腳本的物件"/> - <check_box label="On someone else's land" name="return_other_land" tool_tip="Return only objects which are on land belonging to someone else"/> - <check_box label="In every region of this estate" name="return_estate_wide" tool_tip="Return objects in all of the regions that make up this estate"/> + <check_box label="包含有腳本" name="return_scripts" tool_tip="只退回包含腳本的物件"/> + <check_box label="位於其他人土地上" name="return_other_land" tool_tip="只退回物件在屬於某個其他人土地上的物件"/> + <check_box label="於這個領地內的每一個地區" name="return_estate_wide" tool_tip="退回這個領地內全部地區中標記為他的物件"/> <button label="退回" name="return_btn"/> - <button label="Get Top Colliders..." name="top_colliders_btn" tool_tip="List of objects experiencing the most potential collisions"/> - <button label="Get Top Scripts..." name="top_scripts_btn" tool_tip="List of objects spending the most time running scripts"/> + <button label="取得最常碰撞的物件..." name="top_colliders_btn" tool_tip="條列出目前運作中最常碰撞的物件清單"/> + <button label="取得最耗能腳本..." name="top_scripts_btn" tool_tip="條列出目前運作中最耗能的腳本清單"/> <button label="地區重新啟動" name="restart_btn" tool_tip="給予兩分鐘倒數計時並重新啟動"/> <button label="延遲重新啟動" name="cancel_restart_btn" tool_tip="延遲地區重新啟動一小時"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_region_estate.xml b/indra/newview/skins/default/xui/zh/panel_region_estate.xml index 1f1676167b..efa3be2f51 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_estate.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="領地" name="Estate"> <text name="estate_help_text"> - Changes to settings on this tab will affect all regions in the estate. + 變更此夜籤中的設定會影響這個領地內的全部地區設定。 </text> <text name="estate_text"> 領地: @@ -16,9 +16,9 @@ (未知) </text> <check_box label="Use Global Time" name="use_global_time_check"/> - <check_box label="Fixed Sun" name="fixed_sun_check"/> + <check_box label="固定太陽" name="fixed_sun_check"/> <slider label="Phase" name="sun_hour_slider"/> - <check_box label="Allow Public Access" name="externally_visible_check"/> + <check_box label="允許公開出入" name="externally_visible_check"/> <text name="Only Allow"> Restrict Access to accounts verified by: </text> @@ -40,7 +40,7 @@ <button label="移除..." name="remove_allowed_avatar_btn"/> <button label="添加..." name="add_allowed_avatar_btn"/> <text name="allow_group_label"> - 允許的社團: + 允許的群組: </text> <button label="移除..." name="remove_allowed_group_btn"/> <button label="添加..." name="add_allowed_group_btn"/> diff --git a/indra/newview/skins/default/xui/zh/panel_region_general.xml b/indra/newview/skins/default/xui/zh/panel_region_general.xml index dce75c997d..38fde494aa 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_general.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_general.xml @@ -18,10 +18,10 @@ <text name="region_type"> 未知 </text> - <check_box label="Block Terraform" name="block_terraform_check"/> - <check_box label="Block Fly" name="block_fly_check"/> - <check_box label="Allow Damage" name="allow_damage_check"/> - <check_box label="Restrict Pushing" name="restrict_pushobject"/> + <check_box label="阻止變形" name="block_terraform_check"/> + <check_box label="阻止飛行" name="block_fly_check"/> + <check_box label="允許傷害" name="allow_damage_check"/> + <check_box label="限制推撞" name="restrict_pushobject"/> <check_box label="允許土地轉售" name="allow_land_resell_check"/> <check_box label="允許土地 合併/分割" name="allow_parcel_changes_check"/> <check_box label="阻擋土地顯示於搜尋中" name="block_parcel_search_check" tool_tip="Let people see this region and its parcels in search results"/> @@ -30,13 +30,13 @@ <text label="Maturity" name="access_text"> 分級: </text> - <icons_combo_box label="Moderate" name="access_combo"> - <icons_combo_box.item label="成人" name="Adult" value="42"/> - <icons_combo_box.item label="Moderate" name="Mature" value="21"/> - <icons_combo_box.item label="一般" name="PG" value="13"/> + <icons_combo_box label="適度成人" name="access_combo"> + <icons_combo_box.item label="完全成人" name="Adult" value="42"/> + <icons_combo_box.item label="適度成人" name="Mature" value="21"/> + <icons_combo_box.item label="一般普級" name="PG" value="13"/> </icons_combo_box> <button label="套用" name="apply_btn"/> - <button label="強制瞬間傳送一位居民回家..." name="kick_btn"/> + <button label="強制瞬間傳送一個居民回家..." name="kick_btn"/> <button label="強制瞬間傳送所有居民回家..." name="kick_all_btn"/> <button label="送出訊息到地區..." name="im_btn"/> <button label="管理瞬間傳送中心..." name="manage_telehub_btn"/> diff --git a/indra/newview/skins/default/xui/zh/panel_script_ed.xml b/indra/newview/skins/default/xui/zh/panel_script_ed.xml index e42d904f32..1dc7c1e089 100644 --- a/indra/newview/skins/default/xui/zh/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/zh/panel_script_ed.xml @@ -4,10 +4,10 @@ 載入中... </panel.string> <panel.string name="can_not_view"> - You can not view or edit this script, since it has been set as "no copy". You need full permissions to view or edit a script inside an object. + 你不察看或編輯此腳本,自從它被設定為 "no copy" 後。你需要完整權限去察看或編輯有包含腳本在內的物件。 </panel.string> <panel.string name="public_objects_can_not_run"> - Public Objects cannot run scripts + 公開物件不能執行腳本 </panel.string> <panel.string name="script_running"> 執行中 @@ -16,7 +16,7 @@ 腳本:[NAME] </panel.string> <panel.string name="external_editor_not_set"> - Select an editor by setting the environment variable LL_SCRIPT_EDITOR or the ExternalEditor setting. + 由環境變數設定 LL_SCRIPT_EDITOR 或是 ExternalEditor 設定來選擇一個編輯器。 </panel.string> <menu_bar name="script_menu"> <menu label="檔案" name="File"> diff --git a/indra/newview/skins/default/xui/zh/panel_side_tray.xml b/indra/newview/skins/default/xui/zh/panel_side_tray.xml index 625213e376..b706f1839a 100644 --- a/indra/newview/skins/default/xui/zh/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/zh/panel_side_tray.xml @@ -13,7 +13,7 @@ </sidetray_tab> <sidetray_tab description="Find your friends, contacts and people nearby." name="sidebar_people" tab_title="People"> <panel_container name="panel_container"> - <panel label="社團檔案" name="panel_group_info_sidetray"/> + <panel label="群組檔案" name="panel_group_info_sidetray"/> <panel label="Blocked Residents & Objects" name="panel_block_list_sidetray"/> </panel_container> </sidetray_tab> 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 9a59d627d0..808e14f3c3 100644 --- a/indra/newview/skins/default/xui/zh/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/zh/panel_status_bar.xml @@ -16,12 +16,12 @@ L$ [AMT] </panel.string> <panel name="balance_bg"> - <text name="balance" tool_tip="Click to refresh your L$ balance" value="L$20"/> + <text name="balance" tool_tip="點擊以重新更新你的 L$ 帳戶餘額" value="L$20"/> <button label="購買 L$" name="buyL" tool_tip="點擊以購買更多 L$"/> </panel> <text name="TimeText" tool_tip="目前時區(太平洋)"> 24:00 AM PST </text> <button name="media_toggle_btn" tool_tip="開始 / 停止全部媒體(音樂、影片、網頁)"/> - <button name="volume_btn" tool_tip="Global Volume Control"/> + <button name="volume_btn" tool_tip="全域音量控制"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_world_map.xml b/indra/newview/skins/default/xui/zh/panel_world_map.xml index ad28361a7f..b5aa659bf0 100644 --- a/indra/newview/skins/default/xui/zh/panel_world_map.xml +++ b/indra/newview/skins/default/xui/zh/panel_world_map.xml @@ -4,7 +4,7 @@ 載入中... </panel.string> <panel.string name="InvalidLocation"> - Invalid Location + 無效的位置 </panel.string> <panel.string name="world_map_north"> N diff --git a/indra/newview/skins/default/xui/zh/role_actions.xml b/indra/newview/skins/default/xui/zh/role_actions.xml index 534c0f39fc..d5c3096b22 100644 --- a/indra/newview/skins/default/xui/zh/role_actions.xml +++ b/indra/newview/skins/default/xui/zh/role_actions.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <role_actions> <action_set description="These Abilities include powers to add and remove group Members, and allow new Members to join without an invitation." name="Membership"> - <action description="Invite People to this Group" longdescription="Invite People to this Group using the 'Invite' button in the Roles section > Members tab." name="member invite" value="1"/> - <action description="將會員由這個社團中踢出" longdescription="Eject Members from this Group using the 'Eject' button in the Roles section > Members tab. An Owner can eject anyone except another Owner. If you're not an Owner, a Member can be ejected from a group if, and only if, they're only in the Everyone Role, and NO other Roles. To remove Members from Roles, you need to have the 'Remove Members from Roles' Ability." name="member eject" value="2"/> + <action description="邀請他人加入這個群組" longdescription="邀請他人加入這個群組,請按下於角色區段中的成員頁籤中的 '邀請' 按鈕。" name="member invite" value="1"/> + <action description="將會員由這個群組中踢出" longdescription="Eject Members from this Group using the 'Eject' button in the Roles section > Members tab. An Owner can eject anyone except another Owner. If you're not an Owner, a Member can be ejected from a group if, and only if, they're only in the Everyone Role, and NO other Roles. To remove Members from Roles, you need to have the 'Remove Members from Roles' Ability." name="member eject" value="2"/> <action description="Toggle 'Open Enrollment' and change 'Enrollment fee'" longdescription="Toggle 'Open Enrollment' to let new Members join without an invitation, and change the 'Enrollment fee' in the General section." name="member options" value="3"/> </action_set> <action_set description="These Abilities include powers to add, remove, and change group Roles, add and remove Members in Roles, and assign Abilities to Roles." name="Roles"> - <action description="Create new Roles" longdescription="Create new Roles in the Roles section > Roles tab." name="role create" value="4"/> + <action description="創立一個新角色" longdescription="創立一個新角色於角色區段 > 角色頁籤。" name="role create" value="4"/> <action description="刪除角色" longdescription="Delete Roles in the Roles section > Roles tab." name="role delete" value="5"/> <action description="Change Role names, titles, descriptions, and whether Role members are publicly revealed" longdescription="Change Role names, titles, descriptions, and whether Role members are publicly revealed. This is done at the bottom of the the Roles section > Roles tab after selecting a Role." name="role properties" value="6"/> <action description="Assign Members to Assigner's Roles" longdescription="Assign Members to Roles in the list of Assigned Roles (Roles section > Members tab). A Member with this Ability can only add Members to a Role that the assigner is already in." name="role assign member limited" value="7"/> @@ -50,7 +50,7 @@ <action_set description="These Abilities include powers to allow members to return objects and place and move Linden plants. This is useful for Members to clean up litter and do landscaping, but it should also be used with care, because there's no undo for returning objects." name="Parcel Content"> <action description="Return objects owned by group" longdescription="Return objects on group-owned parcels that are owned by the group in About Land > Objects tab." name="land return group owned" value="48"/> <action description="Return objects set to group" longdescription="Return objects on group-owned parcels that are set to the group in About Land > Objects tab." name="land return group set" value="33"/> - <action description="Return non-group objects" longdescription="Return objects on group-owned parcels that are non-group in About Land > Objects tab." name="land return non group" value="34"/> + <action description="退回非群組物件" longdescription="Return objects on group-owned parcels that are non-group in About Land > Objects tab." name="land return non group" value="34"/> <action description="Landscaping using Linden plants" longdescription="Landscaping ability to place and move Linden trees, plants, and grasses. These items can be found in your inventory's Library > Objects folder, or they can be created via the Build menu." name="land gardening" value="35"/> </action_set> <action_set description="These Abilities include powers to deed, modify, and sell group-owned objects. These changes are done in the Build Tools > General tab. Right-click an object and Edit to see its settings." name="Object Management"> @@ -66,8 +66,8 @@ <action description="接收通知與察看過去通知" longdescription="Members in a Role with this Ability can receive Notices and view past Notices in Group > Notices section." name="notices receive" value="43"/> </action_set> <action_set description="These Abilities include powers to allow or restrict access to group chat sessions and group voice chat." name="Chat"> - <action description="Join Group Chat" longdescription="Members in a Role with this Ability can join group chat sessions, for text and voice." name="join group chat" value="16"/> - <action description="Join Group Voice Chat" longdescription="Members in a Role with this Ability can join group voice chat sessions. NOTE: The Join Group Chat ability is required to access the voice chat session." name="join voice chat" value="27"/> - <action description="Moderate Group Chat" longdescription="Members in a Role with this Ability can control access and participation in group voice and text chat sessions." name="moderate group chat" value="37"/> + <action description="加入群組聊天" longdescription="Members in a Role with this Ability can join group chat sessions, for text and voice." name="join group chat" value="16"/> + <action description="加入群組語音聊天" longdescription="Members in a Role with this Ability can join group voice chat sessions. NOTE: The Join Group Chat ability is required to access the voice chat session." name="join voice chat" value="27"/> + <action description="適度成人內容的群組聊天" longdescription="Members in a Role with this Ability can control access and participation in group voice and text chat sessions." name="moderate group chat" value="37"/> </action_set> </role_actions> 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 f28638d93d..adc815fb4b 100644 --- a/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/zh/sidepanel_item_info.xml @@ -52,7 +52,7 @@ </text> <check_box label="覆製" name="CheckEveryoneCopy"/> <text name="GroupLabel"> - 社團: + 群組: </text> <check_box label="分享" name="CheckShareWithGroup" tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."/> <text name="NextOwnerLabel"> 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 f308f2d4d0..5aad4568bd 100644 --- a/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/zh/sidepanel_task_info.xml @@ -7,19 +7,19 @@ Deed </panel.string> <panel.string name="text modify info 1"> - You can modify this object + 你可以修改這個物件 </panel.string> <panel.string name="text modify info 2"> - You can modify these objects + 你可以修改這些物件 </panel.string> <panel.string name="text modify info 3"> - You can't modify this object + 你不可以修改這個物件 </panel.string> <panel.string name="text modify info 4"> - You can't modify these objects + 你不可以修改這些物件 </panel.string> <panel.string name="text modify warning"> - This object has linked parts + 這個物件有聯結到其他部分 </panel.string> <panel.string name="Cost Default"> 價格: L$ @@ -28,13 +28,13 @@ 總價: L$ </panel.string> <panel.string name="Cost Per Unit"> - Price Per: L$ + 單價: 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="(Inworld)"/> @@ -52,9 +52,9 @@ 擁有者: </text> <text name="Group_label"> - 社團: + 群組: </text> - <button name="button set group" tool_tip="Choose a group to share this object's permissions"/> + <button name="button set group" tool_tip="選擇一個群組以分享這個物件的權限"/> <name_box initial_value="載入中..." name="Group Name Proxy"/> <button label="Deed" label_selected="Deed" name="button deed" tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."/> <text name="label click action"> @@ -77,7 +77,7 @@ <check_box label="覆製" name="checkbox allow everyone copy"/> <check_box label="移動" name="checkbox allow everyone move"/> <text name="GroupLabel"> - 社團: + 群組: </text> <check_box label="分享" name="checkbox share with group" tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."/> <text name="NextOwnerLabel"> diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index 53f997017d..0949e61fa1 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -38,25 +38,25 @@ 回存中... </string> <string name="ProgressChangingResolution"> - Changing Resolution... + 變更解析度... </string> <string name="Fullbright"> - Fullbright (Legacy) + 全亮(舊版) </string> <string name="LoginInProgress"> - Logging in. [APP_NAME] may appear frozen. Please wait. + 登入中。[APP_NAME] 可能出現凍結狀態。請耐心稍等。 </string> <string name="LoginInProgressNoFrozen"> - Logging in... + 登入中... </string> <string name="LoginAuthenticating"> - Authenticating + 身份驗證中 </string> <string name="LoginMaintenance"> - Performing account maintenance... + 進行帳戶維護... </string> <string name="LoginAttempt"> - Previous login attempt failed. Logging in, attempt [NUMBER] + 先前企圖嘗試登入失敗。現登入中,嘗試 [NUMBER] </string> <string name="LoginPrecaching"> 世界載入中... @@ -101,7 +101,7 @@ 服裝下載中... </string> <string name="InvalidCertificate"> - The server returned an invalid or corrupt certificate. Please contact the Grid administrator. + 伺服器回傳一個無效果損壞的憑證。請連繫網格管理者。 </string> <string name="CertInvalidHostname"> An invalid hostname was used to access the server, please check your SLURL or Grid hostname. @@ -146,7 +146,7 @@ 你已經被所在的地區中斷聯結。 </string> <string name="SentToInvalidRegion"> - You were sent to an invalid region. + 你被傳送到一個無效的地區。 </string> <string name="TestingDisconnect"> 測試瀏覽器斷線 @@ -155,28 +155,28 @@ 人 </string> <string name="TooltipNoName"> - (no name) + (無名稱) </string> <string name="TooltipOwner"> 擁有者: </string> <string name="TooltipPublic"> - Public + 公開 </string> <string name="TooltipIsGroup"> - (社團) + (群組) </string> <string name="TooltipForSaleL$"> 出售: L$[AMOUNT] </string> <string name="TooltipFlagGroupBuild"> - Group Build + 群組建造 </string> <string name="TooltipFlagNoBuild"> 禁止建造 </string> <string name="TooltipFlagNoEdit"> - 社團建造 + 群組建造 </string> <string name="TooltipFlagNotSafe"> 非安全 @@ -185,7 +185,7 @@ 禁止飛行 </string> <string name="TooltipFlagGroupScripts"> - 社團腳本 + 群組腳本 </string> <string name="TooltipFlagNoScripts"> 禁止腳本 @@ -210,10 +210,10 @@ 瞭解更多有關這個居民 </string> <string name="TooltipAgentMute"> - Click to mute this Resident + 點擊以封鎖這位居民 </string> <string name="TooltipAgentUnmute"> - Click to unmute this Resident + 點擊以解除封鎖這位居民 </string> <string name="TooltipAgentIM"> 點擊開始 IM 這位居民 @@ -222,47 +222,47 @@ 點擊以支付這位居民 </string> <string name="TooltipAgentOfferTeleport"> - Click to offer a teleport request to this Resident + 點擊以送出瞬間傳送邀請給這位居民 </string> <string name="TooltipAgentRequestFriend"> - Click to send a friend request to this Resident + 點擊以送出交友邀請給這位居民 </string> <string name="TooltipGroupUrl"> - Click to view this group's description + 點擊以察看這個群組的描述 </string> <string name="TooltipEventUrl"> - Click to view this event's description + 點擊以察看這個活動的描述 </string> <string name="TooltipClassifiedUrl"> Click to view this classified </string> <string name="TooltipParcelUrl"> - Click to view this parcel's description + 點擊以察看這個地段的描述 </string> <string name="TooltipTeleportUrl"> - Click to teleport to this location + 點擊以傳送到這個位置 </string> <string name="TooltipObjectIMUrl"> - Click to view this object's description + 點擊以察看這個物件的描述 </string> <string name="TooltipMapUrl"> - Click to view this location on a map + 點擊以察看此處在地圖上的位置 </string> <string name="TooltipSLAPP"> - Click to run the secondlife:// command + 點擊以執行 secondlife:// 指令 </string> - <string name="CurrentURL" value="CurrentURL: [CurrentURL]"/> + <string name="CurrentURL" value="目前網址:[CurrentURL]"/> <string name="SLurlLabelTeleport"> 瞬間傳送到 </string> <string name="SLurlLabelShowOnMap"> - Show Map for + 顯示地圖為了 </string> <string name="SLappAgentMute"> - Mute + 封鎖 </string> <string name="SLappAgentUnmute"> - Unmute + 解除封鎖 </string> <string name="SLappAgentIM"> IM @@ -271,7 +271,7 @@ 支付 </string> <string name="SLappAgentOfferTeleport"> - Offer Teleport to + 發給瞬間傳送請求到 </string> <string name="SLappAgentRequestFriend"> 交友要求 @@ -295,7 +295,7 @@ 脫下 </string> <string name="BUTTON_DOCK"> - Dock + 停泊固定 </string> <string name="BUTTON_HELP"> 顯示幫助 @@ -307,22 +307,22 @@ 未發現。 </string> <string name="RetrievingData"> - Retrieving... + 檢索... </string> <string name="ReleaseNotes"> - Release Notes + 釋出版本說明 </string> <string name="LoadingData"> 載入中... </string> <string name="AvatarNameNobody"> - (nobody) + (沒有人) </string> <string name="AvatarNameWaiting"> - (waiting) + (等待中) </string> <string name="AvatarNameMultiple"> - (multiple) + (多個) </string> <string name="GroupNameNone"> (無) @@ -334,25 +334,25 @@ 無錯誤 </string> <string name="AssetErrorRequestFailed"> - Asset request: failed + 資產請求:失敗 </string> <string name="AssetErrorNonexistentFile"> - Asset request: non-existent file + 資產要求:非已存在檔案 </string> <string name="AssetErrorNotInDatabase"> - Asset request: asset not found in database + 資產要求:資產並未發現於資料庫中 </string> <string name="AssetErrorEOF"> - End of file + 檔案結尾 </string> <string name="AssetErrorCannotOpenFile"> - Cannot open file + 無法開啟檔案 </string> <string name="AssetErrorFileNotFound"> - File not found + 檔案未發現 </string> <string name="AssetErrorTCPTimeout"> - File transfer timeout + 檔案傳輸逾時 </string> <string name="AssetErrorCircuitGone"> Circuit gone @@ -370,13 +370,13 @@ 聲音 </string> <string name="calling card"> - calling card + 名片 </string> <string name="landmark"> 地標 </string> <string name="legacy script"> - legacy script + 舊版腳本 </string> <string name="clothing"> 服裝 @@ -427,16 +427,16 @@ 姿勢 </string> <string name="simstate"> - simstate + 模擬器狀態 </string> <string name="favorite"> - favorite + 我的最愛 </string> <string name="symbolic link"> - link + 聯結 </string> <string name="symbolic folder link"> - folder link + 資料夾聯結 </string> <string name="AvatarEditingAppearance"> (外觀編輯中) @@ -448,13 +448,13 @@ 忙碌 </string> <string name="AvatarMuted"> - Blocked + 封鎖的 </string> <string name="anim_express_afraid"> - Afraid + 害怕 </string> <string name="anim_express_anger"> - Angry + 生氣 </string> <string name="anim_away"> Away @@ -472,19 +472,19 @@ Blow Kiss </string> <string name="anim_express_bored"> - Bored + 無聊 </string> <string name="anim_bow"> Bow </string> <string name="anim_clap"> - Clap + 拍手 </string> <string name="anim_courtbow"> Court Bow </string> <string name="anim_express_cry"> - Cry + 哭泣 </string> <string name="anim_dance1"> Dance 1 @@ -541,19 +541,19 @@ Kiss My Butt </string> <string name="anim_express_kiss"> - Kiss + 親吻 </string> <string name="anim_laugh_short"> - Laugh + 笑 </string> <string name="anim_musclebeach"> Muscle Beach </string> <string name="anim_no_unhappy"> - No (Unhappy) + 不(不快樂) </string> <string name="anim_no_head"> - No + 不 </string> <string name="anim_nyanya"> Nya-nya-nya @@ -598,10 +598,10 @@ Roundhouse Kick </string> <string name="anim_express_sad"> - Sad + 傷心 </string> <string name="anim_salute"> - Salute + 敬禮 </string> <string name="anim_shout"> Shout @@ -610,7 +610,7 @@ Shrug </string> <string name="anim_express_smile"> - Smile + 微笑 </string> <string name="anim_smoke_idle"> Smoke Idle @@ -622,7 +622,7 @@ Smoke Throw Down </string> <string name="anim_express_surprise"> - Surprise + 驚喜 </string> <string name="anim_sword_strike_r"> Sword Strike @@ -637,22 +637,22 @@ Wave </string> <string name="anim_whisper"> - Whisper + 耳語 </string> <string name="anim_whistle"> - Whistle + 吹口哨 </string> <string name="anim_express_wink"> - Wink + 眨眼 </string> <string name="anim_wink_hollywood"> - Wink (Hollywood) + 眨眼(好萊塢) </string> <string name="anim_express_worry"> - Worry + 擔心 </string> <string name="anim_yes_happy"> - Yes (Happy) + 是(快樂) </string> <string name="anim_yes_head"> 是 @@ -679,25 +679,25 @@ Can't find ROOT or JOINT. </string> <string name="whisper"> - whispers: + 低語: </string> <string name="shout"> - shouts: + 吶喊: </string> <string name="ringing"> - Connecting to in-world Voice Chat... + 聯接到虛擬世界的語音功能中... </string> <string name="connected"> - Connected + 已聯接 </string> <string name="unavailable"> - Voice not available at your current location + 語音聊天功能於你目前所在的位置無法使用 </string> <string name="hang_up"> - Disconnected from in-world Voice Chat + 虛擬世界中的語音聊天中斷 </string> <string name="reconnect_nearby"> - You will now be reconnected to Nearby Voice Chat + 現在你將重新聯接到附近的語音聊天 </string> <string name="ScriptQuestionCautionChatGranted"> '[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS]. @@ -706,7 +706,7 @@ '[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS]. </string> <string name="ScriptTakeMoney"> - Take Linden dollars (L$) from you + 由你身上拿走林登幣(L$) </string> <string name="ActOnControlInputs"> Act on your control inputs @@ -730,25 +730,25 @@ Add and remove joints with other objects </string> <string name="ChangePermissions"> - Change its permissions + 變更它的權限 </string> <string name="TrackYourCamera"> - Track your camera + 追蹤你的攝影機 </string> <string name="ControlYourCamera"> - Control your camera + 控制你的攝影機 </string> <string name="NotConnected"> - Not Connected + 未聯接 </string> <string name="SIM_ACCESS_PG"> - 一般 + 一般普級 </string> <string name="SIM_ACCESS_MATURE"> - Moderate + 適度成人 </string> <string name="SIM_ACCESS_ADULT"> - 成人 + 完全成人 </string> <string name="SIM_ACCESS_DOWN"> 離線 @@ -796,16 +796,16 @@ Bitmap 圖像 </string> <string name="avi_movie_file"> - AVI 影片檔案 + AVI 視頻檔案 </string> <string name="xaf_animation_file"> XAF Anim File </string> <string name="xml_file"> - XML File + XML 檔案 </string> <string name="raw_file"> - RAW File + RAW 檔案 </string> <string name="compressed_image_files"> 壓縮的圖像 @@ -868,13 +868,13 @@ 裙子 </string> <string name="alpha"> - Alpha + 半透明 </string> <string name="tattoo"> 刺青 </string> <string name="physics"> - Physics + 身體物理 </string> <string name="invalid"> 無效 @@ -910,13 +910,13 @@ 裙子未穿 </string> <string name="alpha_not_worn"> - Alpha not worn + 半透明未穿 </string> <string name="tattoo_not_worn"> 刺青未穿 </string> <string name="physics_not_worn"> - Physics not worn + 身體物理未穿 </string> <string name="invalid_not_worn"> 無效 @@ -961,13 +961,13 @@ 創造新裙子 </string> <string name="create_new_alpha"> - Create new alpha + 創造新半透明 </string> <string name="create_new_tattoo"> 創造新刺青 </string> <string name="create_new_physics"> - Create new physics + 創造新身體物理 </string> <string name="create_new_invalid"> 無效 @@ -982,10 +982,10 @@ 確定 </string> <string name="GroupNotifyGroupNotice"> - 社團通知 + 群組通知 </string> <string name="GroupNotifyGroupNotices"> - 社團通知 + 群組通知 </string> <string name="GroupNotifySentBy"> 送出由 @@ -1012,34 +1012,34 @@ 你有約 %d 通知 </string> <string name="BodyPartsRightArm"> - Right Arm + 右臂 </string> <string name="BodyPartsHead"> 頭部 </string> <string name="BodyPartsLeftArm"> - Left Arm + 左臂 </string> <string name="BodyPartsLeftLeg"> - Left Leg + 左腿 </string> <string name="BodyPartsTorso"> 軀幹 </string> <string name="BodyPartsRightLeg"> - Right Leg + 右腿 </string> <string name="GraphicsQualityLow"> - Low + 低 </string> <string name="GraphicsQualityMid"> - Mid + 中 </string> <string name="GraphicsQualityHigh"> - High + 高 </string> <string name="LeaveMouselook"> - Press ESC to return to World View + 按下 ESC 鍵回復到世界的視角 </string> <string name="InventoryNoMatchingItems"> Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]. @@ -1053,19 +1053,19 @@ <string name="InventoryNoTexture"> You do not have a copy of this texture in your inventory </string> - <string name="no_transfer" value="(no transfer)"/> - <string name="no_modify" value="(no modify)"/> - <string name="no_copy" value="(no copy)"/> - <string name="worn" value="(worn)"/> - <string name="link" value="(link)"/> - <string name="broken_link" value="(broken_link)"/> + <string name="no_transfer" value="(禁止轉讓)"/> + <string name="no_modify" value="(禁止修改)"/> + <string name="no_copy" value="(禁止複製)"/> + <string name="worn" value="(已穿)"/> + <string name="link" value="(聯結)"/> + <string name="broken_link" value="(損壞的聯結)"/> <string name="LoadingContents"> 內容載入中... </string> <string name="NoContents"> - No contents + 無內容 </string> - <string name="WornOnAttachmentPoint" value="(worn on [ATTACHMENT_POINT])"/> + <string name="WornOnAttachmentPoint" value="(已穿 [ATTACHMENT_POINT])"/> <string name="ActiveGesture" value="[GESLABEL] (active)"/> <string name="PermYes"> 是 @@ -1084,7 +1084,7 @@ <string name="ViewAllGestures" value="察看全部 >>"/> <string name="GetMoreGestures" value="取得更多 >>"/> <string name="Animations" value="動作,"/> - <string name="Calling Cards" value="Calling Cards,"/> + <string name="Calling Cards" value="名片,"/> <string name="Clothing" value="服裝,"/> <string name="Gestures" value="姿勢,"/> <string name="Landmarks" value="地標,"/> @@ -1093,14 +1093,17 @@ <string name="Scripts" value="腳本,"/> <string name="Sounds" value="聲音,"/> <string name="Textures" value="材質,"/> - <string name="Snapshots" value="Snapshots,"/> + <string name="Snapshots" value="快照,"/> <string name="No Filters" value="No"/> <string name="Since Logoff" value="- 自上次登出"/> <string name="InvFolder My Inventory"> 我的收納區 </string> + <string name="InvFolder My Favorites"> + 我的最愛 + </string> <string name="InvFolder Library"> - Library + 資源庫 </string> <string name="InvFolder Textures"> 材質 @@ -1109,7 +1112,7 @@ 聲音 </string> <string name="InvFolder Calling Cards"> - Calling Cards + 名片 </string> <string name="InvFolder Landmarks"> 地標 @@ -1148,7 +1151,7 @@ Lost And Found </string> <string name="InvFolder Uncompressed Sounds"> - Uncompressed Sounds + 無壓縮聲音 </string> <string name="InvFolder Animations"> 動作 @@ -1157,10 +1160,10 @@ 姿勢 </string> <string name="InvFolder Favorite"> - My Favorites + 我的最愛 </string> <string name="InvFolder favorite"> - My Favorites + 我的最愛 </string> <string name="InvFolder Current Outfit"> 目前裝扮 @@ -1217,34 +1220,34 @@ Ctrl </string> <string name="Chest"> - Chest + 胸部 </string> <string name="Skull"> - Skull + 頭顱 </string> <string name="Left Shoulder"> - Left Shoulder + 左肩 </string> <string name="Right Shoulder"> - Right Shoulder + 右肩 </string> <string name="Left Hand"> - Left Hand + 左手 </string> <string name="Right Hand"> - Right Hand + 右手 </string> <string name="Left Foot"> - Left Foot + 左腳 </string> <string name="Right Foot"> - Right Foot + 右腳 </string> <string name="Spine"> - Spine + 脊椎 </string> <string name="Pelvis"> - Pelvis + 骨盆 </string> <string name="Mouth"> 嘴 @@ -1268,46 +1271,46 @@ 鼻子 </string> <string name="R Upper Arm"> - R Upper Arm + 右上臂 </string> <string name="R Forearm"> - R Forearm + 右前臂 </string> <string name="L Upper Arm"> - L Upper Arm + 左上臂 </string> <string name="L Forearm"> - L Forearm + 左前臂 </string> <string name="Right Hip"> - Right Hip + 右臀 </string> <string name="R Upper Leg"> - R Upper Leg + 右大腿 </string> <string name="R Lower Leg"> - R Lower Leg + 右小腿 </string> <string name="Left Hip"> - Left Hip + 左臀 </string> <string name="L Upper Leg"> - L Upper Leg + 左大腿 </string> <string name="L Lower Leg"> - L Lower Leg + 左小腿 </string> <string name="Stomach"> - Stomach + 腹肌 </string> <string name="Left Pec"> - Left Pec + 左胸肌 </string> <string name="Right Pec"> - Right Pec + 右胸肌 </string> <string name="Invalid Attachment"> - Invalid Attachment Point + 無效的附件聯接點 </string> <string name="YearsMonthsOld"> [AGEYEARS] [AGEMONTHS] old @@ -1325,7 +1328,7 @@ [AGEDAYS] old </string> <string name="TodayOld"> - 高日剛加入 + 今日剛加入 </string> <string name="AgeYearsA"> [COUNT] 年 @@ -1394,40 +1397,40 @@ No Payment Info On File </string> <string name="AgeVerified"> - Age-verified + 已年齡驗證 </string> <string name="NotAgeVerified"> - Not Age-verified + 未年齡驗證 </string> <string name="Center 2"> - Center 2 + 中央 2 </string> <string name="Top Right"> - Top Right + 右上 </string> <string name="Top"> - Top + 上方 </string> <string name="Top Left"> - Top Left + 左上 </string> <string name="Center"> - Center + 中央 </string> <string name="Bottom Left"> - Bottom Left + 左下 </string> <string name="Bottom"> - Bottom + 下方 </string> <string name="Bottom Right"> - Bottom Right + 右下 </string> <string name="CompileQueueDownloadedCompiling"> - Downloaded, now compiling + 已下載,現在進行編譯中 </string> <string name="CompileQueueScriptNotFound"> - Script not found on server. + 伺服器上未發現腳本。 </string> <string name="CompileQueueProblemDownloading"> Problem downloading @@ -1442,16 +1445,16 @@ Unknown failure to download </string> <string name="CompileQueueTitle"> - Recompilation Progress + 重新編譯進度 </string> <string name="CompileQueueStart"> - recompile + 重新編譯 </string> <string name="ResetQueueTitle"> - Reset Progress + 重設進度 </string> <string name="ResetQueueStart"> - reset + 重設 </string> <string name="RunQueueTitle"> 設定執行中程序 @@ -1478,19 +1481,19 @@ 腳本(物件超出範圍) </string> <string name="GodToolsObjectOwnedBy"> - Object [OBJECT] owned by [OWNER] + 物件 [OBJECT] 為 [OWNER] 所擁有 </string> <string name="GroupsNone"> 無 </string> - <string name="Group" value="(社團)"/> + <string name="Group" value="(群組)"/> <string name="Unknown"> (未知) </string> <string name="SummaryForTheWeek" value="Summary for this week, beginning on"/> <string name="NextStipendDay" value="The next stipend day is"/> <string name="GroupIndividualShare" value="Group Individual Share"/> - <string name="GroupColumn" value="社團"/> + <string name="GroupColumn" value="群組"/> <string name="Balance"> Balance </string> @@ -1531,7 +1534,7 @@ Allowed Residents: ([ALLOWEDAGENTS], max [MAXACCESS]) </string> <string name="RegionInfoAllowedGroups"> - Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS]) + 允許的群群組:([ALLOWEDGROUPS],最大 [MAXACCESS]) </string> <string name="ScriptLimitsParcelScriptMemory"> 地段腳本記憶體 @@ -1546,7 +1549,7 @@ Memory used: [COUNT] kb </string> <string name="ScriptLimitsParcelScriptURLs"> - Parcel Script URLs + 地段腳本 URLs </string> <string name="ScriptLimitsURLsUsed"> URLs used: [COUNT] out of [MAX]; [AVAILABLE] available @@ -1558,7 +1561,7 @@ Error requesting information </string> <string name="ScriptLimitsRequestNoParcelSelected"> - No Parcel Selected + 無地段被選擇 </string> <string name="ScriptLimitsRequestWrongRegion"> Error: script information is only available in your current region @@ -1573,46 +1576,46 @@ Sitting On </string> <string name="ATTACH_CHEST"> - Chest + 胸部 </string> <string name="ATTACH_HEAD"> 頭部 </string> <string name="ATTACH_LSHOULDER"> - Left Shoulder + 左肩 </string> <string name="ATTACH_RSHOULDER"> - Right Shoulder + 右肩 </string> <string name="ATTACH_LHAND"> - Left Hand + 左手 </string> <string name="ATTACH_RHAND"> - Right Hand + 右手 </string> <string name="ATTACH_LFOOT"> - Left Foot + 左腳 </string> <string name="ATTACH_RFOOT"> - Right Foot + 右腳 </string> <string name="ATTACH_BACK"> - Back + 背部 </string> <string name="ATTACH_PELVIS"> - Pelvis + 骨盆 </string> <string name="ATTACH_MOUTH"> - Mouth + 嘴巴 </string> <string name="ATTACH_CHIN"> 下巴 </string> <string name="ATTACH_LEAR"> - Left Ear + 左耳 </string> <string name="ATTACH_REAR"> - Right Ear + 右耳 </string> <string name="ATTACH_LEYE"> 左眼 @@ -1624,43 +1627,43 @@ 鼻子 </string> <string name="ATTACH_RUARM"> - Right Upper Arm + 右上臂 </string> <string name="ATTACH_RLARM"> - Right Lower Arm + 右前臂 </string> <string name="ATTACH_LUARM"> - Left Upper Arm + 左上臂 </string> <string name="ATTACH_LLARM"> - Left Lower Arm + 左前臂 </string> <string name="ATTACH_RHIP"> - Right Hip + 右臀 </string> <string name="ATTACH_RULEG"> - Right Upper Leg + 右大腿 </string> <string name="ATTACH_RLLEG"> - Right Lower Leg + 右小腿 </string> <string name="ATTACH_LHIP"> - Left Hip + 左臀 </string> <string name="ATTACH_LULEG"> - Left Upper Leg + 左大腿 </string> <string name="ATTACH_LLLEG"> - Left Lower Leg + 左小腿 </string> <string name="ATTACH_BELLY"> - Belly + 腹部 </string> <string name="ATTACH_RPEC"> - Right Pec + 右胸肌 </string> <string name="ATTACH_LPEC"> - Left Pec + 左胸肌 </string> <string name="ATTACH_HUD_CENTER_2"> HUD Center 2 @@ -1699,13 +1702,13 @@ [mthnum,datetime,slt]/[day,datetime,slt] </string> <string name="PanelContentsTooltip"> - Content of object + 物件的內容 </string> <string name="PanelContentsNewScript"> - New Script + 新腳本 </string> <string name="BusyModeResponseDefault"> - The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing. + 你傳送訊息的居民目前處於忙碌模式中,這意味著他要求不被打擾。你所傳的訊息仍將會留存並顯示於 IM 面板上供他稍後時查閱。 </string> <string name="MuteByName"> (由名稱) @@ -1717,22 +1720,22 @@ (物件) </string> <string name="MuteGroup"> - (社團) + (群組) </string> <string name="MuteExternal"> - (External) + (外部) </string> <string name="RegionNoCovenant"> - There is no Covenant provided for this Estate. + 此領地未提供任何契約要求。 </string> <string name="RegionNoCovenantOtherOwner"> There is no Covenant provided for this Estate. The land on this estate is being sold by the Estate owner, not Linden Lab. Please contact the Estate Owner for sales details. </string> - <string name="covenant_last_modified" value="Last Modified: "/> + <string name="covenant_last_modified" value="最後修改於:"/> <string name="none_text" value="(無)"/> <string name="never_text" value="(絕不)"/> <string name="GroupOwned"> - 社團所擁有 + 群組所擁有 </string> <string name="Public"> 公開 @@ -1741,7 +1744,7 @@ Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile </string> <string name="ClassifiedUpdateAfterPublish"> - (will update after publish) + (將於發布後自動更新) </string> <string name="NoPicksClassifiedsText"> You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified. @@ -1762,10 +1765,10 @@ An object named </string> <string name="InvOfferOwnedByGroup"> - owned by the group + 群組所擁有 </string> <string name="InvOfferOwnedByUnknownGroup"> - owned by an unknown group + 由一個未知的群組所擁有 </string> <string name="InvOfferOwnedBy"> owned by @@ -1952,7 +1955,7 @@ Linden Location </string> <string name="Adult"> - 成人 + 完全成人 </string> <string name="Arts&Culture"> Arts & Culture @@ -2057,7 +2060,7 @@ If this message persists, restart your computer. Would you like to send a crash report? </string> <string name="MBAlert"> - Notification + 通知 </string> <string name="MBNoDirectX"> [APP_NAME] is unable to detect DirectX 9.0b or greater. @@ -2066,7 +2069,7 @@ Would you like to send a crash report? Do you wish to continue? </string> <string name="MBWarning"> - Warning + 警告 </string> <string name="MBNoAutoUpdate"> Automatic updating is not yet implemented for Linux. @@ -2076,7 +2079,7 @@ Please download the latest version from www.secondlife.com. RegisterClass failed </string> <string name="MBError"> - Error + 錯誤 </string> <string name="MBFullScreenErr"> Unable to run fullscreen at [WIDTH] x [HEIGHT]. @@ -3574,13 +3577,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Health </string> <string name="LocationCtrlAdultIconTooltip"> - 成人地區 + 完全成人地區 </string> <string name="LocationCtrlModerateIconTooltip"> - Moderate Region + 適度成人地區 </string> <string name="LocationCtrlGeneralIconTooltip"> - 一般地區 + 一般普級地區 </string> <string name="UpdaterWindowTitle"> [APP_NAME] 更新 @@ -3637,10 +3640,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Your text chat has been disabled by a Group Moderator. </string> <string name="IM_default_text_label"> - Click here to instant message. + 點擊此處以傳送即時訊息。 </string> <string name="IM_to_label"> - To + 至 </string> <string name="IM_moderator_label"> (Moderator) @@ -3739,10 +3742,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Error while moderating. </string> <string name="removed"> - You have been removed from the group. + 你已經由群組中被移除。 </string> <string name="removed_from_group"> - You have been removed from the group. + 你已經由群組中被移除。 </string> <string name="close_on_no_ability"> You no longer have the ability to be in the chat session. @@ -3790,10 +3793,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. for deeding land </string> <string name="to create a group"> - 以創造社團 + 以創造群組 </string> <string name="to join a group"> - 以加入社團 + 以加入群組 </string> <string name="to upload"> 以上傳 @@ -3823,7 +3826,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Officers </string> <string name="group_role_owners"> - Owners + 擁有者 </string> <string name="group_member_status_online"> 上線 @@ -3873,16 +3876,16 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. 新裙子 </string> <string name="New Alpha"> - New Alpha + 新半透明 </string> <string name="New Tattoo"> 新刺青 </string> <string name="New Physics"> - New Physics + 新身體物理 </string> <string name="Invalid Wearable"> - Invalid Wearable + 無效的可穿裝扮 </string> <string name="New Gesture"> 新姿勢 diff --git a/indra/newview/skins/default/xui/zh/teleport_strings.xml b/indra/newview/skins/default/xui/zh/teleport_strings.xml index b18eb4a390..ffb4c903bb 100644 --- a/indra/newview/skins/default/xui/zh/teleport_strings.xml +++ b/indra/newview/skins/default/xui/zh/teleport_strings.xml @@ -3,25 +3,25 @@ <message_set name="errors"> <message name="invalid_tport"> Problem encountered processing your teleport request. You may need to log back in before you can teleport. -If you continue to get this message, please check the [SUPPORT_SITE]. +如果你持續得到此訊息,請查閱 [SUPPORT_SITE]。 </message> <message name="invalid_region_handoff"> Problem encountered processing your region crossing. You may need to log back in before you can cross regions. -If you continue to get this message, please check the [SUPPORT_SITE]. +如果你持續得到此訊息,請查閱 [SUPPORT_SITE]。 </message> <message name="blocked_tport"> - Sorry, teleport is currently blocked. Try again in a moment. -If you still cannot teleport, please log out and log back in to resolve the problem. + 抱歉,目前瞬間傳送已被阻擋。請稍後再試。 +如果你仍無法進行瞬間傳送,請登出後重新入來解決此一問題。 </message> <message name="nolandmark_tport"> - Sorry, but system was unable to locate landmark destination. + 抱歉,不過系統無法找到地標所在目的地。 </message> <message name="timeout_tport"> - Sorry, but system was unable to complete the teleport connection. -Try again in a moment. + 抱歉,不過系統無法完成瞬間傳送的聯接。 +請稍後再試。 </message> <message name="noaccess_tport"> - Sorry, you do not have access to that teleport destination. + 抱歉,你並沒有權限進入要瞬間傳送的目的地。 </message> <message name="missing_attach_tport"> Your attachments have not arrived yet. Try waiting for a few more seconds or log out and back in again before attempting to teleport. @@ -47,7 +47,7 @@ Try again in a moment. Sending to destination. </message> <message name="redirecting"> - Redirecting to different location. + 重新導向至不同位置。 </message> <message name="relaying"> Relaying to destination. diff --git a/indra/newview/skins/minimal/xui/da/notifications.xml b/indra/newview/skins/minimal/xui/da/notifications.xml index e77eeee8df..3d003ea3b3 100644 --- a/indra/newview/skins/minimal/xui/da/notifications.xml +++ b/indra/newview/skins/minimal/xui/da/notifications.xml @@ -1327,7 +1327,7 @@ Prøv igen om lidt. No valid parcel could be found. </notification> <notification name="ObjectGiveItem"> - Et objekt ved navn <nolink>[OBJECTFROMNAME]</nolink> ejet af [NAME_SLURL] tilbyder dig [ITEM_SLURL]. For at bruge denne genstand skal du skifte til avanceret tilstand, hvor du kan finde genstanden i din beholdning. Ønsker du at logge ud for at skifte tilstand? Valg af tilstand findes på login skærmbilledet. + Et objekt ved navn <nolink>[OBJECTFROMNAME]</nolink> ejet af [NAME_SLURL] tilbyder dig <nolink>[ITEM_SLURL]</nolink>. For at bruge denne genstand skal du skifte til avanceret tilstand, hvor du kan finde genstanden i din beholdning. Ønsker du at logge ud for at skifte tilstand? Valg af tilstand findes på login skærmbilledet. <form name="form"> <button name="Keep" text="Behold genstand"/> <button name="Discard" text="Afvis genstand"/> diff --git a/indra/newview/skins/minimal/xui/de/notifications.xml b/indra/newview/skins/minimal/xui/de/notifications.xml index 1eee1d1c9b..9abf8cdbb9 100644 --- a/indra/newview/skins/minimal/xui/de/notifications.xml +++ b/indra/newview/skins/minimal/xui/de/notifications.xml @@ -9,7 +9,7 @@ </form> </notification> <notification name="ObjectGiveItem"> - Ein Objekt namens <nolink>[OBJECTFROMNAME]</nolink>, das [NAME_SLURL] gehört, bietet Ihnen [ITEM_SLURL] an. Zur Verwendung dieses Artikels müssen Sie in den erweiterten Modus umschalten, wo Sie den Artikel in Ihrem Inventar finden werden. Um in den erweiterten Modus umzuschalten, beenden Sie die Anwendung, starten Sie sie neu und ändern Sie die Moduseinstellung auf dem Anmeldebildschirm. + Ein Objekt namens <nolink>[OBJECTFROMNAME]</nolink>, das [NAME_SLURL] gehört, bietet Ihnen <nolink>[ITEM_SLURL]</nolink> an. Zur Verwendung dieses Artikels müssen Sie in den erweiterten Modus umschalten, wo Sie den Artikel in Ihrem Inventar finden werden. Um in den erweiterten Modus umzuschalten, beenden Sie die Anwendung, starten Sie sie neu und ändern Sie die Moduseinstellung auf dem Anmeldebildschirm. <form name="form"> <button name="Keep" text="Artikel behalten"/> <button name="Discard" text="Artikel ablehnen"/> diff --git a/indra/newview/skins/minimal/xui/en/main_view.xml b/indra/newview/skins/minimal/xui/en/main_view.xml index ec2683880a..0ce6cbc984 100644 --- a/indra/newview/skins/minimal/xui/en/main_view.xml +++ b/indra/newview/skins/minimal/xui/en/main_view.xml @@ -187,9 +187,9 @@ name="status_bar_container" tab_stop="false" height="30" - left="-120" + left="-160" top="0" - width="120" + width="160" visible="false"/> <panel follows="top|bottom" height="500" diff --git a/indra/newview/skins/minimal/xui/en/notifications.xml b/indra/newview/skins/minimal/xui/en/notifications.xml index 84da9472cc..7b7cdb5fc6 100644 --- a/indra/newview/skins/minimal/xui/en/notifications.xml +++ b/indra/newview/skins/minimal/xui/en/notifications.xml @@ -24,7 +24,7 @@ icon="notify.tga" name="ObjectGiveItem" type="offer"> - An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLURL] is offering you [ITEM_SLURL]. Using this item requires you to switch to Advanced mode where you will find the item in your Inventory. To switch to Advanced mode, quit and restart this application and change the mode setting on the login screen. + An object named <nolink>[OBJECTFROMNAME]</nolink> owned by [NAME_SLURL] is offering you <nolink>[ITEM_SLURL]</nolink>. Using this item requires you to switch to Advanced mode where you will find the item in your Inventory. To switch to Advanced mode, quit and restart this application and change the mode setting on the login screen. <form name="form"> <button index="0" diff --git a/indra/newview/skins/minimal/xui/en/panel_login.xml b/indra/newview/skins/minimal/xui/en/panel_login.xml index d89a0c6be1..40d2df78e1 100644 --- a/indra/newview/skins/minimal/xui/en/panel_login.xml +++ b/indra/newview/skins/minimal/xui/en/panel_login.xml @@ -118,16 +118,33 @@ label="Remember password" name="connect_btn" top="35" width="90" /> - <menu_button -left_pad="10" -top="35" -width="80" -height="23" -label="Mode ▲" -name="mode_menu" -tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." -menu_filename="menu_mode_change.xml" - /> + <text + follows="left|bottom" + font="SansSerifSmall" + height="15" + left_pad="10" + name="mode_selection_text" + top="20" + width="130"> + Mode: + </text> + <combo_box + follows="left|bottom" + height="23" + max_chars="128" + tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." + top_pad="0" + name="mode_combo" + width="110"> + <combo_box.item + label="Basic" + name="Basic" + value="settings_minimal.xml" /> + <combo_box.item + label="Advanced" + name="Advanced" + value="" /> + </combo_box> </layout_panel> <layout_panel tab_stop="false" diff --git a/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml index e50911b8d2..cb9acd4d6a 100644 --- a/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml @@ -63,7 +63,7 @@ width="31" /> mouse_opaque="false" name="location_combo" top_delta="0" - width="390"> + width="350"> </location_input> <icon follows="right" height="20" diff --git a/indra/newview/skins/minimal/xui/en/panel_status_bar.xml b/indra/newview/skins/minimal/xui/en/panel_status_bar.xml index 42e6f30d48..874a8b47e0 100644 --- a/indra/newview/skins/minimal/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/minimal/xui/en/panel_status_bar.xml @@ -12,7 +12,7 @@ name="status" top="19" tab_stop="false" - width="120"> + width="160"> <panel.string name="packet_loss_tooltip"> Packet Loss @@ -33,18 +33,27 @@ name="buycurrencylabel"> L$ [AMT] </panel.string> - <menu_button - follows="right|top" - image_color="0 0 0 0" - hover_glow_amount="0" - left="5" - top="7" - width="55" - height="18" - label="Mode ▼" - tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." - menu_filename="menu_mode_change.xml" - /> + <combo_box + follows="right|top" + left="5" + drop_down_button.image_color="0 0 0 0" + drop_down_button.hover_glow_amount="0" + drop_down_button.pad_right="0" + top="7" + width="95" + height="20" + name="mode_combo" + tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features." + > + <combo_box.item + label="Basic Mode" + name="Basic" + value="settings_minimal.xml" /> + <combo_box.item + label="Advanced Mode" + name="Advanced" + value="" /> + </combo_box> <button follows="right|top" height="16" @@ -53,7 +62,7 @@ image_pressed="Pause_Press" image_pressed_selected="Play_Press" is_toggle="true" - left="65" + left_pad="5" top="7" name="media_toggle_btn" tool_tip="Start/Stop All Media (Music, Video, Web pages)" diff --git a/indra/newview/skins/minimal/xui/es/notifications.xml b/indra/newview/skins/minimal/xui/es/notifications.xml index b08ebb5f76..78b617c429 100644 --- a/indra/newview/skins/minimal/xui/es/notifications.xml +++ b/indra/newview/skins/minimal/xui/es/notifications.xml @@ -9,7 +9,7 @@ </form> </notification> <notification name="ObjectGiveItem"> - Un objeto de nombre <nolink>[OBJECTFROMNAME]</nolink>, propiedad de [NAME_SLURL], te ofrece un/a [ITEM_SLURL]. Para utilizar este ítem, cambia al modo Avanzado y búscalo en el inventario. Para cambiar al modo Avanzado, sal de la aplicación, reiníciala y cambia el ajuste de modo en la pantalla de inicio de sesión. + Un objeto de nombre <nolink>[OBJECTFROMNAME]</nolink>, propiedad de [NAME_SLURL], te ofrece un/a <nolink>[ITEM_SLURL]</nolink>. Para utilizar este ítem, cambia al modo Avanzado y búscalo en el inventario. Para cambiar al modo Avanzado, sal de la aplicación, reiníciala y cambia el ajuste de modo en la pantalla de inicio de sesión. <form name="form"> <button name="Keep" text="Conservar ítem"/> <button name="Discard" text="Rechazar ítem"/> diff --git a/indra/newview/skins/minimal/xui/fr/notifications.xml b/indra/newview/skins/minimal/xui/fr/notifications.xml index 41dd42c39f..05fa03cdc1 100644 --- a/indra/newview/skins/minimal/xui/fr/notifications.xml +++ b/indra/newview/skins/minimal/xui/fr/notifications.xml @@ -9,7 +9,7 @@ </form> </notification> <notification name="ObjectGiveItem"> - Un objet nommé <nolink>[OBJECTFROMNAME]</nolink> appartenant à [NAME_SLURL] vous offre [ITEM_SLURL]. Pour utiliser cet article, vous devez passer en mode Avancé. L'article se trouve dans votre inventaire. Pour changer de mode, quittez l'application, redémarrez-la, puis sélectionnez un autre mode sur l'écran de connexion. + Un objet nommé <nolink>[OBJECTFROMNAME]</nolink> appartenant à [NAME_SLURL] vous offre <nolink>[ITEM_SLURL]</nolink>. Pour utiliser cet article, vous devez passer en mode Avancé. L'article se trouve dans votre inventaire. Pour changer de mode, quittez l'application, redémarrez-la, puis sélectionnez un autre mode sur l'écran de connexion. <form name="form"> <button name="Keep" text="Garder l'article"/> <button name="Discard" text="Refuser l'article"/> diff --git a/indra/newview/skins/minimal/xui/it/notifications.xml b/indra/newview/skins/minimal/xui/it/notifications.xml index 05e13bc4f3..998e38ff5a 100644 --- a/indra/newview/skins/minimal/xui/it/notifications.xml +++ b/indra/newview/skins/minimal/xui/it/notifications.xml @@ -2418,7 +2418,7 @@ Riprova tra qualche istante. Non è stato trovato nessun territorio valido. </notification> <notification name="ObjectGiveItem"> - Un oggetto denominato <nolink>[OBJECTFROMNAME]</nolink> di proprietà di [NAME_SLURL] ti ha offerto [ITEM_SLURL]: Per usare questo oggetto è necessario passare alla modalità Avanzata e cercarlo nell'Inventario. Per passare alla modalità Avanzata, esci e riavvia l'applicazione e cambia le impostazioni della modalità nella schermata di accesso. + Un oggetto denominato <nolink>[OBJECTFROMNAME]</nolink> di proprietà di <nolink>[ITEM_SLURL]</nolink> ti ha offerto [ITEM_SLURL]: Per usare questo oggetto è necessario passare alla modalità Avanzata e cercarlo nell'Inventario. Per passare alla modalità Avanzata, esci e riavvia l'applicazione e cambia le impostazioni della modalità nella schermata di accesso. <form name="form"> <button name="Keep" text="Mantieni oggetto"/> <button name="Discard" text="Rifiuta oggetto"/> diff --git a/indra/newview/skins/minimal/xui/ja/notifications.xml b/indra/newview/skins/minimal/xui/ja/notifications.xml index 6ad0ed1ac6..43934c9317 100644 --- a/indra/newview/skins/minimal/xui/ja/notifications.xml +++ b/indra/newview/skins/minimal/xui/ja/notifications.xml @@ -2465,7 +2465,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ 有効な区画が見つかりませんでした。 </notification> <notification name="ObjectGiveItem"> - [NAME_SLURL] が所有する <nolink>[OBJECTFROMNAME]</nolink> という名前のオブジェクトが、あなたに [ITEM_SLURL] を渡そうとしています。このアイテムを使うにはアドバンスモードへの切り替えが必要です。アドバンスモードでログインしなおすと、あなたの持ち物にこのアイテムが見つかります。アドバンスモードに切り替えるには、このアプリケーションを終了して再起動し、ログイン画面でモード設定を変更してください。 + [NAME_SLURL] が所有する <nolink>[OBJECTFROMNAME]</nolink> という名前のオブジェクトが、あなたに <nolink>[ITEM_SLURL]</nolink> を渡そうとしています。このアイテムを使うにはアドバンスモードへの切り替えが必要です。アドバンスモードでログインしなおすと、あなたの持ち物にこのアイテムが見つかります。アドバンスモードに切り替えるには、このアプリケーションを終了して再起動し、ログイン画面でモード設定を変更してください。 <form name="form"> <button name="Keep" text="アイテムを受け取る"/> <button name="Discard" text="アイテムを拒否する"/> diff --git a/indra/newview/skins/minimal/xui/pl/notifications.xml b/indra/newview/skins/minimal/xui/pl/notifications.xml index 6e62478ed0..6475a37465 100644 --- a/indra/newview/skins/minimal/xui/pl/notifications.xml +++ b/indra/newview/skins/minimal/xui/pl/notifications.xml @@ -2384,7 +2384,7 @@ Spróbuj ponowanie za kilka minut. Nieważana posiadłość. </notification> <notification name="ObjectGiveItem"> - Obiekt o nazwie <nolink>[OBJECTFROMNAME]</nolink>, którego właścicielem jest [NAME_SLURL] oferuje Tobie [ITEM_SLURL]. Korzystanie z tego obieku wymaga przelączenia się na tryb zaawansowany, w którym będzie można odszukać obiekt w Twojej Szafie. W celu przełączenia trybu życia na zaawansowany, zamknij i uruchom ponownie aplikację. Przed ponownym zalogowaniem zmień tryb życia na ekranie logowania. + Obiekt o nazwie <nolink>[OBJECTFROMNAME]</nolink>, którego właścicielem jest [NAME_SLURL] oferuje Tobie <nolink>[ITEM_SLURL]</nolink>. Korzystanie z tego obieku wymaga przelączenia się na tryb zaawansowany, w którym będzie można odszukać obiekt w Twojej Szafie. W celu przełączenia trybu życia na zaawansowany, zamknij i uruchom ponownie aplikację. Przed ponownym zalogowaniem zmień tryb życia na ekranie logowania. <form name="form"> <button name="Keep" text="Zaakceptuj obiekt"/> <button name="Discard" text="Odrzuć obiekt"/> diff --git a/indra/newview/skins/minimal/xui/pt/notifications.xml b/indra/newview/skins/minimal/xui/pt/notifications.xml index 30ba6f68bf..9e5ff6fe60 100644 --- a/indra/newview/skins/minimal/xui/pt/notifications.xml +++ b/indra/newview/skins/minimal/xui/pt/notifications.xml @@ -9,7 +9,7 @@ </form> </notification> <notification name="ObjectGiveItem"> - Um objeto chamado <nolink>[OBJECTFROMNAME]</nolink>, de [NAME_SLURL], está lhe oferecendo [ITEM_SLURL]. Esta ação requer o modo Avançado. Passe para o modo Avançado e você verá o item em seu Inventário. Para passar para o modo Avançado, feche e reinicialize esse aplicativo e mude o modo (indicado na tela de login). + Um objeto chamado <nolink>[OBJECTFROMNAME]</nolink>, de [NAME_SLURL], está lhe oferecendo <nolink>[ITEM_SLURL]</nolink>. Esta ação requer o modo Avançado. Passe para o modo Avançado e você verá o item em seu Inventário. Para passar para o modo Avançado, feche e reinicialize esse aplicativo e mude o modo (indicado na tela de login). <form name="form"> <button name="Keep" text="Guardar item"/> <button name="Discard" text="Recusar item"/> diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index daa10819fc..0235400976 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -86,6 +86,9 @@ std::string LLControlGroup::getString(const std::string& name) return ""; } +// Stub for --no-verify-ssl-cert +BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } + LLSD LLCredential::getLoginParams() { LLSD result = LLSD::emptyMap(); |