diff options
author | Oz Linden <oz@lindenlab.com> | 2012-03-30 13:31:26 -0400 |
---|---|---|
committer | Oz Linden <oz@lindenlab.com> | 2012-03-30 13:31:26 -0400 |
commit | e56ea836383bd357809f86e2ffebafee8f481222 (patch) | |
tree | 8b5dd20b28261fba8b33953ef0f522914b2252c0 | |
parent | 6f71df192720ec3f16e7e7102ad21f4d140b8e07 (diff) | |
parent | e60dac5ce486f55fe69949a6a3a2949d4f868193 (diff) |
merge changes for latest core and updates from Kitty
190 files changed, 5876 insertions, 3573 deletions
@@ -228,6 +228,10 @@ c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start 80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release +a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release +fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release +a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release +fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release @@ -244,5 +248,30 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release 3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2 65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2 +c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release +c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release 2174ed1c7129562428a5cfe8651ed77b8d26ae18 3.2.6-start +286d73ff5c19f6c00e023dc1b60975ed6bbe2872 DRTVWR-109_3.2.6-beta1 4891c46a56fed7512c783b9cbe7cb7260727bf0c 3.2.7-start +286d73ff5c19f6c00e023dc1b60975ed6bbe2872 3.2.6-beta1 +c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release +c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release +3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1 +3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1 +89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start +16f8e2915f3f2e4d732fb3125daf229cb0fd1875 DRTVWR-114_3.2.8-beta1 +16f8e2915f3f2e4d732fb3125daf229cb0fd1875 3.2.8-beta1 +987425b1acf4752379b2e1eb20944b4b35d67a85 DRTVWR-115_3.2.8-beta2 +987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2 +51b2fd52e36aab8f670e0874e7e1472434ec4b4a DRTVWR-113_3.2.8-release +51b2fd52e36aab8f670e0874e7e1472434ec4b4a 3.2.8-release +37dd400ad721e2a89ee820ffc1e7e433c68f3ca2 3.2.9-start +e9c82fca5ae6fb8a8af29012d78fb194a29323f3 DRTVWR-117_3.2.9-beta1 +e9c82fca5ae6fb8a8af29012d78fb194a29323f3 3.2.9-beta1 +a01ef9bed28627f4ca543fbc1d70c79cc297a90f DRTVWR-118_3.2.9-beta2 +a01ef9bed28627f4ca543fbc1d70c79cc297a90f 3.2.9-beta2 +987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2 +d5f263687f43f278107363365938f0a214920a4b DRTVWR-119 +d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1 +5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate +5e8d2662f38a66eca6c591295f5880d47afc73f7 3.3.0-release diff --git a/autobuild.xml b/autobuild.xml index 5d5e244456..3089ed8e5d 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1014,9 +1014,9 @@ <key>archive</key> <map> <key>hash</key> - <string>350c004d703b1896d1dc195ddc8a6673</string> + <string>30f5757dac9bfd21357842921fcaccc2</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/245926/arch/Darwin/installer/libhunspell-1.3.2-darwin-20111130.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/252036/arch/Darwin/installer/libhunspell-1.3.2-darwin-20120325.tar.bz2</string> </map> <key>name</key> <string>darwin</string> @@ -1026,9 +1026,9 @@ <key>archive</key> <map> <key>hash</key> - <string>d7a472a0d576f7da4dcf03c5b60b310d</string> + <string>ed50b8df78c05c6426c1a1587d3068f1</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/245926/arch/Linux/installer/libhunspell-1.3.2-linux-20111130.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/252036/arch/Linux/installer/libhunspell-1.3.2-linux-20120325.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -1038,9 +1038,9 @@ <key>archive</key> <map> <key>hash</key> - <string>4a07cf590a93b4a8adfe2e71f0ceaa37</string> + <string>a30d1d536f407cb51422627a65dde570</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/245926/arch/CYGWIN/installer/libhunspell-1.3.2-windows-20111130.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz_3p-hunspell/rev/252036/arch/CYGWIN/installer/libhunspell-1.3.2-windows-20120325.tar.bz2</string> </map> <key>name</key> <string>windows</string> diff --git a/doc/contributions.txt b/doc/contributions.txt index 84f399cc89..c5db396c97 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -607,6 +607,9 @@ Jonathan Yap STORM-1737 STORM-1733 STORM-1790 + STORM-1788 + STORM-1799 + STORM-1796 Kadah Coba STORM-1060 Jondan Lundquist diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 4063cc730b..a6ad6b125c 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -337,11 +337,7 @@ LLMutex::~LLMutex() void LLMutex::lock() { -#if LL_DARWIN - if (mLockingThread == LLThread::currentID()) -#else - if (mLockingThread == sThreadID) -#endif + if(isSelfLocked()) { //redundant lock mCount++; return; @@ -398,6 +394,15 @@ bool LLMutex::isLocked() } } +bool LLMutex::isSelfLocked() +{ +#if LL_DARWIN + return mLockingThread == LLThread::currentID(); +#else + return mLockingThread == sThreadID; +#endif +} + U32 LLMutex::lockingThread() const { return mLockingThread; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index f0e0de6173..b52e70ab2e 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -151,6 +151,7 @@ public: void lock(); // blocks void unlock(); bool isLocked(); // non-blocking, but does do a lock/unlock so not free + bool isSelfLocked(); //return true if locked in a same thread U32 lockingThread() const; //get ID of locking thread protected: diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 99ab053b25..a869c74189 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,8 +28,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 2; -const S32 LL_VERSION_PATCH = 8; +const S32 LL_VERSION_MINOR = 3; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 0c6cf1dfae..761fc171c4 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2078,6 +2078,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; + mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims mIsMeshAssetLoaded = FALSE; mLODScaleBias.setVec(1,1,1); mHullPoints = NULL; @@ -3144,6 +3145,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, { F32 area = sculptGetSurfaceArea(); + mSurfaceArea = area; + const F32 SCULPT_MAX_AREA = 384.f; if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index afd1ec5eed..76cf9de613 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -963,6 +963,7 @@ public: S32 getNumFaces() const; S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } F32 getDetail() const { return mDetail; } + F32 getSurfaceArea() const { return mSurfaceArea; } const LLVolumeParams& getParams() const { return mParams; } LLVolumeParams getCopyOfParams() const { return mParams; } const LLProfile& getProfile() const { return *mProfilep; } @@ -1065,6 +1066,7 @@ public: BOOL mUnique; F32 mDetail; S32 mSculptLevel; + F32 mSurfaceArea; //unscaled surface area BOOL mIsMeshAssetLoaded; LLVolumeParams mParams; diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp index 0316797f00..250cace6e9 100644 --- a/indra/llmessage/llbuffer.cpp +++ b/indra/llmessage/llbuffer.cpp @@ -32,6 +32,9 @@ #include "llmath.h" #include "llmemtype.h" #include "llstl.h" +#include "llthread.h" + +#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED llassert(!mMutexp || mMutexp->isSelfLocked()); /** * LLSegment @@ -224,7 +227,8 @@ void LLHeapBuffer::allocate(S32 size) * LLBufferArray */ LLBufferArray::LLBufferArray() : - mNextBaseChannel(0) + mNextBaseChannel(0), + mMutexp(NULL) { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); } @@ -233,6 +237,8 @@ LLBufferArray::~LLBufferArray() { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer()); + + delete mMutexp; } // static @@ -243,14 +249,57 @@ LLChannelDescriptors LLBufferArray::makeChannelConsumer( return rv; } +void LLBufferArray::lock() +{ + if(mMutexp) + { + mMutexp->lock() ; + } +} + +void LLBufferArray::unlock() +{ + if(mMutexp) + { + mMutexp->unlock() ; + } +} + +LLMutex* LLBufferArray::getMutex() +{ + return mMutexp ; +} + +void LLBufferArray::setThreaded(bool threaded) +{ + if(threaded) + { + if(!mMutexp) + { + mMutexp = new LLMutex(NULL); + } + } + else + { + if(mMutexp) + { + delete mMutexp ; + mMutexp = NULL ; + } + } +} + LLChannelDescriptors LLBufferArray::nextChannel() { LLChannelDescriptors rv(mNextBaseChannel++); return rv; } +//mMutexp should be locked before calling this. S32 LLBufferArray::capacity() const { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED + S32 total = 0; const_buffer_iterator_t iter = mBuffers.begin(); const_buffer_iterator_t end = mBuffers.end(); @@ -263,6 +312,8 @@ S32 LLBufferArray::capacity() const bool LLBufferArray::append(S32 channel, const U8* src, S32 len) { + LLMutexLock lock(mMutexp) ; + LLMemType m1(LLMemType::MTYPE_IO_BUFFER); std::vector<LLSegment> segments; if(copyIntoBuffers(channel, src, len, segments)) @@ -273,8 +324,11 @@ bool LLBufferArray::append(S32 channel, const U8* src, S32 len) return false; } +//mMutexp should be locked before calling this. bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED + LLMemType m1(LLMemType::MTYPE_IO_BUFFER); std::vector<LLSegment> segments; if(copyIntoBuffers(channel, src, len, segments)) @@ -293,6 +347,8 @@ bool LLBufferArray::insertAfter( { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); std::vector<LLSegment> segments; + + LLMutexLock lock(mMutexp) ; if(mSegments.end() != segment) { ++segment; @@ -305,8 +361,11 @@ bool LLBufferArray::insertAfter( return false; } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED + LLMemType m1(LLMemType::MTYPE_IO_BUFFER); segment_iterator_t end = mSegments.end(); segment_iterator_t it = getSegment(address); @@ -335,20 +394,26 @@ LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address) return rv; } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::beginSegment() { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED return mSegments.begin(); } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::endSegment() { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED return mSegments.end(); } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter( U8* address, LLSegment& segment) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED LLMemType m1(LLMemType::MTYPE_IO_BUFFER); segment_iterator_t rv = mSegments.begin(); segment_iterator_t end = mSegments.end(); @@ -395,8 +460,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter( return rv; } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED segment_iterator_t end = mSegments.end(); if(!address) { @@ -414,9 +481,11 @@ LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address) return end; } +//mMutexp should be locked before calling this. LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment( U8* address) const { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED const_segment_iterator_t end = mSegments.end(); if(!address) { @@ -466,6 +535,8 @@ S32 LLBufferArray::countAfter(S32 channel, U8* start) const S32 count = 0; S32 offset = 0; const_segment_iterator_t it; + + LLMutexLock lock(mMutexp) ; const_segment_iterator_t end = mSegments.end(); if(start) { @@ -517,6 +588,8 @@ U8* LLBufferArray::readAfter( len = 0; S32 bytes_to_copy = 0; const_segment_iterator_t it; + + LLMutexLock lock(mMutexp) ; const_segment_iterator_t end = mSegments.end(); if(start) { @@ -568,6 +641,7 @@ U8* LLBufferArray::seek( U8* start, S32 delta) const { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED LLMemType m1(LLMemType::MTYPE_IO_BUFFER); const_segment_iterator_t it; const_segment_iterator_t end = mSegments.end(); @@ -709,9 +783,14 @@ U8* LLBufferArray::seek( return rv; } +//test use only bool LLBufferArray::takeContents(LLBufferArray& source) { LLMemType m1(LLMemType::MTYPE_IO_BUFFER); + + LLMutexLock lock(mMutexp); + source.lock(); + std::copy( source.mBuffers.begin(), source.mBuffers.end(), @@ -723,13 +802,17 @@ bool LLBufferArray::takeContents(LLBufferArray& source) std::back_insert_iterator<segment_list_t>(mSegments)); source.mSegments.clear(); source.mNextBaseChannel = 0; + source.unlock(); + return true; } +//mMutexp should be locked before calling this. LLBufferArray::segment_iterator_t LLBufferArray::makeSegment( S32 channel, S32 len) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED LLMemType m1(LLMemType::MTYPE_IO_BUFFER); // start at the end of the buffers, because it is the most likely // to have free space. @@ -765,8 +848,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::makeSegment( return send; } +//mMutexp should be locked before calling this. bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED LLMemType m1(LLMemType::MTYPE_IO_BUFFER); // Find out which buffer contains the segment, and if it is found, @@ -792,13 +877,14 @@ bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter) return rv; } - +//mMutexp should be locked before calling this. bool LLBufferArray::copyIntoBuffers( S32 channel, const U8* src, S32 len, std::vector<LLSegment>& segments) { + ASSERT_LLBUFFERARRAY_MUTEX_LOCKED LLMemType m1(LLMemType::MTYPE_IO_BUFFER); if(!src || !len) return false; S32 copied = 0; diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index 1c42b6fbc6..ccdb9fa7ee 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -39,6 +39,7 @@ #include <list> #include <vector> +class LLMutex; /** * @class LLChannelDescriptors * @brief A way simple interface to accesss channels inside a buffer @@ -564,6 +565,29 @@ public: * @return Returns true on success. */ bool eraseSegment(const segment_iterator_t& iter); + + /** + * @brief Lock the mutex if it exists + * This method locks mMutexp to make accessing LLBufferArray thread-safe + */ + void lock(); + + /** + * @brief Unlock the mutex if it exists + */ + void unlock(); + + /** + * @brief Return mMutexp + */ + LLMutex* getMutex(); + + /** + * @brief Set LLBufferArray to be shared across threads or not + * This method is to create mMutexp if is threaded. + * @param threaded Indicates this LLBufferArray instance is shared across threads if true. + */ + void setThreaded(bool threaded); //@} protected: @@ -595,6 +619,7 @@ protected: S32 mNextBaseChannel; buffer_list_t mBuffers; segment_list_t mSegments; + LLMutex* mMutexp; }; #endif // LL_LLBUFFER_H diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp index 6257983c43..8d8ad05ad5 100644 --- a/indra/llmessage/llbufferstream.cpp +++ b/indra/llmessage/llbufferstream.cpp @@ -31,6 +31,7 @@ #include "llbuffer.h" #include "llmemtype.h" +#include "llthread.h" static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4; @@ -62,6 +63,7 @@ int LLBufferStreamBuf::underflow() return EOF; } + LLMutexLock lock(mBuffer->getMutex()); LLBufferArray::segment_iterator_t iter; LLBufferArray::segment_iterator_t end = mBuffer->endSegment(); U8* last_pos = (U8*)gptr(); @@ -149,6 +151,7 @@ int LLBufferStreamBuf::overflow(int c) // since we got here, we have a buffer, and we have a character to // put on it. LLBufferArray::segment_iterator_t it; + LLMutexLock lock(mBuffer->getMutex()); it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE); if(it != mBuffer->endSegment()) { @@ -210,6 +213,7 @@ int LLBufferStreamBuf::sync() // *NOTE: I bet we could just --address if address is not NULL. // Need to think about that. + LLMutexLock lock(mBuffer->getMutex()); address = mBuffer->seek(mChannels.out(), address, -1); if(address) { @@ -273,6 +277,8 @@ streampos LLBufferStreamBuf::seekoff( // NULL is fine break; } + + LLMutexLock lock(mBuffer->getMutex()); address = mBuffer->seek(mChannels.in(), base_addr, off); if(address) { @@ -304,6 +310,8 @@ streampos LLBufferStreamBuf::seekoff( // NULL is fine break; } + + LLMutexLock lock(mBuffer->getMutex()); address = mBuffer->seek(mChannels.out(), base_addr, off); if(address) { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index e17380fdf5..3bcaffc275 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,10 +72,9 @@ static const U32 EASY_HANDLE_POOL_SIZE = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; -static // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -87,6 +86,11 @@ std::vector<LLMutex*> LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; LLCurlThread* LLCurl::sCurlThread = NULL ; +LLMutex* LLCurl::sHandleMutexp = NULL ; +S32 LLCurl::sTotalHandles = 0 ; +bool LLCurl::sNotQuitting = true; +F32 LLCurl::sCurlRequestTimeOut = 120.f; //seonds +S32 LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined). void check_curl_code(CURLcode code) { @@ -224,13 +228,15 @@ LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; //static CURL* LLCurl::Easy::allocEasyHandle() { + llassert(LLCurl::getCurlThread()) ; + CURL* ret = NULL; LLMutexLock lock(sHandleMutexp) ; if (sFreeHandles.empty()) { - ret = curl_easy_init(); + ret = LLCurl::newEasyHandle(); } else { @@ -250,16 +256,27 @@ CURL* LLCurl::Easy::allocEasyHandle() //static void LLCurl::Easy::releaseEasyHandle(CURL* handle) { + static const S32 MAX_NUM_FREE_HANDLES = 32 ; + if (!handle) { - llerrs << "handle cannot be NULL!" << llendl; + return ; //handle allocation failed. + //llerrs << "handle cannot be NULL!" << llendl; } LLMutexLock lock(sHandleMutexp) ; if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); - sFreeHandles.insert(handle); + + if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) + { + sFreeHandles.insert(handle); + } + else + { + LLCurl::deleteEasyHandle(handle) ; + } } else { @@ -302,6 +319,14 @@ LLCurl::Easy::~Easy() --gCurlEasyCount; curl_slist_free_all(mHeaders); for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); + + if (mResponder && LLCurl::sNotQuitting) //aborted + { + std::string reason("Request timeout, aborted.") ; + mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort + reason, mChannels, mOutput); + } + mResponder = NULL; } void LLCurl::Easy::resetState() @@ -474,6 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, LLProxy::getInstance()->applyProxySettings(this); mOutput.reset(new LLBufferArray); + mOutput->setThreaded(true); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); @@ -517,8 +543,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, } //////////////////////////////////////////////////////////////////////////// -LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ; -LLCurl::Multi::Multi() +LLCurl::Multi::Multi(F32 idle_time_out) : mQueued(0), mErrorCount(0), mState(STATE_READY), @@ -527,28 +552,47 @@ LLCurl::Multi::Multi() mDeletionMutexp(NULL), mEasyMutexp(NULL) { - mCurlMultiHandle = initMulti(); + mCurlMultiHandle = LLCurl::newMultiHandle(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; - mCurlMultiHandle = initMulti(); + mCurlMultiHandle = LLCurl::newMultiHandle(); } - llassert_always(mCurlMultiHandle); - - if(LLCurl::getCurlThread()->getThreaded()) + //llassert_always(mCurlMultiHandle); + + if(mCurlMultiHandle) { - mMutexp = new LLMutex(NULL) ; - mDeletionMutexp = new LLMutex(NULL) ; - mEasyMutexp = new LLMutex(NULL) ; - } - LLCurl::getCurlThread()->addMulti(this) ; + if(LLCurl::getCurlThread()->getThreaded()) + { + mMutexp = new LLMutex(NULL) ; + mDeletionMutexp = new LLMutex(NULL) ; + mEasyMutexp = new LLMutex(NULL) ; + } + LLCurl::getCurlThread()->addMulti(this) ; - ++gCurlMultiCount; + mIdleTimeOut = idle_time_out ; + if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) + { + mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; + } + + ++gCurlMultiCount; + } } LLCurl::Multi::~Multi() { + cleanup() ; +} + +void LLCurl::Multi::cleanup() +{ + if(!mCurlMultiHandle) + { + return ; //nothing to clean. + } + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) @@ -564,7 +608,8 @@ LLCurl::Multi::~Multi() for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer()); mEasyFreeList.clear(); - check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); + check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); + mCurlMultiHandle = NULL ; delete mMutexp ; mMutexp = NULL ; @@ -572,15 +617,13 @@ LLCurl::Multi::~Multi() mDeletionMutexp = NULL ; delete mEasyMutexp ; mEasyMutexp = NULL ; - + + mQueued = 0 ; + mState = STATE_COMPLETED; + --gCurlMultiCount; -} - -CURLM* LLCurl::Multi::initMulti() -{ - LLMutexLock lock(sMultiInitMutexp) ; - return curl_multi_init() ; + return ; } void LLCurl::Multi::lock() @@ -604,6 +647,7 @@ void LLCurl::Multi::markDead() LLMutexLock lock(mDeletionMutexp) ; mDead = TRUE ; + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -630,6 +674,11 @@ bool LLCurl::Multi::isCompleted() bool LLCurl::Multi::waitToComplete() { + if(!isValid()) + { + return true ; + } + if(!mMutexp) //not threaded { doPerform() ; @@ -639,7 +688,7 @@ bool LLCurl::Multi::waitToComplete() bool completed = (STATE_COMPLETED == mState) ; if(!completed) { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ; } return completed; @@ -689,7 +738,12 @@ bool LLCurl::Multi::doPerform() } mQueued = q; - setState(STATE_COMPLETED) ; + setState(STATE_COMPLETED) ; + mIdleTimer.reset() ; + } + else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. + { + dead = true ; } return dead ; @@ -697,6 +751,11 @@ bool LLCurl::Multi::doPerform() S32 LLCurl::Multi::process() { + if(!isValid()) + { + return 0 ; + } + waitToComplete() ; if (getState() != STATE_COMPLETED) @@ -849,7 +908,11 @@ bool LLCurlThread::CurlRequest::processRequest() if(mMulti) { completed = mCurlThread->doMultiPerform(mMulti) ; - setPriority(LLQueuedThread::PRIORITY_LOW) ; + + if(!completed) + { + setPriority(LLQueuedThread::PRIORITY_LOW) ; + } } return completed ; @@ -857,24 +920,26 @@ bool LLCurlThread::CurlRequest::processRequest() void LLCurlThread::CurlRequest::finishRequest(bool completed) { - mCurlThread->deleteMulti(mMulti) ; + if(mMulti->isDead()) + { + mCurlThread->deleteMulti(mMulti) ; + } + else + { + mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. + } + mMulti = NULL ; } LLCurlThread::LLCurlThread(bool threaded) : LLQueuedThread("curlthread", threaded) { - if(!LLCurl::Multi::sMultiInitMutexp) - { - LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ; - } } //virtual LLCurlThread::~LLCurlThread() { - delete LLCurl::Multi::sMultiInitMutexp ; - LLCurl::Multi::sMultiInitMutexp = NULL ; } S32 LLCurlThread::update(F32 max_time_ms) @@ -896,7 +961,19 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi) void LLCurlThread::killMulti(LLCurl::Multi* multi) { - multi->markDead() ; + if(!multi) + { + return ; + } + + if(multi->isValid()) + { + multi->markDead() ; + } + else + { + deleteMulti(multi) ; + } } //private @@ -910,6 +987,13 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi) { delete multi ; } + +//private +void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) +{ + multi->cleanup() ; +} + //------------------------------------------------------------ //static @@ -942,7 +1026,14 @@ LLCurlRequest::~LLCurlRequest() void LLCurlRequest::addMulti() { LLCurl::Multi* multi = new LLCurl::Multi(); - + if(!multi->isValid()) + { + LLCurl::getCurlThread()->killMulti(multi) ; + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + return; + } + mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -956,7 +1047,12 @@ LLCurl::Easy* LLCurlRequest::allocEasy() { addMulti(); } - llassert_always(mActiveMulti); + if(!mActiveMulti) + { + return NULL ; + } + + //llassert_always(mActiveMulti); ++mActiveRequestCount; LLCurl::Easy* easy = mActiveMulti->allocEasy(); return easy; @@ -1066,6 +1162,19 @@ S32 LLCurlRequest::process() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; + + if(!multi->isValid()) + { + if(multi == mActiveMulti) + { + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + } + mMultiSet.erase(curiter) ; + LLCurl::getCurlThread()->killMulti(multi) ; + continue ; + } + S32 tres = multi->process(); res += tres; if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) @@ -1086,6 +1195,19 @@ S32 LLCurlRequest::getQueued() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; + + if(!multi->isValid()) + { + if(multi == mActiveMulti) + { + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + } + LLCurl::getCurlThread()->killMulti(multi); + mMultiSet.erase(curiter) ; + continue ; + } + queued += multi->mQueued; if (multi->getState() != LLCurl::Multi::STATE_READY) { @@ -1105,13 +1227,22 @@ LLCurlEasyRequest::LLCurlEasyRequest() { mMulti = new LLCurl::Multi(); - mEasy = mMulti->allocEasy(); - if (mEasy) + if(mMulti->isValid()) { - mEasy->setErrorBuffer(); - mEasy->setCA(); - // Set proxy settings if configured to do so. - LLProxy::getInstance()->applyProxySettings(mEasy); + mEasy = mMulti->allocEasy(); + if (mEasy) + { + mEasy->setErrorBuffer(); + mEasy->setCA(); + // Set proxy settings if configured to do so. + LLProxy::getInstance()->applyProxySettings(mEasy); + } + } + else + { + LLCurl::getCurlThread()->killMulti(mMulti) ; + mEasy = NULL ; + mMulti = NULL ; } } @@ -1122,7 +1253,7 @@ LLCurlEasyRequest::~LLCurlEasyRequest() void LLCurlEasyRequest::setopt(CURLoption option, S32 value) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(option, value); } @@ -1130,7 +1261,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value) void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setoptString(option, value); } @@ -1138,7 +1269,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value void LLCurlEasyRequest::setPost(char* postdata, S32 size) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_POST, 1); mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1148,7 +1279,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size) void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1157,7 +1288,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1166,7 +1297,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1175,7 +1306,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback); mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1184,7 +1315,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* void LLCurlEasyRequest::slist_append(const char* str) { - if (mEasy) + if (isValid() && mEasy) { mEasy->slist_append(str); } @@ -1195,7 +1326,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url) llassert_always(!mRequestSent); mRequestSent = true; lldebugs << url << llendl; - if (mEasy) + if (isValid() && mEasy) { mEasy->setHeaders(); mEasy->setoptString(CURLOPT_URL, url); @@ -1207,7 +1338,7 @@ void LLCurlEasyRequest::requestComplete() { llassert_always(mRequestSent); mRequestSent = false; - if (mEasy) + if (isValid() && mEasy) { mMulti->removeEasy(mEasy); } @@ -1216,6 +1347,10 @@ void LLCurlEasyRequest::requestComplete() // Usage: Call getRestult until it returns false (no more messages) bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info) { + if(!isValid()) + { + return false ; + } if (!mMulti->isCompleted()) { //we're busy, try again later return false; @@ -1280,7 +1415,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info) std::string LLCurlEasyRequest::getErrorString() { - return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); + return isValid() && mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); } //////////////////////////////////////////////////////////////////////////// @@ -1306,8 +1441,11 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass(bool multi_threaded) +void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded) { + sCurlRequestTimeOut = curl_reuest_timeout ; //seconds + sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). + // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html @@ -1328,12 +1466,15 @@ void LLCurl::initClass(bool multi_threaded) sCurlThread = new LLCurlThread(multi_threaded) ; if(multi_threaded) { + sHandleMutexp = new LLMutex(NULL) ; Easy::sHandleMutexp = new LLMutex(NULL) ; } } void LLCurl::cleanupClass() { + sNotQuitting = false; //set quitting + //shut down curl thread while(1) { @@ -1354,7 +1495,7 @@ void LLCurl::cleanupClass() for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { CURL* curl = *iter; - curl_easy_cleanup(curl); + LLCurl::deleteEasyHandle(curl); } Easy::sFreeHandles.clear(); @@ -1362,9 +1503,77 @@ void LLCurl::cleanupClass() delete Easy::sHandleMutexp ; Easy::sHandleMutexp = NULL ; + delete sHandleMutexp ; + sHandleMutexp = NULL ; + llassert(Easy::sActiveHandles.empty()); } +//static +CURLM* LLCurl::newMultiHandle() +{ + LLMutexLock lock(sHandleMutexp) ; + + if(sTotalHandles + 1 > sMaxHandles) + { + llwarns << "no more handles available." << llendl ; + return NULL ; //failed + } + sTotalHandles++; + + CURLM* ret = curl_multi_init() ; + if(!ret) + { + llwarns << "curl_multi_init failed." << llendl ; + } + + return ret ; +} + +//static +CURLMcode LLCurl::deleteMultiHandle(CURLM* handle) +{ + if(handle) + { + LLMutexLock lock(sHandleMutexp) ; + sTotalHandles-- ; + return curl_multi_cleanup(handle) ; + } + return CURLM_OK ; +} + +//static +CURL* LLCurl::newEasyHandle() +{ + LLMutexLock lock(sHandleMutexp) ; + + if(sTotalHandles + 1 > sMaxHandles) + { + llwarns << "no more handles available." << llendl ; + return NULL ; //failed + } + sTotalHandles++; + + CURL* ret = curl_easy_init() ; + if(!ret) + { + llwarns << "curl_easy_init failed." << llendl ; + } + + return ret ; +} + +//static +void LLCurl::deleteEasyHandle(CURL* handle) +{ + if(handle) + { + LLMutexLock lock(sHandleMutexp) ; + curl_easy_cleanup(handle) ; + sTotalHandles-- ; + } +} + const unsigned int LLCurl::MAX_REDIRECTS = 5; // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 9c2c215c7a..fd664c0fa1 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -43,6 +43,7 @@ #include "llsd.h" #include "llthread.h" #include "llqueuedthread.h" +#include "llframetimer.h" class LLMutex; class LLCurlThread; @@ -162,7 +163,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(bool multi_threaded = false); + static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -182,11 +183,24 @@ public: static unsigned long ssl_thread_id(void); static LLCurlThread* getCurlThread() { return sCurlThread ;} + + static CURLM* newMultiHandle() ; + static CURLMcode deleteMultiHandle(CURLM* handle) ; + static CURL* newEasyHandle() ; + static void deleteEasyHandle(CURL* handle) ; + private: static std::string sCAPath; static std::string sCAFile; static const unsigned int MAX_REDIRECTS; static LLCurlThread* sCurlThread; + + static LLMutex* sHandleMutexp ; + static S32 sTotalHandles ; + static S32 sMaxHandles; +public: + static bool sNotQuitting; + static F32 sCurlRequestTimeOut; }; class LLCurl::Easy @@ -277,7 +291,7 @@ public: STATE_COMPLETED=2 } ePerformState; - Multi(); + Multi(F32 idle_time_out = 0.f); LLCurl::Easy* allocEasy(); bool addEasy(LLCurl::Easy* easy); @@ -288,7 +302,10 @@ public: void setState(ePerformState state) ; ePerformState getState() ; + bool isCompleted() ; + bool isValid() {return mCurlMultiHandle != NULL ;} + bool isDead() {return mDead;} bool waitToComplete() ; @@ -299,9 +316,9 @@ public: S32 mQueued; S32 mErrorCount; - static CURLM* initMulti() ; private: void easyFree(LLCurl::Easy*); + void cleanup() ; CURLM* mCurlMultiHandle; @@ -319,8 +336,8 @@ private: LLMutex* mMutexp ; LLMutex* mDeletionMutexp ; LLMutex* mEasyMutexp ; - - static LLMutex* sMultiInitMutexp ; + LLFrameTimer mIdleTimer ; + F32 mIdleTimeOut; }; class LLCurlThread : public LLQueuedThread @@ -357,6 +374,7 @@ public: private: bool doMultiPerform(LLCurl::Multi* multi) ; void deleteMulti(LLCurl::Multi* multi) ; + void cleanupMulti(LLCurl::Multi* multi) ; } ; namespace boost @@ -414,6 +432,7 @@ public: std::string getErrorString(); bool isCompleted() {return mMulti->isCompleted() ;} bool wait() { return mMulti->waitToComplete(); } + bool isValid() {return mMulti && mMulti->isValid(); } LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 2bca517e97..612d765969 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -232,7 +232,8 @@ LLSD LLHTTPAssetRequest::getFullDetails() const void LLHTTPAssetRequest::setupCurlHandle() { // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC - mCurlHandle = curl_easy_init(); + mCurlHandle = LLCurl::newEasyHandle(); + llassert_always(mCurlHandle != NULL) ; // Apply proxy settings if configured to do so LLProxy::getInstance()->applyProxySettings(mCurlHandle); @@ -278,7 +279,7 @@ void LLHTTPAssetRequest::setupCurlHandle() void LLHTTPAssetRequest::cleanupCurlHandle() { - curl_easy_cleanup(mCurlHandle); + LLCurl::deleteEasyHandle(mCurlHandle); if (mAssetStoragep) { // Terminating a request. Thus upload or download is no longer pending. @@ -429,12 +430,13 @@ void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& l // curl_global_init moved to LLCurl::initClass() - mCurlMultiHandle = curl_multi_init(); + mCurlMultiHandle = LLCurl::newMultiHandle() ; + llassert_always(mCurlMultiHandle != NULL) ; } LLHTTPAssetStorage::~LLHTTPAssetStorage() { - curl_multi_cleanup(mCurlMultiHandle); + LLCurl::deleteMultiHandle(mCurlMultiHandle); mCurlMultiHandle = NULL; // curl_global_cleanup moved to LLCurl::initClass() diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index dd4e3a6300..231cb7ca8f 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -228,6 +228,12 @@ static void request( LLPumpIO::chain_t chain; LLURLRequest* req = new LLURLRequest(method, url); + if(!req->isValid())//failed + { + delete req ; + return ; + } + req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); @@ -423,7 +429,9 @@ static LLSD blocking_request( { lldebugs << "blockingRequest of " << url << llendl; char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; - CURL* curlp = curl_easy_init(); + CURL* curlp = LLCurl::newEasyHandle(); + llassert_always(curlp != NULL) ; + LLHTTPBuffer http_buffer; std::string body_str; @@ -517,7 +525,7 @@ static LLSD blocking_request( } // * Cleanup - curl_easy_cleanup(curlp); + LLCurl::deleteEasyHandle(curlp); return response; } diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 73e8a69085..987f386aa3 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -818,6 +818,8 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( // Copy everything after mLast read to the out. LLBufferArray::segment_iterator_t seg_iter; + + buffer->lock(); seg_iter = buffer->splitAfter(mLastRead); if(seg_iter != buffer->endSegment()) { @@ -838,7 +840,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( } #endif } - + buffer->unlock(); // // *FIX: get rid of extra bytes off the end // diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp index 6e4eec74a6..8f827f7a30 100644 --- a/indra/llmessage/lliopipe.cpp +++ b/indra/llmessage/lliopipe.cpp @@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe() //lldebugs << "destroying LLIOPipe" << llendl; } +//virtual +bool LLIOPipe::isValid() +{ + return true ; +} + // static std::string LLIOPipe::lookupStatusString(EStatus status) { diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index 8e656b6da1..cbd17b5a3d 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -231,6 +231,8 @@ public: */ virtual ~LLIOPipe(); + virtual bool isValid() ; + protected: /** * @brief Base Constructor. diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 54ceab3422..d5b4d45821 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -445,6 +445,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( // efficient - not only because writev() is better, but also // because we won't have to do as much work to find the start // address. + buffer->lock(); LLBufferArray::segment_iterator_t it; LLBufferArray::segment_iterator_t end = buffer->endSegment(); LLSegment segment; @@ -524,6 +525,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( } } + buffer->unlock(); + PUMP_DEBUG; if(done && eos) { diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a8d2a0a224..f3ef4f2684 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -195,7 +195,7 @@ bool LLPumpIO::prime(apr_pool_t* pool) return ((pool == NULL) ? false : true); } -bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) +bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); if(chain.empty()) return false; @@ -204,8 +204,10 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) LLScopedLock lock(mChainsMutex); #endif LLChainInfo info; + info.mHasCurlRequest = has_curl_request; info.setTimeoutSeconds(timeout); info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray); + info.mData->setThreaded(has_curl_request); LLLinkInfo link; #if LL_DEBUG_PIPE_TYPE_IN_PUMP lldebugs << "LLPumpIO::addChain() " << chain[0] << " '" @@ -440,6 +442,15 @@ void LLPumpIO::pump() static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); +LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) +{ + std::for_each( + (*run_chain).mDescriptors.begin(), + (*run_chain).mDescriptors.end(), + ll_delete_apr_pollset_fd_client_data()); + return mRunningChains.erase(run_chain); +} + //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { @@ -585,10 +596,16 @@ void LLPumpIO::pump(const S32& poll_timeout) // << (*run_chain).mChainLinks[0].mPipe // << " because we reached the end." << llendl; #endif - run_chain = mRunningChains.erase(run_chain); + run_chain = removeRunningChain(run_chain); continue; } } + else if(isChainExpired(*run_chain)) + { + run_chain = removeRunningChain(run_chain); + continue; + } + PUMP_DEBUG; if((*run_chain).mLock) { @@ -696,11 +713,7 @@ void LLPumpIO::pump(const S32& poll_timeout) PUMP_DEBUG; // This chain is done. Clean up any allocated memory and // erase the chain info. - std::for_each( - (*run_chain).mDescriptors.begin(), - (*run_chain).mDescriptors.end(), - ll_delete_apr_pollset_fd_client_data()); - run_chain = mRunningChains.erase(run_chain); + run_chain = removeRunningChain(run_chain); // *NOTE: may not always need to rebuild the pollset. mRebuildPollset = true; @@ -1095,6 +1108,24 @@ void LLPumpIO::processChain(LLChainInfo& chain) PUMP_DEBUG; } +bool LLPumpIO::isChainExpired(LLChainInfo& chain) +{ + if(!chain.mHasCurlRequest) + { + return false ; + } + + for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter) + { + if(!(*iter).mPipe->isValid()) + { + return true ; + } + } + + return false ; +} + bool LLPumpIO::handleChainError( LLChainInfo& chain, LLIOPipe::EStatus error) @@ -1136,6 +1167,9 @@ bool LLPumpIO::handleChainError( #endif keep_going = false; break; + case LLIOPipe::STATUS_EXPIRED: + keep_going = false; + break ; default: if(LLIOPipe::isSuccess(error)) { @@ -1157,7 +1191,8 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false) + mEOS(false), + mHasCurlRequest(false) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 9303c9d7fc..d2c5d37571 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -111,9 +111,10 @@ public: * @param chain The pipes for the chain * @param timeout The number of seconds in the future to * expire. Pass in 0.0f to never expire. + * @param has_curl_request The chain contains LLURLRequest if true. * @return Returns true if anything was added to the pump. */ - bool addChain(const chain_t& chain, F32 timeout); + bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false); /** * @brief Struct to associate a pipe with it's buffer io indexes. @@ -356,12 +357,13 @@ protected: // basic member data bool mInit; + bool mEOS; + bool mHasCurlRequest; S32 mLock; LLFrameTimer mTimer; links_t::iterator mHead; links_t mChainLinks; - LLIOPipe::buffer_ptr_t mData; - bool mEOS; + LLIOPipe::buffer_ptr_t mData; LLSD mContext; // tracking inside the pump @@ -402,7 +404,7 @@ protected: protected: void initialize(apr_pool_t* pool); void cleanup(); - + current_chain_t removeRunningChain(current_chain_t& chain) ; /** * @brief Given the internal state of the chains, rebuild the pollset * @see setConditional() @@ -429,6 +431,9 @@ protected: */ bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error); + //if the chain is expired, remove it + bool isChainExpired(LLChainInfo& chain) ; + public: /** * @brief Return number of running chains. diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h index 9fb49a5c33..0cecf4f688 100644 --- a/indra/llmessage/llsdrpcclient.h +++ b/indra/llmessage/llsdrpcclient.h @@ -240,9 +240,16 @@ public: virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const { lldebugs << "LLSDRPCClientFactory::build" << llendl; - LLIOPipe::ptr_t service(new Client); - chain.push_back(service); LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + if(!http->isValid()) + { + llwarns << "Creating LLURLRequest failed." << llendl ; + delete http; + return false; + } + + LLIOPipe::ptr_t service(new Client); + chain.push_back(service); LLIOPipe::ptr_t http_pipe(http); http->addHeader("Content-Type: text/llsd"); if(mURL.empty()) @@ -283,9 +290,16 @@ public: virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const { lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; - LLIOPipe::ptr_t service(new Client); - chain.push_back(service); + LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + if(!http->isValid()) + { + llwarns << "Creating LLURLRequest failed." << llendl ; + delete http; + return false ; + } + LLIOPipe::ptr_t service(new Client); + chain.push_back(service); LLIOPipe::ptr_t http_pipe(http); http->addHeader("Content-Type: text/xml"); if(mURL.empty()) diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 261e57e79e..a16f5c7bf0 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -83,6 +83,12 @@ LLURLRequestDetail::LLURLRequestDetail() : { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mCurlRequest = new LLCurlEasyRequest(); + + if(!mCurlRequest->isValid()) //failed. + { + delete mCurlRequest ; + mCurlRequest = NULL ; + } } LLURLRequestDetail::~LLURLRequestDetail() @@ -250,12 +256,24 @@ void LLURLRequest::allowCookies() mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, ""); } +//virtual +bool LLURLRequest::isValid() +{ + return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); +} + // virtual LLIOPipe::EStatus LLURLRequest::handleError( LLIOPipe::EStatus status, LLPumpIO* pump) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); + + if(!isValid()) + { + return STATUS_EXPIRED ; + } + if(mCompletionCallback && pump) { LLURLRequestComplete* complete = NULL; @@ -441,6 +459,12 @@ void LLURLRequest::initialize() LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mState = STATE_INITIALIZED; mDetail = new LLURLRequestDetail; + + if(!isValid()) + { + return ; + } + mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index ec5c2c1941..44d358d906 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -188,6 +188,8 @@ public: */ void allowCookies(); + /*virtual*/ bool isValid() ; + public: /** * @brief Give this pipe a chance to handle a generated error diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cd827f5091..b0ddacbb05 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -997,7 +997,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction) const glh::matrix4f& mat = gGL.getModelviewMatrix(); mat.mult_matrix_dir(dir); - mSpotDirection.set(direction); + mSpotDirection.set(dir.v); } } @@ -1434,6 +1434,8 @@ void LLRender::loadIdentity() flush(); { + llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); mMatHash[mMatrixMode]++; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 20a450fbfb..eb302392bb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -148,7 +148,7 @@ U32 wpo2(U32 i) return r; } -U8* LLVBOPool::allocate(U32& name, U32 size) +volatile U8* LLVBOPool::allocate(U32& name, U32 size) { llassert(nhpo2(size) == size); @@ -159,20 +159,25 @@ U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList.resize(i+1); } - U8* ret = NULL; + volatile U8* ret = NULL; if (mFreeList[i].empty()) { //make a new buffer glGenBuffersARB(1, &name); glBindBufferARB(mType, name); - glBufferDataARB(mType, size, 0, mUsage); LLVertexBuffer::sAllocatedBytes += size; - if (LLVertexBuffer::sDisableVBOMapping) + if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) { + glBufferDataARB(mType, size, 0, mUsage); ret = (U8*) ll_aligned_malloc_16(size); } + else + { //always use a true hint of static draw when allocating non-client-backed buffers + glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); + } + glBindBufferARB(mType, 0); } else @@ -188,7 +193,7 @@ U8* LLVBOPool::allocate(U32& name, U32 size) return ret; } -void LLVBOPool::release(U32 name, U8* buffer, U32 size) +void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) { llassert(nhpo2(size) == size); @@ -201,8 +206,15 @@ void LLVBOPool::release(U32 name, U8* buffer, U32 size) rec.mClientData = buffer; sBytesPooled += size; - - mFreeList[i].push_back(rec); + + if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB) + { + glDeleteBuffersARB(1, &rec.mGLName); + } + else + { + mFreeList[i].push_back(rec); + } } void LLVBOPool::cleanup() @@ -221,7 +233,7 @@ void LLVBOPool::cleanup() if (r.mClientData) { - ll_aligned_free_16(r.mClientData); + ll_aligned_free_16((void*) r.mClientData); } l.pop_front(); @@ -536,7 +548,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { validateRange(start, end, count, indices_offset); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -591,7 +603,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumIndices >= 0); @@ -637,7 +649,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -787,9 +799,26 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : if (mUsage && mUsage != GL_STREAM_DRAW_ARB) { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default - mUsage = GL_DYNAMIC_DRAW_ARB; + if (sDisableVBOMapping) + { //always use stream draw if VBO mapping is disabled + mUsage = GL_STREAM_DRAW_ARB; + } + else + { + mUsage = GL_DYNAMIC_DRAW_ARB; + } } - + + + if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping) + { + mMappable = TRUE; + } + else + { + mMappable = FALSE; + } + //zero out offsets for (U32 i = 0; i < TYPE_MAX; i++) { @@ -1042,7 +1071,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - FREE_MEM(sPrivatePoolp, mMappedData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedData) ; mMappedData = NULL; mEmpty = TRUE; } @@ -1063,7 +1092,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - FREE_MEM(sPrivatePoolp, mMappedIndexData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ; mMappedIndexData = NULL; mEmpty = TRUE; } @@ -1282,8 +1311,11 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) return true; } +static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range"); +static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map"); + // Map for data access -U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) +volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { bindGLBuffer(true); LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); @@ -1298,7 +1330,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran if (useVBOs()) { - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1323,7 +1355,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran if (!mapped) { //not already mapped, map new region - MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count); + MappedRegion region(type, mMappable && map_range ? -1 : index, count); mMappedVertexRegions.push_back(region); } } @@ -1340,19 +1372,20 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran sMappedCount++; stop_glerror(); - if(sDisableVBOMapping) + if(!mMappable) { map_range = false; } else { - U8* src = NULL; + volatile U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range + LLFastTimer t(FTM_VBO_MAP_BUFFER_RANGE); S32 offset = mOffsets[type] + sTypeSize[type]*index; S32 length = (sTypeSize[type]*count+0xF) & ~0xF; src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, @@ -1376,6 +1409,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran } } + LLFastTimer t(FTM_VBO_MAP_BUFFER); src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1403,7 +1437,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran llassert(src != NULL); - mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src); mAlignedOffset = mMappedData - src; stop_glerror(); @@ -1416,7 +1450,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran //check the availability of memory LLMemory::logMemoryInfo(TRUE) ; - if(!sDisableVBOMapping) + if(mMappable) { //-------------------- //print out more debug info before crash @@ -1448,7 +1482,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran map_range = false; } - if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && mMappable) { return mMappedData; } @@ -1458,7 +1492,11 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran } } -U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) + +static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX_RANGE("IBO Map Range"); +static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map"); + +volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); bindGLIndices(true); @@ -1473,7 +1511,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) if (useVBOs()) { - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1495,7 +1533,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) if (!mapped) { //not already mapped, map new region - MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count); + MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count); mMappedIndexRegions.push_back(region); } } @@ -1524,19 +1562,20 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) } } - if(sDisableVBOMapping) + if(!mMappable) { map_range = false; } else { - U8* src = NULL; + volatile U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range + LLFastTimer t(FTM_VBO_MAP_INDEX_RANGE); S32 offset = sizeof(U16)*index; S32 length = sizeof(U16)*count; src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, @@ -1548,6 +1587,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) else { #ifdef GL_ARB_map_buffer_range + LLFastTimer t(FTM_VBO_MAP_INDEX); src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1569,6 +1609,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) } else { + LLFastTimer t(FTM_VBO_MAP_INDEX); map_range = false; src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } @@ -1587,7 +1628,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) log_glerror(); LLMemory::logMemoryInfo(TRUE) ; - if(!sDisableVBOMapping) + if(mMappable) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); @@ -1609,7 +1650,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) map_range = false; } - if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && mMappable) { return mMappedIndexData; } @@ -1619,6 +1660,13 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) } } +static LLFastTimer::DeclareTimer FTM_VBO_UNMAP("VBO Unmap"); +static LLFastTimer::DeclareTimer FTM_VBO_FLUSH_RANGE("Flush VBO Range"); + + +static LLFastTimer::DeclareTimer FTM_IBO_UNMAP("IBO Unmap"); +static LLFastTimer::DeclareTimer FTM_IBO_FLUSH_RANGE("Flush IBO Range"); + void LLVertexBuffer::unmapBuffer() { LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER); @@ -1631,10 +1679,11 @@ void LLVertexBuffer::unmapBuffer() if (mMappedData && mVertexLocked) { + LLFastTimer t(FTM_VBO_UNMAP); bindGLBuffer(true); updated_all = mIndexLocked; //both vertex and index buffers done updating - if(sDisableVBOMapping) + if(!mMappable) { if (!mMappedVertexRegions.empty()) { @@ -1644,7 +1693,7 @@ void LLVertexBuffer::unmapBuffer() const MappedRegion& region = mMappedVertexRegions[i]; S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; S32 length = sTypeSize[region.mType]*region.mCount; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset); stop_glerror(); } @@ -1653,7 +1702,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData); stop_glerror(); } } @@ -1671,6 +1720,7 @@ void LLVertexBuffer::unmapBuffer() S32 length = sTypeSize[region.mType]*region.mCount; if (gGLManager.mHasMapBufferRange) { + LLFastTimer t(FTM_VBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); #endif @@ -1698,8 +1748,9 @@ void LLVertexBuffer::unmapBuffer() if (mMappedIndexData && mIndexLocked) { + LLFastTimer t(FTM_IBO_UNMAP); bindGLIndices(); - if(sDisableVBOMapping) + if(!mMappable) { if (!mMappedIndexRegions.empty()) { @@ -1708,7 +1759,7 @@ void LLVertexBuffer::unmapBuffer() const MappedRegion& region = mMappedIndexRegions[i]; S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; S32 length = sizeof(U16)*region.mCount; - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset); stop_glerror(); } @@ -1717,7 +1768,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData); stop_glerror(); } } @@ -1734,6 +1785,7 @@ void LLVertexBuffer::unmapBuffer() S32 length = sizeof(U16)*region.mCount; if (gGLManager.mHasMapBufferRange) { + LLFastTimer t(FTM_IBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); #endif @@ -1778,7 +1830,7 @@ template <class T,S32 type> struct VertexBufferStrider { if (type == LLVertexBuffer::TYPE_INDEX) { - U8* ptr = vbo.mapIndexBuffer(index, count, map_range); + volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); if (ptr == NULL) { @@ -1794,7 +1846,7 @@ template <class T,S32 type> struct VertexBufferStrider { S32 stride = LLVertexBuffer::sTypeSize[type]; - U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); + volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); if (ptr == NULL) { @@ -2109,7 +2161,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER); stop_glerror(); - U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; /*if ((data_mask & mTypeMask) != data_mask) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 3e6f6a959a..e1cbfd3b61 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -60,10 +60,10 @@ public: U32 mType; //size MUST be a power of 2 - U8* allocate(U32& name, U32 size); + volatile U8* allocate(U32& name, U32 size); //size MUST be the size provided to allocate that returned the given name - void release(U32 name, U8* buffer, U32 size); + void release(U32 name, volatile U8* buffer, U32 size); //destroy all records in mFreeList void cleanup(); @@ -72,7 +72,7 @@ public: { public: U32 mGLName; - U8* mClientData; + volatile U8* mClientData; }; typedef std::list<Record> record_list_t; @@ -208,8 +208,8 @@ public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); - U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); + volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 @@ -244,16 +244,17 @@ public: S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } - U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } U32 getTypeMask() const { return mTypeMask; } bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; S32 getIndicesSize() const { return mIndicesSize; } - U8* getMappedData() const { return mMappedData; } - U8* getMappedIndices() const { return mMappedIndexData; } + volatile U8* getMappedData() const { return mMappedData; } + volatile U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } + BOOL isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; } void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; @@ -278,12 +279,13 @@ protected: U32 mGLIndices; // GL IBO handle U32 mGLArray; // GL VAO handle - U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) - U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) + volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) + volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory BOOL mFinal; // if TRUE, buffer can not be mapped again BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. + mutable BOOL mMappable; // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) S32 mOffsets[TYPE_MAX]; std::vector<MappedRegion> mMappedVertexRegions; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 0e7060e22c..2f1c2a47c9 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -34,6 +34,10 @@ #include "llpanel.h" #include "llresizebar.h" #include "llcriticaldamp.h" +#include "boost/foreach.hpp" + +static const F32 MIN_FRACTIONAL_SIZE = 0.0001f; +static const F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel"); @@ -49,39 +53,29 @@ void LLLayoutStack::OrientationNames::declareValues() // LLLayoutPanel::Params::Params() : expanded_min_dim("expanded_min_dim", 0), - min_dim("min_dim", 0), - max_dim("max_dim", S32_MAX), - user_resize("user_resize", true), + min_dim("min_dim", -1), + user_resize("user_resize", false), auto_resize("auto_resize", true) { addSynonym(min_dim, "min_width"); addSynonym(min_dim, "min_height"); - addSynonym(max_dim, "max_width"); - addSynonym(max_dim, "max_height"); } LLLayoutPanel::LLLayoutPanel(const Params& p) : LLPanel(p), - mExpandedMinDimSpecified(false), - mExpandedMinDim(p.min_dim), + mExpandedMinDim(p.expanded_min_dim.isProvided() ? p.expanded_min_dim : p.min_dim), mMinDim(p.min_dim), - mMaxDim(p.max_dim), mAutoResize(p.auto_resize), mUserResize(p.user_resize), mCollapsed(FALSE), mCollapseAmt(0.f), mVisibleAmt(1.f), // default to fully visible mResizeBar(NULL), - mFractionalSize(0.f), + mFractionalSize(MIN_FRACTIONAL_SIZE), + mTargetDim(0), + mIgnoreReshape(false), mOrientation(LLLayoutStack::HORIZONTAL) { - // Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value - if (p.expanded_min_dim.isProvided()) - { - mExpandedMinDimSpecified = true; - mExpandedMinDim = p.expanded_min_dim(); - } - // panels initialized as hidden should not start out partially visible if (!getVisible()) { @@ -103,33 +97,83 @@ LLLayoutPanel::~LLLayoutPanel() mResizeBar = NULL; } -void LLLayoutPanel::reshape(S32 width, S32 height, BOOL called_from_parent) +F32 LLLayoutPanel::getAutoResizeFactor() const +{ + return mVisibleAmt * (1.f - mCollapseAmt); +} + +F32 LLLayoutPanel::getVisibleAmount() const +{ + return mVisibleAmt; +} + +S32 LLLayoutPanel::getLayoutDim() const +{ + return llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight())); +} + +S32 LLLayoutPanel::getVisibleDim() const +{ + F32 min_dim = getRelevantMinDim(); + return llround(mVisibleAmt + * (min_dim + + (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); +} + +void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation ) +{ + mOrientation = orientation; + S32 layout_dim = llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight())); + + mTargetDim = llmax(layout_dim, getMinDim()); +} + +void LLLayoutPanel::setVisible( BOOL visible ) { - if (mOrientation == LLLayoutStack::HORIZONTAL) + if (visible != getVisible()) { - mFractionalSize += width - llround(mFractionalSize); + LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); + if (stackp) + { + stackp->mNeedsLayout = true; + } } - else + LLPanel::setVisible(visible); +} + +void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ ) +{ + if (width == getRect().getWidth() && height == getRect().getHeight()) return; + + if (!mIgnoreReshape && mAutoResize == false) { - mFractionalSize += height - llround(mFractionalSize); + mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height; + LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); + if (stackp) + { + stackp->mNeedsLayout = true; + } } LLPanel::reshape(width, height, called_from_parent); } -F32 LLLayoutPanel::getCollapseFactor() +void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) { - if (mOrientation == LLLayoutStack::HORIZONTAL) + LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); + if (stackp) { - F32 collapse_amt = - clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth())); - return mVisibleAmt * collapse_amt; - } - else - { - F32 collapse_amt = - clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight()))); - return mVisibleAmt * collapse_amt; + stackp->mNeedsLayout = true; + if (by_user) + { + // tell layout stack to account for new shape + stackp->updatePanelRect(this, new_rect); + } } + LLPanel::handleReshape(new_rect, by_user); } // @@ -142,20 +186,21 @@ LLLayoutStack::Params::Params() clip("clip", true), open_time_constant("open_time_constant", 0.02f), close_time_constant("close_time_constant", 0.03f), + resize_bar_overlap("resize_bar_overlap", 1), border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) {} LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) : LLView(p), - mMinWidth(0), - mMinHeight(0), mPanelSpacing(p.border_size), mOrientation(p.orientation), mAnimate(p.animate), mAnimatedThisFrame(false), + mNeedsLayout(true), mClip(p.clip), mOpenTimeConstant(p.open_time_constant), - mCloseTimeConstant(p.close_time_constant) + mCloseTimeConstant(p.close_time_constant), + mResizeBarOverlap(p.resize_bar_overlap) {} LLLayoutStack::~LLLayoutStack() @@ -169,26 +214,26 @@ void LLLayoutStack::draw() { updateLayout(); - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + // always clip to stack itself + LLLocalClipRect clip(getLocalRect()); + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { // clip to layout rectangle, not bounding rectangle - LLRect clip_rect = (*panel_it)->getRect(); + LLRect clip_rect = panelp->getRect(); // scale clipping rectangle by visible amount if (mOrientation == HORIZONTAL) { - clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor()); + clip_rect.mRight = clip_rect.mLeft + panelp->getVisibleDim(); } else { - clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); + clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim(); } - LLPanel* panelp = (*panel_it); - - LLLocalClipRect clip(clip_rect, mClip); - // only force drawing invisible children if visible amount is non-zero - drawChild(panelp, 0, 0, !clip_rect.isEmpty()); + {LLLocalClipRect clip(clip_rect, mClip); + // only force drawing invisible children if visible amount is non-zero + drawChild(panelp, 0, 0, !clip_rect.isEmpty()); + } } mAnimatedThisFrame = false; } @@ -201,12 +246,10 @@ void LLLayoutStack::removeChild(LLView* view) { mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); delete embedded_panelp; + updateFractionalSizes(); + mNeedsLayout = true; } - // need to update resizebars - - calcMinExtents(); - LLView::removeChild(view); } @@ -221,29 +264,15 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group) LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child); if (panelp) { - panelp->mFractionalSize = (mOrientation == HORIZONTAL) - ? panelp->getRect().getWidth() - : panelp->getRect().getHeight(); panelp->setOrientation(mOrientation); mPanels.push_back(panelp); + createResizeBar(panelp); + mNeedsLayout = true; } - return LLView::addChild(child, tab_group); -} + BOOL result = LLView::addChild(child, tab_group); -void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front) -{ - LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move); - LLLayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel); - - if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel) - { - llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl; - return; - } - e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move); - mPanels.erase(it); - it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel); - mPanels.insert(it, embedded_panel_to_move); + updateFractionalSizes(); + return result; } void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) @@ -258,84 +287,274 @@ void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) } } -void LLLayoutStack::removePanel(LLPanel* panel) -{ - removeChild(panel); -} - void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) { LLLayoutPanel* panel_container = findEmbeddedPanel(panel); if (!panel_container) return; panel_container->mCollapsed = collapsed; + mNeedsLayout = true; } -void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize) -{ - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); +static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); - if (panel) +void LLLayoutStack::updateLayout() +{ + LLFastTimer ft(FTM_UPDATE_LAYOUT); + + if (!mNeedsLayout) return; + + bool animation_in_progress = animatePanels(); + F32 total_visible_fraction = 0.f; + F32 total_open_fraction = 0.f; + S32 space_to_distribute = (mOrientation == HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight(); + + // first, assign minimum dimensions + LLLayoutPanel* panelp = NULL; + BOOST_FOREACH(panelp, mPanels) { - panel->mAutoResize = auto_resize; + if (panelp->mAutoResize) + { + panelp->mTargetDim = panelp->getRelevantMinDim(); + if (!panelp->mCollapsed && panelp->getVisible()) + { + total_open_fraction += panelp->mFractionalSize; + } + } + space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount()); + total_visible_fraction += panelp->mFractionalSize; } -} -void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize) + llassert(total_visible_fraction < 1.01f); + + // don't need spacing after last panel + space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; + + F32 fraction_distributed = 0.f; + if (space_to_distribute > 0 && total_visible_fraction > 0.f) + { // give space proportionally to visible auto resize panels + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction); + S32 delta = llround((F32)space_to_distribute * fraction_to_distribute); + fraction_distributed += fraction_to_distribute; + panelp->mTargetDim += delta; + } + } + } + + if (fraction_distributed < total_visible_fraction) + { // distribute any left over pixels to non-collapsed, visible panels + F32 fraction_left = total_visible_fraction - fraction_distributed; + S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction)); + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize + && !panelp->mCollapsed + && panelp->getVisible()) + { + S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction))); + panelp->mTargetDim += space_for_panel; + space_left -= space_for_panel; + total_open_fraction -= panelp->mFractionalSize; + } + } + } + + F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim); + F32 panel_visible_dim = panelp->getVisibleDim(); + + LLRect panel_rect; + if (mOrientation == HORIZONTAL) + { + panel_rect.setLeftTopAndSize(llround(cur_pos), + getRect().getHeight(), + llround(panel_dim), + getRect().getHeight()); + } + else + { + panel_rect.setLeftTopAndSize(0, + llround(cur_pos), + getRect().getWidth(), + llround(panel_dim)); + } + panelp->setIgnoreReshape(true); + panelp->setShape(panel_rect); + panelp->setIgnoreReshape(false); + + LLRect resize_bar_rect(panel_rect); + + F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); + if (mOrientation == HORIZONTAL) + { + resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap; + resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap; + + cur_pos += panel_visible_dim + panel_spacing; + } + else //VERTICAL + { + resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap; + resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap; + + cur_pos -= panel_visible_dim + panel_spacing; + } + panelp->mResizeBar->setShape(resize_bar_rect); + } + + updateResizeBarLimits(); + + // clear animation flag at end, since panel resizes will set it + // and leave it set if there is any animation in progress + mNeedsLayout = animation_in_progress; +} // end LLLayoutStack::updateLayout + +LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const { - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); + if (!panelp) return NULL; - if (panel) + e_panel_list_t::const_iterator panel_it; + BOOST_FOREACH(LLLayoutPanel* p, mPanels) { - panel->mUserResize = user_resize; + if (p == panelp) + { + return p; + } } + return NULL; } -bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp) +LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const { - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); + LLLayoutPanel* result = NULL; - if (panel && min_dimp) + BOOST_FOREACH(LLLayoutPanel* p, mPanels) { - *min_dimp = panel->getRelevantMinDim(); + if (p->getName() == name) + { + result = p; + break; + } } - return NULL != panel; + return result; } -bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_dimp) +void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) { - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); + BOOST_FOREACH(LLLayoutPanel* lp, mPanels) + { + if (lp->mResizeBar == NULL) + { + LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; + LLRect resize_bar_rect = getRect(); - if (panel) + LLResizeBar::Params resize_params; + resize_params.name("resize"); + resize_params.resizing_view(lp); + resize_params.min_size(lp->getRelevantMinDim()); + resize_params.side(side); + resize_params.snapping_enabled(false); + LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params); + lp->mResizeBar = resize_bar; + LLView::addChild(resize_bar, 0); + } + } + // bring all resize bars to the front so that they are clickable even over the panels + // with a bit of overlap + for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) { - if (max_dimp) *max_dimp = panel->mMaxDim; + LLResizeBar* resize_barp = (*panel_it)->mResizeBar; + sendChildToFront(resize_barp); } +} - return NULL != panel; +// update layout stack animations, etc. once per frame +// NOTE: we use this to size world view based on animating UI, *before* we draw the UI +// we might still need to call updateLayout during UI draw phase, in case UI elements +// are resizing themselves dynamically +//static +void LLLayoutStack::updateClass() +{ + for (instance_iter it = beginInstances(); it != endInstances(); ++it) + { + it->updateLayout(); + } } -static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); -void LLLayoutStack::updateLayout(BOOL force_resize) +void LLLayoutStack::updateFractionalSizes() { - LLFastTimer ft(FTM_UPDATE_LAYOUT); - static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0); - calcMinExtents(); - createResizeBars(); + F32 total_resizable_dim = 0; + S32 num_auto_resize_panels = 0; - // calculate current extents - F32 total_size = 0.f; + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); + num_auto_resize_panels++; + } + } + F32 total_fractional_size = 0.f; + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); + panelp->mFractionalSize = panel_resizable_dim > 0.f + ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) + : MIN_FRACTIONAL_SIZE; + total_fractional_size += panelp->mFractionalSize; + llassert(!llisnan(panelp->mFractionalSize)); + } + } + + if (total_fractional_size == 0.f) + { // equal distribution + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize = MAX_FRACTIONAL_SIZE / (F32)num_auto_resize_panels; + } + } + } + else + { // renormalize + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize /= total_fractional_size; + } + } + } +} + +bool LLLayoutStack::animatePanels() +{ + bool animation_in_progress = false; + // // animate visibility // - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { - LLLayoutPanel* panelp = (*panel_it); - if (panelp->getVisible()) + if (panelp->getVisible()) { - if (mAnimate) + if (mAnimate && panelp->mVisibleAmt < 1.f) { if (!mAnimatedThisFrame) { @@ -345,15 +564,21 @@ void LLLayoutStack::updateLayout(BOOL force_resize) panelp->mVisibleAmt = 1.f; } } + + animation_in_progress = true; } else { - panelp->mVisibleAmt = 1.f; + if (panelp->mVisibleAmt != 1.f) + { + panelp->mVisibleAmt = 1.f; + animation_in_progress = true; + } } } else // not visible { - if (mAnimate) + if (mAnimate && panelp->mVisibleAmt > 0.f) { if (!mAnimatedThisFrame) { @@ -363,297 +588,213 @@ void LLLayoutStack::updateLayout(BOOL force_resize) panelp->mVisibleAmt = 0.f; } } + + animation_in_progress = true; } else { - panelp->mVisibleAmt = 0.f; + if (panelp->mVisibleAmt != 0.f) + { + panelp->mVisibleAmt = 0.f; + animation_in_progress = true; + } } } F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); - - total_size += panelp->mFractionalSize * panelp->getCollapseFactor(); - // want n-1 panel gaps for n panels - if (panel_it != mPanels.begin()) - { - total_size += mPanelSpacing; - } - } - - S32 num_resizable_panels = 0; - F32 shrink_headroom_available = 0.f; - F32 shrink_headroom_total = 0.f; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - - // panels that are not fully visible do not count towards shrink headroom - if (panelp->getCollapseFactor() < 1.f) - { - continue; - } - - F32 cur_size = panelp->mFractionalSize; - F32 min_size = (F32)panelp->getRelevantMinDim(); - - // if currently resizing a panel or the panel is flagged as not automatically resizing - // only track total available headroom, but don't use it for automatic resize logic - if (panelp->mResizeBar->hasMouseCapture() - || (!panelp->mAutoResize - && !force_resize)) - { - shrink_headroom_total += cur_size - min_size; - } - else - { - num_resizable_panels++; - - shrink_headroom_available += cur_size - min_size; - shrink_headroom_total += cur_size - min_size; - } - } - - // calculate how many pixels need to be distributed among layout panels - // positive means panels need to grow, negative means shrink - F32 pixels_to_distribute = (mOrientation == HORIZONTAL) - ? getRect().getWidth() - total_size - : getRect().getHeight() - total_size; - - // now we distribute the pixels... - F32 cur_x = 0.f; - F32 cur_y = (F32)getRect().getHeight(); - - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - - F32 min_size = panelp->getRelevantMinDim(); - F32 delta_size = 0.f; - - // if panel can automatically resize (not animating, and resize flag set)... - if (panelp->getCollapseFactor() == 1.f - && (force_resize || panelp->mAutoResize) - && !panelp->mResizeBar->hasMouseCapture()) + if (panelp->mCollapseAmt != collapse_state) { - if (pixels_to_distribute < 0.f) + if (!mAnimatedThisFrame) { - // shrink proportionally to amount over minimum - // so we can do this in one pass - delta_size = (shrink_headroom_available > 0.f) - ? pixels_to_distribute * ((F32)(panelp->mFractionalSize - min_size) / shrink_headroom_available) - : 0.f; - shrink_headroom_available -= (panelp->mFractionalSize - min_size); + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); } - else + animation_in_progress = true; + + if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) { - // grow all elements equally - delta_size = pixels_to_distribute / (F32)num_resizable_panels; - num_resizable_panels--; + panelp->mCollapseAmt = collapse_state; } - - panelp->mFractionalSize = llmax(min_size, panelp->mFractionalSize + delta_size); - pixels_to_distribute -= delta_size; } + } - // adjust running headroom count based on new sizes - shrink_headroom_total += delta_size; + mAnimatedThisFrame = true; - LLRect panel_rect; - if (mOrientation == HORIZONTAL) - { - panel_rect.setLeftTopAndSize(llround(cur_x), - llround(cur_y), - llround(panelp->mFractionalSize), - getRect().getHeight()); - } - else - { - panel_rect.setLeftTopAndSize(llround(cur_x), - llround(cur_y), - getRect().getWidth(), - llround(panelp->mFractionalSize)); - } - panelp->setShape(panel_rect); + return animation_in_progress; +} - LLRect resize_bar_rect = panel_rect; - if (mOrientation == HORIZONTAL) - { - resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap; - resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + resize_bar_overlap; - } - else - { - resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap; - resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - resize_bar_overlap; - } - (*panel_it)->mResizeBar->setRect(resize_bar_rect); +void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) +{ + S32 new_dim = (mOrientation == HORIZONTAL) + ? new_rect.getWidth() + : new_rect.getHeight(); + S32 delta_dim = new_dim - resized_panel->getVisibleDim(); + if (delta_dim == 0) return; - F32 size = ((*panel_it)->mFractionalSize * (*panel_it)->getCollapseFactor()) + (F32)mPanelSpacing; - if (mOrientation == HORIZONTAL) - { - cur_x += size; - } - else //VERTICAL - { - cur_y -= size; - } - } + F32 total_visible_fraction = 0.f; + F32 delta_auto_resize_headroom = 0.f; + F32 total_auto_resize_headroom = 0.f; - // update resize bars with new limits - LLLayoutPanel* last_resizeable_panel = NULL; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - S32 relevant_min = panelp->getRelevantMinDim(); + LLLayoutPanel* other_resize_panel = NULL; + LLLayoutPanel* following_panel = NULL; - if (mOrientation == HORIZONTAL) + BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) { - (*panel_it)->mResizeBar->setResizeLimits( - relevant_min, - relevant_min + llround(shrink_headroom_total)); + total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); + total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); } - else //VERTICAL + + if (panelp == resized_panel) { - (*panel_it)->mResizeBar->setResizeLimits( - relevant_min, - relevant_min + llround(shrink_headroom_total)); + other_resize_panel = following_panel; } - // toggle resize bars based on panel visibility, resizability, etc - BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize; - (*panel_it)->mResizeBar->setVisible(resize_bar_enabled); - - if ((*panel_it)->mUserResize || (*panel_it)->mAutoResize) + if (panelp->getVisible() && !panelp->mCollapsed) { - last_resizeable_panel = (*panel_it); + following_panel = panelp; } } - // hide last resize bar as there is nothing past it - // resize bars need to be in between two resizable panels - if (last_resizeable_panel) + if (resized_panel->mAutoResize == FALSE) { - last_resizeable_panel->mResizeBar->setVisible(FALSE); + delta_auto_resize_headroom += -delta_dim; } - - // not enough room to fit existing contents - if (force_resize == FALSE - // layout did not complete by reaching target position - && ((mOrientation == VERTICAL && llround(cur_y) != -mPanelSpacing) - || (mOrientation == HORIZONTAL && llround(cur_x) != getRect().getWidth() + mPanelSpacing))) + if (other_resize_panel && other_resize_panel->mAutoResize == FALSE) { - // do another layout pass with all stacked elements contributing - // even those that don't usually resize - llassert_always(force_resize == FALSE); - updateLayout(TRUE); + delta_auto_resize_headroom += delta_dim; } - mAnimatedThisFrame = true; -} // end LLLayoutStack::updateLayout + F32 fraction_given_up = 0.f; + F32 fraction_remaining = 1.f; + F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom; - -LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const -{ - if (!panelp) return NULL; - - e_panel_list_t::const_iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + enum { - if ((*panel_it) == panelp) - { - return *panel_it; - } - } - return NULL; -} + BEFORE_RESIZED_PANEL, + RESIZED_PANEL, + NEXT_PANEL, + AFTER_RESIZED_PANEL + } which_panel = BEFORE_RESIZED_PANEL; -LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const -{ - LLLayoutPanel* result = NULL; - - for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { - LLLayoutPanel* p = *panel_it; + if (!panelp->getVisible() || panelp->mCollapsed) continue; - if (p->getName() == name) + if (panelp == resized_panel) { - result = p; - break; + which_panel = RESIZED_PANEL; } - } - - return result; -} - -// Compute sum of min_width or min_height of children -void LLLayoutStack::calcMinExtents() -{ - mMinWidth = 0; - mMinHeight = 0; - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - if (mOrientation == HORIZONTAL) + switch(which_panel) { - mMinWidth += (*panel_it)->getRelevantMinDim(); - if (panel_it != mPanels.begin()) + case BEFORE_RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze current size as fraction of overall auto_resize space + F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom; + F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); + F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize); + fraction_given_up -= fraction_delta; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize += fraction_delta; + llassert(!llisnan(panelp->mFractionalSize)); + } + else { - mMinWidth += mPanelSpacing; + // leave non auto-resize panels alone } - } - else //VERTICAL - { - mMinHeight += (*panel_it)->getRelevantMinDim(); - if (panel_it != mPanels.begin()) + break; + case RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze new size as fraction + F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) + ? MAX_FRACTIONAL_SIZE + : llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + llassert(!llisnan(panelp->mFractionalSize)); + } + else + { // freeze new size as original size + panelp->mTargetDim = new_dim; + fraction_remaining -= fraction_given_up; + } + which_panel = NEXT_PANEL; + break; + case NEXT_PANEL: + if (panelp->mAutoResize) + { + fraction_remaining -= panelp->mFractionalSize; + if (fraction_given_up != 0.f) + { + panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + fraction_given_up = 0.f; + } + else + { + F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) + / updated_auto_resize_headroom, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + } + } + else + { + panelp->mTargetDim -= delta_dim; + } + which_panel = AFTER_RESIZED_PANEL; + break; + case AFTER_RESIZED_PANEL: + if (panelp->mAutoResize) { - mMinHeight += mPanelSpacing; + panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up, + MIN_FRACTIONAL_SIZE, + MAX_FRACTIONAL_SIZE); } + default: + break; } } } -void LLLayoutStack::createResizeBars() +void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) { - for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + mNeedsLayout = true; + LLView::reshape(width, height, called_from_parent); +} + +void LLLayoutStack::updateResizeBarLimits() +{ + LLLayoutPanel* previous_visible_panelp = NULL; + BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels) { - LLLayoutPanel* lp = (*panel_it); - if (lp->mResizeBar == NULL) + if (!visible_panelp->getVisible() || visible_panelp->mCollapsed) { - LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; - LLRect resize_bar_rect = getRect(); - - LLResizeBar::Params resize_params; - resize_params.name("resize"); - resize_params.resizing_view(lp); - resize_params.min_size(lp->getRelevantMinDim()); - resize_params.side(side); - resize_params.snapping_enabled(false); - LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params); - lp->mResizeBar = resize_bar; - LLView::addChild(resize_bar, 0); + visible_panelp->mResizeBar->setVisible(FALSE); + continue; + } - // bring all resize bars to the front so that they are clickable even over the panels - // with a bit of overlap - for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLResizeBar* resize_barp = (*panel_it)->mResizeBar; - sendChildToFront(resize_barp); - } + // toggle resize bars based on panel visibility, resizability, etc + if (previous_visible_panelp + && (visible_panelp->mUserResize || previous_visible_panelp->mUserResize) // one of the pair is user resizable + && (visible_panelp->mAutoResize || visible_panelp->mUserResize) // current panel is resizable + && (previous_visible_panelp->mAutoResize || previous_visible_panelp->mUserResize)) // previous panel is resizable + { + visible_panelp->mResizeBar->setVisible(TRUE); + S32 previous_panel_headroom = previous_visible_panelp->getVisibleDim() - previous_visible_panelp->getRelevantMinDim(); + visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), + visible_panelp->getVisibleDim() + previous_panel_headroom); + } + else + { + visible_panelp->mResizeBar->setVisible(FALSE); } - } -} -// update layout stack animations, etc. once per frame -// NOTE: we use this to size world view based on animating UI, *before* we draw the UI -// we might still need to call updateLayout during UI draw phase, in case UI elements -// are resizing themselves dynamically -//static -void LLLayoutStack::updateClass() -{ - for (instance_iter it = beginInstances(); it != endInstances(); ++it) - { - it->updateLayout(); + previous_visible_panelp = visible_panelp; } } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 3b308a359d..efe93f6def 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2010, Linden Reshasearch, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -60,6 +60,7 @@ public: clip; Optional<F32> open_time_constant, close_time_constant; + Optional<S32> resize_bar_overlap; Params(); }; @@ -72,12 +73,11 @@ public: /*virtual*/ void removeChild(LLView*); /*virtual*/ BOOL postBuild(); /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - S32 getMinWidth() const { return mMinWidth; } - S32 getMinHeight() const { return mMinHeight; } - typedef enum e_animate { NO_ANIMATE, @@ -85,47 +85,24 @@ public: } EAnimate; void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); - void removePanel(LLPanel* panel); void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE); S32 getNumPanels() { return mPanels.size(); } - /** - * Moves panel_to_move before target_panel inside layout stack (both panels should already be there). - * If move_to_front is true target_panel is ignored and panel_to_move is moved to the beginning of mPanels - */ - void movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front = false); - - void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize); - void setPanelUserResize(const std::string& panel_name, BOOL user_resize); - - /** - * Gets minimal dimension along layout_stack axis of the specified by name panel. - * - * @returns true if specified by panel_name internal panel exists, false otherwise. - */ - bool getPanelMinSize(const std::string& panel_name, S32* min_dimp); - - /** - * Gets maximal dimension along layout_stack axis of the specified by name panel. - * - * @returns true if specified by panel_name internal panel exists, false otherwise. - */ - bool getPanelMaxSize(const std::string& panel_name, S32* max_dim); - - void updateLayout(BOOL force_resize = FALSE); - + + void updateLayout(); + S32 getPanelSpacing() const { return mPanelSpacing; } - BOOL getAnimate () const { return mAnimate; } - void setAnimate (BOOL animate) { mAnimate = animate; } static void updateClass(); protected: LLLayoutStack(const Params&); friend class LLUICtrlFactory; + friend class LLLayoutPanel; private: - void createResizeBars(); - void calcMinExtents(); + void updateResizeBarLimits(); + bool animatePanels(); + void createResizeBar(LLLayoutPanel* panel); const ELayoutOrientation mOrientation; @@ -134,17 +111,19 @@ private: LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const; LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; + void updateFractionalSizes(); + void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); - S32 mMinWidth; // calculated by calcMinExtents - S32 mMinHeight; // calculated by calcMinExtents S32 mPanelSpacing; // true if we already applied animation this frame bool mAnimatedThisFrame; bool mAnimate; bool mClip; - F32 mOpenTimeConstant; - F32 mCloseTimeConstant; + F32 mOpenTimeConstant; + F32 mCloseTimeConstant; + bool mNeedsLayout; + S32 mResizeBarOverlap; }; // end class LLLayoutStack @@ -156,8 +135,7 @@ public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { Optional<S32> expanded_min_dim, - min_dim, - max_dim; + min_dim; Optional<bool> user_resize, auto_resize; @@ -168,16 +146,19 @@ public: void initFromParams(const Params& p); + void handleReshape(const LLRect& new_rect, bool by_user); + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + - S32 getMinDim() const { return mMinDim; } - void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; } + void setVisible(BOOL visible); - S32 getMaxDim() const { return mMaxDim; } - void setMaxDim(S32 value) { mMaxDim = value; } + S32 getLayoutDim() const; + S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); } + void setMinDim(S32 value) { mMinDim = value; } - S32 getExpandedMinDim() const { return mExpandedMinDim; } - void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; } + S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; } + void setExpandedMinDim(S32 value) { mExpandedMinDim = value; } S32 getRelevantMinDim() const { @@ -185,29 +166,35 @@ public: if (!mCollapsed) { - min_dim = mExpandedMinDim; + min_dim = getExpandedMinDim(); } return min_dim; } - F32 getCollapseFactor(); - void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } + F32 getAutoResizeFactor() const; + F32 getVisibleAmount() const; + S32 getVisibleDim() const; + + void setOrientation(LLLayoutStack::ELayoutOrientation orientation); + void storeOriginalDim(); + + void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } protected: LLLayoutPanel(const Params& p); - bool mExpandedMinDimSpecified; + const bool mAutoResize; + const bool mUserResize; + S32 mExpandedMinDim; - S32 mMinDim; - S32 mMaxDim; - bool mAutoResize; - bool mUserResize; bool mCollapsed; F32 mVisibleAmt; F32 mCollapseAmt; F32 mFractionalSize; + S32 mTargetDim; + bool mIgnoreReshape; LLLayoutStack::ELayoutOrientation mOrientation; class LLResizeBar* mResizeBar; }; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 42cfc4cae9..0dc381231d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1948,8 +1948,8 @@ void LLLineEditor::draw() gGL.color4ub(255, 0, 0, 200); while (pxStart < pxEnd) { - gl_line_2d(pxStart, text_bottom - 2, pxStart + 3, text_bottom + 1); - gl_line_2d(pxStart + 3, text_bottom + 1, pxStart + 6, text_bottom - 2); + gl_line_2d(pxStart, (S32)text_bottom - 2, pxStart + 3, (S32)text_bottom + 1); + gl_line_2d(pxStart + 3, (S32)text_bottom + 1, pxStart + 6, (S32)text_bottom - 2); pxStart += 6; } } diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 02f60c76fa..87aeb4d7a7 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -79,6 +79,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask) { + if (!canResize()) return FALSE; + // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. gFocusMgr.setMouseCapture( this ); @@ -243,7 +245,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) handled = TRUE; } - if( handled ) + if( handled && canResize() ) { switch( mSide ) { diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 0725fbd846..6daf191918 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -70,6 +70,7 @@ public: void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; } void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; } + bool canResize() { return getEnabled() && mMaxSize > mMinSize; } private: S32 mDragLastScreenX; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index fe3f688fc5..ad4cc20d9a 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -424,63 +424,66 @@ void LLScrollContainer::draw() focusFirstItem(); } - // Draw background - if( mIsOpaque ) + if (getRect().isValid()) { - F32 alpha = getCurrentTransparency(); + // Draw background + if( mIsOpaque ) + { + F32 alpha = getCurrentTransparency(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha); - } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha); + } - // Draw mScrolledViews and update scroll bars. - // get a scissor region ready, and draw the scrolling view. The - // scissor region ensures that we don't draw outside of the bounds - // of the rectangle. - if( mScrolledView ) - { - updateScroll(); - - // Draw the scrolled area. + // Draw mScrolledViews and update scroll bars. + // get a scissor region ready, and draw the scrolling view. The + // scissor region ensures that we don't draw outside of the bounds + // of the rectangle. + if( mScrolledView ) { - S32 visible_width = 0; - S32 visible_height = 0; - BOOL show_v_scrollbar = FALSE; - BOOL show_h_scrollbar = FALSE; - calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); - - LLLocalClipRect clip(LLRect(mInnerRect.mLeft, - mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, - mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0), - mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) - )); - drawChild(mScrolledView); - } - } - - // Highlight border if a child of this container has keyboard focus - if( mBorder->getVisible() ) - { - mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) ); - } + updateScroll(); - // Draw all children except mScrolledView - // Note: scrollbars have been adjusted by above drawing code - for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); - child_iter != getChildList()->rend(); ++child_iter) - { - LLView *viewp = *child_iter; - if( sDebugRects ) - { - sDepth++; + // Draw the scrolled area. + { + S32 visible_width = 0; + S32 visible_height = 0; + BOOL show_v_scrollbar = FALSE; + BOOL show_h_scrollbar = FALSE; + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + + LLLocalClipRect clip(LLRect(mInnerRect.mLeft, + mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, + mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0), + mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + )); + drawChild(mScrolledView); + } } - if( (viewp != mScrolledView) && viewp->getVisible() ) + + // Highlight border if a child of this container has keyboard focus + if( mBorder->getVisible() ) { - drawChild(viewp); + mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) ); } - if( sDebugRects ) + + // Draw all children except mScrolledView + // Note: scrollbars have been adjusted by above drawing code + for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); + child_iter != getChildList()->rend(); ++child_iter) { - sDepth--; + LLView *viewp = *child_iter; + if( sDebugRects ) + { + sDepth++; + } + if( (viewp != mScrolledView) && viewp->getVisible() ) + { + drawChild(viewp); + } + if( sDebugRects ) + { + sDepth--; + } } } } // end draw diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index 65207144f8..aa39e21a96 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -41,6 +41,7 @@ static const std::string DICT_DIR = "dictionaries"; static const std::string DICT_CUSTOM_SUFFIX = "_custom"; static const std::string DICT_IGNORE_SUFFIX = "_ignore"; +LLSD LLSpellChecker::sDictMap; LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; LLSpellChecker::LLSpellChecker() @@ -86,9 +87,10 @@ S32 LLSpellChecker::getSuggestions(const std::string& word, std::vector<std::str return suggestions.size(); } -const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_name) const +// static +const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_name) { - for (LLSD::array_const_iterator it = mDictMap.beginArray(); it != mDictMap.endArray(); ++it) + for (LLSD::array_const_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) { const LLSD& dict_entry = *it; if (dict_name == dict_entry["language"].asString()) @@ -97,6 +99,7 @@ const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_name) const return LLSD(); } +// static void LLSpellChecker::refreshDictionaryMap() { const std::string app_path = getDictionaryAppPath(); @@ -104,24 +107,22 @@ void LLSpellChecker::refreshDictionaryMap() // Load dictionary information (file name, friendly name, ...) llifstream user_map(user_path + "dictionaries.xml", std::ios::binary); - if ( (!user_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(mDictMap, user_map)) || (0 == mDictMap.size()) ) + if ( (!user_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_map)) || (0 == sDictMap.size()) ) { llifstream app_map(app_path + "dictionaries.xml", std::ios::binary); - if ( (!app_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(mDictMap, app_map)) || (0 == mDictMap.size()) ) + if ( (!app_map.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_map)) || (0 == sDictMap.size()) ) return; } // Look for installed dictionaries std::string tmp_app_path, tmp_user_path; - for (LLSD::array_iterator it = mDictMap.beginArray(); it != mDictMap.endArray(); ++it) + for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it) { LLSD& sdDict = *it; tmp_app_path = (sdDict.has("name")) ? app_path + sdDict["name"].asString() : LLStringUtil::null; tmp_user_path = (sdDict.has("name")) ? user_path + sdDict["name"].asString() : LLStringUtil::null; sdDict["installed"] = - (!tmp_app_path.empty()) && - ( ((gDirUtilp->fileExists(tmp_user_path + ".aff")) && (gDirUtilp->fileExists(tmp_user_path + ".dic"))) || - ((gDirUtilp->fileExists(tmp_app_path + ".aff")) && (gDirUtilp->fileExists(tmp_app_path + ".dic"))) ); + (!tmp_app_path.empty()) && ((gDirUtilp->fileExists(tmp_user_path + ".dic")) || (gDirUtilp->fileExists(tmp_app_path + ".dic"))); sdDict["has_custom"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(tmp_user_path + DICT_CUSTOM_SUFFIX + ".dic")); sdDict["has_ignore"] = (!tmp_user_path.empty()) && (gDirUtilp->fileExists(tmp_user_path + DICT_IGNORE_SUFFIX + ".dic")); } @@ -240,7 +241,7 @@ void LLSpellChecker::initHunspell(const std::string& dict_name) } const LLSD dict_entry = (!dict_name.empty()) ? getDictionaryData(dict_name) : LLSD(); - if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) + if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) || (!dict_entry["is_primary"].asBoolean())) { sSettingsChangeSignal(); return; @@ -343,3 +344,10 @@ void LLSpellChecker::setUseSpellCheck(const std::string& dict_name) LLSpellChecker::instance().initHunspell(dict_name); } } + +// static +void LLSpellChecker::initClass() +{ + if (sDictMap.isUndefined()) + refreshDictionaryMap(); +} diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 8351655b49..d736a7f082 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -28,13 +28,15 @@ #define LLSPELLCHECK_H #include "llsingleton.h" +#include "llui.h" #include <boost/signals2.hpp> class Hunspell; -class LLSpellChecker : public LLSingleton<LLSpellChecker> +class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker> { friend class LLSingleton<LLSpellChecker>; + friend class LLInitClass<LLSpellChecker>; protected: LLSpellChecker(); ~LLSpellChecker(); @@ -52,28 +54,30 @@ public: typedef std::list<std::string> dict_list_t; const std::string& getActiveDictionary() const { return mDictName; } - const LLSD getDictionaryData(const std::string& dict_name) const; - const LLSD& getDictionaryMap() const { return mDictMap; } const dict_list_t& getSecondaryDictionaries() const { return mDictSecondary; } - void refreshDictionaryMap(); void setSecondaryDictionaries(dict_list_t dict_list); static const std::string getDictionaryAppPath(); static const std::string getDictionaryUserPath(); + static const LLSD getDictionaryData(const std::string& dict_name); + static const LLSD& getDictionaryMap() { return sDictMap; } static bool getUseSpellCheck(); + static void refreshDictionaryMap(); static void setUseSpellCheck(const std::string& dict_name); typedef boost::signals2::signal<void()> settings_change_signal_t; static boost::signals2::connection setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb); +protected: + static void initClass(); protected: Hunspell* mHunspell; std::string mDictName; std::string mDictFile; - LLSD mDictMap; dict_list_t mDictSecondary; std::vector<std::string> mIgnoreList; + static LLSD sDictMap; static settings_change_signal_t sSettingsChangeSignal; }; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2231d9b983..ce405cd4a4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -552,7 +552,7 @@ void LLTextBase::drawText() const LLWString& wstrText = getWText(); mMisspellRanges.clear(); - segment_set_t::iterator seg_it = getSegIterContaining(start); + segment_set_t::const_iterator seg_it = getSegIterContaining(start); while (mSegments.end() != seg_it) { LLTextSegmentPtr text_segment = *seg_it; @@ -673,11 +673,15 @@ void LLTextBase::drawText() { // Skip the current word if the user is still busy editing it if ( (!mSpellCheckTimer.hasExpired()) && (misspell_it->first <= (U32)mCursorPos) && (misspell_it->second >= (U32)mCursorPos) ) + { + ++misspell_it; continue; + } + U32 misspell_start = llmax<U32>(misspell_it->first, seg_start), misspell_end = llmin<U32>(misspell_it->second, seg_end); S32 squiggle_start = 0, squiggle_end = 0, pony = 0; - cur_segment->getDimensions(seg_start - cur_segment->getStart(), misspell_it->first - seg_start, squiggle_start, pony); - cur_segment->getDimensions(misspell_it->first - cur_segment->getStart(), misspell_it->second - misspell_it->first, squiggle_end, pony); + cur_segment->getDimensions(seg_start - cur_segment->getStart(), misspell_start - seg_start, squiggle_start, pony); + cur_segment->getDimensions(misspell_start - cur_segment->getStart(), misspell_end - misspell_start, squiggle_end, pony); squiggle_start += text_rect.mLeft; pony = (squiggle_end + 3) / 6; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 004681325f..e1ee0a5b14 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1093,6 +1093,11 @@ void LLView::drawChildren() { child_list_reverse_iter_t child = child_iter++; LLView *viewp = *child; + + if (viewp == NULL) + { + continue; + } if (viewp->getVisible() && viewp->getRect().isValid()) { diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index ae8b30b1ba..f5c463c961 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -160,7 +160,7 @@ void LLWindowShade::draw() notification_area->reshape(notification_area->getRect().getWidth(), llclamp(message_rect.getHeight() + 15, - llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), + llmax(mFormHeight, MIN_NOTIFICATION_AREA_HEIGHT), MAX_NOTIFICATION_AREA_HEIGHT)); LLUICtrl::draw(); @@ -176,12 +176,12 @@ void LLWindowShade::draw() { hide(); } - else if (notification_area->getCollapseFactor() < 0.01f) + else if (notification_area->getVisibleAmount() < 0.01f) { displayLatestNotification(); } - if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f)) + if (!notification_area->getVisible() && (notification_area->getVisibleAmount() < 0.001f)) { getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false); setMouseOpaque(false); @@ -371,6 +371,11 @@ void LLWindowShade::setTextColor(LLColor4 color) getChild<LLTextBox>("notification_text")->setColor(color); } +bool LLWindowShade::isShown() const +{ + return getChildRef<LLLayoutPanel>("notification_area").getVisible(); +} + void LLWindowShade::setCanClose(bool can_close) { getChildView("close_panel")->setVisible(can_close); diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 1ae84028dd..6d753d1161 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -48,6 +48,9 @@ public: void show(LLNotificationPtr); /*virtual*/ void draw(); void hide(); + + bool isShown() const; + void setBackgroundImage(LLUIImage* image); void setTextColor(LLColor4 color); void setCanClose(bool can_close); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 954b9f2b15..228fbefd19 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1747,7 +1747,7 @@ void LLWindowWin32::gatherInput() LLMemType m1(LLMemType::MTYPE_GATHER_INPUT); - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE) + while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput"); TranslateMessage(&msg); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bb0c4a9979..0ec3e0e08a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -217,6 +217,7 @@ set(viewer_SOURCE_FILES llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp + llfloateroutbox.cpp llfloaterpay.cpp llfloaterperms.cpp llfloaterpostprocess.cpp @@ -315,6 +316,8 @@ set(viewer_SOURCE_FILES llmaniprotate.cpp llmanipscale.cpp llmaniptranslate.cpp + llmarketplacefunctions.cpp + llmarketplacenotifications.cpp llmediactrl.cpp llmediadataclient.cpp llmemoryview.cpp @@ -371,7 +374,6 @@ set(viewer_SOURCE_FILES llpanelmaininventory.cpp llpanelmarketplaceinbox.cpp llpanelmarketplaceinboxinventory.cpp - llpanelmarketplaceoutbox.cpp llpanelmarketplaceoutboxinventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp @@ -771,6 +773,7 @@ set(viewer_HEADER_FILES llfloaternotificationsconsole.h llfloaterobjectweights.h llfloateropenobject.h + llfloateroutbox.h llfloaterpay.h llfloaterperms.h llfloaterpostprocess.h @@ -869,6 +872,8 @@ set(viewer_HEADER_FILES llmaniprotate.h llmanipscale.h llmaniptranslate.h + llmarketplacefunctions.h + llmarketplacenotifications.h llmediactrl.h llmediadataclient.h llmemoryview.h @@ -919,7 +924,6 @@ set(viewer_HEADER_FILES llpanelmaininventory.h llpanelmarketplaceinbox.h llpanelmarketplaceinboxinventory.h - llpanelmarketplaceoutbox.h llpanelmarketplaceoutboxinventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index a44b895f7b..1d1d39c786 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -135,6 +135,16 @@ is_running_function="Floater.IsOpen" is_running_parameters="moveview" /> + <command name="outbox" + available_in_toybox="false" + icon="Command_Outbox_Icon" + label_ref="Command_Outbox_Label" + tooltip_ref="Command_Outbox_Tooltip" + execute_function="Floater.ToggleOrBringToFront" + execute_parameters="outbox" + is_running_function="Floater.IsOpen" + is_running_parameters="outbox" + /> <command name="people" available_in_toybox="true" icon="Command_People_Icon" diff --git a/indra/newview/app_settings/dictionaries/dictionaries.xml b/indra/newview/app_settings/dictionaries/dictionaries.xml new file mode 100644 index 0000000000..0ba959766b --- /dev/null +++ b/indra/newview/app_settings/dictionaries/dictionaries.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>name</key> + <string>en_gb</string> + <key>is_primary</key> + <boolean>1</boolean> + <key>language</key> + <string>English (United Kingdom)</string> + </map> + <map> + <key>name</key> + <string>en_us</string> + <key>is_primary</key> + <boolean>1</boolean> + <key>language</key> + <string>English (United States)</string> + </map> + <map> + <key>name</key> + <string>es_es</string> + <key>is_primary</key> + <boolean>1</boolean> + <key>language</key> + <string>Español (España)</string> + </map> + <map> + <key>name</key> + <string>pt_br</string> + <key>is_primary</key> + <boolean>1</boolean> + <key>language</key> + <string>Português (Brasil)</string> + </map> + <map> + <key>name</key> + <string>sl</string> + <key>is_primary</key> + <boolean>0</boolean> + <key>language</key> + <string>Second Life Glossary</string> + </map> + </array> +</llsd> diff --git a/indra/newview/app_settings/dictionaries/sl.dic b/indra/newview/app_settings/dictionaries/sl.dic new file mode 100644 index 0000000000..06decad74b --- /dev/null +++ b/indra/newview/app_settings/dictionaries/sl.dic @@ -0,0 +1,226 @@ +225
+account
+aditi
+adult
+agent
+agni
+alpha
+alt
+animation
+AR
+asset
+attachment
+autoreturn
+avatar
+avie
+baked
+ban
+banlines
+banlist
+BDSM
+beacon
+bling
+block
+blog
+blogger
+bodyparts
+bot
+box
+build
+busy
+cache
+cage
+camp
+campie
+Catznip
+chim
+classified
+client
+coalesced
+collar
+collision
+combat
+community
+concierge
+conference
+continent
+contribution
+coordinate
+copy
+covenant
+CS
+damage
+damage-enabled
+death
+deed
+detach
+displayname
+Dolphin
+drama
+drop
+estate
+event
+face
+facelight
+favorites
+FIC
+Firestorm
+flexible
+flexiprim
+floater
+fly
+flycam
+FMOD
+follower
+forums
+freebie
+freeze
+friendship
+fullperm
+furry
+gadget
+general
+gesture
+goo
+grid
+gridnaut
+griefer
+griefing
+ground
+group
+GSLR
+GUI
+Havok
+hippo
+hippotropolis
+home
+homestead
+host
+HUD
+IM
+impostors
+Imprudence
+indra
+infohub
+inspector
+inventory
+invisiprim
+inworld
+island
+item
+JIRA
+JPEG2000
+Kakadu
+KDU
+kick
+L$
+lag
+land
+landmark
+LDPW
+liaison
+library
+limits
+linden
+LindeX
+link
+linkset
+live
+lock
+log
+machinima
+mainland
+mainlanders
+map
+marketplace
+mature
+media
+mega
+megaprim
+mentor
+mesh
+minimap
+mini-map
+moderate
+modify
+mono
+morph
+MOTD
+mouselook
+mouseview
+move
+mute
+neko
+newbie
+non-physical
+notecard
+NPIOF
+object
+occlusion
+off-world
+officer
+offline
+ogg
+online
+ONSR
+openspace
+orbiter
+orientation
+parcel
+particles
+partner
+permission
+PG
+phantom
+Phoenix
+physics
+pick
+poofer
+position
+premium
+prim
+primitar
+primitive
+profile
+quaternion
+Radegast
+region
+relog
+resi
+resident
+return
+rez
+rezday
+RLV
+RLVa
+roleplay
+run
+ruth
+script
+sculpted
+sculptie
+sculpty
+shout
+sim
+simulator
+Singularity
+skin
+SLEX
+SLurl
+snapshot
+stipend
+telehub
+teleport
+terraform
+texture
+tier
+TOS
+transfer
+unlink
+username
+UUID
+vendor
+viewer
+walk
+whisper
+windlight
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1ad3ee1dd1..7dc06cda0e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1828,6 +1828,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>CurlMaximumNumberOfHandles</key> + <map> + <key>Comment</key> + <string>Maximum number of handles curl can use (requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>256</integer> + </map> + <key>CurlRequestTimeOut</key> + <map> + <key>Comment</key> + <string>Max idle time of a curl request before killed (requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>120.0</real> + </map> <key>CurlUseMultipleThreads</key> <map> <key>Comment</key> @@ -4271,16 +4293,49 @@ <key>Value</key> <integer>0</integer> </map> - <key>InventoryMarketplaceUserStatus</key> + <key>InventoryOutboxLogging</key> + <map> + <key>Comment</key> + <string>Enable debug output associated with the Merchant Outbox.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>InventoryOutboxMaxFolderCount</key> <map> <key>Comment</key> - <string>Marketplace user status.</string> + <string>Maximum number of subfolders allowed in a listing in the merchant outbox.</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> - <string>String</string> + <string>U32</string> <key>Value</key> - <string /> + <integer>21</integer> + </map> + <key>InventoryOutboxMaxFolderDepth</key> + <map> + <key>Comment</key> + <string>Maximum number of nested levels of subfolders allowed in a listing in the merchant outbox.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>4</integer> + </map> + <key>InventoryOutboxMaxItemCount</key> + <map> + <key>Comment</key> + <string>Maximum number of items allowed in a listing in the merchant outbox.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>200</integer> </map> <key>InventorySortOrder</key> <map> @@ -9024,6 +9079,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderAutoMuteByteLimit</key> + <map> + <key>Comment</key> + <string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderAutoMuteSurfaceAreaLimit</key> + <map> + <key>Comment</key> + <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderUseShaderLOD</key> <map> <key>Comment</key> @@ -11345,17 +11422,6 @@ <key>Value</key> <real>3</real> </map> - <key>UIResizeBarOverlap</key> - <map> - <key>Comment</key> - <string>Size of UI resize bar overlap</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <real>1</real> - </map> <key>UIScaleFactor</key> <map> <key>Comment</key> @@ -12102,7 +12168,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>English (United States)</string> + <string>English (United States),Second Life Glossary</string> </map> <key>UseNewWalkRun</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl index 0170ad4b55..40b0cf47ac 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -61,17 +61,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -79,7 +79,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 93b1a114db..8c96d55342 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -70,17 +70,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -88,7 +88,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; @@ -123,7 +123,6 @@ void main() col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); vary_pointlight_col = col.rgb*diffuse_color.rgb; - col.rgb = vec3(0,0,0); // Add windlight lights diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index d7b90978ba..c0edddc40a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -65,17 +65,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -83,7 +83,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl index 5a3955ef00..83815b1786 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -63,21 +63,21 @@ uniform vec3 light_diffuse[8]; float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { - //get light vector +//get light vector vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -85,7 +85,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 9540ddd2e8..1660f9687e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -69,17 +69,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -87,7 +87,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 9c7a332417..84c27edb26 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -66,17 +66,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa vec3 lv = lp.xyz-v; //get distance - float d = length(lv); + float d = dot(lv,lv); float da = 0.0; if (d > 0.0 && la > 0.0 && fa > 0.0) { //normalize light vector - lv *= 1.0/d; + lv = normalize(lv); //distance attenuation - float dist2 = d*d/(la*la); + float dist2 = d/la; da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); // spotlight coefficient. @@ -84,7 +84,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation - da *= calcDirectionalLight(n, lv); + da *= max(dot(n, lv), 0.0); } return da; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 54ad3cd187..ab9b5ff436 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3314,6 +3314,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * } llinfos << "Received cached texture response for " << num_results << " textures." << llendl; + gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them"); gAgentAvatarp->updateMeshTextures(); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 13b62cb019..09305a5b4d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -185,6 +185,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) { if (avatar) { + avatar->outputRezTiming("Sending wearables request"); sendAgentWearablesRequest(); } } @@ -949,6 +950,11 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs if (mInitialWearablesUpdateReceived) return; + if (isAgentAvatarValid()) + { + gAgentAvatarp->outputRezTiming("Received initial wearables update"); + } + // notify subscribers that wearables started loading. See EXT-7777 // *TODO: find more proper place to not be called from deprecated method. // Seems such place is found: LLInitialWearablesFetch::processContents() @@ -1619,6 +1625,11 @@ void LLAgentWearables::queryWearableCache() //VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout if(gAgent.getRegion()) { + if (isAgentAvatarValid()) + { + gAgentAvatarp->outputRezTiming("Fetching textures from cache"); + } + llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); gAgentQueryManager.mNumPendingQueries++; diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 1edc96e165..8cba54347e 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -87,6 +87,10 @@ public: LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) : LLInventoryFetchDescendentsObserver(cof_id) { + if (isAgentAvatarValid()) + { + gAgentAvatarp->outputRezTiming("Initial wearables fetch started"); + } } LLInitialWearablesFetch::~LLInitialWearablesFetch() @@ -101,6 +105,10 @@ void LLInitialWearablesFetch::done() // idle tick instead. gInventory.removeObserver(this); doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this)); + if (isAgentAvatarValid()) + { + gAgentAvatarp->outputRezTiming("Initial wearables fetch done"); + } } void LLInitialWearablesFetch::add(InitialWearableData &data) @@ -111,6 +119,12 @@ void LLInitialWearablesFetch::add(InitialWearableData &data) void LLInitialWearablesFetch::processContents() { + if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted. + { + delete this; + return ; + } + // Fetch the wearable items from the Current Outfit Folder LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h index 7dafab4a33..bedc445c0e 100644 --- a/indra/newview/llagentwearablesfetch.h +++ b/indra/newview/llagentwearablesfetch.h @@ -40,6 +40,8 @@ //-------------------------------------------------------------------- class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver { + LOG_CLASS(LLInitialWearablesFetch); + public: LLInitialWearablesFetch(const LLUUID& cof_id); ~LLInitialWearablesFetch(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 663257042e..33f5373d7e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -268,6 +268,8 @@ struct LLFoundData class LLWearableHoldingPattern { + LOG_CLASS(LLWearableHoldingPattern); + public: LLWearableHoldingPattern(); ~LLWearableHoldingPattern(); @@ -436,6 +438,11 @@ void LLWearableHoldingPattern::checkMissingWearables() void LLWearableHoldingPattern::onAllComplete() { + if (isAgentAvatarValid()) + { + gAgentAvatarp->outputRezTiming("Agent wearables fetch complete"); + } + if (!isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; @@ -2363,6 +2370,8 @@ void LLAppearanceMgr::autopopulateOutfits() // Handler for anything that's deferred until avatar de-clouds. void LLAppearanceMgr::onFirstFullyVisible() { + gAgentAvatarp->outputRezTiming("Avatar fully loaded"); + gAgentAvatarp->reportAvatarRezTime(); gAgentAvatarp->debugAvatarVisible(); // The auto-populate is failing at the point of generating outfits diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d185215a9e..fac5416aab 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -45,6 +45,8 @@ #include "llwindow.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" +#include "llmarketplacefunctions.h" +#include "llmarketplacenotifications.h" #include "llmd5.h" #include "llmeshrepository.h" #include "llpumpio.h" @@ -722,7 +724,9 @@ bool LLAppViewer::init() // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. - LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads")); + LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), + gSavedSettings.getS32("CurlMaximumNumberOfHandles"), + gSavedSettings.getBOOL("CurlUseMultipleThreads")); LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; LLMachineID::init(); @@ -1485,6 +1489,9 @@ void LLAppViewer::flushVFSIO() bool LLAppViewer::cleanup() { + //ditch LLVOAvatarSelf instance + gAgentAvatarp = NULL; + // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); @@ -2495,7 +2502,8 @@ bool LLAppViewer::initConfiguration() if (gSavedSettings.getBOOL("SpellCheck")) { std::list<std::string> dict_list; - boost::split(dict_list, gSavedSettings.getString("SpellCheckDictionary"), boost::is_any_of(std::string(","))); + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); if (!dict_list.empty()) { LLSpellChecker::setUseSpellCheck(dict_list.front()); @@ -4418,6 +4426,10 @@ void LLAppViewer::idle() // update media focus LLViewerMediaFocus::getInstance()->update(); + + // Update marketplace + LLMarketplaceInventoryImporter::update(); + LLMarketplaceInventoryNotifications::update(); // objects and camera should be in sync, do LOD calculations now { diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 7abecc643b..9a7cdcfa21 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -724,7 +724,7 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - inventory_selected_uuids = sidepanel_inventory->getInboxOrOutboxSelectionList(); + inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); } } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 42de47e777..f530d10ddc 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -621,7 +621,6 @@ void LLChatHistory::initFromParams(const LLChatHistory::Params& p) panel_p.has_border = false; panel_p.mouse_opaque = false; panel_p.min_dim = 30; - panel_p.max_dim = S32_MAX; panel_p.auto_resize = true; panel_p.user_resize = false; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index a879651060..f1bc51fbe7 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -42,28 +42,6 @@ namespace { const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel) - { - S32 minimal_width = 0; - llassert(stack); - if ( stack && panel && panel->getVisible() ) - { - stack->getPanelMinSize(panel->getName(), &minimal_width); - } - return minimal_width; - } - - S32 get_panel_max_width(LLLayoutStack* stack, LLPanel* panel) - { - S32 max_width = 0; - llassert(stack); - if ( stack && panel && panel->getVisible() ) - { - stack->getPanelMaxSize(panel->getName(), &max_width); - } - return max_width; - } - S32 get_curr_width(LLUICtrl* ctrl) { S32 cur_width = 0; @@ -234,15 +212,8 @@ void LLChicletBar::reshape(S32 width, S32 height, BOOL called_from_parent) { // Firstly, update layout stack to ensure we deal with correct panel sizes. { - BOOL saved_anim = mToolbarStack->getAnimate(); - // Set chiclet panel to be autoresized by default. - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); - // Disable animation to prevent layout updating in several frames. - mToolbarStack->setAnimate(FALSE); // Force the updating of layout to reset panels collapse factor. mToolbarStack->updateLayout(); - // Restore animate state. - mToolbarStack->setAnimate(saved_anim); } // chiclet bar is narrowed diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index debac9dcbf..21b21c152a 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -1077,6 +1077,7 @@ BOOL LLDrawable::isVisible() const LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) : LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB) { + mBridge = this; mDrawable = root; root->setSpatialBridge(this); @@ -1105,6 +1106,15 @@ LLSpatialBridge::~LLSpatialBridge() { group->mSpatialPartition->remove(this, group); } + + //delete octree here so listeners will still be able to access bridge specific state + destroyTree(); +} + +void LLSpatialBridge::destroyTree() +{ + delete mOctree; + mOctree = NULL; } void LLSpatialBridge::updateSpatialExtents() diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 5a2981e749..64774d06df 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -133,6 +133,7 @@ public: PASS_ALPHA, PASS_ALPHA_MASK, PASS_FULLBRIGHT_ALPHA_MASK, + PASS_ALPHA_INVISIBLE, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ddb7d3ceeb..5b62dbc560 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -337,6 +337,7 @@ void LLDrawPoolAlpha::render(S32 pass) pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); if(shaders) { diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 55b314fbb1..b002c11af5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1285,7 +1285,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face->setGeomIndex(0); face->setIndicesIndex(0); - if (buffer.isNull() || buffer->getTypeMask() != data_mask) + if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) { //make a new buffer if (sShaderLevel > 0) { @@ -1319,7 +1319,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* LLMatrix3 mat_normal(mat3); //let getGeometryVolume know if alpha should override shiny - if (face->getFaceColor().mV[3] < 1.f) + U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); + + if (type == LLDrawPool::POOL_ALPHA) { face->setPoolType(LLDrawPool::POOL_ALPHA); } diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 8f47d3c5e5..64eb11fc9b 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -139,7 +139,7 @@ void LLDriverParamInfo::toStream(std::ostream &out) } else { - llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp << " for driver parameter " << getID() << llendl; + llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl; } out << std::endl; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 6dbeae6677..cd33a19a2a 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -693,6 +693,49 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of tex_coord.mV[1] = t; } +// Transform the texture coordinates for this face. +static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) +{ + //tex coord is two coords, <s0, t0, s1, t1> + LLVector4a st; + + // Texture transforms are done about the center of the face. + st.setAdd(tex_coord, trans); + + // Handle rotation + LLVector4a rot_st; + + // <s0 * cosAng, s0*-sinAng, s1*cosAng, s1*-sinAng> + LLVector4a s0; + s0.splat(st, 0); + LLVector4a s1; + s1.splat(st, 2); + LLVector4a ss; + ss.setSelectWithMask(mask, s1, s0); + + LLVector4a a; + a.setMul(rot0, ss); + + // <t0*sinAng, t0*cosAng, t1*sinAng, t1*cosAng> + LLVector4a t0; + t0.splat(st, 1); + LLVector4a t1; + t1.splat(st, 3); + LLVector4a tt; + tt.setSelectWithMask(mask, t1, t0); + + LLVector4a b; + b.setMul(rot1, tt); + + st.setAdd(a,b); + + // Then scale + st.mul(scale); + + // Then offset + tex_coord.setAdd(st, offset); +} + bool less_than_max_mag(const LLVector4a& vec) { @@ -1060,6 +1103,16 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail"); +static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos"); +static LLFastTimer::DeclareTimer FTM_FACE_TEXTURE_INDEX_STORE("TexIdx"); +static LLFastTimer::DeclareTimer FTM_FACE_POSITION_PAD("Pad"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); + +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, @@ -1078,7 +1131,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, updateRebuildFlags(); } - bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange; + + //don't use map range (generates many redundant unmap calls) + bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange; if (mVertexBuffer.notNull()) { @@ -1104,16 +1159,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } LLStrider<LLVector3> vert; - LLVector4a* vertices = NULL; LLStrider<LLVector2> tex_coords; LLStrider<LLVector2> tex_coords2; - LLVector4a* normals = NULL; LLStrider<LLVector3> norm; LLStrider<LLColor4U> colors; - LLVector4a* binormals = NULL; LLStrider<LLVector3> binorm; LLStrider<U16> indicesp; - LLVector4a* weights = NULL; LLStrider<LLVector4> wght; BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); @@ -1202,7 +1253,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLFastTimer t(FTM_FACE_GEOM_INDEX); mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range); - __m128i* dst = (__m128i*) indicesp.get(); + volatile __m128i* dst = (__m128i*) indicesp.get(); __m128i* src = (__m128i*) vf.mIndices; __m128i offset = _mm_set1_epi16(index_offset); @@ -1211,12 +1262,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < end; i++) { __m128i res = _mm_add_epi16(src[i], offset); - _mm_storeu_si128(dst+i, res); + _mm_storeu_si128((__m128i*) dst++, res); } - for (S32 i = end*8; i < num_indices; ++i) { - indicesp[i] = vf.mIndices[i]+index_offset; + LLFastTimer t(FTM_FACE_GEOM_INDEX_TAIL); + U16* idx = (U16*) dst; + + for (S32 i = end*8; i < num_indices; ++i) + { + *idx++ = vf.mIndices[i]+index_offset; + } } if (map_range) @@ -1373,19 +1429,48 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { + LLFastTimer t(FTM_FACE_TEX_QUICK); if (!do_tex_mat) { if (!do_xform) { + LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); } else { - for (S32 i = 0; i < num_vertices; i++) + LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); + F32* dst = (F32*) tex_coords.get(); + LLVector4a* src = (LLVector4a*) vf.mTexCoords; + + LLVector4a trans; + trans.splat(-0.5f); + + LLVector4a rot0; + rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + + LLVector4a rot1; + rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + + LLVector4a scale; + scale.set(ms, mt, ms, mt); + + LLVector4a offset; + offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<2>(); + mask.setElement<3>(); + + U32 count = num_vertices/2 + num_vertices%2; + + for (S32 i = 0; i < count; i++) { - LLVector2 tc(vf.mTexCoords[i]); - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - *tex_coords++ = tc; + LLVector4a res = *src++; + xform4a(res, trans, mask, rot0, rot1, offset, scale); + res.store4a(dst); + dst += 4; } } } @@ -1407,6 +1492,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //no bump, no atlas, tex gen planar + LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); if (do_tex_mat) { for (S32 i = 0; i < num_vertices; i++) @@ -1451,6 +1537,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //either bump mapped or in atlas, just do the whole expensive loop + LLFastTimer t(FTM_FACE_TEX_DEFAULT); mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); std::vector<LLVector2> bump_tc; @@ -1642,44 +1729,55 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - vertices = (LLVector4a*) vert.get(); - + + LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLVector4a* src = vf.mPositions; - LLVector4a* dst = vertices; + volatile F32* dst = (volatile F32*) vert.get(); - LLVector4a* end = dst+num_vertices; - do - { - mat_vert.affineTransform(*src++, *dst++); - } - while(dst < end); + volatile F32* end = dst+num_vertices*4; + LLVector4a res; - F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); + LLVector4a texIdx; + F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); - F32 *index_dst = (F32*) vertices; - F32 *index_end = (F32*) end; - index_dst += 3; - index_end += 3; - do + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + texIdx.set(0,0,0,index); + { - *index_dst = index; - index_dst += 4; + LLFastTimer t(FTM_FACE_POSITION_STORE); + LLVector4a tmp; + + do + { + mat_vert.affineTransform(*src++, res); + tmp.setSelectWithMask(mask, texIdx, res); + tmp.store4a((F32*) dst); + dst += 4; + } + while(dst < end); } - while (index_dst < index_end); - - S32 aligned_pad_vertices = mGeomCount - num_vertices; - LLVector4a* last_vec = end - 1; - while (aligned_pad_vertices > 0) + { - --aligned_pad_vertices; - *dst++ = *last_vec; + LLFastTimer t(FTM_FACE_POSITION_PAD); + S32 aligned_pad_vertices = mGeomCount - num_vertices; + res.set(res[0], res[1], res[2], 0.f); + + while (aligned_pad_vertices > 0) + { + --aligned_pad_vertices; + res.store4a((F32*) dst); + dst += 4; + } } - + if (map_range) { mVertexBuffer->flush(); @@ -1690,14 +1788,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(FTM_FACE_GEOM_NORMAL); mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); - normals = (LLVector4a*) norm.get(); + F32* normals = (F32*) norm.get(); for (S32 i = 0; i < num_vertices; i++) { LLVector4a normal; mat_normal.rotate(vf.mNormals[i], normal); normal.normalize3fast(); - normals[i] = normal; + normal.store4a(normals); + normals += 4; } if (map_range) @@ -1710,14 +1809,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(FTM_FACE_GEOM_BINORMAL); mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); - binormals = (LLVector4a*) binorm.get(); + F32* binormals = (F32*) binorm.get(); for (S32 i = 0; i < num_vertices; i++) { LLVector4a binormal; mat_normal.rotate(vf.mBinormals[i], binormal); binormal.normalize3fast(); - binormals[i] = binormal; + binormal.store4a(binormals); + binormals += 4; } if (map_range) @@ -1730,8 +1830,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); - weights = (LLVector4a*) wght.get(); - LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + F32* weights = (F32*) wght.get(); + LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); if (map_range) { mVertexBuffer->flush(); @@ -1750,7 +1850,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, src.loadua((F32*) vec); - LLVector4a* dst = (LLVector4a*) colors.get(); + F32* dst = (F32*) colors.get(); S32 num_vecs = num_vertices/4; if (num_vertices%4 > 0) { @@ -1759,7 +1859,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < num_vecs; i++) { - dst[i] = src; + src.store4a(dst); + dst += 4; } if (map_range) @@ -1789,7 +1890,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, src.loadua((F32*) vec); - LLVector4a* dst = (LLVector4a*) emissive.get(); + F32* dst = (F32*) emissive.get(); S32 num_vecs = num_vertices/4; if (num_vertices%4 > 0) { @@ -1798,7 +1899,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < num_vecs; i++) { - dst[i] = src; + src.store4a(dst); + dst += 4; } if (map_range) @@ -1821,6 +1923,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mTexExtents[1][1] *= et ; } + mLastVertexBuffer = mVertexBuffer; mLastGeomCount = mGeomCount; mLastGeomIndex = mGeomIndex; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index b13a9aab88..95da8ff948 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2025,7 +2025,6 @@ void LLPanelLandOptions::refresh() } mSeeAvatarsCtrl->set(parcel->getSeeAVs()); - mSeeAvatarsCtrl->setLabel(getString("see_avs_text")); mSeeAvatarsCtrl->setEnabled(can_change_options && parcel->getHaveNewParcelLimitData()); BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, @@ -2475,27 +2474,6 @@ void LLPanelLandAccess::refresh() mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix); } } - - LLCheckBoxWithTBAcess* maturity_checkbox = (LLCheckBoxWithTBAcess*) getChild<LLCheckBoxCtrl>( "public_access"); - LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if(region) - { - LLTextBox* maturity_textbox = maturity_checkbox->getTextBox(); - insert_maturity_into_textbox(maturity_textbox, gFloaterView->getParentFloater(this), getString("allow_public_access")); - maturity_checkbox->reshape(maturity_checkbox->getRect().getWidth(), maturity_checkbox->getRect().getHeight(), FALSE); - } - else - { - std::string maturity_string = getString("allow_public_access"); - size_t maturity_pos = maturity_string.find(MATURITY); - - if (maturity_pos != std::string::npos) - { - maturity_string.replace(maturity_pos, MATURITY.length(), std::string("")); - } - - maturity_checkbox->setLabel(maturity_string); - } if(parcel->getRegionDenyAnonymousOverride()) { diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 64bdcccd9f..9122e5a8f5 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3969,7 +3969,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices(); if (num_indices > 2) { - glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f); + glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*) mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f); } tri_count += num_indices/3; stop_gloderror(); @@ -4083,14 +4083,14 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim { buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true); buff->setBuffer(type_mask); - glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer()); + glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*) buff->getIndicesPointer()); stop_gloderror(); } else { //this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0) buff->allocateBuffer(1, 3, true); - memset(buff->getMappedData(), 0, buff->getSize()); - memset(buff->getIndicesPointer(), 0, buff->getIndicesSize()); + memset((U8*) buff->getMappedData(), 0, buff->getSize()); + memset((U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize()); } buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0); @@ -4880,8 +4880,8 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget ) LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0); buff->allocateBuffer(1, 3, true); - memset( buff->getMappedData(), 0, buff->getSize() ); - memset( buff->getIndicesPointer(), 0, buff->getIndicesSize() ); + memset( (U8*) buff->getMappedData(), 0, buff->getSize() ); + memset( (U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize() ); buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 ); diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 29af81d64c..2681d4b34d 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -220,7 +220,7 @@ void LLFloaterNotificationConsole::addChannel(const std::string& name, bool open void LLFloaterNotificationConsole::removeChannel(const std::string& name) { LLPanel* panelp = getChild<LLPanel>(name); - getChildRef<LLLayoutStack>("notification_channels").removePanel(panelp); + getChildRef<LLView>("notification_channels").removeChild(panelp); delete panelp; updateResizeLimits(); diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp new file mode 100644 index 0000000000..540f977305 --- /dev/null +++ b/indra/newview/llfloateroutbox.cpp @@ -0,0 +1,567 @@ +/** + * @file llfloateroutbox.cpp + * @brief Implementation of the merchant outbox window + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateroutbox.h" + +#include "llfloaterreg.h" +#include "llfolderview.h" +#include "llinventorybridge.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" +#include "llmarketplacefunctions.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" +#include "lltextbox.h" +#include "lltransientfloatermgr.h" +#include "lltrans.h" +#include "llviewernetwork.h" +#include "llwindowshade.h" + +#define USE_WINDOWSHADE_DIALOGS 0 + + +///---------------------------------------------------------------------------- +/// LLOutboxNotification class +///---------------------------------------------------------------------------- + +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +{ + LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); + + outbox_floater->showNotification(notify); + + return false; +} + + +///---------------------------------------------------------------------------- +/// LLOutboxAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater) + : LLInventoryCategoryAddedObserver() + , mOutboxFloater(outboxFloater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_OUTBOX) + { + mOutboxFloater->setupOutbox(added_category->getUUID()); + } + } + } + +private: + LLFloaterOutbox * mOutboxFloater; +}; + +///---------------------------------------------------------------------------- +/// LLFloaterOutbox +///---------------------------------------------------------------------------- + +LLFloaterOutbox::LLFloaterOutbox(const LLSD& key) + : LLFloater(key) + , mCategoriesObserver(NULL) + , mCategoryAddedObserver(NULL) + , mImportBusy(false) + , mImportButton(NULL) + , mInventoryFolderCountText(NULL) + , mInventoryImportInProgress(NULL) + , mInventoryPlaceholder(NULL) + , mInventoryText(NULL) + , mInventoryTitle(NULL) + , mOutboxId(LLUUID::null) + , mOutboxInventoryPanel(NULL) + , mOutboxItemCount(0) + , mOutboxTopLevelDropZone(NULL) + , mWindowShade(NULL) +{ +} + +LLFloaterOutbox::~LLFloaterOutbox() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterOutbox::postBuild() +{ + mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count"); + mInventoryImportInProgress = getChild<LLView>("import_progress_indicator"); + mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title"); + + mImportButton = getChild<LLButton>("outbox_import_btn"); + mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this)); + + mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target"); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); + + return TRUE; +} + +void LLFloaterOutbox::onClose(bool app_quitting) +{ + if (mWindowShade) + { + delete mWindowShade; + + mWindowShade = NULL; + } +} + +void LLFloaterOutbox::onOpen(const LLSD& key) +{ + // + // Look for an outbox and set up the inventory API + // + + if (mOutboxId.isNull()) + { + const bool do_not_create_folder = false; + const bool do_not_find_in_library = false; + + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); + + if (outbox_id.isNull()) + { + // Observe category creation to catch outbox creation + mCategoryAddedObserver = new LLOutboxAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + } + else + { + setupOutbox(outbox_id); + } + } + + updateView(); + + // + // Trigger fetch of outbox contents + // + + fetchOutboxContents(); +} + +void LLFloaterOutbox::onFocusReceived() +{ + fetchOutboxContents(); +} + +void LLFloaterOutbox::fetchOutboxContents() +{ + if (mOutboxId.notNull()) + { + LLInventoryModelBackgroundFetch::instance().start(mOutboxId); + } +} + +void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) +{ + llassert(outboxId.notNull()); + llassert(mOutboxId.isNull()); + llassert(mCategoriesObserver == NULL); + + mOutboxId = outboxId; + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + + // Create observer for outbox modifications + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); + + // + // Set up the outbox inventory view + // + + mOutboxInventoryPanel = + LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", + mInventoryPlaceholder->getParent(), + LLInventoryPanel::child_registry_t::instance()); + + llassert(mOutboxInventoryPanel); + + // Reshape the inventory to the proper size + LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); + mOutboxInventoryPanel->setShape(inventory_placeholder_rect); + + // Set the sort order newest to oldest + mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + mOutboxInventoryPanel->getFilter()->markDefault(); + + fetchOutboxContents(); + + // + // Initialize the marketplace import API + // + + LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); + + importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2)); + importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); + importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); + importer.initialize(); +} + +void LLFloaterOutbox::setStatusString(const std::string& statusString) +{ + llassert(mInventoryFolderCountText != NULL); + + mInventoryFolderCountText->setText(statusString); +} + +void LLFloaterOutbox::updateFolderCount() +{ + S32 item_count = 0; + + if (mOutboxId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mOutboxId, cats, items); + + item_count = cats->count() + items->count(); + } + + mOutboxItemCount = item_count; + + if (!mImportBusy) + { + updateFolderCountStatus(); + } +} + +void LLFloaterOutbox::updateFolderCountStatus() +{ + if (mOutboxInventoryPanel) + { + switch (mOutboxItemCount) + { + case 0: setStatusString(getString("OutboxFolderCount0")); break; + case 1: setStatusString(getString("OutboxFolderCount1")); break; + default: + { + std::string item_count_str = llformat("%d", mOutboxItemCount); + + LLStringUtil::format_map_t args; + args["[NUM]"] = item_count_str; + + setStatusString(getString("OutboxFolderCountN", args)); + break; + } + } + } + + mImportButton->setEnabled(mOutboxItemCount > 0); +} + +void LLFloaterOutbox::updateView() +{ + updateFolderCount(); + + if (mOutboxItemCount > 0) + { + mOutboxInventoryPanel->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + } + else + { + if (mOutboxInventoryPanel) + { + mOutboxInventoryPanel->setVisible(FALSE); + } + + mInventoryPlaceholder->setVisible(TRUE); + + std::string outbox_text; + std::string outbox_title; + std::string outbox_tooltip; + + const LLSD& subs = getMarketplaceStringSubstitutions(); + + if (mOutboxId.notNull()) + { + outbox_text = LLTrans::getString("InventoryOutboxNoItems", subs); + outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); + } + else + { + outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + + mInventoryText->setValue(outbox_text); + mInventoryTitle->setValue(outbox_title); + mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip); + } +} + +bool isAccepted(EAcceptance accept) +{ + return (accept >= ACCEPT_YES_COPY_SINGLE); +} + +BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if ((mOutboxInventoryPanel == NULL) || + (mWindowShade && mWindowShade->isShown()) || + LLMarketplaceInventoryImporter::getInstance()->isImportInProgress()) + { + return FALSE; + } + + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // Determine if the mouse is inside the inventory panel itself or just within the floater + bool pointInInventoryPanel = false; + bool pointInInventoryPanelChild = false; + LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); + if (mOutboxInventoryPanel->getVisible()) + { + S32 inv_x, inv_y; + localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel); + + pointInInventoryPanel = mOutboxInventoryPanel->getRect().pointInRect(inv_x, inv_y); + + LLView * inventory_panel_child_at_point = mOutboxInventoryPanel->childFromPoint(inv_x, inv_y, true); + pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder); + } + + // Pass all drag and drop for this floater to the outbox inventory control + if (!handled || !isAccepted(*accept)) + { + // Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel + // (otherwise the inventory panel itself will handle the drag and drop operation, without any override) + if (!pointInInventoryPanel) + { + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept)); + } + else + { + mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild); + } + + return handled; +} + +BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask) +{ + mOutboxTopLevelDropZone->setBackgroundVisible(FALSE); + + return LLFloater::handleHover(x, y, mask); +} + +void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mOutboxTopLevelDropZone->setBackgroundVisible(FALSE); + + LLFloater::onMouseLeave(x, y, mask); +} + +void LLFloaterOutbox::onImportButtonClicked() +{ + mOutboxInventoryPanel->clearSelection(); + + mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport(); +} + +void LLFloaterOutbox::onOutboxChanged() +{ + llassert(!mOutboxId.isNull()); + + if (mOutboxInventoryPanel) + { + mOutboxInventoryPanel->requestSort(); + } + + fetchOutboxContents(); + + updateView(); +} + +void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) +{ + if (status == MarketplaceErrorCodes::IMPORT_DONE) + { + LLNotificationsUtil::add("OutboxImportComplete"); + } + else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) + { + const LLSD& subs = getMarketplaceStringSubstitutions(); + + LLNotificationsUtil::add("OutboxImportHadErrors", subs); + } + else + { + char status_string[16]; + sprintf(status_string, "%d", status); + + LLSD subs; + subs["[ERROR_CODE]"] = status_string; + + LLNotificationsUtil::add("OutboxImportFailed", subs); + } + + updateView(); +} + +void LLFloaterOutbox::importStatusChanged(bool inProgress) +{ + if (inProgress) + { + if (mImportBusy) + { + setStatusString(getString("OutboxImporting")); + } + else + { + setStatusString(getString("OutboxInitializing")); + } + + mImportBusy = true; + mImportButton->setEnabled(false); + mInventoryImportInProgress->setVisible(true); + } + else + { + mImportBusy = false; + mImportButton->setEnabled(mOutboxItemCount > 0); + mInventoryImportInProgress->setVisible(false); + } + + updateView(); +} + +void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) +{ + if (status != MarketplaceErrorCodes::IMPORT_DONE) + { + char status_string[16]; + sprintf(status_string, "%d", status); + + LLSD subs; + subs["[ERROR_CODE]"] = status_string; + + LLNotificationsUtil::add("OutboxInitFailed", subs); + } + + updateView(); +} + +void LLFloaterOutbox::showNotification(const LLSD& notify) +{ + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if (!notification) + { + llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; + + return; + } + +#if USE_WINDOWSHADE_DIALOGS + + if (mWindowShade) + { + delete mWindowShade; + } + + LLRect floater_rect = getLocalRect(); + floater_rect.mTop -= getHeaderHeight(); + floater_rect.stretch(-5, 0); + + LLWindowShade::Params params; + params.name = "notification_shade"; + params.rect = floater_rect; + params.follows.flags = FOLLOWS_ALL; + params.modal = true; + params.can_close = false; + params.shade_color = LLColor4::white % 0.25f; + params.text_color = LLColor4::white; + + mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); + + addChild(mWindowShade); + mWindowShade->show(notification); + +#else + + LLNotificationsUI::LLEventHandler * handler = + LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); + + LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); + llassert(sys_handler); + + sys_handler->processNotification(notify); + +#endif +} + diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h new file mode 100644 index 0000000000..18baccf1c9 --- /dev/null +++ b/indra/newview/llfloateroutbox.h @@ -0,0 +1,114 @@ +/** + * @file llfloateroutbox.h + * @brief LLFloaterOutbox + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATEROUTBOX_H +#define LL_LLFLOATEROUTBOX_H + +#include "llfloater.h" +#include "llfoldertype.h" +#include "llnotificationptr.h" + + +class LLButton; +class LLInventoryCategoriesObserver; +class LLInventoryCategoryAddedObserver; +class LLInventoryPanel; +class LLLoadingIndicator; +class LLNotification; +class LLTextBox; +class LLView; +class LLWindowShade; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterOutbox +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFloaterOutbox : public LLFloater +{ +public: + LLFloaterOutbox(const LLSD& key); + ~LLFloaterOutbox(); + + void setupOutbox(const LLUUID& outboxId); + + // virtuals + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void showNotification(const LLSD& notify); + + BOOL handleHover(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + +protected: + void fetchOutboxContents(); + + void importReportResults(U32 status, const LLSD& content); + void importStatusChanged(bool inProgress); + void initializationReportError(U32 status, const LLSD& content); + + void onClose(bool app_quitting); + void onOpen(const LLSD& key); + + void onFocusReceived(); + + void onImportButtonClicked(); + void onOutboxChanged(); + + void setStatusString(const std::string& statusString); + + void updateFolderCount(); + void updateFolderCountStatus(); + void updateView(); + +private: + LLInventoryCategoriesObserver * mCategoriesObserver; + LLInventoryCategoryAddedObserver * mCategoryAddedObserver; + + bool mImportBusy; + LLButton * mImportButton; + + LLTextBox * mInventoryFolderCountText; + LLView * mInventoryImportInProgress; + LLView * mInventoryPlaceholder; + LLTextBox * mInventoryText; + LLTextBox * mInventoryTitle; + + LLUUID mOutboxId; + LLInventoryPanel * mOutboxInventoryPanel; + U32 mOutboxItemCount; + LLPanel * mOutboxTopLevelDropZone; + + LLWindowShade * mWindowShade; +}; + +#endif // LL_LLFLOATEROUTBOX_H diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 29b07d2479..c444d2bb6f 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -448,6 +448,8 @@ BOOL LLFloaterPreference::postBuild() getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); + gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterPreference::refreshDictLists, this, false)); + getChild<LLUICtrl>("combo_spellcheck_dict")->setCommitCallback(boost::bind(&LLFloaterPreference::refreshDictLists, this, false)); getChild<LLUICtrl>("btn_spellcheck_moveleft")->setCommitCallback(boost::bind(&LLFloaterPreference::onClickDictMove, this, "list_spellcheck_active", "list_spellcheck_available")); getChild<LLUICtrl>("btn_spellcheck_moveright")->setCommitCallback(boost::bind(&LLFloaterPreference::onClickDictMove, this, "list_spellcheck_available", "list_spellcheck_active")); @@ -585,14 +587,19 @@ void LLFloaterPreference::apply() if (hasChild("check_spellcheck"), TRUE) { - LLScrollListCtrl* list_ctrl = findChild<LLScrollListCtrl>("list_spellcheck_active"); - std::vector<LLScrollListItem*> list_items = list_ctrl->getAllData(); - std::list<std::string> list_dict; - list_dict.push_back(LLSpellChecker::instance().getActiveDictionary()); - for (std::vector<LLScrollListItem*>::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) - list_dict.push_back((*item_it)->getColumn(0)->getValue().asString()); + LLComboBox* dict_combo = findChild<LLComboBox>("combo_spellcheck_dict"); + const std::string dict_name = dict_combo->getSelectedItemLabel(); + if (!dict_name.empty()) + { + list_dict.push_back(dict_name); + + LLScrollListCtrl* list_ctrl = findChild<LLScrollListCtrl>("list_spellcheck_active"); + std::vector<LLScrollListItem*> list_items = list_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) + list_dict.push_back((*item_it)->getColumn(0)->getValue().asString()); + } gSavedSettings.setString("SpellCheckDictionary", boost::join(list_dict, ",")); } @@ -706,7 +713,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) // Load (double-)click to walk/teleport settings. updateClickActionControls(); - buildDictLists(); + refreshDictLists(true); // Enabled/disabled popups, might have been changed by user actions // while preferences floater was closed. @@ -970,58 +977,80 @@ void LLFloaterPreference::refreshSkin(void* data) self->getChild<LLRadioGroup>("skin_selection", true)->setValue(sSkin); } -void LLFloaterPreference::buildDictLists() +void LLFloaterPreference::refreshDictLists(bool from_settings) { + bool enabled = gSavedSettings.getBOOL("SpellCheck"); + getChild<LLUICtrl>("btn_spellcheck_moveleft")->setEnabled(enabled); + getChild<LLUICtrl>("btn_spellcheck_moveright")->setEnabled(enabled); + + // Populate the dictionary combobox LLComboBox* dict_combo = findChild<LLComboBox>("combo_spellcheck_dict"); + std::string dict_cur = dict_combo->getSelectedItemLabel(); + if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck())) + dict_cur = LLSpellChecker::instance().getActiveDictionary(); dict_combo->clearRows(); + dict_combo->setEnabled(enabled); - LLScrollListCtrl* active_ctrl = findChild<LLScrollListCtrl>("list_spellcheck_active"); - active_ctrl->clearRows(); + const LLSD& dict_map = LLSpellChecker::getDictionaryMap(); + if (dict_map.size()) + { + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict["is_primary"].asBoolean()) && (dict.has("language")) ) + dict_combo->add(dict["language"].asString()); + } + if (!dict_combo->selectByValue(dict_cur)) + dict_combo->clear(); + } + // Populate the available and active dictionary list LLScrollListCtrl* avail_ctrl = findChild<LLScrollListCtrl>("list_spellcheck_available"); - avail_ctrl->clearRows(); + LLScrollListCtrl* active_ctrl = findChild<LLScrollListCtrl>("list_spellcheck_active"); - if (LLSpellChecker::getUseSpellCheck()) + LLSpellChecker::dict_list_t active_list; + if ( ((!avail_ctrl->getItemCount()) && (!active_ctrl->getItemCount())) || (from_settings) ) { - // Populate the main dictionary combobox - const LLSD& dict_map = LLSpellChecker::instance().getDictionaryMap(); - if (dict_map.size()) + if (LLSpellChecker::getUseSpellCheck()) + active_list = LLSpellChecker::instance().getSecondaryDictionaries(); + } + else + { + std::vector<LLScrollListItem*> active_items = active_ctrl->getAllData(); + for (std::vector<LLScrollListItem*>::const_iterator item_it = active_items.begin(); item_it != active_items.end(); ++item_it) { - for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) - { - const LLSD& dict = *dict_it; - if ( (dict["installed"].asBoolean()) && (dict.has("language")) ) - dict_combo->add(dict["language"].asString()); - } - dict_combo->selectByValue(LLSpellChecker::instance().getActiveDictionary()); + std::string dict = (*item_it)->getColumn(0)->getValue().asString(); + if (dict_cur != dict) + active_list.push_back(dict); } + } - LLSD row; - row["columns"][0]["column"] = "name"; - row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][0]["font"]["style"] = "NORMAL"; - - // Populate the active dictionary list - LLSpellChecker::dict_list_t active_list = LLSpellChecker::instance().getSecondaryDictionaries(); - active_ctrl->sortByColumnIndex(0, true); - for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it) - { - row["columns"][0]["value"] = *it; - active_ctrl->addElement(row); - } - active_list.push_back(LLSpellChecker::instance().getActiveDictionary()); + LLSD row; + row["columns"][0]["column"] = "name"; + row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; + row["columns"][0]["font"]["style"] = "NORMAL"; - // Populate the available dictionary list - avail_ctrl->sortByColumnIndex(0, true); - for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + active_ctrl->clearRows(); + active_ctrl->setEnabled(enabled); + active_ctrl->sortByColumnIndex(0, true); + for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it) + { + row["columns"][0]["value"] = *it; + active_ctrl->addElement(row); + } + active_list.push_back(dict_cur); + + avail_ctrl->clearRows(); + avail_ctrl->setEnabled(enabled); + avail_ctrl->sortByColumnIndex(0, true); + for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it) + { + const LLSD& dict = *dict_it; + if ( (dict["installed"].asBoolean()) && (dict.has("language")) && + (active_list.end() == std::find(active_list.begin(), active_list.end(), dict["language"].asString())) ) { - const LLSD& dict = *dict_it; - if ( (dict["installed"].asBoolean()) && (dict.has("language")) && - (active_list.end() == std::find(active_list.begin(), active_list.end(), dict["language"].asString())) ) - { - row["columns"][0]["value"] = dict["language"].asString(); - avail_ctrl->addElement(row); - } + row["columns"][0]["value"] = dict["language"].asString(); + avail_ctrl->addElement(row); } } } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index cd258b5614..f75f71cc3d 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -161,8 +161,8 @@ public: void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); - void buildDictLists(); void buildPopupLists(); + void refreshDictLists(bool from_settings); static void refreshSkin(void* data); private: static std::string sSkin; diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 4c9c4cb154..d741b5b133 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -915,14 +915,16 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) { panel->buildFromFile(path); // build it LLRect new_size = panel->getRect(); // get its rectangle - panel->setOrigin(0,0); // reset its origin point so it's not offset by -left or other XUI attributes + panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) panel->updateBoundingRect(); // update bounding rect LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect LLRect new_rect = panel->getRect(); // get the panel's rect new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible - (*floaterp)->reshape(new_rect.getWidth(), new_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions + LLRect floater_rect = new_rect; + floater_rect.stretch(4, 4); + (*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) (*floaterp)->addChild(panel); // add panel as child (*floaterp)->openFloater(); // open floater (needed?) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index ecd4c2c3de..e0d7d67f7d 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -172,6 +172,7 @@ LLFolderView::Params::Params() title("title"), use_label_suffix("use_label_suffix"), allow_multiselect("allow_multiselect", true), + show_empty_message("show_empty_message", true), show_load_status("show_load_status", true), use_ellipses("use_ellipses", false) { @@ -185,6 +186,7 @@ LLFolderView::LLFolderView(const Params& p) mScrollContainer( NULL ), mPopupMenuHandle(), mAllowMultiSelect(p.allow_multiselect), + mShowEmptyMessage(p.show_empty_message), mShowFolderHierarchy(FALSE), mSourceID(p.task_id), mRenameItem( NULL ), @@ -349,10 +351,6 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } - if (folder->numSelected()) - { - recursiveIncrementNumDescendantsSelected(folder->numSelected()); - } folder->setShowLoadStatus(mShowLoadStatus); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); @@ -694,26 +692,6 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) return rv; } -void LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items) -{ - // now store resulting selection - if (mAllowMultiSelect) - { - LLFolderViewItem *cur_selection = getCurSelectedItem(); - LLFolderViewFolder::extendSelection(selection, cur_selection, items); - for (S32 i = 0; i < items.count(); i++) - { - addToSelectionList(items[i]); - } - } - else - { - setSelection(selection, FALSE, FALSE); - } - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; -} - static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); void LLFolderView::sanitizeSelection() { @@ -932,7 +910,7 @@ void LLFolderView::draw() mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); } - else + else if (mShowEmptyMessage) { if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) { @@ -966,7 +944,6 @@ void LLFolderView::draw() // See EXT-7564, EXT-7047. arrangeFromRoot(); } - } // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, @@ -1222,7 +1199,9 @@ void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_f void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { - if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) + if ((mAutoOpenItems.check() == item) || + (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || + item->isOpen()) { return; } @@ -1945,9 +1924,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { if (getListener()->getUUID().notNull()) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } else { if (!mFolders.empty()) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8af01e9102..1d018b5e6a 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -75,6 +75,7 @@ public: Optional<std::string> title; Optional<bool> use_label_suffix, allow_multiselect, + show_empty_message, show_load_status, use_ellipses; @@ -106,6 +107,8 @@ public: U32 getSortOrder() const; BOOL isFilterModified(); + bool getAllowMultiSelect() { return mAllowMultiSelect; } + // Close all folders in the view void closeAllFolders(); void openTopLevelFolders(); @@ -141,8 +144,6 @@ public: // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); - virtual std::set<LLUUID> getSelectionList() const; // make sure if ancestor is selected, descendents are not @@ -156,7 +157,6 @@ public: void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - // deletion functionality void removeSelectedItems(); @@ -282,6 +282,7 @@ protected: selected_items_t mSelectedItems; BOOL mKeyboardSelection; BOOL mAllowMultiSelect; + BOOL mShowEmptyMessage; BOOL mShowFolderHierarchy; LLUUID mSourceID; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f27fd035db..8d6114c887 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -386,13 +386,6 @@ void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL getRoot()->changeSelection(selection, selected); } -void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection) -{ - LLDynamicArray<LLFolderViewItem*> selected_items; - - getRoot()->extendSelection(selection, NULL, selected_items); -} - std::set<LLUUID> LLFolderViewItem::getSelectionList() const { std::set<LLUUID> selection; @@ -496,10 +489,6 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, if (selection == this && !mIsSelected) { selectItem(); - if (mListener) - { - mListener->selectItem(); - } } else if (mIsSelected) // Deselect everything else. { @@ -510,7 +499,7 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) { - if (selection == this && mIsSelected != selected) + if (selection == this) { if (mIsSelected) { @@ -520,10 +509,6 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte { selectItem(); } - if (mListener) - { - mListener->selectItem(); - } return TRUE; } return FALSE; @@ -531,29 +516,18 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte void LLFolderViewItem::deselectItem(void) { - llassert(mIsSelected); - mIsSelected = FALSE; - - // Update ancestors' count of selected descendents. - LLFolderViewFolder* parent_folder = getParentFolder(); - if (parent_folder) - { - parent_folder->recursiveIncrementNumDescendantsSelected(-1); - } } void LLFolderViewItem::selectItem(void) { - llassert(!mIsSelected); - - mIsSelected = TRUE; - - // Update ancestors' count of selected descendents. - LLFolderViewFolder* parent_folder = getParentFolder(); - if (parent_folder) + if (mIsSelected == FALSE) { - parent_folder->recursiveIncrementNumDescendantsSelected(1); + if (mListener) + { + mListener->selectItem(); + } + mIsSelected = TRUE; } } @@ -697,7 +671,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } else if (mask & MASK_SHIFT) { - extendSelectionFromRoot(this); + getParentFolder()->extendSelectionTo(this); } else { @@ -812,7 +786,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) } else if (mask & MASK_SHIFT) { - extendSelectionFromRoot(this); + getParentFolder()->extendSelectionTo(this); } else { @@ -1125,7 +1099,6 @@ void LLFolderViewItem::draw() LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): LLFolderViewItem( p ), // 0 = no create time - mNumDescendantsSelected(0), mIsOpen(FALSE), mExpanderHighlighted(FALSE), mCurHeight(0.f), @@ -1572,21 +1545,6 @@ BOOL LLFolderViewFolder::hasFilteredDescendants() return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); } -void LLFolderViewFolder::recursiveIncrementNumDescendantsSelected(S32 increment) -{ - LLFolderViewFolder* parent_folder = this; - do - { - parent_folder->mNumDescendantsSelected += increment; - - // Make sure we don't have negative values. - llassert(parent_folder->mNumDescendantsSelected >= 0); - - parent_folder = parent_folder->getParentFolder(); - } - while(parent_folder); -} - // Passes selection information on to children and record selection // information if necessary. BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -1599,10 +1557,6 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem { selectItem(); } - if (mListener) - { - mListener->selectItem(); - } rv = TRUE; } else @@ -1663,10 +1617,6 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec deselectItem(); } } - if (mListener && selected) - { - mListener->selectItem(); - } } for (folders_t::iterator iter = mFolders.begin(); @@ -1690,119 +1640,261 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec return rv; } -void LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items) +LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) { - // pass on to child folders first - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; + + std::deque<LLFolderViewFolder*> item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) { - folders_t::iterator fit = iter++; - (*fit)->extendSelection(selection, last_selected, selected_items); + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); } - // handle selection of our immediate children... - BOOL reverse_select = FALSE; - BOOL found_last_selected = FALSE; - BOOL found_selection = FALSE; - LLDynamicArray<LLFolderViewItem*> items_to_select; - LLFolderViewItem* item; + std::deque<LLFolderViewFolder*> item_b_ancestors; + + parent = item_b->getParentFolder(); + while(parent) + { + item_b_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } - //...folders first... - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + LLFolderViewFolder* common_ancestor = item_a->getRoot(); + + while(item_a_ancestors.size() > item_b_ancestors.size()) { - folders_t::iterator fit = iter++; - item = (*fit); - if(item == selection) - { - found_selection = TRUE; - } - else if (item == last_selected) + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + } + + while(item_b_ancestors.size() > item_a_ancestors.size()) + { + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + while(item_a_ancestors.size()) + { + common_ancestor = item_a_ancestors.front(); + + if (item_a_ancestors.front() == item_b_ancestors.front()) { - found_last_selected = TRUE; - if (found_selection) + // which came first, sibling a or sibling b? + for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); + it != end_it; + ++it) { - reverse_select = TRUE; + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } } - } - if (found_selection || found_last_selected) - { - // deselect currently selected items so they can be pushed back on queue - if (item->isSelected()) + for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); + it != end_it; + ++it) { - item->changeSelection(item, FALSE); + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } } - items_to_select.put(item); + break; } - if (found_selection && found_last_selected) - { - break; - } + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); } - if (!(found_selection && found_last_selected)) + return NULL; +} + +void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items) +{ + bool selecting = start == NULL; + if (reverse) { - //,,,then items - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); + it != end_it; + ++it) { - items_t::iterator iit = iter++; - item = (*iit); - if(item == selection) + if (*it == end) { - found_selection = TRUE; + return; } - else if (item == last_selected) + if (selecting) { - found_last_selected = TRUE; - if (found_selection) - { - reverse_select = TRUE; - } + items.push_back(*it); } - if (found_selection || found_last_selected) + if (*it == start) { - // deselect currently selected items so they can be pushed back on queue - if (item->isSelected()) - { - item->changeSelection(item, FALSE); - } - items_to_select.put(item); + selecting = true; + } + } + for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; } - if (found_selection && found_last_selected) + if (selecting) { - break; + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; } } } - - if (found_last_selected && found_selection) + else { - // we have a complete selection inside this folder - for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0; - reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++) + for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); + it != end_it; + ++it) { - LLFolderViewItem* item = items_to_select[index]; - if (item->changeSelection(item, TRUE)) + if (*it == end) { - selected_items.put(item); + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; } } } - else if (found_selection) +} + +void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) +{ + if (getRoot()->getAllowMultiSelect() == FALSE) return; + + LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); + if (cur_selected_item == NULL) { - // last selection was not in this folder....go ahead and select just the new item - if (selection->changeSelection(selection, TRUE)) + cur_selected_item = new_selection; + } + + + bool reverse = false; + LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); + if (!common_ancestor) return; + + LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; + LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); + + std::vector<LLFolderViewItem*> items_to_select_forward; + + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); + + last_selected_item_from_cur = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + std::vector<LLFolderViewItem*> items_to_select_reverse; + + LLFolderViewItem* last_selected_item_from_new = new_selection; + cur_folder = new_selection->getParentFolder(); + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); + + last_selected_item_from_new = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); + + for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); + it != end_it; + ++it) + { + items_to_select_forward.push_back(*it); + } + + LLFolderView* root = getRoot(); + + for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + if (item->isSelected()) + { + root->removeFromSelectionList(item); + } + else { - selected_items.put(selection); + item->selectItem(); } + root->addToSelectionList(item); + } + + if (new_selection->isSelected()) + { + root->removeFromSelectionList(new_selection); + } + else + { + new_selection->selectItem(); } + root->addToSelectionList(new_selection); } + void LLFolderViewFolder::destroyView() { for (items_t::iterator iter = mItems.begin(); @@ -1874,19 +1966,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) ft = std::find(mFolders.begin(), mFolders.end(), f); if (ft != mFolders.end()) { - if ((*ft)->numSelected()) - { - recursiveIncrementNumDescendantsSelected(-(*ft)->numSelected()); - } mFolders.erase(ft); } } else { - if ((*it)->isSelected()) - { - recursiveIncrementNumDescendantsSelected(-1); - } mItems.erase(it); } //item has been removed, need to update filter @@ -2055,11 +2139,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) { mItems.push_back(item); - if (item->isSelected()) - { - recursiveIncrementNumDescendantsSelected(1); - } - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); item->setVisible(FALSE); @@ -2067,8 +2146,14 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->dirtyFilter(); - // Update the folder creation date if the child is newer than our current date - setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); + // Update the folder creation date if the folder has no creation date + bool setting_date = false; + const time_t item_creation_date = item->getCreationDate(); + if ((item_creation_date > 0) && (mCreationDate == 0)) + { + setCreationDate(item_creation_date); + setting_date = true; + } // Handle sorting requestArrange(); @@ -2078,8 +2163,11 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) LLFolderViewFolder* parentp = getParentFolder(); while (parentp) { - // Update the folder creation date if the child is newer than our current date - parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate())); + // Update the parent folder creation date + if (setting_date && (parentp->mCreationDate == 0)) + { + parentp->setCreationDate(item_creation_date); + } if (parentp->mSortFunction.isByDate()) { @@ -2097,10 +2185,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) { mFolders.push_back(folder); - if (folder->numSelected()) - { - recursiveIncrementNumDescendantsSelected(folder->numSelected()); - } folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); @@ -2276,33 +2360,16 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - LLFolderView* root_view = getRoot(); - BOOL handled = FALSE; - if(mIsOpen) + + if (mIsOpen) { - handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg) != NULL; + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); } if (!handled) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - root_view->autoOpenTest(this); - } + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; } @@ -2310,6 +2377,33 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, return TRUE; } +BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return TRUE; +} + BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 3433e3f7f3..2fc79f5765 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -122,6 +122,8 @@ public: // Mostly for debugging printout purposes. const std::string& getSearchableLabel() { return mSearchableLabel; } + + BOOL isLoading() const { return mIsLoading; } private: BOOL mIsSelected; @@ -164,9 +166,6 @@ protected: // helper function to change the selection from the root. void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); - // helper function to change the selection from the root. - void extendSelectionFromRoot(LLFolderViewItem* selection); - // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } @@ -224,9 +223,6 @@ public: // Returns TRUE if the selection state of this item was changed. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - // this method is used to group select items - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items) { } - // this method is used to deselect this element void deselectItem(); @@ -373,13 +369,6 @@ public: typedef std::list<LLFolderViewItem*> items_t; typedef std::list<LLFolderViewFolder*> folders_t; -private: - S32 mNumDescendantsSelected; - -public: // Accessed needed by LLFolderViewItem - void recursiveIncrementNumDescendantsSelected(S32 increment); - S32 numSelected(void) const { return mNumDescendantsSelected + (isSelected() ? 1 : 0); } - protected: items_t mItems; folders_t mFolders; @@ -461,7 +450,7 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); // this method is used to group select items - virtual void extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); + void extendSelectionTo(LLFolderViewItem* selection); // Returns true is this object and all of its children can be removed. virtual BOOL isRemovable(); @@ -547,11 +536,15 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); virtual void draw(); time_t getCreationDate() const; bool isTrash() const; - S32 getNumSelectedDescendants(void) const { return mNumDescendantsSelected; } folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } @@ -560,6 +553,8 @@ public: items_t::const_iterator getItemsBegin() const { return mItems.begin(); } items_t::const_iterator getItemsEnd() const { return mItems.end(); } items_t::size_type getItemsCount() const { return mItems.size(); } + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); + void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f5cda52d44..f67464078b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -234,12 +234,6 @@ LLIMFloater::~LLIMFloater() //virtual BOOL LLIMFloater::postBuild() { - // User-resizable control panels in P2P sessions look ugly (EXT-3470). - if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE) - { - getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE); - } - const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); if (other_party_id.notNull()) { @@ -385,9 +379,6 @@ void LLIMFloater::onSlide() getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); - - LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels"); - if (stack) stack->setAnimate(true); } //static diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index bf6cf52298..a12ec390af 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -60,12 +60,10 @@ public: private: void update(); - void onNameCache(const LLUUID& id, const std::string& name, bool is_group); private: LLUUID mObjectID; LLUUID mOwnerID; - std::string mOwnerLegacyName; std::string mSLurl; std::string mName; bool mGroupOwned; @@ -75,7 +73,6 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) : LLInspect(LLSD()), mObjectID(NULL), mOwnerID(NULL), - mOwnerLegacyName(), mSLurl(""), mName(""), mGroupOwned(false) @@ -111,14 +108,6 @@ void LLInspectRemoteObject::onOpen(const LLSD& data) mGroupOwned = data["group_owned"].asBoolean(); mSLurl = data["slurl"].asString(); - // work out the owner's name - mOwnerLegacyName = ""; - if (gCacheName) - { - gCacheName->get(mOwnerID, mGroupOwned, // muting - boost::bind(&LLInspectRemoteObject::onNameCache, this, _1, _2, _3)); - } - // update the inspector with the current object state update(); @@ -144,8 +133,7 @@ void LLInspectRemoteObject::onClickMap() void LLInspectRemoteObject::onClickBlock() { - LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT; - LLMute mute(mOwnerID, mOwnerLegacyName, mute_type); + LLMute mute(mObjectID, mName, LLMute::OBJECT); LLMuteList::getInstance()->add(mute); LLPanelBlockedList::showPanelAndSelect(mute.mID); closeFloater(); @@ -156,12 +144,6 @@ void LLInspectRemoteObject::onClickClose() closeFloater(); } -void LLInspectRemoteObject::onNameCache(const LLUUID& id, const std::string& name, bool is_group) -{ - mOwnerLegacyName = name; - update(); -} - void LLInspectRemoteObject::update() { // show the object name as the inspector's title @@ -198,8 +180,8 @@ void LLInspectRemoteObject::update() // disable the Map button if we don't have a SLurl getChild<LLUICtrl>("map_btn")->setEnabled(! mSLurl.empty()); - // disable the Block button if we don't have the owner ID - getChild<LLUICtrl>("block_btn")->setEnabled(! mOwnerID.isNull()); + // disable the Block button if we don't have the object ID (will this ever happen?) + getChild<LLUICtrl>("block_btn")->setEnabled(! mObjectID.isNull()); } ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index eaf9b53eb9..c0065a94e6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -53,6 +53,7 @@ #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" +#include "llmarketplacefunctions.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpreviewanim.h" @@ -60,6 +61,7 @@ #include "llpreviewtexture.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" +#include "lltooldraganddrop.h" #include "lltrans.h" #include "llviewerassettype.h" #include "llviewerfoldertype.h" @@ -71,7 +73,9 @@ #include "llwearablelist.h" // Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 +#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0 +#define BLOCK_WORN_ITEMS_IN_OUTBOX 1 typedef std::pair<LLUUID, LLUUID> two_uuids_t; typedef std::list<two_uuids_t> two_uuids_list_t; @@ -127,6 +131,11 @@ bool isMarketplaceCopyAction(const std::string& action) return (("copy_to_outbox" == action) || ("move_to_outbox" == action)); } +bool isMarketplaceSendAction(const std::string& action) +{ + return ("send_to_marketplace" == action); +} + // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -462,14 +471,13 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, - const menuentry_vec_t &disabled_entries, - BOOL append) // If append is TRUE, then new enabled entries + const menuentry_vec_t &disabled_entries) { const LLView::child_list_t *list = menu.getChildList(); // For removing double separators or leading separator. Start at true so that // if the first element is a separator, it will not be shown. - BOOL is_previous_entry_separator = TRUE; + bool is_previous_entry_separator = true; for (LLView::child_list_t::const_iterator itor = list->begin(); itor != list->end(); @@ -485,7 +493,6 @@ void hide_context_entries(LLMenuGL& menu, hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); } - bool found = false; menuentry_vec_t::const_iterator itor2; for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) @@ -493,6 +500,7 @@ void hide_context_entries(LLMenuGL& menu, if (*itor2 == name) { found = true; + break; } } @@ -500,9 +508,8 @@ void hide_context_entries(LLMenuGL& menu, // between two separators). if (found) { - const BOOL is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL); - if (is_entry_separator && is_previous_entry_separator) - found = false; + const bool is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL); + found = !(is_entry_separator && is_previous_entry_separator); is_previous_entry_separator = is_entry_separator; } @@ -512,6 +519,7 @@ void hide_context_entries(LLMenuGL& menu, { menu_item->setVisible(FALSE); } + menu_item->setEnabled(FALSE); } else @@ -520,17 +528,14 @@ void hide_context_entries(LLMenuGL& menu, // A bit of a hack so we can remember that some UI element explicitly set this to be visible // so that some other UI element from multi-select doesn't later set this invisible. menu_item->pushVisible(TRUE); - if (append) - { - menu_item->setEnabled(TRUE); - } - for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + + bool enabled = (menu_item->getEnabled() == TRUE); + for (itor2 = disabled_entries.begin(); enabled && (itor2 != disabled_entries.end()); ++itor2) { - if (*itor2 == name) - { - menu_item->setEnabled(FALSE); - } + enabled &= (*itor2 != name); } + + menu_item->setEnabled(enabled); } } } @@ -598,25 +603,16 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { items.push_back(std::string("Marketplace Separator")); - bool copyable = true; - LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); - if (inv_item) - { - copyable = inv_item->getPermissions().allowCopyBy(gAgent.getID()); - } - - const std::string merchant_action = ((copyable == true) ? "Merchant Copy" : "Merchant Move"); - items.push_back(merchant_action); - + items.push_back(std::string("Merchant Copy")); if (!canListOnMarketplaceNow()) { - disabled_items.push_back(merchant_action); + disabled_items.push_back(std::string("Merchant Copy")); } } } } - // Don't allow items to be pasted directly into the COF or the inbox + // Don't allow items to be pasted directly into the COF or the inbox/outbox if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) { items.push_back(std::string("Paste")); @@ -657,7 +653,7 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if(isOutboxFolder()) { - items.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, items, disabled_items); } else { @@ -734,6 +730,32 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) items.push_back(std::string("Open")); } +void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + items.push_back(std::string("Rename")); + items.push_back(std::string("Delete")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Rename")); + } + +#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU + if (isOutboxFolderDirectParent()) + { + items.push_back(std::string("Marketplace Separator")); + items.push_back(std::string("Marketplace Send")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Marketplace Send")); + } + } +#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU +} + // *TODO: remove this BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const { @@ -854,6 +876,22 @@ BOOL LLInvFVBridge::isOutboxFolder() const return gInventory.isObjectDescendentOf(mUUID, outbox_id); } +BOOL LLInvFVBridge::isOutboxFolderDirectParent() const +{ + BOOL outbox_is_parent = FALSE; + + const LLInventoryCategory *cat = gInventory.getCategory(mUUID); + + if (cat) + { + const LLUUID outbox_id = getOutboxFolder(); + + outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID())); + } + + return outbox_is_parent; +} + const LLUUID LLInvFVBridge::getOutboxFolder() const { const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); @@ -1040,82 +1078,134 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } -BOOL LLInvFVBridge::canShare() const +bool LLInvFVBridge::canShare() const { - if (!isAgentInventory()) return FALSE; + bool can_share = false; - const LLInventoryModel* model = getInventoryModel(); - if (!model) return FALSE; - - const LLViewerInventoryItem *item = model->getItem(mUUID); - if (item) + if (isAgentInventory()) { - if (!LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) - return FALSE; - return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item); + const LLInventoryModel* model = getInventoryModel(); + if (model) + { + const LLViewerInventoryItem *item = model->getItem(mUUID); + if (item) + { + if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) + { + can_share = LLGiveInventory::isInventoryGiveAcceptable(item); + } + } + else + { + // Categories can be given. + can_share = (model->getCategory(mUUID) != NULL); + } + } } - // Categories can be given. - if (model->getCategory(mUUID)) return TRUE; - - return FALSE; + return can_share; } -BOOL LLInvFVBridge::canListOnMarketplace() const +bool LLInvFVBridge::canListOnMarketplace() const { #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU + LLInventoryModel * model = getInventoryModel(); + const LLViewerInventoryCategory * cat = model->getCategory(mUUID); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { - return FALSE; + return false; } if (!isAgentInventory()) { - return FALSE; + return false; } if (getOutboxFolder().isNull()) { - return FALSE; + return false; } if (isInboxFolder() || isOutboxFolder()) { - return FALSE; + return false; } - + LLViewerInventoryItem * item = model->getItem(mUUID); - if (item && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + if (item) { - return FALSE; + if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + return false; + } + + if (LLAssetType::AT_CALLINGCARD == item->getType()) + { + return false; + } } - return TRUE; + return true; + #else - return FALSE; + return false; #endif } -BOOL LLInvFVBridge::canListOnMarketplaceNow() const +bool LLInvFVBridge::canListOnMarketplaceNow() const { #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - if (get_is_item_worn(mUUID)) + + bool can_list = true; + + // Do not allow listing while import is in progress + if (LLMarketplaceInventoryImporter::instanceExists()) { - return FALSE; + can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress(); } + + const LLInventoryObject* obj = getInventoryObject(); + can_list &= (obj != NULL); - // Loop through all items worn by avatar and check to see if they are descendants - // of the item we are trying to list on the marketplace - if (get_is_parent_to_worn_item(mUUID)) + if (can_list) { - return FALSE; + const LLUUID& object_id = obj->getLinkedUUID(); + can_list = object_id.notNull(); + + if (can_list) + { + LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); + if (object_folderp) + { + can_list = !object_folderp->isLoading(); + } + } + + if (can_list) + { + // Get outbox id + const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); + + if (outbox_itemp) + { + MASK mask = 0x0; + BOOL drop = FALSE; + EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); + void * cargo_data = (void *) obj; + std::string tooltip_msg; + + can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + } + } } + + return can_list; - return TRUE; #else - return FALSE; + return false; #endif } @@ -1225,7 +1315,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) if (!itemp) return; const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); - copy_item_to_outbox(itemp, outbox_id, LLUUID::null); + copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId()); } } @@ -1235,6 +1325,7 @@ void LLItemBridge::selectItem() if(item && !item->isFinished()) { item->fetchFromServer(); + //LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false); } } @@ -1564,11 +1655,7 @@ BOOL LLItemBridge::isItemCopyable() const return FALSE; } - // All items can be copied in god mode since you can - // at least paste-as-link the item, though you - // still may not be able paste the item. - return TRUE; - // return (item->getPermissions().allowCopyBy(gAgent.getID())); + return item->getPermissions().allowCopyBy(gAgent.getID()) || gSavedSettings.getBOOL("InventoryLinking"); } return FALSE; } @@ -1681,12 +1768,8 @@ BOOL LLFolderBridge::isUpToDate() const BOOL LLFolderBridge::isItemCopyable() const { - if (gSavedSettings.getBOOL("InventoryLinking")) - { - // Can copy folders to paste-as-link, but not for straight paste. - return TRUE; - } - return FALSE; + // Can copy folders to paste-as-link, but not for straight paste. + return gSavedSettings.getBOOL("InventoryLinking"); } BOOL LLFolderBridge::copyToClipboard() const @@ -1787,30 +1870,41 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg) { - bool worn = get_is_item_worn(inv_item->getUUID()); + // Collapse links directly to items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + if (linked_item != NULL) + { + inv_item = linked_item; + } + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); - if (!allow_transfer) { tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + return false; } - else if(worn) + +#if BLOCK_WORN_ITEMS_IN_OUTBOX + bool worn = get_is_item_worn(inv_item->getUUID()); + if (worn) { tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + return false; } +#endif - return !worn && allow_transfer; -} - - - -void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) -{ - copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID()); + bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType()); + if (calling_card) + { + tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard"); + return false; + } + + return true; } - int get_folder_levels(LLInventoryCategory* inv_cat) { LLInventoryModel::cat_array_t* cats; @@ -1865,54 +1959,78 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (!isAgentAvatarValid()) return FALSE; if (!isAgentInventory()) return FALSE; // cannot drag categories into library + const LLUUID &cat_id = inv_cat->getUUID(); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id); // check to make sure source is agent inventory, and is represented there. LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL) && (LLToolDragAndDrop::SOURCE_AGENT == source); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL accept = FALSE; if (is_agent_inventory) { - const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); - const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_cat->getUUID(), outbox_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. // BOOL is_movable = TRUE; - if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + + if (is_movable && (mUUID == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipDragOntoSelf"); + } + if (is_movable && (model->isObjectDescendentOf(mUUID, cat_id))) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipDragOntoOwnChild"); + } + if (is_movable && LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { is_movable = FALSE; - if (move_is_into_outfit) + // tooltip? + } + if (is_movable && move_is_into_outfit) + { is_movable = FALSE; - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) + // tooltip? + } + if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE))) + { is_movable = FALSE; + // tooltip? + } + LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - for (S32 i=0; i < descendent_categories.count(); ++i) + if (is_movable) { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); + for (S32 i=0; i < descendent_categories.count(); ++i) { - // Can't move "special folders" (e.g. Textures Folder). - is_movable = FALSE; - break; + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + // Can't move "special folders" (e.g. Textures Folder). + is_movable = FALSE; + break; + } } } - if (move_is_into_trash) + if (is_movable && move_is_into_trash) { for (S32 i=0; i < descendent_items.count(); ++i) { @@ -1924,7 +2042,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - if (move_is_into_landmarks) + if (is_movable && move_is_into_landmarks) { for (S32 i=0; i < descendent_items.count(); ++i) { @@ -1939,35 +2057,100 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - if (move_is_into_outbox) + if (is_movable && move_is_into_outbox) { - for (S32 i=0; i < descendent_items.count(); ++i) + const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + + if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth")) { - LLInventoryItem* item = descendent_items[i]; - if (!can_move_to_outbox(item, tooltip_msg)) - { - is_movable = FALSE; - break; - } + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); + is_movable = FALSE; } + else + { + int dragged_folder_count = descendent_categories.count(); + int existing_item_count = 0; + int existing_folder_count = 0; + + const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); + + if (master_folder != NULL) + { + if (model->isObjectDescendentOf(cat_id, master_folder->getUUID())) + { + // Don't use count because we're already inside the same category anyway + dragged_folder_count = 0; + } + else + { + existing_folder_count = 1; // Include the master folder in the count! + + // If we're in the drop operation as opposed to the drag without drop, we are doing a + // single category at a time so don't block based on the total amount of cargo data items + if (drop) + { + dragged_folder_count += 1; + } + else + { + // NOTE: The cargo id's count is a total of categories AND items but we err on the side of + // prevention rather than letting too many folders into the hierarchy of the outbox, + // when we're dragging the item to a new parent + dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount(); + } + } + + // Tally the total number of categories and items inside the master folder - int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; - if (nested_folder_levels > 4) - { - tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); - is_movable = FALSE; + model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_folder_count += existing_categories.count(); + existing_item_count += existing_items.count(); + } + else + { + // Assume a single category is being dragged to the outbox since we evaluate one at a time + // when not putting them under a parent item. + dragged_folder_count += 1; + } + + const int nested_folder_count = existing_folder_count + dragged_folder_count; + const int nested_item_count = existing_item_count + descendent_items.count(); + + if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders"); + is_movable = FALSE; + } + else if (nested_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); + is_movable = FALSE; + } + + if (is_movable == TRUE) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_outbox(item, tooltip_msg)) + { + is_movable = FALSE; + break; + } + } + } } - } // //-------------------------------------------------------------------------------- - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity + accept = is_movable; + if (accept && drop) { // Look for any gestures and deactivate them @@ -1999,7 +2182,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // Recursively create links in target outfit. LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); } } @@ -2017,7 +2200,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const std::string empty_description = ""; link_inventory_item( gAgent.getID(), - inv_cat->getUUID(), + cat_id, mUUID, inv_cat->getName(), empty_description, @@ -2029,13 +2212,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (move_is_into_outbox && !move_is_from_outbox) { - dropFolderToOutbox(inv_cat); + copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId()); } else { - if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) + if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) { - set_dad_inbox_object(inv_cat->getUUID()); + set_dad_inbox_object(cat_id); } // Reparent the folder and restamp children if it's moving @@ -2050,15 +2233,28 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (LLToolDragAndDrop::SOURCE_WORLD == source) { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); + if (move_is_into_outbox) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + accept = move_inv_category_world_to_agent(cat_id, mUUID, drop); + } } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) { - // Accept folders that contain complete outfits. - accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID()); + if (move_is_into_outbox) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + // Accept folders that contain complete outfits. + accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(cat_id); + } if (accept && drop) { @@ -2201,7 +2397,6 @@ public: delete this; } - protected: LLUUID mCatID; bool mCopyItems; @@ -2450,8 +2645,19 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) if (!cat) return; const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); - copy_folder_to_outbox(cat, outbox_id, cat->getUUID()); + copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId()); } +#if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU + else if (isMarketplaceSendAction(action)) + { + llinfos << "Send to marketplace action!" << llendl; + + LLInventoryCategory * cat = gInventory.getCategory(mUUID); + if (!cat) return; + + send_to_marketplace(cat); + } +#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU } void LLFolderBridge::openItem() @@ -2718,103 +2924,10 @@ void LLFolderBridge::pasteLinkFromClipboard() void LLFolderBridge::staticFolderOptionsMenu() { LLFolderBridge* selfp = sSelf.get(); - if (selfp) - { - selfp->folderOptionsMenu(); - } -} -void LLFolderBridge::folderOptionsMenu() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - const LLInventoryCategory* category = model->getCategory(mUUID); - if(!category) return; - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (trash_id == mUUID) return; - if (isItemInTrash()) return; - if (!isAgentInventory()) return; - if (isOutboxFolder()) return; - - LLFolderType::EType type = category->getPreferredType(); - const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); - // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = (type == LLFolderType::FT_NONE || - LLFolderType::lookupIsEnsembleType(type)); - - // Only enable calling-card related options for non-system folders. - if (!is_system_folder) - { - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) - { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); - } - } - - if (!isItemRemovable()) + if (selfp && selfp->mRoot) { - mDisabledItems.push_back(std::string("Delete")); - } - -#ifndef LL_RELEASE_FOR_DOWNLOAD - if (LLFolderType::lookupIsProtectedType(type)) - { - mItems.push_back(std::string("Delete System Folder")); - } -#endif - - // wearables related functionality for folders. - //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mItems.push_back(std::string("Folder Wearables Separator")); - - // Only enable add/replace outfit for non-system folders. - if (!is_system_folder) - { - // Adding an outfit onto another (versus replacing) doesn't make sense. - if (type != LLFolderType::FT_OUTFIT) - { - mItems.push_back(std::string("Add To Outfit")); - } - - mItems.push_back(std::string("Replace Outfit")); - } - if (is_ensemble) - { - mItems.push_back(std::string("Wear As Ensemble")); - } - mItems.push_back(std::string("Remove From Outfit")); - if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) - { - mDisabledItems.push_back(std::string("Remove From Outfit")); - } - if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) - { - mDisabledItems.push_back(std::string("Replace Outfit")); - } - mItems.push_back(std::string("Outfit Separator")); - } - LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get()); - if (menup) - { - hide_context_entries(*menup, mItems, mDisabledItems, TRUE); - - // Reposition the menu, in case we're adding items to an existing menu. - menup->needsArrange(); - menup->arrangeAndClear(); + selfp->mRoot->updateMenu(); } } @@ -2830,17 +2943,11 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv return ((item_array.count() > 0) ? TRUE : FALSE ); } -// Flags unused -void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) { - mItems.clear(); - mDisabledItems.clear(); - - lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; - -// menuentry_vec_t disabled_items; LLInventoryModel* model = getInventoryModel(); - if(!model) return; + llassert(model != NULL); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); @@ -2857,10 +2964,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.push_back(std::string("New Body Parts")); } - // clear out old menu and folder pointers - mMenu.markDead(); - sSelf.markDead(); - if(trash_id == mUUID) { // This is the trash. @@ -2874,20 +2977,23 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if(isOutboxFolder()) { - mItems.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, mItems, mDisabledItems); } else if(isAgentInventory()) // do not allow creating in library { - LLViewerInventoryCategory *cat = getCategory(); + LLViewerInventoryCategory *cat = getCategory(); // BAP removed protected check to re-enable standard ops in untyped folders. // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox + if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) + { mItems.push_back(std::string("New Folder")); + } + mItems.push_back(std::string("New Script")); mItems.push_back(std::string("New Note")); mItems.push_back(std::string("New Gesture")); @@ -2958,34 +3064,138 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.push_back(std::string("Share")); } } +} - hide_context_entries(menu, mItems, mDisabledItems); +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +{ + // Build folder specific options back up + LLInventoryModel* model = getInventoryModel(); + if(!model) return; - // Add menu items that are dependent on the contents of the folder. - uuid_vec_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) + const LLInventoryCategory* category = model->getCategory(mUUID); + if(!category) return; + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id == mUUID) return; + if (isItemInTrash()) return; + if (!isAgentInventory()) return; + if (isOutboxFolder()) return; + + LLFolderType::EType type = category->getPreferredType(); + const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); + // BAP change once we're no longer treating regular categories as ensembles. + const bool is_ensemble = (type == LLFolderType::FT_NONE || + LLFolderType::lookupIsEnsembleType(type)); + + // Only enable calling-card related options for non-system folders. + if (!is_system_folder) { - folders.push_back(category->getUUID()); + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) + { + mItems.push_back(std::string("Calling Card Separator")); + mItems.push_back(std::string("Conference Chat Folder")); + mItems.push_back(std::string("IM All Contacts In Folder")); + } } - mMenu = menu.getHandle(); - sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); - fetch->startFetch(); - inc_busy_count(); - if(fetch->isFinished()) + if (!isItemRemovable()) { - // everything is already here - call done. - fetch->done(); + mDisabledItems.push_back(std::string("Delete")); } - else + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (LLFolderType::lookupIsProtectedType(type)) { - // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - gInventory.addObserver(fetch); + mItems.push_back(std::string("Delete System Folder")); + } +#endif + + // wearables related functionality for folders. + //is_wearable + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (mWearables || + checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mItems.push_back(std::string("Folder Wearables Separator")); + + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) + { + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (type != LLFolderType::FT_OUTFIT) + { + mItems.push_back(std::string("Add To Outfit")); + } + + mItems.push_back(std::string("Replace Outfit")); + } + if (is_ensemble) + { + mItems.push_back(std::string("Wear As Ensemble")); + } + mItems.push_back(std::string("Remove From Outfit")); + if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) + { + mDisabledItems.push_back(std::string("Remove From Outfit")); + } + if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) + { + mDisabledItems.push_back(std::string("Replace Outfit")); + } + mItems.push_back(std::string("Outfit Separator")); } } +// Flags unused +void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + sSelf.markDead(); + + mItems.clear(); + mDisabledItems.clear(); + + lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + + buildContextMenuBaseOptions(flags); + + // Add menu items that are dependent on the contents of the folder. + LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); + if (category) + { + uuid_vec_t folders; + folders.push_back(category->getUUID()); + + sSelf = getHandle(); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + fetch->startFetch(); + inc_busy_count(); + if (fetch->isFinished()) + { + buildContextMenuFolderOptions(flags); + } + else + { + // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + gInventory.addObserver(fetch); + } + } + + hide_context_entries(menu, mItems, mDisabledItems); + + // Reposition the menu, in case we're adding items to an existing menu. + menu.needsArrange(); + menu.arrangeAndClear(); +} + BOOL LLFolderBridge::hasChildren() const { LLInventoryModel* model = getInventoryModel(); @@ -3306,8 +3516,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLInventoryModel* model = getInventoryModel(); - if(!model || !inv_item) return FALSE; - if(!isAgentInventory()) return FALSE; // cannot drag into library + if (!model || !inv_item) return FALSE; + if (!isAgentInventory()) return FALSE; // cannot drag into library if (!isAgentAvatarValid()) return FALSE; const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3375,10 +3585,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = TRUE; if (!is_movable) + { accept = FALSE; - if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + } + else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + { accept = FALSE; - if (move_is_into_current_outfit || move_is_into_outfit) + } + else if (move_is_into_current_outfit || move_is_into_outfit) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } @@ -3389,9 +3603,32 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, else if (move_is_into_outbox) { accept = can_move_to_outbox(inv_item, tooltip_msg); + + if (accept) + { + const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); + + int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount(); + + if (master_folder != NULL) + { + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; + + gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_item_count += existing_items.count(); + } + + if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); + accept = FALSE; + } + } } - if(accept && drop) + if (accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) @@ -3440,9 +3677,16 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_outbox && !move_is_from_outbox) + else if (move_is_into_outbox) { - copy_item_to_outbox(inv_item, outbox_id, LLUUID::null); + if (move_is_from_outbox) + { + move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId()); + } + else + { + copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId()); + } } // NORMAL or TRASH folder // (move the item, restamp if into trash) @@ -3463,7 +3707,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // //-------------------------------------------------------------------------------- - } } else if (LLToolDragAndDrop::SOURCE_WORLD == source) @@ -3472,7 +3715,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // anonymous objects, it would be possible to bypass // permissions. object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) + if (!object) { llinfos << "Object not found for drop." << llendl; return FALSE; @@ -3482,10 +3725,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // move/copy this item. LLPermissions perm(inv_item->getPermissions()); BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) - { accept = TRUE; } @@ -3501,7 +3743,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // Don't allow placing an original item into Current Outfit or an outfit folder // because they must contain only links to wearable items. // *TODO: Probably we should create a link to an item if it was dragged to outfit or COF. - if(move_is_into_current_outfit || move_is_into_outfit) + if (move_is_into_current_outfit || move_is_into_outfit) { accept = FALSE; } @@ -3512,8 +3754,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = FALSE; } - - if(drop && accept) + else if (move_is_into_outbox) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + + if (accept && drop) { LLMoveInv* move_inv = new LLMoveInv; move_inv->mObjectID = inv_item->getParentUUID(); @@ -3535,15 +3782,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLNotifications::instance().forceResponse(params, 0); } } - } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { - // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder - // because they must contain only links to wearable items. - accept = !(move_is_into_current_outfit || move_is_into_outfit); - - if(accept && drop) + if (move_is_into_outbox) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder + // because they must contain only links to wearable items. + accept = !(move_is_into_current_outfit || move_is_into_outfit); + } + + if (accept && drop) { copy_inventory_from_notecard(mUUID, // Drop to the chosen destination folder LLToolDragAndDrop::getInstance()->getObjectID(), @@ -3558,7 +3812,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = TRUE; - if (move_is_into_current_outfit || move_is_into_outfit) + if (move_is_into_outbox) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else if (move_is_into_current_outfit || move_is_into_outfit) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } @@ -3649,7 +3908,7 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if(isOutboxFolder()) { - items.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, items, disabled_items); } else { @@ -3723,29 +3982,29 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if (isOutboxFolder()) { - items.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, items, disabled_items); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if (isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Sound Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Sound Separator")); items.push_back(std::string("Sound Play")); } @@ -3781,29 +4040,29 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if(isOutboxFolder()) { - items.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, items, disabled_items); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if(isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Landmark Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Landmark Separator")); items.push_back(std::string("About Landmark")); } @@ -4336,36 +4595,35 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if(isOutboxFolder()) { items.push_back(std::string("Delete")); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if(isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Animation Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Animation Separator")); items.push_back(std::string("Animation Play")); items.push_back(std::string("Animation Audition")); } hide_context_entries(menu, items, disabled_items); - } // virtual @@ -5350,7 +5608,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if(isOutboxFolder()) { - items.push_back(std::string("Delete")); + addOutboxContextMenuOptions(flags, items, disabled_items); } else { @@ -5359,7 +5617,6 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 2d625befb4..871657a58a 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -69,9 +69,9 @@ public: U32 flags = 0x00); virtual ~LLInvFVBridge() {} - BOOL canShare() const; - BOOL canListOnMarketplace() const; - BOOL canListOnMarketplaceNow() const; + bool canShare() const; + bool canListOnMarketplace() const; + bool canListOnMarketplaceNow() const; //-------------------------------------------------------------------- // LLInvFVBridge functionality @@ -131,6 +131,9 @@ protected: virtual void addDeleteContextMenuOptions(menuentry_vec_t &items, menuentry_vec_t &disabled_items); virtual void addOpenRightClickMenuOption(menuentry_vec_t &items); + virtual void addOutboxContextMenuOptions(U32 flags, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items); protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); @@ -144,6 +147,7 @@ protected: BOOL isCOFFolder() const; // true if COF or descendent of BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox + BOOL isOutboxFolderDirectParent() const; const LLUUID getOutboxFolder() const; virtual BOOL isItemPermissive() const; @@ -278,6 +282,9 @@ public: LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } protected: + void buildContextMenuBaseOptions(U32 flags); + void buildContextMenuFolderOptions(U32 flags); + //-------------------------------------------------------------------- // Menu callbacks //-------------------------------------------------------------------- @@ -306,8 +313,6 @@ protected: void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); - void dropToOutbox(LLInventoryItem* inv_item); - void dropFolderToOutbox(LLInventoryCategory* inv_cat); //-------------------------------------------------------------------- // Messy hacks for handling folder options @@ -315,12 +320,10 @@ protected: public: static LLHandle<LLFolderBridge> sSelf; static void staticFolderOptionsMenu(); - void folderOptionsMenu(); private: BOOL mCallingCards; BOOL mWearables; - LLHandle<LLView> mMenu; menuentry_vec_t mItems; menuentry_vec_t mDisabledItems; LLRootHandle<LLFolderBridge> mHandle; @@ -650,7 +653,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, // are set as enabled. void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, - const menuentry_vec_t &disabled_entries, - BOOL append = FALSE); + const menuentry_vec_t &disabled_entries); #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 5fb3f15cd5..dd92188e9d 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -58,6 +58,7 @@ #include "llinventorymodel.h" #include "llinventorypanel.h" #include "lllineeditor.h" +#include "llmarketplacenotifications.h" #include "llmenugl.h" #include "llnotificationsutil.h" #include "llpanelmaininventory.h" @@ -82,6 +83,8 @@ #include "llvoavatarself.h" #include "llwearablelist.h" +#include <boost/foreach.hpp> + BOOL LLInventoryState::sWearNewClothing = FALSE; LLUUID LLInventoryState::sWearNewClothingTransactionID; @@ -530,21 +533,37 @@ void show_item_original(const LLUUID& item_uuid) } } -void move_to_outbox_cb(const LLSD& notification, const LLSD& response) + +void open_outbox() +{ + LLFloaterReg::showInstance("outbox"); +} + +LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled + llassert(item); + llassert(destFolderId.notNull()); + + LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName()); + gInventory.notifyObservers(); + + LLNotificationsUtil::add("OutboxFolderCreated"); + + return created_folder_id; +} - LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID(); +void move_to_outbox_cb_action(const LLSD& payload) +{ + LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID()); + LLUUID dest_folder_id = payload["dest_folder_id"].asUUID(); if (viitem) { // when moving item directly into outbox create folder with that name if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) { - dest_folder_id = gInventory.createNewCategory(dest_folder_id, LLFolderType::FT_NONE, viitem->getName()); - gInventory.notifyObservers(); + S32 operation_id = payload["operation_id"].asInteger(); + dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id); } LLUUID parent = viitem->getParentUUID(); @@ -555,12 +574,12 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response) dest_folder_id, false); - LLUUID top_level_folder = notification["payload"]["top_level_folder"].asUUID(); + LLUUID top_level_folder = payload["top_level_folder"].asUUID(); if (top_level_folder != LLUUID::null) { LLViewerInventoryCategory* category; - + while (parent.notNull()) { LLInventoryModel::cat_array_t* cat_array; @@ -589,42 +608,75 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response) } } + open_outbox(); } } - -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder) +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id) { - if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + // Collapse links directly to items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory(); + if (linked_category != NULL) { - // when moving item directly into outbox create folder with that name - if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id); + } + else + { + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + if (linked_item != NULL) { - dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); - gInventory.notifyObservers(); + inv_item = (LLInventoryItem *) linked_item; + } + + // Check for copy permissions + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); + } + + copy_inventory_item(gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + dest_folder, + inv_item->getName(), + LLPointer<LLInventoryCallback>(NULL)); + + open_outbox(); + } + else + { + LLSD payload; + payload["item_id"] = inv_item->getUUID(); + payload["dest_folder_id"] = dest_folder; + payload["top_level_folder"] = top_level_folder; + payload["operation_id"] = operation_id; + + LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action); } - - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - dest_folder, - inv_item->getName(), - LLPointer<LLInventoryCallback>(NULL)); } - else - { - LLSD args; - args["ITEM_NAME"] = inv_item->getName(); - LLSD payload; - payload["item_id"] = inv_item->getUUID(); - payload["dest_folder_id"] = dest_folder; - payload["top_level_folder"] = top_level_folder; - LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); +} + +void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id) +{ + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id); } + + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + + change_item_parent(&gInventory, + viewer_inv_item, + dest_folder, + false); } -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder) +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id) { LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName()); gInventory.notifyObservers(); @@ -639,7 +691,7 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) { LLInventoryItem* item = *iter; - copy_item_to_outbox(item, new_folder_id, top_level_folder); + copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id); } LLInventoryModel::cat_array_t cat_array_copy = *cat_array; @@ -647,14 +699,10 @@ void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_fold for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { LLViewerInventoryCategory* category = *iter; - copy_folder_to_outbox(category, new_folder_id, top_level_folder); + copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id); } - // delete the folder if we have emptied it - //if (cat_array->empty() && item_array->empty()) - //{ - // remove_category(inventory_model, inv_cat->getUUID()); - //} + open_outbox(); } ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 7b452537f8..ce2b89b22e 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -74,9 +74,10 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); -void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder); +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id); +void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id); -void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder); +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id); /** Miscellaneous global functions ** ** diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 568ec4c5e2..a71b699fdd 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -217,6 +217,38 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons return NULL; } +// +// Search up the parent chain until we get to the specified parent, then return the first child category under it +// +const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const +{ + if (master_parent_id == obj_id) + { + return NULL; + } + + const LLViewerInventoryCategory* current_cat = getCategory(obj_id); + + if (current_cat == NULL) + { + current_cat = getCategory(getObject(obj_id)->getParentUUID()); + } + + while (current_cat != NULL) + { + const LLUUID& current_parent_id = current_cat->getParentUUID(); + + if (current_parent_id == master_parent_id) + { + return current_cat; + } + + current_cat = getCategory(current_parent_id); + } + + return NULL; +} + // Get the object by id. Returns NULL if not found. LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 19d1e4e01f..7cd85c4ab7 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -239,6 +239,9 @@ public: // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; + + // Get first descendant of the child object under the specified parent + const LLViewerInventoryCategory *getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const; // Get the object by id. Returns NULL if not found. // NOTE: Use the pointer returned for read operations - do diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 80b53d5702..382569fa3a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -132,6 +132,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mAcceptsDragAndDrop(p.accepts_drag_and_drop), mAllowMultiSelect(p.allow_multi_select), mShowItemLinkOverlays(p.show_item_link_overlays), + mShowEmptyMessage(p.show_empty_message), mShowLoadStatus(p.show_load_status), mViewsInitialized(false), mInvFVBridgeBuilder(NULL) @@ -617,6 +618,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.listener = bridge; p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; + p.show_empty_message = mShowEmptyMessage; p.show_load_status = mShowLoadStatus; return LLUICtrlFactory::create<LLFolderView>(p); @@ -1157,7 +1159,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L LLViewerInventoryCategory * cat = gInventory.getCategory(obj_id); bool in_inbox = false; - bool in_outbox = false; LLViewerInventoryCategory * parent_cat = NULL; @@ -1173,10 +1174,9 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L if (parent_cat) { in_inbox = (LLFolderType::FT_INBOX == parent_cat->getPreferredType()); - in_outbox = (LLFolderType::FT_OUTBOX == parent_cat->getPreferredType()); } - if (in_inbox || in_outbox) + if (in_inbox) { LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); LLInventoryPanel * inventory_panel = NULL; @@ -1186,11 +1186,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L sidepanel_inventory->openInbox(); inventory_panel = sidepanel_inventory->getInboxPanel(); } - else - { - sidepanel_inventory->openOutbox(); - inventory_panel = sidepanel_inventory->getOutboxPanel(); - } if (inventory_panel) { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 2a24327115..8279163762 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -84,6 +84,7 @@ public: Optional<Filter> filter; Optional<std::string> start_folder; Optional<bool> use_label_suffix; + Optional<bool> show_empty_message; Optional<bool> show_load_status; Optional<LLScrollContainer::Params> scroll; Optional<bool> accepts_drag_and_drop; @@ -96,6 +97,7 @@ public: filter("filter"), start_folder("start_folder"), use_label_suffix("use_label_suffix", true), + show_empty_message("show_empty_message", true), show_load_status("show_load_status"), scroll("scroll"), accepts_drag_and_drop("accepts_drag_and_drop") @@ -188,6 +190,7 @@ protected: BOOL mAcceptsDragAndDrop; BOOL mAllowMultiSelect; BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons + BOOL mShowEmptyMessage; BOOL mShowLoadStatus; LLFolderView* mFolderRoot; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp new file mode 100644 index 0000000000..93dd82957f --- /dev/null +++ b/indra/newview/llmarketplacefunctions.cpp @@ -0,0 +1,478 @@ +/** + * @file llmarketplacefunctions.cpp + * @brief Implementation of assorted functions related to the marketplace + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmarketplacefunctions.h" + +#include "llagent.h" +#include "llhttpclient.h" +#include "lltimer.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" +#include "llviewernetwork.h" + + +// +// Helpers +// + +static std::string getMarketplaceDomain() +{ + std::string domain = "secondlife.com"; + + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + const std::string& grid_label = LLGridManager::getInstance()->getGridLabel(); + const std::string& grid_label_lower = utf8str_tolower(grid_label); + + if (grid_label_lower == "damballah") + { + domain = "secondlife-staging.com"; + } + else + { + domain = llformat("%s.lindenlab.com", grid_label_lower.c_str()); + } + } + + return domain; +} + +static std::string getMarketplaceURL(const std::string& urlStringName) +{ + LLStringUtil::format_map_t domain_arg; + domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain(); + + std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg); + + return marketplace_url; +} + +LLSD getMarketplaceStringSubstitutions() +{ + std::string marketplace_url = getMarketplaceURL("MarketplaceURL"); + std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore"); + std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard"); + std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports"); + std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore"); + + LLSD marketplace_sub_map; + + marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url; + marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create; + marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info; + marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard; + marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports; + + return marketplace_sub_map; +} + +namespace LLMarketplaceImport +{ + // Basic interface for this namespace + + bool hasSessionCookie(); + bool inProgress(); + bool resultPending(); + U32 getResultStatus(); + const LLSD& getResults(); + + bool establishMarketplaceSessionCookie(); + bool pollStatus(); + bool triggerImport(); + + // Internal state variables + + static std::string sMarketplaceCookie = ""; + static LLSD sImportId = LLSD::emptyMap(); + static bool sImportInProgress = false; + static bool sImportPostPending = false; + static bool sImportGetPending = false; + static U32 sImportResultStatus = 0; + static LLSD sImportResults = LLSD::emptyMap(); + + static LLTimer slmGetTimer; + static LLTimer slmPostTimer; + + // Responders + + class LLImportPostResponder : public LLHTTPClient::Responder + { + public: + LLImportPostResponder() : LLCurl::Responder() {} + + void completed(U32 status, const std::string& reason, const LLSD& content) + { + slmPostTimer.stop(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST status: " << status << llendl; + llinfos << " SLM POST reason: " << reason << llendl; + llinfos << " SLM POST content: " << content.asString() << llendl; + + llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; + } + + if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || + (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || + (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST clearing marketplace cookie due to authentication failure or timeout" << llendl; + } + + sMarketplaceCookie.clear(); + } + + sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE); + sImportPostPending = false; + sImportResultStatus = status; + sImportId = content; + } + }; + + class LLImportGetResponder : public LLHTTPClient::Responder + { + public: + LLImportGetResponder() : LLCurl::Responder() {} + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + const std::string& set_cookie_string = content["set-cookie"].asString(); + + if (!set_cookie_string.empty()) + { + sMarketplaceCookie = set_cookie_string; + } + } + + void completed(U32 status, const std::string& reason, const LLSD& content) + { + slmGetTimer.stop(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET status: " << status << llendl; + llinfos << " SLM GET reason: " << reason << llendl; + llinfos << " SLM GET content: " << content.asString() << llendl; + + llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; + } + + if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || + (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl; + } + + sMarketplaceCookie.clear(); + } + + sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); + sImportGetPending = false; + sImportResultStatus = status; + sImportResults = content; + } + }; + + // Basic API + + bool hasSessionCookie() + { + return !sMarketplaceCookie.empty(); + } + + bool inProgress() + { + return sImportInProgress; + } + + bool resultPending() + { + return (sImportPostPending || sImportGetPending); + } + + U32 getResultStatus() + { + return sImportResultStatus; + } + + const LLSD& getResults() + { + return sImportResults; + } + + static std::string getInventoryImportURL() + { + std::string url = getMarketplaceURL("MarketplaceURL"); + + url += "api/1/"; + url += gAgent.getID().getString(); + url += "/inventory/import/"; + + return url; + } + + bool establishMarketplaceSessionCookie() + { + if (hasSessionCookie()) + { + return false; + } + + sImportInProgress = true; + sImportGetPending = true; + + std::string url = getInventoryImportURL(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET: " << url << llendl; + } + + slmGetTimer.start(); + LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders()); + + return true; + } + + bool pollStatus() + { + if (!hasSessionCookie()) + { + return false; + } + + sImportGetPending = true; + + std::string url = getInventoryImportURL(); + + url += sImportId.asString(); + + // Make the headers for the post + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Cookie"] = sMarketplaceCookie; + headers["Content-Type"] = "application/llsd+xml"; + headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET: " << url << llendl; + } + + slmGetTimer.start(); + LLHTTPClient::get(url, new LLImportGetResponder(), headers); + + return true; + } + + bool triggerImport() + { + if (!hasSessionCookie()) + { + return false; + } + + sImportId = LLSD::emptyMap(); + sImportInProgress = true; + sImportPostPending = true; + sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING; + sImportResults = LLSD::emptyMap(); + + std::string url = getInventoryImportURL(); + + // Make the headers for the post + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Connection"] = "Keep-Alive"; + headers["Cookie"] = sMarketplaceCookie; + headers["Content-Type"] = "application/xml"; + headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST: " << url << llendl; + } + + slmPostTimer.start(); + LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); + + return true; + } +} + + +// +// Interface class +// + + +//static +void LLMarketplaceInventoryImporter::update() +{ + if (instanceExists()) + { + LLMarketplaceInventoryImporter::instance().updateImport(); + } +} + +LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter() + : mAutoTriggerImport(false) + , mImportInProgress(false) + , mInitialized(false) + , mErrorInitSignal(NULL) + , mStatusChangedSignal(NULL) + , mStatusReportSignal(NULL) +{ +} + +boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErrorCallback(const status_report_signal_t::slot_type& cb) +{ + if (mErrorInitSignal == NULL) + { + mErrorInitSignal = new status_report_signal_t(); + } + + return mErrorInitSignal->connect(cb); +} + +boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb) +{ + if (mStatusChangedSignal == NULL) + { + mStatusChangedSignal = new status_changed_signal_t(); + } + + return mStatusChangedSignal->connect(cb); +} + +boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallback(const status_report_signal_t::slot_type& cb) +{ + if (mStatusReportSignal == NULL) + { + mStatusReportSignal = new status_report_signal_t(); + } + + return mStatusReportSignal->connect(cb); +} + +void LLMarketplaceInventoryImporter::initialize() +{ + llassert(!mInitialized); + + if (!LLMarketplaceImport::hasSessionCookie()) + { + LLMarketplaceImport::establishMarketplaceSessionCookie(); + } +} + +void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport() +{ + mInitialized = false; + + initialize(); + + mAutoTriggerImport = true; +} + +bool LLMarketplaceInventoryImporter::triggerImport() +{ + const bool import_triggered = LLMarketplaceImport::triggerImport(); + + if (!import_triggered) + { + reinitializeAndTriggerImport(); + } + + return import_triggered; +} + +void LLMarketplaceInventoryImporter::updateImport() +{ + const bool in_progress = LLMarketplaceImport::inProgress(); + + if (in_progress && !LLMarketplaceImport::resultPending()) + { + const bool polling_status = LLMarketplaceImport::pollStatus(); + + if (!polling_status) + { + reinitializeAndTriggerImport(); + } + } + + if (mImportInProgress != in_progress) + { + mImportInProgress = in_progress; + + // If we are no longer in progress + if (!mImportInProgress) + { + if (mInitialized) + { + // Report results + if (mStatusReportSignal) + { + (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + } + else + { + // Look for results success + mInitialized = LLMarketplaceImport::hasSessionCookie(); + + if (mInitialized) + { + // Follow up with auto trigger of import + if (mAutoTriggerImport) + { + mAutoTriggerImport = false; + + mImportInProgress = triggerImport(); + } + } + else if (mErrorInitSignal) + { + (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + } + } + + // Make sure we trigger the status change with the final state (in case of auto trigger after initialize) + if (mStatusChangedSignal) + { + (*mStatusChangedSignal)(mImportInProgress); + } + } +} + diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h new file mode 100644 index 0000000000..4b8f7a1ac7 --- /dev/null +++ b/indra/newview/llmarketplacefunctions.h @@ -0,0 +1,94 @@ +/** + * @file llmarketplacefunctions.h + * @brief Miscellaneous marketplace-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&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_LLMARKETPLACEFUNCTIONS_H +#define LL_LLMARKETPLACEFUNCTIONS_H + + +#include <llsd.h> +#include <boost/function.hpp> +#include <boost/signals2.hpp> + +#include "llsingleton.h" +#include "llstring.h" + + +LLSD getMarketplaceStringSubstitutions(); + + +namespace MarketplaceErrorCodes +{ + enum eCode + { + IMPORT_DONE = 200, + IMPORT_PROCESSING = 202, + IMPORT_REDIRECT = 302, + IMPORT_AUTHENTICATION_ERROR = 401, + IMPORT_DONE_WITH_ERRORS = 409, + IMPORT_JOB_FAILED = 410, + IMPORT_JOB_TIMEOUT = 499, + }; +} + + +class LLMarketplaceInventoryImporter + : public LLSingleton<LLMarketplaceInventoryImporter> +{ +public: + static void update(); + + LLMarketplaceInventoryImporter(); + + typedef boost::signals2::signal<void (bool)> status_changed_signal_t; + typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t; + + boost::signals2::connection setInitializationErrorCallback(const status_report_signal_t::slot_type& cb); + boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb); + boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb); + + void initialize(); + bool triggerImport(); + bool isImportInProgress() const { return mImportInProgress; } + +protected: + void reinitializeAndTriggerImport(); + void updateImport(); + +private: + bool mAutoTriggerImport; + bool mImportInProgress; + bool mInitialized; + + status_report_signal_t * mErrorInitSignal; + status_changed_signal_t * mStatusChangedSignal; + status_report_signal_t * mStatusReportSignal; +}; + + + +#endif // LL_LLMARKETPLACEFUNCTIONS_H + diff --git a/indra/newview/llmarketplacenotifications.cpp b/indra/newview/llmarketplacenotifications.cpp new file mode 100644 index 0000000000..0886f9a990 --- /dev/null +++ b/indra/newview/llmarketplacenotifications.cpp @@ -0,0 +1,90 @@ +/** + * @file llmarketplacenotifications.cpp + * @brief Handler for notifications related to marketplace file I/O + * class definition + * + * $LicenseInfo:firstyear=2001&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$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" + +#include "llmarketplacenotifications.h" +#include "llnotificationsutil.h" + +#include "llerror.h" + +#include <boost/foreach.hpp> +#include <boost/signals2.hpp> + + +namespace LLMarketplaceInventoryNotifications +{ + typedef boost::signals2::signal<void (const LLSD& param)> no_copy_payload_cb_signal_t; + + static no_copy_payload_cb_signal_t* no_copy_cb_action = NULL; + static bool no_copy_notify_active = false; + static std::list<LLSD> no_copy_payloads; + + void notifyNoCopyCallback(const LLSD& notification, const LLSD& response) + { + const S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (option == 0) + { + llassert(!no_copy_payloads.empty()); + llassert(no_copy_cb_action != NULL); + + BOOST_FOREACH(const LLSD& payload, no_copy_payloads) + { + (*no_copy_cb_action)(payload); + } + } + + delete no_copy_cb_action; + no_copy_cb_action = NULL; + + no_copy_notify_active = false; + no_copy_payloads.clear(); + } + + void update() + { + if (!no_copy_notify_active && !no_copy_payloads.empty()) + { + no_copy_notify_active = true; + + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", LLSD(), LLSD(), boost::bind(¬ifyNoCopyCallback, _1, _2)); + } + } + + void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb) + { + if (no_copy_cb_action == NULL) + { + no_copy_cb_action = new no_copy_payload_cb_signal_t; + no_copy_cb_action->connect(boost::bind(cb, _1)); + } + + no_copy_payloads.push_back(payload); + } +} diff --git a/indra/newview/llmarketplacenotifications.h b/indra/newview/llmarketplacenotifications.h new file mode 100644 index 0000000000..83a4e163c7 --- /dev/null +++ b/indra/newview/llmarketplacenotifications.h @@ -0,0 +1,57 @@ +/** + * @file llmarketplacenotifications.h + * @brief Handler for notifications related to marketplace file I/O + * class definition + * + * $LicenseInfo:firstyear=2001&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_LLMARKETPLACENOTIFICATIONS_H +#define LL_LLMARKETPLACENOTIFICATIONS_H + + +#include <llsd.h> +#include <boost/function.hpp> + + +// +// This is a set of helper functions to handle a unique notification with multiple +// payloads, helpful when dragging and dropping items to the merchant outbox that +// trigger notifications that can potentially interfere with the current drag and +// drop operation. +// +// Notification payloads are cached locally when initiated, the notification itself +// is triggered on the following frame during the call to "update" and then the +// response is triggered once per payload. +// + +namespace LLMarketplaceInventoryNotifications +{ + void update(); + + typedef boost::function<void (const LLSD&)> NoCopyCallbackFunction; + + void addNoCopyNotification(const LLSD& payload, const NoCopyCallbackFunction& cb); +}; + + +#endif // LL_LLMARKETPLACENOTIFICATIONS_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a97e256c89..b02bf79a28 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -88,6 +88,9 @@ const S32 MAX_MESH_VERSION = 999; U32 LLMeshRepository::sBytesReceived = 0; U32 LLMeshRepository::sHTTPRequestCount = 0; U32 LLMeshRepository::sHTTPRetryCount = 0; +U32 LLMeshRepository::sLODProcessing = 0; +U32 LLMeshRepository::sLODPending = 0; + U32 LLMeshRepository::sCacheBytesRead = 0; U32 LLMeshRepository::sCacheBytesWritten = 0; U32 LLMeshRepository::sPeakKbps = 0; @@ -205,6 +208,12 @@ public: LLMeshHeaderResponder(const LLVolumeParams& mesh_params) : mMeshParams(mesh_params) { + LLMeshRepoThread::sActiveHeaderRequests++; + } + + ~LLMeshHeaderResponder() + { + LLMeshRepoThread::sActiveHeaderRequests--; } virtual void completedRaw(U32 status, const std::string& reason, @@ -224,6 +233,12 @@ public: LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) { + LLMeshRepoThread::sActiveLODRequests++; + } + + ~LLMeshLODResponder() + { + LLMeshRepoThread::sActiveLODRequests--; } virtual void completedRaw(U32 status, const std::string& reason, @@ -497,10 +512,13 @@ void LLMeshRepoThread::run() mMutex->lock(); LODRequest req = mLODReqQ.front(); mLODReqQ.pop(); + LLMeshRepository::sLODProcessing--; mMutex->unlock(); - if (fetchMeshLOD(req.mMeshParams, req.mLOD)) + if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit { - count++; + mMutex->lock(); + mLODReqQ.push(req) ; + mMutex->unlock(); } } } @@ -512,9 +530,11 @@ void LLMeshRepoThread::run() HeaderRequest req = mHeaderReqQ.front(); mHeaderReqQ.pop(); mMutex->unlock(); - if (fetchMeshHeader(req.mMeshParams)) + if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit { - count++; + mMutex->lock(); + mHeaderReqQ.push(req) ; + mMutex->unlock(); } } } @@ -603,6 +623,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) { LLMutexLock lock(mMutex); mLODReqQ.push(req); + LLMeshRepository::sLODProcessing++; } } else @@ -658,6 +679,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) return false; } + bool ret = true ; U32 header_size = mMeshHeaderSize[mesh_id]; if (header_size > 0) @@ -673,7 +695,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //check VFS for mesh skin info LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) - { + { LLMeshRepository::sCacheBytesRead += size; file.seek(offset); U8* buffer = new U8[size]; @@ -689,7 +711,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) if (!zero) { //attempt to parse if (skinInfoReceived(mesh_id, buffer, size)) - { + { delete[] buffer; return true; } @@ -704,11 +726,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshSkinInfoResponder(mesh_id, offset, size)); + if(ret) + { + LLMeshRepository::sHTTPRequestCount++; + } } } } @@ -718,7 +742,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) @@ -732,7 +756,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) } U32 header_size = mMeshHeaderSize[mesh_id]; - + bool ret = true ; + if (header_size > 0) { S32 version = mMeshHeader[mesh_id]["version"].asInteger(); @@ -748,6 +773,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) if (file.getSize() >= offset+size) { LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); U8* buffer = new U8[size]; file.read(buffer, size); @@ -777,11 +803,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshDecompositionResponder(mesh_id, offset, size)); + if(ret) + { + LLMeshRepository::sHTTPRequestCount++; + } } } } @@ -791,7 +819,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) @@ -805,6 +833,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) } U32 header_size = mMeshHeaderSize[mesh_id]; + bool ret = true ; if (header_size > 0) { @@ -850,11 +879,14 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + + if(ret) + { + LLMeshRepository::sHTTPRequestCount++; + } } } else @@ -868,13 +900,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } -bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +//return false if failed to get header +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count) { - bool retval = false; - { //look for mesh in asset in vfs LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); @@ -889,36 +920,39 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) file.read(buffer, bytes); if (headerReceived(mesh_params, buffer, bytes)) { //did not do an HTTP request, return false - return false; + return true; } } } - //either cache entry doesn't exist or is corrupt, request header from simulator - + //either cache entry doesn't exist or is corrupt, request header from simulator + bool retval = true ; std::vector<std::string> headers; headers.push_back("Accept: application/octet-stream"); std::string http_url = constructUrl(mesh_params.getSculptID()); if (!http_url.empty()) { - ++sActiveHeaderRequests; - retval = true; //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits //within the first 4KB - //NOTE -- this will break of headers ever exceed 4KB - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + //NOTE -- this will break of headers ever exceed 4KB + retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + if(retval) + { + LLMeshRepository::sHTTPRequestCount++; + } + count++; } return retval; } -bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +//return false if failed to get mesh lod. +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count) { //protected by mMutex mHeaderMutex->lock(); - bool retval = false; + bool retval = true; LLUUID mesh_id = mesh_params.getSculptID(); @@ -955,7 +989,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) if (lodReceived(mesh_params, lod, buffer, size)) { delete[] buffer; - return false; + return true; } } @@ -968,12 +1002,15 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - retval = true; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + { + retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, new LLMeshLODResponder(mesh_params, lod, offset, size)); + + if(retval) + { + LLMeshRepository::sHTTPRequestCount++; + } + count++; } else { @@ -1045,6 +1082,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat { LODRequest req(mesh_params, iter->second[i]); mLODReqQ.push(req); + LLMeshRepository::sLODProcessing++; } } mPendingLOD.erase(iter); @@ -1540,8 +1578,17 @@ void LLMeshUploadThread::doWholeModelUpload() LLSD body = full_model_data["asset_resources"]; dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num)); LLCurlRequest::headers_t headers; - mCurlRequest->post(mWholeModelUploadURL, headers, body, - new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut); + + { + LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ; + + while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut)) + { + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } + } + do { mCurlRequest->process(); @@ -1571,8 +1618,15 @@ void LLMeshUploadThread::requestWholeModelFee() mPendingUploads++; LLCurlRequest::headers_t headers; - mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, - new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); + + { + LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ; + while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut)) + { + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } + } do { @@ -1712,7 +1766,6 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, const LLIOPipe::buffer_ptr_t& buffer) { - LLMeshRepoThread::sActiveLODRequests--; S32 data_size = buffer->countAfter(channels.in(), NULL); if (status < 200 || status > 400) @@ -1929,7 +1982,6 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - LLMeshRepoThread::sActiveHeaderRequests--; if (status < 200 || status > 400) { //llwarns @@ -2147,6 +2199,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para //first request for this mesh mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); + LLMeshRepository::sLODPending++; } } @@ -2359,6 +2412,7 @@ void LLMeshRepository::notifyLoadedMeshes() LLMeshRepoThread::LODRequest& request = mPendingRequests.front(); mThread->loadMeshLOD(request.mMeshParams, request.mLOD); mPendingRequests.erase(mPendingRequests.begin()); + LLMeshRepository::sLODPending--; push_count--; } } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 31b84ea0d9..da81bb057b 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -323,8 +323,8 @@ public: virtual void run(); void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); - bool fetchMeshHeader(const LLVolumeParams& mesh_params); - bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count); + bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count); bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size); bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size); bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); @@ -441,6 +441,8 @@ public: static U32 sBytesReceived; static U32 sHTTPRequestCount; static U32 sHTTPRetryCount; + static U32 sLODPending; + static U32 sLODProcessing; static U32 sCacheBytesRead; static U32 sCacheBytesWritten; static U32 sPeakKbps; diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 28a69f2373..23dbb6b047 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -283,9 +283,17 @@ class LLBrowserNotification : public LLSingleton<LLBrowserNotification> { public: virtual bool processNotification(const LLSD& notify); +}; +/** + * Handler for outbox notifications + */ +class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +{ +public: + virtual bool processNotification(const LLSD& notify); }; - + class LLHandlerUtil { public: diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6988227128..6105eff8ea 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -62,6 +62,7 @@ void LLNotificationManager::init() LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); + LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); @@ -72,6 +73,7 @@ void LLNotificationManager::init() LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); + LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 68ef13cd68..374afb90be 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -593,7 +593,7 @@ void LLPanelMainInventory::onFocusReceived() return; } - sidepanel_inventory->clearSelections(false, true, true); + sidepanel_inventory->clearSelections(false, true); } void LLPanelMainInventory::setFilterTextFromFilter() diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 7cb4bbf891..66c9c323cb 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -48,6 +48,8 @@ const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams // protected LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p) : LLPanel(p) + , mFreshCountCtrl(NULL) + , mInboxButton(NULL) , mInventoryPanel(NULL) { } @@ -60,6 +62,9 @@ LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox() BOOL LLPanelMarketplaceInbox::postBuild() { LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this)); + + mFreshCountCtrl = getChild<LLUICtrl>("inbox_fresh_new_count"); + mInboxButton = getChild<LLButton>("inbox_btn"); return TRUE; } @@ -109,7 +114,7 @@ void LLPanelMarketplaceInbox::onFocusReceived() LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - sidepanel_inventory->clearSelections(true, false, true); + sidepanel_inventory->clearSelections(true, false); } gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); @@ -216,7 +221,7 @@ void LLPanelMarketplaceInbox::draw() { U32 item_count = getTotalItemCount(); - LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count"); + llassert(mFreshCountCtrl != NULL); if (item_count > 0) { @@ -224,26 +229,26 @@ void LLPanelMarketplaceInbox::draw() LLStringUtil::format_map_t args; args["[NUM]"] = item_count_str; - getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args)); + mInboxButton->setLabel(getString("InboxLabelWithArg", args)); #if SUPPORTING_FRESH_ITEM_COUNT // set green text to fresh item count U32 fresh_item_count = getFreshItemCount(); - fresh_new_count_view->setVisible((fresh_item_count > 0)); + mFreshCountCtrl->setVisible((fresh_item_count > 0)); if (fresh_item_count > 0) { - getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count)); + mFreshCountCtrl->setTextArg("[NUM]", llformat("%d", fresh_item_count)); } #else - fresh_new_count_view->setVisible(FALSE); + mFreshCountCtrl->setVisible(FALSE); #endif } else { - getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg")); + mInboxButton->setLabel(getString("InboxLabelNoArg")); - fresh_new_count_view->setVisible(FALSE); + mFreshCountCtrl->setVisible(FALSE); } LLPanel::draw(); diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h index 3531518e51..9eb74581a2 100644 --- a/indra/newview/llpanelmarketplaceinbox.h +++ b/indra/newview/llpanelmarketplaceinbox.h @@ -29,7 +29,9 @@ #include "llpanel.h" +class LLButton; class LLInventoryPanel; +class LLUICtrl; class LLPanelMarketplaceInbox : public LLPanel { @@ -66,9 +68,10 @@ private: void onFocusReceived(); private: - LLInventoryPanel* mInventoryPanel; + LLUICtrl * mFreshCountCtrl; + LLButton * mInboxButton; + LLInventoryPanel * mInventoryPanel; }; #endif //LL_LLPANELMARKETPLACEINBOX_H - diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp deleted file mode 100644 index 12960fd0d6..0000000000 --- a/indra/newview/llpanelmarketplaceoutbox.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/** - * @file llpanelmarketplaceoutbox.cpp - * @brief Panel for marketplace outbox - * -* $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceoutbox.h" -#include "llpanelmarketplaceoutboxinventory.h" - -#include "llappviewer.h" -#include "llbutton.h" -#include "llcoros.h" -#include "lleventcoro.h" -#include "llfloatersidepanelcontainer.h" -#include "llinventorypanel.h" -#include "llloadingindicator.h" -#include "llnotificationsutil.h" -#include "llpanelmarketplaceinbox.h" -#include "llsdutil.h" -#include "llsidepanelinventory.h" -#include "lltimer.h" -#include "llviewernetwork.h" -#include "llagent.h" -#include "llviewermedia.h" -#include "llfolderview.h" -#include "llinventoryfunctions.h" - -static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox"); - -const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() -{ - return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>(); -} - -// protected -LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p) - : LLPanel(p) - , mInventoryPanel(NULL) - , mSyncButton(NULL) - , mSyncIndicator(NULL) - , mSyncInProgress(false) -{ -} - -LLPanelMarketplaceOutbox::~LLPanelMarketplaceOutbox() -{ -} - -// virtual -BOOL LLPanelMarketplaceOutbox::postBuild() -{ - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceOutbox::handleLoginComplete, this)); - - LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceOutbox::onFocusReceived, this)); - - return TRUE; -} - -void LLPanelMarketplaceOutbox::handleLoginComplete() -{ - mSyncButton = getChild<LLButton>("outbox_sync_btn"); - mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this)); - mSyncButton->setEnabled(!isOutboxEmpty()); - - mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator"); -} - -void LLPanelMarketplaceOutbox::onFocusReceived() -{ - LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - if (sidepanel_inventory) - { - sidepanel_inventory->clearSelections(true, true, false); - } -} - -void LLPanelMarketplaceOutbox::onSelectionChange() -{ - LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - if (sidepanel_inventory) - { - sidepanel_inventory->updateVerbs(); - } -} - -LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() -{ - LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel"); - LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent(); - - mInventoryPanel = - LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", - outbox_inventory_parent, - LLInventoryPanel::child_registry_t::instance()); - - llassert(mInventoryPanel); - - // Reshape the inventory to the proper size - LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect(); - mInventoryPanel->setShape(inventory_placeholder_rect); - - // Set the sort order newest to oldest - mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); - mInventoryPanel->getFilter()->markDefault(); - - // Set selection callback for proper update of inventory status buttons - mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this)); - - // Set up the note to display when the outbox is empty - mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems"); - - // Hide the placeholder text - outbox_inventory_placeholder->setVisible(FALSE); - - return mInventoryPanel; -} - -BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - if (!handled && mInventoryPanel && mInventoryPanel->getRootFolder()) - { - handled = mInventoryPanel->getRootFolder()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - - if (handled) - { - mInventoryPanel->getRootFolder()->setDragAndDropThisFrame(); - } - } - - return handled; -} - -bool LLPanelMarketplaceOutbox::isOutboxEmpty() const -{ - return (getTotalItemCount() == 0); -} - -bool LLPanelMarketplaceOutbox::isSyncInProgress() const -{ - return mSyncInProgress; -} - - -std::string gTimeDelayDebugFunc = ""; - -void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel) -{ - waitForEventOn(self, "mainloop"); - - LLTimer delayTimer; - delayTimer.reset(); - delayTimer.setTimerExpirySec(5.0f); - - while (!delayTimer.hasExpired()) - { - waitForEventOn(self, "mainloop"); - } - - outboxPanel->onSyncComplete(true, LLSD::emptyMap()); - - gTimeDelayDebugFunc = ""; -} - - -class LLInventorySyncResponder : public LLHTTPClient::Responder -{ -public: - LLInventorySyncResponder(LLPanelMarketplaceOutbox * outboxPanel) - : LLCurl::Responder() - , mOutboxPanel(outboxPanel) - { - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { - llinfos << "inventory_import complete status: " << status << ", reason: " << reason << llendl; - - if (isGoodStatus(status)) - { - // Complete success - llinfos << "success" << llendl; - } - else - { - llwarns << "failed" << llendl; - } - - mOutboxPanel->onSyncComplete(isGoodStatus(status), content); - } - -private: - LLPanelMarketplaceOutbox * mOutboxPanel; -}; - -void LLPanelMarketplaceOutbox::onSyncButtonClicked() -{ - // Get the sync animation going - mSyncInProgress = true; - updateSyncButtonStatus(); - - // Make the url for the inventory import request - std::string url = "https://marketplace.secondlife.com/"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); - - // TEMP for Jim's pdp - //url = "http://pdp24.lindenlab.com:3000/"; - } - - url += "api/1/users/"; - url += gAgent.getID().getString(); - url += "/inventory_import"; - - llinfos << "http get: " << url << llendl; - LLHTTPClient::get(url, new LLInventorySyncResponder(this), LLViewerMedia::getHeaders()); - - // Set a timer (for testing only) - //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this)); -} - -void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& content) -{ - mSyncInProgress = false; - updateSyncButtonStatus(); - - const LLSD& errors_list = content["errors"]; - - if (goodStatus && (errors_list.size() == 0)) - { - LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap()); - } - else - { - LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap()); - } - - llinfos << "Marketplace upload llsd:" << llendl; - llinfos << ll_pretty_print_sd(content) << llendl; - llinfos << llendl; - - const LLSD& imported_list = content["imported"]; - LLSD::array_const_iterator it = imported_list.beginArray(); - for ( ; it != imported_list.endArray(); ++it) - { - LLUUID imported_folder = (*it).asUUID(); - llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl; - } - - for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it) - { - const LLSD& item_error_map = (*it); - - LLUUID error_folder = item_error_map["folder_id"].asUUID(); - const std::string& error_string = item_error_map["identifier"].asString(); - LLUUID error_item = item_error_map["item_id"].asUUID(); - const std::string& error_item_name = item_error_map["item_name"].asString(); - const std::string& error_message = item_error_map["message"].asString(); - - llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", " - << error_item.asString() << ", " << error_item_name << ", " << error_message << llendl; - - LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder); - LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast<LLOutboxFolderViewFolder *>(item_folder); - - llassert(outbox_item_folder); - - outbox_item_folder->setErrorString(error_string); - } -} - -void LLPanelMarketplaceOutbox::updateSyncButtonStatus() -{ - if (isSyncInProgress()) - { - mSyncButton->setVisible(false); - - mSyncIndicator->setVisible(true); - mSyncIndicator->reset(); - mSyncIndicator->start(); - } - else - { - mSyncIndicator->stop(); - mSyncIndicator->setVisible(false); - - mSyncButton->setVisible(true); - mSyncButton->setEnabled(!isOutboxEmpty()); - } -} - -U32 LLPanelMarketplaceOutbox::getTotalItemCount() const -{ - U32 item_count = 0; - - if (mInventoryPanel) - { - const LLFolderViewFolder * outbox_folder = mInventoryPanel->getRootFolder(); - - if (outbox_folder) - { - item_count += outbox_folder->getFoldersCount(); - } - } - - return item_count; -} - -void LLPanelMarketplaceOutbox::draw() -{ - const U32 item_count = getTotalItemCount(); - const bool not_empty = (item_count > 0); - - if (not_empty) - { - std::string item_count_str = llformat("%d", item_count); - - LLStringUtil::format_map_t args; - args["[NUM]"] = item_count_str; - getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelWithArg", args)); - } - else - { - getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelNoArg")); - } - - if (!isSyncInProgress()) - { - mSyncButton->setEnabled(not_empty); - } - - LLPanel::draw(); -} diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h deleted file mode 100644 index c6b4a5abe2..0000000000 --- a/indra/newview/llpanelmarketplaceoutbox.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file llpanelmarketplaceoutbox.h - * @brief Panel for marketplace outbox - * -* $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPANELMARKETPLACEOUTBOX_H -#define LL_LLPANELMARKETPLACEOUTBOX_H - -#include "llpanel.h" - - -class LLButton; -class LLInventoryPanel; -class LLLoadingIndicator; - - -class LLPanelMarketplaceOutbox : public LLPanel -{ -public: - - struct Params : public LLInitParam::Block<Params, LLPanel::Params> - {}; - - LOG_CLASS(LLPanelMarketplaceOutbox); - - // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8 - static const LLPanelMarketplaceOutbox::Params& getDefaultParams(); - - LLPanelMarketplaceOutbox(const Params& p = getDefaultParams()); - ~LLPanelMarketplaceOutbox(); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void draw(); - - LLInventoryPanel * setupInventoryPanel(); - - U32 getTotalItemCount() const; - - bool isOutboxEmpty() const; - bool isSyncInProgress() const; - - void onSyncComplete(bool goodStatus, const LLSD& content); - - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - -protected: - void onSyncButtonClicked(); - void updateSyncButtonStatus(); - - void handleLoginComplete(); - void onFocusReceived(); - void onSelectionChange(); - -private: - LLInventoryPanel * mInventoryPanel; - - LLButton * mSyncButton; - LLLoadingIndicator * mSyncIndicator; - bool mSyncInProgress; -}; - - -#endif //LL_LLPANELMARKETPLACEOUTBOX_H - diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index ed1206aec8..ff62cb23db 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -47,50 +47,6 @@ static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_fol // -// Marketplace errors -// - -enum -{ - MKTERR_NONE = 0, - - MKTERR_NOT_MERCHANT, - MKTERR_FOLDER_EMPTY, - MKTERR_UNASSOCIATED_PRODUCTS, - MKTERR_OBJECT_LIMIT, - MKTERR_FOLDER_DEPTH, - MKTERR_UNSELLABLE_ITEM, - MKTERR_INTERNAL_IMPORT, - - MKTERR_COUNT -}; - -static const std::string MARKETPLACE_ERROR_STRINGS[MKTERR_COUNT] = -{ - "NO_ERROR", - "NOT_MERCHANT_ERROR", - "FOLDER_EMPTY_ERROR", - "UNASSOCIATED_PRODUCTS_ERROR", - "OBJECT_LIMIT_ERROR", - "FOLDER_DEPTH_ERROR", - "UNSELLABLE_ITEM_FOUND", - "INTERNAL_IMPORT_ERROR", -}; - -static const std::string MARKETPLACE_ERROR_NAMES[MKTERR_COUNT] = -{ - "Marketplace Error None", - "Marketplace Error Not Merchant", - "Marketplace Error Empty Folder", - "Marketplace Error Unassociated Products", - "Marketplace Error Object Limit", - "Marketplace Error Folder Depth", - "Marketplace Error Unsellable Item", - "Marketplace Error Internal Import", -}; - - -// // LLOutboxInventoryPanel Implementation // @@ -111,37 +67,6 @@ void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); - // leslie -- temporary HACK to work around sim not creating outbox with proper system folder type - if (root_id.isNull()) - { - std::string start_folder_name(params.start_folder()); - - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - - gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); - - if (cats) - { - for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) - { - LLInventoryCategory* cat = *cat_it; - - if (cat->getName() == start_folder_name) - { - root_id = cat->getUUID(); - break; - } - } - } - - if (root_id == LLUUID::null) - { - llwarns << "No category found that matches outbox inventory panel start_folder: " << start_folder_name << llendl; - } - } - // leslie -- end temporary HACK - if (root_id == LLUUID::null) { llwarns << "Outbox inventory panel has no root folder!" << llendl; @@ -206,66 +131,26 @@ LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) : LLFolderViewFolder(p) - , LLBadgeOwner(getHandle()) - , mError(0) -{ - initBadgeParams(p.error_badge()); -} - -LLOutboxFolderViewFolder::~LLOutboxFolderViewFolder() { } -// virtual -void LLOutboxFolderViewFolder::draw() -{ - if (!badgeHasParent()) - { - addBadgeToParentPanel(); - } - - setBadgeVisibility(hasError()); - - LLFolderViewFolder::draw(); -} +// +// LLOutboxFolderViewItem Implementation +// -void LLOutboxFolderViewFolder::setErrorString(const std::string& errorString) +LLOutboxFolderViewItem::LLOutboxFolderViewItem(const Params& p) + : LLFolderViewItem(p) { - S32 error_code = MKTERR_NONE; - - for (S32 i = 1; i < MKTERR_COUNT; ++i) - { - if (MARKETPLACE_ERROR_STRINGS[i] == errorString) - { - error_code = i; - break; - } - } - - setError(error_code); } -void LLOutboxFolderViewFolder::setError(S32 errorCode) +BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) { - mError = errorCode; - - if (hasError()) - { - setToolTip(LLTrans::getString(MARKETPLACE_ERROR_NAMES[mError])); - } - else - { - setToolTip(LLStringExplicit("")); - } + return TRUE; } -// -// LLOutboxFolderViewItem Implementation -// - -BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) +void LLOutboxFolderViewItem::openItem() { - return TRUE; + // Intentionally do nothing to block attaching items from the outbox } // eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h index 346680a79d..a6c522b7c2 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ b/indra/newview/llpanelmarketplaceoutboxinventory.h @@ -28,7 +28,6 @@ #define LL_OUTBOXINVENTORYPANEL_H -#include "llbadgeowner.h" #include "llinventorypanel.h" #include "llfolderviewitem.h" @@ -53,44 +52,26 @@ public: }; -class LLOutboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner +class LLOutboxFolderViewFolder : public LLFolderViewFolder { public: struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> { - Optional<LLBadge::Params> error_badge; - - Params() - : error_badge("error_badge") - { - } + Params() {} }; LLOutboxFolderViewFolder(const Params& p); - ~LLOutboxFolderViewFolder(); - - void draw(); - - void setErrorString(const std::string& errorString); - void setError(S32 errorCode); - - bool hasError() const { return (mError != 0); } - -protected: - S32 mError; }; class LLOutboxFolderViewItem : public LLFolderViewItem { public: - LLOutboxFolderViewItem(const Params& p) - : LLFolderViewItem(p) - { - } + LLOutboxFolderViewItem(const Params& p); // virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + void openItem(); }; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 5d0d1ef9a3..6111255a66 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5556,38 +5556,37 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) //helper function for pushing relevant vertices from drawable to GL void pushWireframe(LLDrawable* drawable) { - if (drawable->isState(LLDrawable::RIGGED)) - { //render straight from rigged volume if this is a rigged attachment - LLVOVolume* vobj = drawable->getVOVolume(); - if (vobj) - { - vobj->updateRiggedVolume(); - LLRiggedVolume* rigged_volume = vobj->getRiggedVolume(); - if (rigged_volume) - { - LLVertexBuffer::unbind(); - gGL.pushMatrix(); - gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); - for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = rigged_volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); - } - gGL.popMatrix(); - } - } - } - else + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj) { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) + LLVertexBuffer::unbind(); + gGL.pushMatrix(); + gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + + LLVolume* volume = NULL; + + if (drawable->isState(LLDrawable::RIGGED)) + { + vobj->updateRiggedVolume(); + volume = vobj->getRiggedVolume(); + } + else + { + volume = vobj->getVolume(); + } + + if (volume) { - LLFace* face = drawable->getFace(i); - if (face->verify()) + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { - pushVerts(face, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + const LLVolumeFace& face = volume->getVolumeFace(i); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); } } + + gGL.popMatrix(); } + } void LLSelectNode::renderOneWireframe(const LLColor4& color) diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 9d069c3996..038b18afbd 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -47,7 +47,6 @@ #include "lloutfitobserver.h" #include "llpanelmaininventory.h" #include "llpanelmarketplaceinbox.h" -#include "llpanelmarketplaceoutbox.h" #include "llselectmgr.h" #include "llsidepaneliteminfo.h" #include "llsidepaneltaskinfo.h" @@ -68,35 +67,22 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_ // No longer want the inbox panel to auto-expand since it creates issues with the "new" tag time stamp #define AUTO_EXPAND_INBOX 0 -// Temporarily disabling the outbox until we straighten out the API -#define ENABLE_MERCHANT_OUTBOX_PANEL 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - static const char * const INBOX_BUTTON_NAME = "inbox_btn"; -static const char * const OUTBOX_BUTTON_NAME = "outbox_btn"; - static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel"; -static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel"; - -static const char * const INBOX_OUTBOX_LAYOUT_PANEL_NAME = "inbox_outbox_layout_panel"; static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel"; -static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox"; -static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox"; - -static const char * const INBOX_OUTBOX_LAYOUT_STACK_NAME = "inbox_outbox_layout_stack"; static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack"; static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox"; -static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox"; // // Helpers // -class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver +class LLInboxAddedObserver : public LLInventoryCategoryAddedObserver { public: - LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory) + LLInboxAddedObserver(LLSidepanelInventory * sidepanelInventory) : LLInventoryCategoryAddedObserver() , mSidepanelInventory(sidepanelInventory) { @@ -116,10 +102,6 @@ public: mSidepanelInventory->enableInbox(true); mSidepanelInventory->observeInboxModifications(added_category->getUUID()); break; - case LLFolderType::FT_OUTBOX: - mSidepanelInventory->enableOutbox(true); - mSidepanelInventory->observeOutboxModifications(added_category->getUUID()); - break; default: break; } @@ -138,12 +120,10 @@ LLSidepanelInventory::LLSidepanelInventory() : LLPanel() , mItemPanel(NULL) , mInventoryPanelInbox(NULL) - , mInventoryPanelOutbox(NULL) , mPanelMainInventory(NULL) , mInboxEnabled(false) - , mOutboxEnabled(false) , mCategoriesObserver(NULL) - , mInboxOutboxAddedObserver(NULL) + , mInboxAddedObserver(NULL) { //buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() } @@ -156,11 +136,11 @@ LLSidepanelInventory::~LLSidepanelInventory() } delete mCategoriesObserver; - if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver)) + if (mInboxAddedObserver && gInventory.containsObserver(mInboxAddedObserver)) { - gInventory.removeObserver(mInboxOutboxAddedObserver); + gInventory.removeObserver(mInboxAddedObserver); } - delete mInboxOutboxAddedObserver; + delete mInboxAddedObserver; } void handleInventoryDisplayInboxChanged() @@ -172,15 +152,6 @@ void handleInventoryDisplayInboxChanged() } } -void handleInventoryDisplayOutboxChanged() -{ - LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - if (sidepanel_inventory) - { - sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox")); - } -} - BOOL LLSidepanelInventory::postBuild() { // UI elements from inventory panel @@ -242,43 +213,27 @@ BOOL LLSidepanelInventory::postBuild() } } - // Marketplace inbox/outbox setup + // Received items inbox setup { LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); - // Disable user_resize on main inventory panel by default - inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false); - inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false); - - // Collapse marketplace panel by default - inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true); - - LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); - - // Collapse both inbox and outbox panels - inout_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); - inout_stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true); + // Collapse inbox panel + inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); // Set up button states and callbacks LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME); - LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME); inbox_button->setToggleState(false); - outbox_button->setToggleState(false); - inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this)); - outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this)); - // Set the inbox and outbox visible based on debug settings (final setting comes from http request below) + // Set the inbox visible based on debug settings (final setting comes from http request below) enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox")); - enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox")); - // Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInboxOutbox, this)); + // Trigger callback for after login so we can setup to track inbox changes after initial inventory load + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInbox, this)); } gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged)); - gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged)); // Update the verbs buttons state. updateVerbs(); @@ -286,168 +241,96 @@ BOOL LLSidepanelInventory::postBuild() return TRUE; } -void LLSidepanelInventory::updateInboxOutbox() +void LLSidepanelInventory::updateInbox() { // - // Track inbox and outbox folder changes + // Track inbox folder changes // const bool do_not_create_folder = false; const bool do_not_find_in_library = false; const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library); - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); - // Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist - if (inbox_id.isNull() || outbox_id.isNull()) + // Set up observer to listen for creation of inbox if at least one of them doesn't exist + if (inbox_id.isNull()) { - observeInboxOutboxCreation(); + observeInboxCreation(); } - // Set up observer for inbox changes, if we have an inbox already - if (!inbox_id.isNull()) + else { // Enable the display of the inbox if it exists enableInbox(true); observeInboxModifications(inbox_id); } - -#if ENABLE_MERCHANT_OUTBOX_PANEL - // Set up observer for outbox changes, if we have an outbox already - if (!outbox_id.isNull()) - { - // Enable the display of the outbox if it exists - enableOutbox(true); - - observeOutboxModifications(outbox_id); - } -#endif } -void LLSidepanelInventory::observeInboxOutboxCreation() +void LLSidepanelInventory::observeInboxCreation() { // - // Set up observer to track inbox and outbox folder creation + // Set up observer to track inbox folder creation // - if (mInboxOutboxAddedObserver == NULL) + if (mInboxAddedObserver == NULL) { - mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this); + mInboxAddedObserver = new LLInboxAddedObserver(this); - gInventory.addObserver(mInboxOutboxAddedObserver); + gInventory.addObserver(mInboxAddedObserver); } } void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID) { // - // Track inbox and outbox folder changes + // Silently do nothing if we already have an inbox inventory panel set up + // (this can happen multiple times on the initial session that creates the inbox) // - + + if (mInventoryPanelInbox != NULL) + { + return; + } + + // + // Track inbox folder changes + // + if (inboxID.isNull()) { - llwarns << "Attempting to track modifications to non-existant inbox" << llendl; + llwarns << "Attempting to track modifications to non-existent inbox" << llendl; return; } - + if (mCategoriesObserver == NULL) { mCategoriesObserver = new LLInventoryCategoriesObserver(); gInventory.addObserver(mCategoriesObserver); } - + mCategoriesObserver->addCategory(inboxID, boost::bind(&LLSidepanelInventory::onInboxChanged, this, inboxID)); - + // // Trigger a load for the entire contents of the Inbox // - + LLInventoryModelBackgroundFetch::instance().start(inboxID); - + // // Set up the inbox inventory view // - + LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL); mInventoryPanelInbox = inbox->setupInventoryPanel(); } - -void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID) -{ - // - // Track outbox folder changes - // - - if (outboxID.isNull()) - { - llwarns << "Attempting to track modifications to non-existant outbox" << llendl; - return; - } - - if (mCategoriesObserver == NULL) - { - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - } - - mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID)); - - // - // Set up the outbox inventory view - // - - LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL); - mInventoryPanelOutbox = outbox->setupInventoryPanel(); -} - void LLSidepanelInventory::enableInbox(bool enabled) { mInboxEnabled = enabled; LLLayoutPanel * inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); inbox_layout_panel->setVisible(enabled); - - if (mInboxEnabled) - { - LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - inout_layout_panel->setVisible(TRUE); - - if (mOutboxEnabled) - { - S32 inbox_min_dim = inbox_layout_panel->getMinDim(); - S32 outbox_min_dim = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->getMinDim(); - - inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); - } - } -} - -void LLSidepanelInventory::enableOutbox(bool enabled) -{ - mOutboxEnabled = enabled; - - LLLayoutPanel * outbox_layout_panel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - outbox_layout_panel->setVisible(enabled); - - if (mOutboxEnabled) - { - LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - inout_layout_panel->setVisible(TRUE); - - if (mInboxEnabled) - { - S32 inbox_min_dim = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->getMinDim(); - S32 outbox_min_dim = outbox_layout_panel->getMinDim(); - - inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); - } - - updateOutboxUserStatus(); - } } void LLSidepanelInventory::openInbox() @@ -459,31 +342,13 @@ void LLSidepanelInventory::openInbox() } } -void LLSidepanelInventory::openOutbox() -{ - if (mOutboxEnabled) - { - getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true); - onToggleOutboxBtn(); - } -} - void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) { // Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting LLInventoryModelBackgroundFetch::instance().start(inbox_id); #if AUTO_EXPAND_INBOX - // If the outbox is expanded, don't auto-expand the inbox - if (mOutboxEnabled) - { - if (getChild<LLButton>(OUTBOX_BUTTON_NAME)->getToggleState()) - { - return; - } - } - - // Expand the inbox since we have fresh items and the outbox is not expanded + // Expand the inbox since we have fresh items if (mInboxEnabled) { getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true); @@ -492,68 +357,16 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) #endif } -void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id) -{ - // Expand the outbox since we have new items in it - if (mOutboxEnabled) - { - getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true); - onToggleOutboxBtn(); - } -} - -bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, - LLButton * otherButton, LLLayoutPanel * otherPanel) -{ - bool expand = pressedButton->getToggleState(); - bool otherExpanded = otherButton->getToggleState(); - - LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); - LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); - LLLayoutPanel* inout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - // Enable user_resize on main inventory panel only when a marketplace box is expanded - inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand); - inv_stack->collapsePanel(inout_panel, !expand); - - // Collapse other marketplace panel if it is expanded - if (expand && otherExpanded) - { - // Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size - pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight()); - - inout_stack->collapsePanel(otherPanel, true); - otherButton->setToggleState(false); - } - else - { - // NOTE: This is an attempt to reshape the inventory panel to the proper size but it doesn't seem to propagate - // properly to the child panels. - - S32 new_height = inout_panel->getRect().getHeight(); - - if (otherPanel->getVisible()) - { - new_height -= otherPanel->getMinDim(); - } - - pressedPanel->reshape(pressedPanel->getRect().getWidth(), new_height); - } - - // Expand/collapse the indicated panel - inout_stack->collapsePanel(pressedPanel, !expand); - - return expand; -} - void LLSidepanelInventory::onToggleInboxBtn() { LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME); LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); - LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); - LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - - const bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel, outboxButton, outboxPanel); + LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); + + const bool inbox_expanded = inboxButton->getToggleState(); + + // Expand/collapse the indicated panel + inv_stack->collapsePanel(inboxPanel, !inbox_expanded); if (inbox_expanded && inboxPanel->isInVisibleChain()) { @@ -561,16 +374,6 @@ void LLSidepanelInventory::onToggleInboxBtn() } } -void LLSidepanelInventory::onToggleOutboxBtn() -{ - LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME); - LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); - LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); - LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - - manageInboxOutboxPanels(outboxButton, outboxPanel, inboxButton, inboxPanel); -} - void LLSidepanelInventory::onOpen(const LLSD& key) { LLFirstUse::newInventory(false); @@ -740,77 +543,6 @@ void LLSidepanelInventory::showInventoryPanel() updateVerbs(); } -void LLSidepanelInventory::updateOutboxUserStatus() -{ - const bool isMerchant = (gSavedSettings.getString("InventoryMarketplaceUserStatus") == "merchant"); - const bool hasOutbox = !gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false).isNull(); - - LLView * outbox_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel"); - LLView * outbox_placeholder_parent = outbox_placeholder->getParent(); - - LLTextBox * outbox_title_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_title"); - LLTextBox * outbox_text_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_text"); - - std::string outbox_text; - std::string outbox_title; - std::string outbox_tooltip; - - if (isMerchant) - { - if (hasOutbox) - { - outbox_text = LLTrans::getString("InventoryOutboxNoItems"); - outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); - } - else - { - outbox_text = LLTrans::getString("InventoryOutboxCreationError"); - outbox_title = LLTrans::getString("InventoryOutboxCreationErrorTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxCreationErrorTooltip"); - } - } - else - { - // - // The string to become a merchant contains 3 URL's which need the domain name patched in. - // - - std::string domain = "secondlife.com"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str()); - } - - LLStringUtil::format_map_t domain_arg; - domain_arg["[DOMAIN_NAME]"] = domain; - - std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg); - std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg); - std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg); - - LLStringUtil::format_map_t args1, args2, args3; - args1["[MARKETPLACE_URL]"] = marketplace_url; - args2["[LEARN_MORE_URL]"] = marketplace_url_info; - args3["[CREATE_STORE_URL]"] = marketplace_url_create; - - // NOTE: This is dumb, ridiculous and very finicky. The order of these is very important - // to have these three string substitutions work properly. - outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1); - LLStringUtil::format(outbox_text, args2); - LLStringUtil::format(outbox_text, args3); - - outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); - } - - outbox_text_box->setValue(outbox_text); - outbox_title_box->setValue(outbox_title); - outbox_placeholder_parent->setToolTip(outbox_tooltip); -} - void LLSidepanelInventory::updateVerbs() { mInfoBtn->setEnabled(FALSE); @@ -926,13 +658,6 @@ U32 LLSidepanelInventory::getSelectedCount() { selection_list = mInventoryPanelInbox->getRootFolder()->getSelectionList(); - count += selection_list.size(); - } - - if ((count == 0) && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - selection_list = mInventoryPanelOutbox->getRootFolder()->getSelectionList(); - count += selection_list.size(); } @@ -957,7 +682,7 @@ BOOL LLSidepanelInventory::isMainInventoryPanelActive() const return mInventoryPanel->getVisible(); } -void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool clearOutbox) +void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) { if (clearMain) { @@ -974,15 +699,10 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool mInventoryPanelInbox->clearSelection(); } - if (clearOutbox && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - mInventoryPanelOutbox->clearSelection(); - } - updateVerbs(); } -std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList() +std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() { std::set<LLUUID> inventory_selected_uuids; @@ -991,10 +711,5 @@ std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList() inventory_selected_uuids = mInventoryPanelInbox->getRootFolder()->getSelectionList(); } - if (inventory_selected_uuids.empty() && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - inventory_selected_uuids = mInventoryPanelOutbox->getRootFolder()->getSelectionList(); - } - return inventory_selected_uuids; } diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 2c6f807013..a33607f50d 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -31,7 +31,7 @@ class LLButton; class LLFolderViewItem; -class LLInboxOutboxAddedObserver; +class LLInboxAddedObserver; class LLInventoryCategoriesObserver; class LLInventoryItem; class LLInventoryPanel; @@ -47,25 +47,23 @@ public: virtual ~LLSidepanelInventory(); private: - void updateInboxOutbox(); + void updateInbox(); public: - void observeInboxOutboxCreation(); + void observeInboxCreation(); void observeInboxModifications(const LLUUID& inboxID); - void observeOutboxModifications(const LLUUID& outboxID); /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any. LLInventoryPanel* getInboxPanel() const { return mInventoryPanelInbox; } - LLInventoryPanel* getOutboxPanel() const { return mInventoryPanelOutbox; } LLPanelMainInventory* getMainInventoryPanel() const { return mPanelMainInventory; } BOOL isMainInventoryPanelActive() const; - void clearSelections(bool clearMain, bool clearInbox, bool clearOutbox); - std::set<LLUUID> getInboxOrOutboxSelectionList(); + void clearSelections(bool clearMain, bool clearInbox); + std::set<LLUUID> getInboxSelectionList(); void showItemInfoPanel(); void showTaskInfoPanel(); @@ -75,18 +73,13 @@ public: bool canShare(); void onToggleInboxBtn(); - void onToggleOutboxBtn(); void enableInbox(bool enabled); - void enableOutbox(bool enabled); void openInbox(); - void openOutbox(); bool isInboxEnabled() const { return mInboxEnabled; } - bool isOutboxEnabled() const { return mOutboxEnabled; } - void updateOutboxUserStatus(); void updateVerbs(); protected: @@ -100,9 +93,6 @@ protected: bool canWearSelected(); // check whether selected items can be worn void onInboxChanged(const LLUUID& inbox_id); - void onOutboxChanged(const LLUUID& outbox_id); - - bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, LLButton * otherButton, LLLayoutPanel * otherPanel); // // UI Elements @@ -110,7 +100,6 @@ protected: private: LLPanel* mInventoryPanel; // Main inventory view LLInventoryPanel* mInventoryPanelInbox; - LLInventoryPanel* mInventoryPanelOutbox; LLSidepanelItemInfo* mItemPanel; // Individual item view LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view LLPanelMainInventory* mPanelMainInventory; @@ -135,10 +124,9 @@ private: LLButton* mShopBtn; bool mInboxEnabled; - bool mOutboxEnabled; - LLInventoryCategoriesObserver* mCategoriesObserver; - LLInboxOutboxAddedObserver* mInboxOutboxAddedObserver; + LLInventoryCategoriesObserver* mCategoriesObserver; + LLInboxAddedObserver* mInboxAddedObserver; }; #endif //LL_LLSIDEPANELINVENTORY_H diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 900f126049..5d196a465f 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -264,7 +264,7 @@ static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); void LLSpatialGroup::buildOcclusion() { - if (mOcclusionVerts.isNull()) + //if (mOcclusionVerts.isNull()) { mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. @@ -726,7 +726,9 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) { group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); @@ -1185,6 +1187,8 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode) LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mState(0), + mGeometryBytes(0), + mSurfaceArea(0.f), mBuilt(0.f), mOctreeNode(node), mSpatialPartition(part), @@ -1410,6 +1414,17 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) } } + //clean up avatar attachment stats + LLSpatialBridge* bridge = mSpatialPartition->asBridge(); + if (bridge) + { + if (bridge->mAvatar.notNull()) + { + bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes; + bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea; + } + } + clearDrawMap(); mVertexBuffer = NULL; mBufferMap.clear(); @@ -1765,7 +1780,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) //============================================== LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) -: mRenderByGroup(render_by_group) +: mRenderByGroup(render_by_group), mBridge(NULL) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); mOcclusionEnabled = TRUE; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 899547ae4d..6c14ecf452 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -405,6 +405,9 @@ public: bridge_list_t mBridgeList; buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers + U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node + F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node + F32 mBuilt; OctreeNode* mOctreeNode; LLSpatialPartition* mSpatialPartition; @@ -474,8 +477,8 @@ public: BOOL isVisible(const LLVector3& v); bool isHUDPartition() ; - virtual LLSpatialBridge* asBridge() { return NULL; } - virtual BOOL isBridge() { return asBridge() != NULL; } + LLSpatialBridge* asBridge() { return mBridge; } + BOOL isBridge() { return asBridge() != NULL; } void renderPhysicsShapes(); void renderDebug(); @@ -487,6 +490,9 @@ public: public: LLSpatialGroup::OctreeNode* mOctree; + LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this + // use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe + // to call asBridge() from the destructor BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane U32 mBufferUsage; @@ -511,8 +517,9 @@ public: LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); - virtual BOOL isSpatialBridge() const { return TRUE; } + void destroyTree(); + virtual BOOL isSpatialBridge() const { return TRUE; } virtual void updateSpatialExtents(); virtual void updateBinRadius(); virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE); @@ -523,11 +530,12 @@ public: virtual void shiftPos(const LLVector4a& vec); virtual void cleanupReferences(); virtual LLSpatialPartition* asPartition() { return this; } - virtual LLSpatialBridge* asBridge() { return this; } - + virtual LLCamera transformCamera(LLCamera& camera); LLDrawable* mDrawable; + LLPointer<LLVOAvatar> mAvatar; + }; class LLCullResult diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 89360778d1..25a765dc8d 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -805,9 +805,8 @@ bool idle_startup() #ifdef _WIN32 MSG msg; while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ) - { - display_startup(); - } + { } + display_startup(); #endif timeout.reset(); return FALSE; diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 85dadb213c..4f43547dae 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -261,6 +261,8 @@ private: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLTexLayerSetBuffer : public LLViewerDynamicTexture { + LOG_CLASS(LLTexLayerSetBuffer); + public: LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); virtual ~LLTexLayerSetBuffer(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 6910b8eced..8c32dfcb4d 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -282,6 +282,8 @@ void LLCategoryDropDescendentsObserver::done() } */ +S32 LLToolDragAndDrop::sOperationId = 0; + LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none, dragOrDrop3dImpl f_self, dragOrDrop3dImpl f_avatar, @@ -626,6 +628,8 @@ BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask) void LLToolDragAndDrop::handleDeselect() { mToolTipMsg.clear(); + + LLToolTipMgr::instance().blockToolTips(); } // protected @@ -642,6 +646,12 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, mToolTipMsg.clear(); + // Increment the operation id for every drop + if (drop) + { + sOperationId++; + } + if (top_view) { handled = TRUE; @@ -767,6 +777,21 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { + // Disallow drag and drop to 3D from the outbox + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + if (outbox_id.notNull()) + { + for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) + { + if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id)) + { + *acceptance = ACCEPT_NO; + mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld"); + return; + } + } + } + dragOrDrop3D( x, y, mask, drop, acceptance ); } } @@ -865,7 +890,7 @@ void LLToolDragAndDrop::pick(const LLPickInfo& pick_info) (U32)mLastAccept, (U32)callMemberFunction(*this, LLDragAndDropDictionary::instance().get(dad_type, target)) - (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); + (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); } if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE)) diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 92f007a251..188d36cd1b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -86,6 +86,9 @@ public: EAcceptance getLastAccept() { return mLastAccept; } boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } + + uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); } + static S32 getOperationId() { return sOperationId; } protected: enum EDropTarget @@ -125,6 +128,8 @@ protected: LLUUID mSourceID; LLUUID mObjectID; + static S32 sOperationId; + LLVector3d mLastCameraPos; LLVector3d mLastHitPos; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 7b6dbfaa0b..d7168a401c 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -507,7 +507,8 @@ bool handleSpellCheckChanged() if (gSavedSettings.getBOOL("SpellCheck")) { std::list<std::string> dict_list; - boost::split(dict_list, gSavedSettings.getString("SpellCheckDictionary"), boost::is_any_of(std::string(","))); + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); if (!dict_list.empty()) { LLSpellChecker::setUseSpellCheck(dict_list.front()); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index cca8f10515..bb870f7651 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -83,6 +83,7 @@ #include "llfloaternotificationsconsole.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" +#include "llfloateroutbox.h" #include "llfloaterpay.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" @@ -238,6 +239,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); + LLFloaterReg::add("outbox", "floater_merchant_outbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutbox>); LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); LLFloaterPayUtil::registerFloater(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 09cce39c3d..046360e9e9 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -26,46 +26,48 @@ #include "llviewerprecompiledheaders.h" +#include "llviewermedia.h" + #include "llagent.h" #include "llagentcamera.h" -#include "llviewermedia.h" -#include "llviewermediafocus.h" -#include "llmimetypes.h" +#include "llappviewer.h" +#include "llaudioengine.h" // for gAudiop +#include "llcallbacklist.h" +#include "lldir.h" +#include "lldiriterator.h" +#include "llevent.h" // LLSimpleListener +#include "llfilepicker.h" +#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. +#include "llfocusmgr.h" +#include "llkeyboard.h" +#include "lllogininstance.h" +#include "llmarketplacefunctions.h" #include "llmediaentry.h" +#include "llmimetypes.h" +#include "llmutelist.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpanelprofile.h" +#include "llparcel.h" +#include "llpluginclassmedia.h" +#include "llplugincookiestore.h" +#include "llurldispatcher.h" +#include "lluuid.h" #include "llversioninfo.h" +#include "llviewermediafocus.h" #include "llviewercontrol.h" -#include "llviewertexture.h" +#include "llviewernetwork.h" #include "llviewerparcelmedia.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewertexture.h" #include "llviewertexturelist.h" -#include "llvovolume.h" -#include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llviewerwindow.h" -#include "llfocusmgr.h" -#include "llcallbacklist.h" -#include "llparcel.h" -#include "llaudioengine.h" // for gAudiop -#include "llurldispatcher.h" #include "llvoavatar.h" #include "llvoavatarself.h" -#include "llviewerregion.h" +#include "llvovolume.h" #include "llwebprofile.h" #include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this! -#include "llfilepicker.h" -#include "llnotifications.h" -#include "lldir.h" -#include "lldiriterator.h" -#include "llevent.h" // LLSimpleListener -#include "llnotificationsutil.h" -#include "lluuid.h" -#include "llkeyboard.h" -#include "llmutelist.h" -#include "llpanelprofile.h" -#include "llappviewer.h" -#include "lllogininstance.h" -//#include "llfirstuse.h" -#include "llviewernetwork.h" #include "llwindow.h" #include "llvieweraudio.h" @@ -1398,75 +1400,11 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom } -// This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory -// just to be able to temporarily disable the outbox. -#define ENABLE_INVENTORY_DISPLAY_OUTBOX 0 // keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - -class LLInventoryUserStatusResponder : public LLHTTPClient::Responder -{ -public: - LLInventoryUserStatusResponder() - : LLCurl::Responder() - { - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { - if (isGoodStatus(status)) - { - std::string merchantStatus = content[gAgent.getID().getString()].asString(); - llinfos << "Marketplace merchant status: " << merchantStatus << llendl; - - // Save the merchant status before turning on the display - gSavedSettings.setString("InventoryMarketplaceUserStatus", merchantStatus); - - // Complete success - gSavedSettings.setBOOL("InventoryDisplayInbox", true); - -#if ENABLE_INVENTORY_DISPLAY_OUTBOX - gSavedSettings.setBOOL("InventoryDisplayOutbox", true); -#endif - } - else if (status == 401) - { - // API is available for use but OpenID authorization failed - gSavedSettings.setBOOL("InventoryDisplayInbox", true); - } - else - { - // API in unavailable - llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl; - } - } -}; - - -void doOnetimeEarlyHTTPRequests() -{ - std::string url = "https://marketplace.secondlife.com/"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); - - // TEMP for Jim's pdp - //url = "http://pdp24.lindenlab.com:3000/"; - } - - url += "api/1/users/"; - url += gAgent.getID().getString(); - url += "/user_status"; - - llinfos << "http get: " << url << llendl; - LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), LLViewerMedia::getHeaders()); -} - - LLSD LLViewerMedia::getHeaders() { LLSD headers = LLSD::emptyMap(); headers["Accept"] = "*/*"; + headers["Content-Type"] = "application/xml"; headers["Cookie"] = sOpenIDCookie; headers["User-Agent"] = getCurrentUserAgent(); @@ -1521,9 +1459,6 @@ void LLViewerMedia::setOpenIDCookie() LLHTTPClient::get(profile_url, new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), headers); - - // FUI: No longer perform the user_status query - //doOnetimeEarlyHTTPRequests(); } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2a11f3cc16..e4cc26885d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -948,6 +948,10 @@ U32 info_display_from_string(std::string info_display) { return LLPipeline::RENDER_DEBUG_COMPOSITION; } + else if ("attachment bytes" == info_display) + { + return LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES; + } else if ("glow" == info_display) { return LLPipeline::RENDER_DEBUG_GLOW; @@ -2787,8 +2791,31 @@ bool enable_object_mute() else { // Just a regular object - return LLSelectMgr::getInstance()->getSelection()-> - contains( object, SELECT_ALL_TES ); + return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && + !LLMuteList::getInstance()->isMuted(object->getID()); + } +} + +bool enable_object_unmute() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; + + LLVOAvatar* avatar = find_avatar_from_object(object); + if (avatar) + { + // It's an avatar + LLNameValue *lastname = avatar->getNVPair("LastName"); + bool is_linden = + lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); + bool is_self = avatar->isSelf(); + return !is_linden && !is_self; + } + else + { + // Just a regular object + return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && + LLMuteList::getInstance()->isMuted(object->getID());; } } @@ -8394,6 +8421,7 @@ void initialize_menus() enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute)); enable.add("Object.EnableMute", boost::bind(&enable_object_mute)); + enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute)); enable.add("Object.EnableBuy", boost::bind(&enable_buy_object)); commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom")); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b8772971aa..37fb77a10a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5520,11 +5520,12 @@ void LLViewerObject::dirtyMesh() { if (mDrawable) { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + /*LLSpatialGroup* group = mDrawable->getSpatialGroup(); if (group) { group->dirtyMesh(); - } + }*/ } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4499955dec..e0653fec30 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -613,7 +613,9 @@ public: addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, LLMeshRepository::sHTTPRetryCount)); - + ypos += y_inc; + + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); @@ -1958,34 +1960,43 @@ void LLViewerWindow::shutdownViews() // clean up warning logger LLError::removeRecorder(RecordToChatConsole::getInstance()); + llinfos << "Warning logger is cleaned." << llendl ; + delete mDebugText; mDebugText = NULL; + llinfos << "DebugText deleted." << llendl ; + // Cleanup global views if (gMorphView) { gMorphView->setVisible(FALSE); } - + llinfos << "Global views cleaned." << llendl ; + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open // will crump with LL_ERRS. LLModalDialog::shutdownModals(); - + llinfos << "LLModalDialog shut down." << llendl; + // destroy the nav bar, not currently part of gViewerWindow // *TODO: Make LLNavigationBar part of gViewerWindow if (LLNavigationBar::instanceExists()) { delete LLNavigationBar::getInstance(); } - + llinfos << "LLNavigationBar destroyed." << llendl ; + // destroy menus after instantiating navbar above, as it needs // access to gMenuHolder cleanup_menus(); - + llinfos << "menus destroyed." << llendl ; + // Delete all child views. delete mRootView; mRootView = NULL; - + llinfos << "RootView deleted." << llendl ; + // Automatically deleted as children of mRootView. Fix the globals. gStatusBar = NULL; gIMMgr = NULL; @@ -2010,6 +2021,12 @@ void LLViewerWindow::shutdownGL() gSky.cleanup(); stop_glerror(); + llinfos << "Cleaning up pipeline" << llendl; + gPipeline.cleanup(); + stop_glerror(); + + //MUST clean up pipeline before cleaning up wearables + llinfos << "Cleaning up wearables" << llendl; LLWearableList::instance().cleanup() ; gTextureList.shutdown(); @@ -2020,10 +2037,6 @@ void LLViewerWindow::shutdownGL() LLWorldMapView::cleanupTextures(); - llinfos << "Cleaning up pipeline" << llendl; - gPipeline.cleanup(); - stop_glerror(); - LLViewerTextureManager::cleanup() ; LLImageGL::cleanupClass() ; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 68637a7ed9..bc7f5a9744 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -651,6 +651,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, LLViewerObject(id, pcode, regionp), mIsDummy(FALSE), mSpecialRenderMode(0), + mAttachmentGeometryBytes(0), + mAttachmentSurfaceArea(0.f), mTurning(FALSE), mPelvisToFoot(0.f), mLastSkeletonSerialNum( 0 ), @@ -3363,6 +3365,16 @@ void LLVOAvatar::slamPosition() mRoot.updateWorldMatrixChildren(); } +bool LLVOAvatar::isVisuallyMuted() +{ + static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); + static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); + + return LLMuteList::getInstance()->isMuted(getID()) || + (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || + (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +} + //------------------------------------------------------------------------ // updateCharacter() // called on both your avatar and other avatars @@ -3429,8 +3441,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) size.setSub(ext[1],ext[0]); F32 mag = size.getLength3().getF32()*0.5f; + F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); - if (LLMuteList::getInstance()->isMuted(getID())) + if (isVisuallyMuted()) { // muted avatars update at 16 hz mUpdatePeriod = 16; } @@ -8333,6 +8346,11 @@ void LLVOAvatar::idleUpdateRenderCost() static std::set<LLUUID> all_textures; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)) + { //set debug text to attachment geometry bytes here so render cost will override + setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea)); + } + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) { return; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 59796370ae..dd0317f555 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -78,6 +78,8 @@ class LLVOAvatar : public LLCharacter, public boost::signals2::trackable { + LOG_CLASS(LLVOAvatar); + public: friend class LLVOAvatarSelf; protected: @@ -380,6 +382,8 @@ private: public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); + bool isVisuallyMuted(); + U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); F32 getLastSkinTime() { return mLastSkinTime; } @@ -391,6 +395,9 @@ public: static void restoreGL(); BOOL mIsDummy; // for special views S32 mSpecialRenderMode; // special lighting + U32 mAttachmentGeometryBytes; //number of bytes in attached geometry + F32 mAttachmentSurfaceArea; //estimated surface area of attachments + private: bool shouldAlphaMask(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 581912f844..e525d6bad0 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -66,10 +66,11 @@ #include <boost/lexical_cast.hpp> -LLVOAvatarSelf *gAgentAvatarp = NULL; +LLPointer<LLVOAvatarSelf> gAgentAvatarp = NULL; + BOOL isAgentAvatarValid() { - return (gAgentAvatarp && + return (gAgentAvatarp.notNull() && (gAgentAvatarp->getRegion() != NULL) && (!gAgentAvatarp->isDead())); } @@ -1574,7 +1575,7 @@ void LLVOAvatarSelf::invalidateAll() { invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE); } - mDebugSelfLoadTimer.reset(); + //mDebugSelfLoadTimer.reset(); } //----------------------------------------------------------------------------- @@ -1896,11 +1897,13 @@ BOOL LLVOAvatarSelf::getIsCloud() gAgentWearables.getWearableCount(LLWearableType::WT_EYES) == 0 || gAgentWearables.getWearableCount(LLWearableType::WT_SKIN) == 0) { + lldebugs << "No body parts" << llendl; return TRUE; } if (!isTextureDefined(TEX_HAIR, 0)) { + lldebugs << "No hair texture" << llendl; return TRUE; } @@ -1909,12 +1912,14 @@ BOOL LLVOAvatarSelf::getIsCloud() if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) && (!isTextureDefined(TEX_LOWER_BAKED, 0))) { + lldebugs << "Lower textures not baked" << llendl; return TRUE; } if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) && (!isTextureDefined(TEX_UPPER_BAKED, 0))) { + lldebugs << "Upper textures not baked" << llendl; return TRUE; } @@ -1931,10 +1936,12 @@ BOOL LLVOAvatarSelf::getIsCloud() const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); if (!baked_img || !baked_img->hasGLTexture()) { + lldebugs << "Texture at index " << i << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl; return TRUE; } } + lldebugs << "Avatar de-clouded" << llendl; } return FALSE; } @@ -2258,6 +2265,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) } } +// FIXME: This is never called. Something may be broken. void LLVOAvatarSelf::outputRezDiagnostics() const { if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) @@ -2315,6 +2323,18 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } } +void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const +{ + LL_DEBUGS("Avatar Rez") + << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) + << llendl; +} + +void LLVOAvatarSelf::reportAvatarRezTime() const +{ + // TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow. +} + //----------------------------------------------------------------------------- // setCachedBakedTexture() // A baked texture id was received from a cache query, make it active diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 74ff47a3e4..655fb3a012 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -41,6 +41,7 @@ struct LocalTextureData; class LLVOAvatarSelf : public LLVOAvatar { + LOG_CLASS(LLVOAvatarSelf); /******************************************************************************** ** ** @@ -358,6 +359,8 @@ public: void debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); } void debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); } void outputRezDiagnostics() const; + void outputRezTiming(const std::string& msg) const; + void reportAvatarRezTime() const; void debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished); static void debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); @@ -380,7 +383,7 @@ private: }; -extern LLVOAvatarSelf *gAgentAvatarp; +extern LLPointer<LLVOAvatarSelf> gAgentAvatarp; BOOL isAgentAvatarValid(); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index c3a2e6a712..bf6158eeaf 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -65,7 +65,7 @@ public: return; } - U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; //assume tex coords 2 and 3 are present U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 20f8674655..03d4c51aff 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4097,6 +4097,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); + LLVOAvatar* pAvatarVO = NULL; + + LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + if (bridge) + { + if (bridge->mAvatar.isNull()) + { + LLViewerObject* vobj = bridge->mDrawable->getVObj(); + if (vobj) + { + bridge->mAvatar = vobj->getAvatar(); + } + } + + pAvatarVO = bridge->mAvatar; + } + + if (pAvatarVO) + { + pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes; + pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea; + } + + group->mGeometryBytes = 0; + group->mSurfaceArea = 0; + group->clearDrawMap(); mFaceList.clear(); @@ -4133,12 +4159,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); + if (!vobj) + { + continue; + } + if (vobj->isMesh() && (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) { continue; } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } + llassert_always(vobj); vobj->updateTextureVirtualSize(true); vobj->preRebuild(); @@ -4183,7 +4221,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //Determine if we've received skininfo that contains an //alternate bind matrix - if it does then apply the translational component //to the joints of the avatar. - LLVOAvatar* pAvatarVO = vobj->getAvatar(); bool pelvisGotSet = false; if ( pAvatarVO ) @@ -4253,13 +4290,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - if (te->getFullbright()) + if (te->getColor().mV[3] > 0.f) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } } } else if (te->getShiny()) @@ -4392,7 +4432,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { - drawablep->setState(LLDrawable::HAS_ALPHA); + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } alpha_faces.push_back(facep); } } @@ -4510,6 +4553,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } mFaceList.clear(); + + if (pAvatarVO) + { + pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes; + pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea; + } } static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); @@ -4806,17 +4855,20 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: //create/delete/resize vertex buffer if needed LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); + + { //try to find a buffer to reuse + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) + if (found_iter != group->mBufferMap[mask].end()) { - buffer = found_iter->second[buffer_index]; + if ((U32) buffer_index < found_iter->second.size()) + { + buffer = found_iter->second[buffer_index]; + } } } - if (!buffer) + if (!buffer || !buffer->isWriteable()) { //create new buffer if needed buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); @@ -4835,6 +4887,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } + group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); + + buffer_map[mask][*face_iter].push_back(buffer); //add face geometry @@ -4892,7 +4947,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: if (is_alpha) { // can we safely treat this as an alpha mask? - if (facep->canRenderAsMask()) + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask()) { if (te->getFullbright() || LLPipeline::sNoAlpha) { diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 7df50ec815..315616e8a5 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -167,7 +167,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) indices_per_quad * num_quads); LLVertexBuffer* buff = face->getVertexBuffer(); - if (!buff) + if (!buff || !buff->isWriteable()) { buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index f1c5499d84..afd902201b 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -774,7 +774,7 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) LLStrider<LLColor4U> colorsp; LLStrider<LLVector2> texcoordsp; - if (mStarsVerts.isNull()) + if (mStarsVerts.isNull() || !mStarsVerts->isWriteable()) { mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW); mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0, TRUE); diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index d8aa0b7d5c..0f7f63061b 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -221,7 +221,7 @@ void LLWearable::createVisualParams() param->resetDrivenParams(); if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp,_1 ), true)) + if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) { llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; continue; diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index ddbcdfc3f7..6f6411ce3c 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -63,7 +63,7 @@ struct LLWearableArrivedData LLWearableList::~LLWearableList() { - llassert_always(mList.empty()) ; + cleanup(); } void LLWearableList::cleanup() diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 920a9a3752..0da70d398b 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -305,6 +305,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) { mCurlRequest = new LLCurlEasyRequest(); } + if(!mCurlRequest->isValid()) + { + llwarns << "mCurlRequest is invalid." << llendl ; + + delete mCurlRequest ; + mCurlRequest = NULL ; + return ; + } + mErrorCert = NULL; // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging @@ -357,10 +366,20 @@ LLXMLRPCTransaction::Impl::~Impl() } delete mCurlRequest; + mCurlRequest = NULL ; } bool LLXMLRPCTransaction::Impl::process() { + if(!mCurlRequest || !mCurlRequest->isValid()) + { + llwarns << "transaction failed." << llendl ; + + delete mCurlRequest ; + mCurlRequest = NULL ; + return true ; //failed, quit. + } + switch(mStatus) { case LLXMLRPCTransaction::StatusComplete: diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 8449e74fb6..c523a78b22 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1217,10 +1217,12 @@ void LLPipeline::restoreGL() BOOL LLPipeline::canUseVertexShaders() { + static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable"; + if (sDisableShaders || !gGLManager.mHasVertexShader || !gGLManager.mHasFragmentShader || - !LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") || + !LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) || (assertInitialized() && mVertexShadersLoaded != 1) ) { return FALSE; @@ -3765,6 +3767,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO"); // Initialize lots of GL state to "safe" values + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -5296,7 +5299,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) light_state->setConstantAttenuation(0.f); if (sRenderDeferred) { - light_state->setLinearAttenuation(light_radius*1.5f); + F32 size = light_radius*1.5f; + light_state->setLinearAttenuation(size*size); light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); } else @@ -5318,7 +5322,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) light_state->setSpotCutoff(90.f); light_state->setSpotExponent(2.f); - light_state->setSpecular(LLColor4::black); + const LLColor4 specular(0.f, 0.f, 0.f, 0.f); + light_state->setSpecular(specular); } else // omnidirectional (point) light { @@ -9419,7 +9424,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) assertInitialized(); - BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID()); + bool muted = avatar->isVisuallyMuted(); pushRenderTypeMask(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 2815d736e4..9c78048c46 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -432,34 +432,35 @@ public: enum LLRenderDebugMask { - RENDER_DEBUG_COMPOSITION = 0x0000001, - RENDER_DEBUG_VERIFY = 0x0000002, - RENDER_DEBUG_BBOXES = 0x0000004, - RENDER_DEBUG_OCTREE = 0x0000008, - RENDER_DEBUG_WIND_VECTORS = 0x0000010, - RENDER_DEBUG_OCCLUSION = 0x0000020, - RENDER_DEBUG_POINTS = 0x0000040, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x0000080, - RENDER_DEBUG_TEXTURE_AREA = 0x0000100, - RENDER_DEBUG_FACE_AREA = 0x0000200, - RENDER_DEBUG_PARTICLES = 0x0000400, - RENDER_DEBUG_GLOW = 0x0000800, - RENDER_DEBUG_TEXTURE_ANIM = 0x0001000, - RENDER_DEBUG_LIGHTS = 0x0002000, - RENDER_DEBUG_BATCH_SIZE = 0x0004000, - RENDER_DEBUG_ALPHA_BINS = 0x0008000, - RENDER_DEBUG_RAYCAST = 0x0010000, - RENDER_DEBUG_SHAME = 0x0020000, - RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000, - RENDER_DEBUG_SCULPTED = 0x0080000, - RENDER_DEBUG_AVATAR_VOLUME = 0x0100000, - RENDER_DEBUG_BUILD_QUEUE = 0x0200000, - RENDER_DEBUG_AGENT_TARGET = 0x0400000, - RENDER_DEBUG_UPDATE_TYPE = 0x0800000, - RENDER_DEBUG_PHYSICS_SHAPES = 0x1000000, - RENDER_DEBUG_NORMALS = 0x2000000, - RENDER_DEBUG_LOD_INFO = 0x4000000, - RENDER_DEBUG_RENDER_COMPLEXITY = 0x8000000 + RENDER_DEBUG_COMPOSITION = 0x00000001, + RENDER_DEBUG_VERIFY = 0x00000002, + RENDER_DEBUG_BBOXES = 0x00000004, + RENDER_DEBUG_OCTREE = 0x00000008, + RENDER_DEBUG_WIND_VECTORS = 0x00000010, + RENDER_DEBUG_OCCLUSION = 0x00000020, + RENDER_DEBUG_POINTS = 0x00000040, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080, + RENDER_DEBUG_TEXTURE_AREA = 0x00000100, + RENDER_DEBUG_FACE_AREA = 0x00000200, + RENDER_DEBUG_PARTICLES = 0x00000400, + RENDER_DEBUG_GLOW = 0x00000800, + RENDER_DEBUG_TEXTURE_ANIM = 0x00001000, + RENDER_DEBUG_LIGHTS = 0x00002000, + RENDER_DEBUG_BATCH_SIZE = 0x00004000, + RENDER_DEBUG_ALPHA_BINS = 0x00008000, + RENDER_DEBUG_RAYCAST = 0x00010000, + RENDER_DEBUG_SHAME = 0x00020000, + RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000, + RENDER_DEBUG_SCULPTED = 0x00080000, + RENDER_DEBUG_AVATAR_VOLUME = 0x00100000, + RENDER_DEBUG_BUILD_QUEUE = 0x00200000, + RENDER_DEBUG_AGENT_TARGET = 0x00400000, + RENDER_DEBUG_UPDATE_TYPE = 0x00800000, + RENDER_DEBUG_PHYSICS_SHAPES = 0x01000000, + RENDER_DEBUG_NORMALS = 0x02000000, + RENDER_DEBUG_LOD_INFO = 0x04000000, + RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000, + RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000, }; public: diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index bc0363014a..b09bf1d816 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -139,6 +139,7 @@ with the same filename but different name <texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" /> <texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" /> <texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" /> + <texture name="Command_Outbox_Icon" file_name="toolbar_icons/outbox.png" preload="true" /> <texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" /> <texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" /> <texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" /> @@ -388,22 +389,9 @@ with the same filename but different name <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" /> <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" /> - <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" /> - <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" /> - <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" /> - <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" /> - <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" /> - <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" /> - <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" /> - <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" /> - <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" /> - <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" /> - <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" /> - <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" /> - <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" /> - <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" /> - <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" /> - <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" /> + <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" /> + <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" /> + <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" /> <texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" /> diff --git a/indra/newview/skins/default/textures/toolbar_icons/outbox.png b/indra/newview/skins/default/textures/toolbar_icons/outbox.png Binary files differnew file mode 100644 index 0000000000..0f3db1c47c --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/outbox.png diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml index ba18306686..d695cd1f89 100644 --- a/indra/newview/skins/default/xui/da/menu_viewer.xml +++ b/indra/newview/skins/default/xui/da/menu_viewer.xml @@ -20,8 +20,6 @@ <menu_item_call label="Væk" name="Set Away"/> <menu_item_call label="Optaget" name="Set Busy"/> </menu> - <menu_item_call label="Anmod om administrator status" name="Request Admin Options"/> - <menu_item_call label="Stop administrator status" name="Leave Admin Options"/> <menu_item_call label="Afslut [APP_NAME]" name="Quit"/> </menu> <menu label="Kommunikér" name="Communicate"> @@ -36,11 +34,10 @@ <menu_item_check label="Søg" name="Search"/> <menu_item_call label="Foto" name="Take Snapshot"/> <menu_item_call label="Opret landemærke for dette sted" name="Create Landmark Here"/> - <menu label="Profil for sted" name="Land"> - <menu_item_call label="Profil for sted" name="Place Profile"/> - <menu_item_call label="Om land" name="About Land"/> - <menu_item_call label="Region/Estate" name="Region/Estate"/> - </menu> + <menu_item_separator/> + <menu_item_call label="Profil for sted" name="Place Profile"/> + <menu_item_call label="Om land" name="About Land"/> + <menu_item_call label="Region/Estate" name="Region/Estate"/> <menu_item_call label="Køb dette land" name="Buy Land"/> <menu_item_call label="Mit land" name="My Land"/> <menu label="Vis" name="LandShow"> @@ -56,7 +53,7 @@ </menu> <menu_item_call label="Teleport hjem" name="Teleport Home"/> <menu_item_call label="Sæt dette sted som 'Hjem'" name="Set Home to Here"/> - <menu label="Sol" name="Environment Settings"> + <menu label="Sol" name="Sun"> <menu_item_call label="Solopgang" name="Sunrise"/> <menu_item_call label="Middag" name="Noon"/> <menu_item_call label="Solnedgang" name="Sunset"/> @@ -155,22 +152,22 @@ <menu_item_check label="Vis muse-sigte" name="ShowCrosshairs"/> </menu> <menu label="Gengivelsestyper" name="Rendering Types"> - <menu_item_check label="Simpel" name="Simple"/> - <menu_item_check label="Alpha" name="Alpha"/> - <menu_item_check label="Træer" name="Tree"/> - <menu_item_check label="Avatarer" name="Character"/> - <menu_item_check label="Surface Patch" name="Surface Patch"/> - <menu_item_check label="Himmel" name="Sky"/> - <menu_item_check label="Vand" name="Water"/> - <menu_item_check label="Jord" name="Ground"/> - <menu_item_check label="Volume" name="Volume"/> - <menu_item_check label="Græs" name="Grass"/> - <menu_item_check label="Skyer" name="Clouds"/> - <menu_item_check label="Partikler" name="Particles"/> - <menu_item_check label="Bump" name="Bump"/> + <menu_item_check label="Simpel" name="Rendering Type Simple"/> + <menu_item_check label="Alpha" name="Rendering Type Alpha"/> + <menu_item_check label="Træer" name="Rendering Type Tree"/> + <menu_item_check label="Avatarer" name="Rendering Type Character"/> + <menu_item_check label="Surface Patch" name="Rendering Type Surface Patch"/> + <menu_item_check label="Himmel" name="Rendering Type Sky"/> + <menu_item_check label="Vand" name="Rendering Type Water"/> + <menu_item_check label="Jord" name="Rendering Type Ground"/> + <menu_item_check label="Volume" name="Rendering Type Volume"/> + <menu_item_check label="Græs" name="Rendering Type Grass"/> + <menu_item_check label="Skyer" name="Rendering Type Clouds"/> + <menu_item_check label="Partikler" name="Rendering Type Particles"/> + <menu_item_check label="Bump" name="Rendering Type Bump"/> </menu> <menu label="Gengivelsesegenskaber" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="Valgte" name="Selected"/> <menu_item_check label="Fremhævede" name="Highlighted"/> <menu_item_check label="Dynamiske teksturer" name="Dynamic Textures"/> @@ -182,10 +179,7 @@ <menu_item_call label="Tøm gruppe cache" name="ClearGroupCache"/> <menu_item_check label="Muse udjævning" name="Mouse Smoothing"/> <menu label="Shortcuts" name="Shortcuts"> - <menu_item_call label="Billede (L$[COST])..." name="Upload Image"/> - <menu_item_check label="Søg" name="Search"/> <menu_item_call label="Frigør taster" name="Release Keys"/> - <menu_item_call label="Sæt UI størrelse til standard" name="Set UI Size to Default"/> <menu_item_check label="Vis avanceret menu (gammel genvej)" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Luk vindue" name="Close Window"/> <menu_item_call label="Luk alle vinduer" name="Close All Windows"/> @@ -194,13 +188,6 @@ <menu_item_check label=""Joystick Flycam"" name="Joystick Flycam"/> <menu_item_call label="Nulstil udsyn" name="Reset View"/> <menu_item_call label="Se på den sidste der chattede" name="Look at Last Chatter"/> - <menu label="Vælg byggeværktøj" name="Select Tool"> - <menu_item_call label="Fokuseringsværktøj" name="Focus"/> - <menu_item_call label="Flyt værktøj" name="Move"/> - <menu_item_call label="Redigeringsværktøj" name="Edit"/> - <menu_item_call label="Opret værktøj" name="Create"/> - <menu_item_call label="Land værktøj" name="Land"/> - </menu> <menu_item_call label="Zoom ind" name="Zoom In"/> <menu_item_call label="Zoom standard" name="Zoom Default"/> <menu_item_call label="Zoom ud" name="Zoom Out"/> @@ -276,9 +263,8 @@ <menu_item_call label="Mist en netværkspakke" name="Drop a Packet"/> </menu> <menu_item_call label="Stød, skub & slag" name="Bumps, Pushes &amp; Hits"/> - <menu label="Verden" name="World"> + <menu label="Verden" name="DevelopWorld"> <menu_item_check label="Vælg anden sol end region" name="Sim Sun Override"/> - <menu_item_check label="Pejlelys blink effekt" name="Cheesy Beacon"/> <menu_item_check label="Fast vejr" name="Fixed Weather"/> <menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/> </menu> @@ -300,11 +286,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> - <menu_item_call label="Iris" name="Iris"/> - <menu_item_call label="Hovede" name="Head"/> - <menu_item_call label="Overkrop" name="Upper Body"/> - <menu_item_call label="Underkrop" name="Lower Body"/> - <menu_item_call label="Nederdel" name="Skirt"/> + <menu_item_call label="Iris" name="Grab Iris"/> + <menu_item_call label="Hovede" name="Grab Head"/> + <menu_item_call label="Overkrop" name="Grab Upper Body"/> + <menu_item_call label="Underkrop" name="Grab Lower Body"/> + <menu_item_call label="Nederdel" name="Grab Skirt"/> </menu> <menu label="Avatar tests" name="Character Tests"> <menu_item_call label="Skift avatar geometri" name="Toggle Character Geometry"/> @@ -326,8 +312,8 @@ <menu_item_check label="Vis administrationsmenu" name="View Admin Options"/> </menu> <menu label="Administrér" name="Admin"> - <menu label="Object"> - <menu_item_call label="Tag kopi" name="Take Copy"/> + <menu label="Object" name="AdminObject"> + <menu_item_call label="Tag kopi" name="Admin Take Copy"/> <menu_item_call label="Gennemtving ejer til mig" name="Force Owner To Me"/> <menu_item_call label="Gennemtving ejer tolerance" name="Force Owner Permissive"/> <menu_item_call label="Slet" name="Delete"/> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 4772f744ea..1d5a6740b7 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1206,10 +1206,6 @@ Only large parcels can be listed in search. name="push_restrict_region_text"> No Pushing (Region Override) </panel.string> - <panel.string - name="see_avs_text"> - Avatars on other parcels can see - </panel.string> <text type="string" length="1" @@ -1524,24 +1520,24 @@ Only large parcels can be listed in search. length="1" follows="left|top" text_color="LtGray" - height="16" + height="32" layout="topleft" left="274" - top="166" + top="150" name="allow_label5" - width="278"> - and chat with avatars on this parcel + width="205" + wrap="true"> + Avatars on other parcels can see and chat with avatars on this parcel </text> <check_box height="16" - label="See Avatars" follows="top" layout="topleft" left="253" top="150" name="SeeAvatarsCheck" tool_tip="Allows avatars on other parcels to see and chat with avatars on this parcel, and you to see and chat with them." - width="120" /> + width="10" /> <text type="string" length="1" @@ -1955,36 +1951,18 @@ Only large parcels can be listed in search. name="access_estate_defined"> (Defined by the Estate) </panel.string> - <panel.string - name="allow_public_access"> - Allow Public Access ([MATURITY]) (Note: Unchecking this will create ban lines) - </panel.string> <panel.string name="estate_override"> One or more of these options is set at the estate level </panel.string> - <text - type="string" - length="1" - follows="left|top" - height="16" - layout="topleft" - left="10" - name="Limit access to this parcel to:" - text_color="White" - top="10" - width="400"> - Access To This Parcel - </text> <check_box follows="top|left" height="16" layout="topleft" - left_delta="0" + left="8" name="public_access" - top_pad="5" - label_text.valign="center" - label_text.v_pad="-2" + label="Allow Public Access (Unchecking this will create ban lines)" + top_pad="10" width="278" /> <text type="string" @@ -1994,28 +1972,28 @@ Only large parcels can be listed in search. layout="topleft" left_delta="20" name="Only Allow" - top="49" + top="30" width="325"> - Restrict Access to Residents verified by: + Allow access only to Residents who: </text> <check_box follows="top|left" height="16" - label="Payment Information on File [ESTATE_PAYMENT_LIMIT]" + label="Have payment Information on File [ESTATE_PAYMENT_LIMIT]" layout="topleft" left_delta="0" name="limit_payment" - tool_tip="Ban unidentified Residents." + tool_tip="Residents must have payment information on file to access this parcel. See the [SUPPORT_SITE] for more information." top_pad="4" width="278" /> <check_box follows="top|left" height="16" - label="Age Verification [ESTATE_AGE_LIMIT]" + label="Have been age-verified [ESTATE_AGE_LIMIT]" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age verified to access this parcel. See the [SUPPORT_SITE] for more information." top_pad="4" width="278" /> <check_box @@ -2025,7 +2003,7 @@ Only large parcels can be listed in search. left="8" name="GroupCheck" tool_tip="Set group in the General tab." - top="109" + top="89" width="278" /> <check_box enabled="false" diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index d101bca694..cd075abc41 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -34,7 +34,6 @@ left_delta="0" top_delta="0" name="external_controls" - user_resize="false" width="620"> <web_browser trusted_content="true" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2f3788ec3d..8a73335261 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -16,7 +16,7 @@ min_width="250" min_height="190"> <layout_stack - animate="false" + animate="true" default_tab_group="2" follows="all" height="320" @@ -32,8 +32,7 @@ min_width="115" width="150" height="320" - auto_resize="false" - user_resize="false"> + auto_resize="false"> <panel name="panel_im_control_panel" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index c3324a6aa4..ce788654aa 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -37,7 +37,6 @@ min_height="20" name="nav_controls" top="400" - user_resize="false" width="800"> <button follows="left|top" @@ -113,7 +112,6 @@ min_height="20" name="time_controls" top_delta="0" - user_resize="false" width="800"> <button follows="left|top" @@ -171,7 +169,6 @@ min_height="20" name="parcel_owner_controls" top_delta="0" - user_resize="false" width="540"> <button enabled="false" @@ -193,7 +190,6 @@ left_delta="0" name="external_controls" top_delta="0" - user_resize="false" width="540"> <web_browser bottom="-30" diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml new file mode 100644 index 0000000000..6f387f4800 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<floater + open_positioning="cascading" + can_close="true" + can_resize="true" + height="440" + help_topic="floater_merchant_outbox" + min_width="300" + min_height="200" + name="floater_merchant_outbox" + save_rect="true" + save_visibility="false" + reuse_instance="true" + title="MERCHANT OUTBOX" + width="333"> + <string name="OutboxFolderCount0"></string> + <string name="OutboxFolderCount1">1 folder</string> + <string name="OutboxFolderCountN">[NUM] folders</string> + <string name="OutboxImporting">Sending folders...</string> + <string name="OutboxInitializing">Initializing...</string> + <panel + follows="all" + layout="topleft" + left="0" + top="0" + label="" + height="440" + width="333"> + <panel + follows="all" + left="10" + bottom="370" + width="313" + top="0" + bg_opaque_color="InventoryBackgroundColor"> + <panel + name="outbox_inventory_placeholder_panel" + follows="all" + layout="topleft" + top="0" + left="0" + width="308" + height="370" + bg_opaque_color="InventoryBackgroundColor"> + <text + name="outbox_inventory_placeholder_title" + type="string" + follows="top|left|right" + layout="topleft" + top="10" + left="0" + width="308" + height="25" + wrap="true" + halign="center" + font="SansSerifBold"> + Loading... + </text> + <text + name="outbox_inventory_placeholder_text" + type="string" + follows="top|left|right" + layout="topleft" + top="35" + left="0" + width="308" + height="130" + wrap="true" + halign="left" /> + </panel> + </panel> + <panel + follows="bottom|left|right" + left="10" + bottom="435" + width="313" + top="370"> + <panel + name="outbox_generic_drag_target" + mouse_opaque="false" + follows="all" + top="5" + left="5" + width="303" + height="25" + background_visible="false" + bg_alpha_color="EmphasisColor_35" + border="true" + bevel_style="in" + visible="true"> + <text + type="string" + follows="all" + layout="topleft" + top="6" + height="20" + left="5" + width="293" + halign="center" + font="SansSerifMedium" + font_shadow="hard" + valign="bottom"> + Drag items here to create folders + </text> + </panel> + <text + name="outbox_folder_count" + type="string" + follows="all" + layout="topleft" + top="40" + left="5" + width="150" + height="20" + wrap="true" + halign="left" + valign="bottom" + font="SansSerif" /> + <button + label="Send to Marketplace" + tool_tip="Push to my Marketplace Storefront" + is_toggle="false" + name="outbox_import_btn" + follows="bottom|right" + tab_stop="false" + halign="center" + top="37" + left="160" + height="25" + width="150" + enabled="false" /> + </panel> + <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> + <layout_panel /> + <layout_panel height="24" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all"> + <layout_panel width="0" /> + <layout_panel width="24" auto_resize="false"> + <loading_indicator + height="24" + layout="topleft" + left="0" + top="0" + width="24" /> + </layout_panel> + <layout_panel width="0" /> + </layout_stack> + </layout_panel> + <layout_panel /> + </layout_stack> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..f95f21e63a --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="true" + can_close="true" + bevel_style="in" + height="300" + layout="topleft" + min_height="40" + min_width="420" + name="Test Floater" + title="LAYOUTSTACK TESTS" + width="420"> + <layout_stack name="test_stack" + left="0" + top="0" + width="100" + height="250" + follows="left|top|bottom" + orientation="vertical"> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + </layout_stack> + <layout_stack name="test_stack" + left_pad="5" + top="0" + width="100" + height="250" + follows="left|top|bottom" + orientation="vertical"> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="100" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + visible="false" + bg_alpha_color="blue" + height="100" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + min_height="10" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + min_height="10" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="100" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="100" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="100" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="100" + visible="true" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + </layout_stack> + <layout_stack name="test_stack" + left_pad="5" + top="0" + width="100" + height="250" + follows="left|top|bottom" + orientation="vertical"> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + height="11" + bg_alpha_color="blue" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + </layout_stack> + <layout_stack name="test_stack" + left_pad="5" + top="0" + width="100" + height="250" + follows="left|top|bottom" + orientation="vertical"> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="fixed" + auto_resize="false" + user_resize="true" + height="50" + bg_alpha_color="green" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="black">fixed</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml index 493d44a9cf..72e6187a14 100644 --- a/indra/newview/skins/default/xui/en/floater_toybox.xml +++ b/indra/newview/skins/default/xui/en/floater_toybox.xml @@ -5,7 +5,7 @@ can_minimize="false" can_resize="false" default_tab_group="1" - height="330" + height="375" help_topic="toybox" layout="topleft" legacy_header_height="18" @@ -46,7 +46,7 @@ Buttons will appear as shown or as icon-only depending on each toolbar's settings. </text> <toolbar - bottom="265" + bottom="310" button_display_mode="icons_with_text" follows="all" left="20" @@ -82,11 +82,11 @@ <panel bevel_style="none" border="true" - bottom="266" + bottom="311" follows="left|bottom|right" left="20" right="-20" - top="266" /> + top="311" /> <button follows="left|bottom|right" height="23" @@ -95,7 +95,7 @@ layout="topleft" left="185" name="btn_clear_all" - top="285" + top="330" width="130"> <button.commit_callback function="Toybox.ClearAll" /> </button> @@ -107,7 +107,7 @@ layout="topleft" left="335" name="btn_restore_defaults" - top="285" + top="330" width="130"> <button.commit_callback function="Toybox.RestoreDefaults" /> </button> diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml index 3921cfcd2c..06d4327293 100644 --- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml @@ -22,6 +22,7 @@ or specifying its path in the "Editor Path" field.</string> layout="topleft" left="0" mouse_opaque="false" + default_tab_group="1" name="main_panel" right="750" top="0"> @@ -196,6 +197,7 @@ or specifying its path in the "Editor Path" field.</string> left="10" name="name_list" right="-10" + tab_group="1" search_column="1" top="80"> <scroll_list.columns diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 6807b01fa3..cea19ec75c 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -49,7 +49,6 @@ width="263"> <layout_panel follows="top|left|right" - user_resize="false" auto_resize="false" layout="topleft" min_height="20" @@ -89,7 +88,7 @@ visible="true" width="20" /> </layout_panel> - <layout_panel name="leave_call_panel" height="26" min_height="26" user_resize="false" auto_resize="false"> + <layout_panel name="leave_call_panel" height="26" min_height="26" auto_resize="false"> <layout_stack clip="true" follows="left|top|right" @@ -110,7 +109,6 @@ </layout_panel> <layout_panel auto_resize="false" - user_resize="false" follows="top|right" height="23" visible="true" @@ -133,7 +131,6 @@ top_pad="0" height="132" name="callers_panel" - user_resize="false" auto_resize="true" width="280"> <avatar_list diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 57d1c92acb..cea10adca8 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -31,7 +31,6 @@ min_height="20" name="nav_controls" top="400" - user_resize="false" width="770"> <button image_overlay="Arrow_Left_Off" @@ -160,7 +159,6 @@ left_delta="0" name="external_controls" top_delta="0" - user_resize="false" auto_resize="true" width="585"> <web_browser @@ -173,8 +171,7 @@ </layout_panel> <layout_panel name="status_bar" height="23" - auto_resize="false" - user_resize="false"> + auto_resize="false"> <text type="string" length="200" diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index b4be17e677..a87027a113 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -23,7 +23,6 @@ left="0" top="0" width="1024" - user_resize="false" auto_resize="false" visible="true"> <view mouse_opaque="false" @@ -40,7 +39,6 @@ name="nav_bar_container" tab_stop="false" width="1024" - user_resize="false" visible="false"/> <layout_panel auto_resize="true" follows="all" diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml index f818ebe2d7..63e154697b 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml @@ -114,6 +114,15 @@ function="Object.EnableMute" /> </menu_item_call> <menu_item_call + label="Unblock" + layout="topleft" + name="unblock"> + <menu_item_call.on_click + function="Object.Mute" /> + <menu_item_call.on_visible + function="Object.EnableUnmute" /> + </menu_item_call> + <menu_item_call label="Zoom In" layout="topleft" name="zoom_in"> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index fb85e5278a..ef4a1bc061 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -686,12 +686,12 @@ parameter="copy_to_outbox" /> </menu_item_call> <menu_item_call - label="Move to Merchant Outbox" + label="Send to Marketplace" layout="topleft" - name="Merchant Move"> + name="Marketplace Send"> <menu_item_call.on_click function="Inventory.DoToSelected" - parameter="move_to_outbox" /> + parameter="send_to_marketplace" /> </menu_item_call> <menu_item_call label="--no options--" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index 0f42000ae7..e91f5af3d5 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -3,6 +3,7 @@ layout="topleft" left="0" mouse_opaque="false" + can_tear_off="true" name="menu_inventory_add" visible="false"> <menu diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index ec2dd10248..1d11abcf73 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -118,7 +118,7 @@ </menu_item_call> <menu_item_call label="Walk / run / fly..." - name="Stop Animating My Avatar"> + name="Walk / run / fly"> <menu_item_call.on_click function="Floater.ToggleOrBringToFront" parameter="moveview" /> @@ -144,32 +144,22 @@ </menu_item_call> </menu> - <menu_item_call - label="Request Admin Status" - name="Request Admin Options" - shortcut="control|alt|G" - visible="false"> - <menu_item_call.on_click - function="Advanced.RequestAdminStatus" /> - </menu_item_call> - <menu_item_call - label="Leave Admin Status" - name="Leave Admin Options" - shortcut="control|alt|shift|G" - visible="false"> - <menu_item_call.on_click - function="Advanced.LeaveAdminStatus" /> - </menu_item_call> - <menu_item_separator/> <menu_item_call - label="Buy L$" + label="Buy L$..." name="Buy and Sell L$"> <menu_item_call.on_click function="BuyCurrency" /> </menu_item_call> <menu_item_call + label="Merchant Outbox..." + name="MerchantOutbox"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="outbox" /> + </menu_item_call> + <menu_item_call label="Account dashboard..." name="Manage My Account"> <menu_item_call.on_click @@ -525,7 +515,7 @@ <menu create_jump_keys="true" label="Sun" - name="Environment Settings" + name="Sun" tear_off="true"> <menu_item_call label="Sunrise" @@ -1452,7 +1442,7 @@ tear_off="true"> <menu_item_check label="Simple" - name="Simple" + name="Rendering Type Simple" shortcut="control|alt|shift|1"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1463,7 +1453,7 @@ </menu_item_check> <menu_item_check label="Alpha" - name="Alpha" + name="Rendering Type Alpha" shortcut="control|alt|shift|2"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1474,7 +1464,7 @@ </menu_item_check> <menu_item_check label="Tree" - name="Tree" + name="Rendering Type Tree" shortcut="control|alt|shift|3"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1485,7 +1475,7 @@ </menu_item_check> <menu_item_check label="Avatars" - name="Character" + name="Rendering Type Character" shortcut="control|alt|shift|4"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1496,7 +1486,7 @@ </menu_item_check> <menu_item_check label="Surface Patch" - name="Surface Patch" + name="Rendering Type Surface Patch" shortcut="control|alt|shift|5"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1507,7 +1497,7 @@ </menu_item_check> <menu_item_check label="Sky" - name="Sky" + name="Rendering Type Sky" shortcut="control|alt|shift|6"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1518,7 +1508,7 @@ </menu_item_check> <menu_item_check label="Water" - name="Water" + name="Rendering Type Water" shortcut="control|alt|shift|7"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1529,7 +1519,7 @@ </menu_item_check> <menu_item_check label="Ground" - name="Ground" + name="Rendering Type Ground" shortcut="control|alt|shift|8"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1540,7 +1530,7 @@ </menu_item_check> <menu_item_check label="Volume" - name="Volume" + name="Rendering Type Volume" shortcut="control|alt|shift|9"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1551,7 +1541,7 @@ </menu_item_check> <menu_item_check label="Grass" - name="Grass" + name="Rendering Type Grass" shortcut="control|alt|shift|0"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1562,7 +1552,7 @@ </menu_item_check> <menu_item_check label="Clouds" - name="Clouds" + name="Rendering Type Clouds" shortcut="control|alt|shift|-"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1573,7 +1563,7 @@ </menu_item_check> <menu_item_check label="Particles" - name="Particles" + name="Rendering Type Particles" shortcut="control|alt|shift|="> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1584,7 +1574,7 @@ </menu_item_check> <menu_item_check label="Bump" - name="Bump" + name="Rendering Type Bump" shortcut="control|alt|shift|\"> <menu_item_check.on_check function="Advanced.CheckRenderType" @@ -1601,7 +1591,7 @@ tear_off="true"> <menu_item_check label="UI" - name="UI" + name="ToggleUI" shortcut="control|alt|F1"> <menu_item_check.on_check function="Advanced.CheckFeature" @@ -1734,28 +1724,6 @@ name="Shortcuts" tear_off="true" visible="false"> - <menu_item_call - label="Image (L$[COST])..." - name="Upload Image" - shortcut="control|U"> - <menu_item_call.on_click - function="File.UploadImage" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_check - label="Search" - name="Search" - shortcut="control|F"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="search" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="search" /> - </menu_item_check> - <!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. --> <menu_item_check label="Show Advanced Menu - legacy shortcut" @@ -1842,55 +1810,6 @@ <menu_item_separator/> - <menu - create_jump_keys="true" - label="Select Build Tool" - name="Select Tool" - tear_off="true"> - <menu_item_call - label="Focus Tool" - name="Focus" - shortcut="control|1"> - <menu_item_call.on_click - function="Tools.SelectTool" - parameter="focus" /> - </menu_item_call> - <menu_item_call - label="Move Tool" - name="Move" - shortcut="control|2"> - <menu_item_call.on_click - function="Tools.SelectTool" - parameter="move" /> - </menu_item_call> - <menu_item_call - label="Edit Tool" - name="Edit" - shortcut="control|3"> - <menu_item_call.on_click - function="Tools.SelectTool" - parameter="edit" /> - </menu_item_call> - <menu_item_call - label="Create Tool" - name="Create" - shortcut="control|4"> - <menu_item_call.on_click - function="Tools.SelectTool" - parameter="create" /> - </menu_item_call> - <menu_item_call - label="Land Tool" - name="Land" - shortcut="control|5"> - <menu_item_call.on_click - function="Tools.SelectTool" - parameter="land" /> - </menu_item_call> - </menu> - - <menu_item_separator/> - <menu_item_call label="Zoom In" name="Zoom In" @@ -2500,6 +2419,16 @@ function="Advanced.ToggleInfoDisplay" parameter="rendercomplexity" /> </menu_item_check> + <menu_item_check + label="Attachment Bytes" + name="attachment bytes"> + <menu_item_check.on_check + function="Advanced.CheckInfoDisplay" + parameter="attachment bytes" /> + <menu_item_check.on_click + function="Advanced.ToggleInfoDisplay" + parameter="attachment bytes" /> + </menu_item_check> <menu_item_check label="Sculpt" name="Sculpt"> @@ -2853,7 +2782,7 @@ <menu create_jump_keys="true" label="World" - name="World" + name="DevelopWorld" tear_off="true"> <menu_item_check label="Sim Sun Override" @@ -2866,16 +2795,6 @@ parameter="SkyOverrideSimSunPosition" /> </menu_item_check> <menu_item_check - label="Cheesy Beacon" - name="Cheesy Beacon"> - <menu_item_check.on_check - function="CheckControl" - parameter="CheesyBeacon" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="CheesyBeacon" /> - </menu_item_check> - <menu_item_check label="Fixed Weather" name="Fixed Weather"> <menu_item_check.on_check @@ -3099,7 +3018,7 @@ tear_off="true"> <menu_item_call label="Iris" - name="Iris"> + name="Grab Iris"> <menu_item_call.on_click function="Advanced.GrabBakedTexture" parameter="iris" /> @@ -3109,7 +3028,7 @@ </menu_item_call> <menu_item_call label="Head" - name="Head"> + name="Grab Head"> <menu_item_call.on_click function="Advanced.GrabBakedTexture" parameter="head" /> @@ -3119,7 +3038,7 @@ </menu_item_call> <menu_item_call label="Upper Body" - name="Upper Body"> + name="Grab Upper Body"> <menu_item_call.on_click function="Advanced.GrabBakedTexture" parameter="upper" /> @@ -3129,7 +3048,7 @@ </menu_item_call> <menu_item_call label="Lower Body" - name="Lower Body"> + name="Grab Lower Body"> <menu_item_call.on_click function="Advanced.GrabBakedTexture" parameter="lower" /> @@ -3139,7 +3058,7 @@ </menu_item_call> <menu_item_call label="Skirt" - name="Skirt"> + name="Grab Skirt"> <menu_item_call.on_click function="Advanced.GrabBakedTexture" parameter="skirt" /> @@ -3458,10 +3377,11 @@ <menu create_jump_keys="true" label="Object" + name="AdminObject" tear_off="true"> <menu_item_call label="Take Copy" - name="Take Copy" + name="Admin Take Copy" shortcut="control|alt|shift|O"> <menu_item_call.on_click function="Admin.ForceTakeCopy" /> @@ -3730,7 +3650,7 @@ <menu create_jump_keys="true" label="Help" - name="Help" + name="DeprecatedHelp" tear_off="true"> <menu_item_call label="Official Linden Blog" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1daf2e6948..af75d49353 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -203,34 +203,80 @@ Save changes to current clothing/body part? icon="alertmodal.tga" name="ConfirmNoCopyToOutbox" type="alertmodal"> - You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item? - [ITEM_NAME] +You don't have permission to copy one or more of these items to the Merchant Outbox. You can move them or leave them behind. + <usetemplate + name="okcancelbuttons" + notext="Don't move item(s)" + yestext="Move item(s)"/> + </notification> + + <notification + icon="OutboxStatus_Success" + name="OutboxFolderCreated" + type="outbox"> + <unique/> +A new folder has been created for each item you have transferred into the top level of your Merchant Outbox. + + <usetemplate + ignoretext="A new folder was created in the Merchant Outbox" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Success" + name="OutboxImportComplete" + type="outbox"> +Success + +All folders were successfully sent to the Marketplace. + <usetemplate - name="okcancelbuttons" - notext="No" - yestext="Yes"/> - </notification> + ignoretext="All folders sent to the Marketplace" + name="okignore" + yestext="OK"/> + </notification> <notification - icon="alertmodal.tga" - name="OutboxUploadComplete" - type="alertmodal"> -Marketplace upload complete. + icon="OutboxStatus_Warning" + name="OutboxImportHadErrors" + type="outbox"> +Some folders did not transfer + +Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox. + +See the [[MARKETPLACE_IMPORTS_URL] error log] for more information. + <usetemplate name="okbutton" - yestext="Hooray!"/> + yestext="OK"/> </notification> <notification - icon="alertmodal.tga" - name="OutboxUploadHadErrors" - type="alertmodal"> -Marketplace upload completed with errors! Please correct the problems in your outbox and retry. Thanks. + icon="OutboxStatus_Error" + name="OutboxImportFailed" + type="outbox"> +Transfer failed + +No folders were sent to the Marketplace because of a system or network error. Try again later. + <usetemplate name="okbutton" - yestext="Boo!"/> + yestext="OK"/> </notification> + <notification + icon="OutboxStatus_Error" + name="OutboxInitFailed" + type="outbox"> +Marketplace initialization failed + +Initialization with the Marketplace failed because of a system or network error. Try again later. + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml index 93cafd4a53..d68fa6ca6c 100644 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml @@ -27,8 +27,7 @@ mouse_opaque="false" width="147" top="0" - name="speakers_list_panel" - user_resize="false"> + name="speakers_list_panel"> <avatar_list color="DkGray2" follows="all" @@ -50,7 +49,6 @@ min_height="25" width="130" name="call_btn_panel" - user_resize="false" visible="false"> <button follows="all" @@ -68,7 +66,6 @@ min_height="25" width="130" name="end_call_btn_panel" - user_resize="false" visible="false"> <button follows="all" @@ -85,7 +82,6 @@ min_height="25" width="130" name="voice_ctrls_btn_panel" - user_resize="false" visible="false"> <button follows="all" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml index b5e1a5f16d..f4722b05d6 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml @@ -31,7 +31,6 @@ width="1000"> <layout_panel auto_resize="false" - user_resize="false" min_width="2" width="2" /> <layout_panel @@ -40,8 +39,7 @@ height="28" layout="topleft" width="310" - min_width="188" - user_resize="false"> + min_width="188"> <panel left="0" filename="panel_nearby_chat_bar.xml" @@ -61,8 +59,7 @@ width="82" top_delta="0" min_width="52" - name="gesture_panel" - user_resize="false"> + name="gesture_panel"> <gesture_combo_list follows="left|right" height="23" @@ -80,7 +77,6 @@ </layout_panel> <layout_panel auto_resize="false" - user_resize="false" min_width="3" name="after_gesture_panel" width="3"/> diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml index 41d1036a4d..ff0146490b 100644 --- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml @@ -27,8 +27,8 @@ min_width="95" mouse_opaque="false" name="chiclet_list_panel" + auto_resize="true" top="0" - user_resize="false" width="189"> <chiclet_panel chiclet_padding="4" @@ -78,7 +78,6 @@ </chiclet_panel> </layout_panel> <layout_panel auto_resize="false" - user_resize="false" width="4" min_width="4"/> <layout_panel @@ -90,7 +89,6 @@ min_width="37" name="im_well_panel" top="0" - user_resize="false" width="37"> <chiclet_im_well follows="right" @@ -139,7 +137,6 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well min_width="37" name="notification_well_panel" top="0" - user_resize="false" width="37"> <chiclet_notification follows="right" diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml index 6c8d994bc6..d4a2745d1d 100644 --- a/indra/newview/skins/default/xui/en/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -289,8 +289,7 @@ left="0" top="0" width="290" - height="16" - user_resize="false"> + height="16"> <text follows="left|top" font.style="BOLD" @@ -327,8 +326,7 @@ left="0" top="0" width="290" - height="16" - user_resize="false"> + height="16"> <text follows="left|top" font.style="BOLD" @@ -357,8 +355,7 @@ left="0" top="0" width="290" - height="215" - user_resize="false"> + height="215"> <text auto_resize="false" follows="left|top" @@ -416,7 +413,6 @@ layout="bottomleft" left="0" name="layout_panel1" - user_resize="false" auto_resize="true" width="101"> <button @@ -436,7 +432,6 @@ layout="bottomleft" left_pad="3" name="show_on_map_btn_lp" - user_resize="false" auto_resize="true" width="100"> <button @@ -455,7 +450,6 @@ layout="bottomleft" left_pad="3" name="edit_btn_lp" - user_resize="false" auto_resize="true" width="101"> <button diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index e512d63f9e..3509eaa285 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -319,7 +319,6 @@ layout="bottomleft" left="0" name="save_changes_btn_lp" - user_resize="false" auto_resize="true" width="156"> <button @@ -339,7 +338,6 @@ layout="bottomleft" left_pad="3" name="show_on_map_btn_lp" - user_resize="false" auto_resize="true" width="157"> <button diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index 6d0be7fdec..553c112e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -202,7 +202,6 @@ layout="topleft" left="0" name="layout_panel1" - user_resize="false" auto_resize="true" width="150"> <button @@ -222,7 +221,6 @@ layout="topleft" left_pad="4" name="layout_panel2" - user_resize="false" auto_resize="true" width="146"> <button diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index 442eb8c28d..2c7c8133d1 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -435,7 +435,6 @@ layout="bottomleft" name="save_changes_btn_lp" top="0" - user_resize="false" auto_resize="true" width="153"> <button @@ -456,7 +455,6 @@ left_pad="3" name="show_on_map_btn_lp" top="0" - user_resize="false" auto_resize="true" width="154"> <button diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index c8764a6a84..69a692e2c4 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -454,7 +454,6 @@ left="0" mouse_opaque="false" name="save_as_btn_lp" - user_resize="false" auto_resize="true" width="154"> <button @@ -474,7 +473,6 @@ left_pad="3" mouse_opaque="false" name="revert_btn_lp" - user_resize="false" auto_resize="true" width="152"> <button diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml index c1dc2aaaf7..ad10e53a4e 100644 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml @@ -26,8 +26,7 @@ mouse_opaque="false" width="145" top="0" - name="speakers_list_panel" - user_resize="false"> + name="speakers_list_panel"> <avatar_list color="DkGray2" follows="all" @@ -48,8 +47,7 @@ layout="topleft" min_height="28" width="130" - name="group_info_btn_panel" - user_resize="false"> + name="group_info_btn_panel"> <button follows="left|right|bottom" height="23" @@ -66,8 +64,7 @@ layout="topleft" min_height="28" width="130" - name="call_btn_panel" - user_resize="false"> + name="call_btn_panel"> <button follows="all" height="23" @@ -84,7 +81,6 @@ min_height="28" width="130" name="end_call_btn_panel" - user_resize="false" visible="false"> <button follows="all" @@ -101,7 +97,6 @@ min_height="28" width="130" name="voice_ctrls_btn_panel" - user_resize="false" visible="false"> <button follows="all" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index ec3f3b48bc..206496cc0e 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -97,6 +97,7 @@ background_visible="true" follows="all" layout="topleft" auto_resize="true" + user_resize="true" height="513" width="313"> <accordion @@ -195,7 +196,6 @@ background_visible="true" layout="bottomleft" left="0" name="btn_refresh_lp" - user_resize="false" auto_resize="false" width="24"> <button @@ -215,7 +215,6 @@ background_visible="true" layout="bottomleft" left_pad="3" name="btn_chat_lp" - user_resize="false" auto_resize="true" width="91"> <button @@ -234,7 +233,6 @@ background_visible="true" layout="bottomleft" left_pad="3" name="call_btn_lp" - user_resize="false" auto_resize="true" width="91"> <button @@ -255,7 +253,6 @@ background_visible="true" layout="bottomleft" left_pad="3" name="btn_apply_lp" - user_resize="false" auto_resize="true" width="91"> <button diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index 9f73b7c540..8fcd6ccbaf 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -32,8 +32,7 @@ min_height="20" width="140" name="view_profile_btn_panel" - top="0" - user_resize="false"> + top="0" > <button follows="left|top|right" height="23" @@ -49,8 +48,7 @@ layout="topleft" min_height="25" width="140" - name="add_friend_btn_panel" - user_resize="false"> + name="add_friend_btn_panel"> <button follows="left|top|right" height="23" @@ -66,8 +64,7 @@ layout="topleft" min_height="25" width="140" - name="teleport_btn_panel" - user_resize="false"> + name="teleport_btn_panel"> <button auto_resize="false" follows="left|top|right" @@ -84,8 +81,7 @@ layout="topleft" min_height="25" width="140" - name="share_btn_panel" - user_resize="false"> + name="share_btn_panel"> <button auto_resize="true" follows="left|top|right" @@ -101,8 +97,7 @@ layout="topleft" min_height="25" width="140" - name="pay_btn_panel" - user_resize="false"> + name="pay_btn_panel"> <button auto_resize="true" follows="left|top|right" @@ -118,8 +113,7 @@ layout="topleft" min_height="25" width="140" - name="call_btn_panel" - user_resize="false"> + name="call_btn_panel"> <button follows="left|top|right" height="23" @@ -135,7 +129,6 @@ min_height="25" width="140" name="end_call_btn_panel" - user_resize="false" visible="false"> <button follows="left|top|right" @@ -152,7 +145,6 @@ min_height="25" width="140" name="voice_ctrls_btn_panel" - user_resize="false" visible="false"> <button follows="left|top|right" @@ -169,7 +161,6 @@ layout="topleft" min_height="0" width="140" - name="spacer" - user_resize="false" /> + name="spacer"/> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 23d8cb11ca..2a5933e3e9 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -114,7 +114,6 @@ height="25" layout="topleft" name="options_gear_btn_panel" - user_resize="false" width="32"> <menu_button follows="bottom|left" @@ -135,7 +134,6 @@ height="25" layout="topleft" name="add_btn_panel" - user_resize="false" width="32"> <button follows="bottom|left" @@ -156,7 +154,6 @@ height="25" layout="topleft" name="dummy_panel" - user_resize="false" width="212"> <icon follows="bottom|left|right" @@ -173,7 +170,6 @@ height="25" layout="topleft" name="trash_btn_panel" - user_resize="false" width="31"> <dnd_button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 6521bf2a4e..223326dd06 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -48,7 +48,6 @@ name="login" layout="topleft" width="705" min_width="705" -user_resize="false" height="80"> <text follows="left|bottom" @@ -165,7 +164,6 @@ follows="right|bottom" name="links" width="205" min_width="205" -user_resize="false" height="80"> <text follows="right|bottom" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index e6c5110999..d6d8b2a83e 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_visible="true" default_tab_group="1" follows="all" height="423" @@ -51,10 +50,6 @@ top="18" width="303" /> <tab_container - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - background_visible="true" - background_opaque="true" follows="all" halign="center" height="339" @@ -71,7 +66,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" follows="all" @@ -90,7 +84,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" follows="all" @@ -119,7 +112,6 @@ height="25" layout="topleft" name="options_gear_btn_panel" - user_resize="false" width="32"> <menu_button follows="bottom|left" @@ -140,7 +132,6 @@ height="25" layout="topleft" name="add_btn_panel" - user_resize="false" width="32"> <button follows="bottom|left" @@ -161,7 +152,6 @@ height="25" layout="topleft" name="dummy_panel" - user_resize="false" width="212"> <icon follows="bottom|left|right" @@ -178,7 +168,6 @@ height="25" layout="topleft" name="trash_btn_panel" - user_resize="false" width="31"> <dnd_button follows="bottom|left" 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 7a8e872dc9..4bf420b79f 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -54,11 +54,11 @@ width="800" height="2"/> <layout_stack - use_border="true" - bevel_style="none" follows="all" height="34" layout="topleft" + border_size="0" + resize_bar_overlap="3" left="0" mouse_opaque="false" name="nvp_stack" @@ -73,130 +73,130 @@ min_width="480" name="navigation_layout_panel" width="480"> - <panel - background_visible="false" - follows="left|top|right" - top="3" - height="23" - layout="topleft" - left="0" - name="navigation_panel" - width="480"> - <pull_button - follows="left|top" - direction="down" - height="23" - image_overlay="Arrow_Left_Off" - image_bottom_pad="1" - layout="topleft" - left="10" - name="back_btn" - tool_tip="Go back to previous location" - top="2" - width="31" /> - <pull_button - follows="left|top" - direction="down" - height="23" - image_overlay="Arrow_Right_Off" - image_bottom_pad="1" - layout="topleft" - left_pad="0" - name="forward_btn" - tool_tip="Go forward one location" - top_delta="0" - width="31" /> - <button - follows="left|top" - height="23" - image_bottom_pad="1" - image_overlay="Home_Off" - layout="topleft" - left_pad="7" - name="home_btn" - tool_tip="Teleport to my home location" - top_delta="0" - width="32" /> - <location_input - follows="all" - halign="right" - height="23" - label="Location" - layout="topleft" - left_pad="7" - max_chars="254" - mouse_opaque="false" - name="location_combo" - top_delta="0" - width="355"> - <combo_list - mouse_wheel_opaque="true"/> - </location_input> - </panel> - </layout_panel> - - <layout_panel - auto_resize="false" - layout="topleft" - max_width="5" - min_width="5" - name="nav_bar_resize_handle_panel" - user_resize="false" - width="5"> - <icon - follows="top|right" - height="25" - image_name="ChatBarHandle" - layout="topleft" - left="-6" - name="resize_handle" - top="4" - width="5" /> - </layout_panel> - + <panel + background_visible="false" + follows="left|top|right" + top="3" + height="23" + layout="topleft" + left="0" + name="navigation_panel" + width="480"> + <pull_button + follows="left|top" + direction="down" + height="23" + image_overlay="Arrow_Left_Off" + image_bottom_pad="1" + layout="topleft" + left="10" + name="back_btn" + tool_tip="Go back to previous location" + top="2" + width="31" /> + <pull_button + follows="left|top" + direction="down" + height="23" + image_overlay="Arrow_Right_Off" + image_bottom_pad="1" + layout="topleft" + left_pad="0" + name="forward_btn" + tool_tip="Go forward one location" + top_delta="0" + width="31" /> + <button + follows="left|top" + height="23" + image_bottom_pad="1" + image_overlay="Home_Off" + layout="topleft" + left_pad="7" + name="home_btn" + tool_tip="Teleport to my home location" + top_delta="0" + width="32" /> + <location_input + follows="all" + halign="right" + height="23" + label="Location" + layout="topleft" + left_pad="7" + max_chars="254" + mouse_opaque="false" + name="location_combo" + top_delta="0" + width="355"> + <combo_list + mouse_wheel_opaque="true"/> + </location_input> + </panel> + <icon + follows="top|right" + height="25" + image_name="ChatBarHandle" + layout="topleft" + left="-3" + name="resize_handle" + top="4" + width="5" /> + </layout_panel> <layout_panel follows="top|left" - layout="topleft" + layout="topleft" auto_resize="true" user_resize="true" min_width="315" name="favorites_layout_panel" width="315"> - <favorites_bar - follows="left|right|top" - font="SansSerifSmall" - height="20" - layout="topleft" - left="0" - name="favorite" - image_drag_indication="Accordion_ArrowOpened_Off" - tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" - width="311"> - <label - follows="left|top" - height="15" - layout="topleft" - left="10" - name="favorites_bar_label" - text_color="LtGray" - tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" - top="12" - width="102"> - Favorites Bar - </label> - <!-- More button actually is a text box. --> - <more_button - follows="left|bottom" - name=">>" - tab_stop="false" - tool_tip="Show more of My Favorites" - top="13" - width="50" - bottom="0" - valign="bottom"> - More ▼ - </more_button> - </favorites_bar> + <icon + follows="top|left" + height="25" + image_name="ChatBarHandle" + layout="topleft" + left="-318" + name="resize_handle" + top="4" + width="5" /> + + <favorites_bar + follows="left|right|top" + font="SansSerifSmall" + height="20" + layout="topleft" + left="0" + top="4" + name="favorite" + image_drag_indication="Accordion_ArrowOpened_Off" + tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" + width="311"> + <label + follows="left|top" + height="15" + layout="topleft" + left="10" + name="favorites_bar_label" + text_color="LtGray" + tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" + top="12" + width="102"> + Favorites Bar + </label> + <!-- More button actually is a text box. --> + <more_button + follows="left|bottom" + name=">>" + tab_stop="false" + tool_tip="Show more of My Favorites" + top="13" + width="50" + bottom="0" + valign="bottom"> + More ▼ + </more_button> + </favorites_bar> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_media.xml b/indra/newview/skins/default/xui/en/panel_nearby_media.xml index bfc503f05b..d1cb64f7ad 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_media.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_media.xml @@ -196,7 +196,6 @@ name="stop" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -224,7 +223,6 @@ name="play" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -252,7 +250,6 @@ name="pause" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="22" @@ -279,7 +276,6 @@ name="volume_slider_ctrl" mouse_opaque="false" auto_resize="true" - user_resize="false" follows="left|right" layout="topleft" top="0" @@ -304,7 +300,6 @@ name="mute" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="72" @@ -333,7 +328,6 @@ name="zoom" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="28" @@ -361,7 +355,6 @@ name="unzoom" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="21" @@ -388,8 +381,7 @@ <layout_panel name="right_bookend" width="0" - mouse_opaque="false" - user_resize="false" /> + mouse_opaque="false"/> </layout_stack> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index 66117615e4..a3d39e55af 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -8,7 +8,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" show_item_link_overlays="true" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index e1cd78bad8..b61f110e32 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -198,7 +198,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap height="154" name="add_button_and_combobox" width="311" - user_resize="false" visible="true"> <!-- List containing items from the COF and Base outfit --> @@ -271,8 +270,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap height="30" name="filter_panel" width="311" - visible="false" - user_resize="false"> + visible="false"> <filter_editor background_image="TextField_Search_Off" @@ -515,7 +513,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap left="0" mouse_opaque="false" name="save_btn_lp" - user_resize="false" auto_resize="true" width="156"> <button @@ -550,7 +547,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap left_pad="3" mouse_opaque="false" name="revert_btn_lp" - user_resize="false" auto_resize="true" width="147"> <button diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 2ad2416179..405d9513db 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -84,7 +84,6 @@ left="0" mouse_opaque="false" name="save_btn_lp" - user_resize="false" auto_resize="true" width="156"> <button @@ -118,7 +117,6 @@ left_pad="3" mouse_opaque="false" name="wear_btn_lp" - user_resize="false" auto_resize="true" width="147"> <button diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 0ebfd9c037..98c7c49ff4 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -284,7 +284,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="25" layout="topleft" name="options_gear_btn_panel" - user_resize="false" width="32"> <menu_button follows="bottom|left" @@ -305,7 +304,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="25" layout="topleft" name="add_btn_panel" - user_resize="false" width="32"> <button follows="bottom|left" @@ -326,7 +324,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="25" layout="topleft" name="dummy_panel" - user_resize="false" width="210"> <icon follows="bottom|left|right" @@ -343,7 +340,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="25" layout="topleft" name="trash_btn_panel" - user_resize="false" width="31"> <dnd_button follows="bottom|left" @@ -602,7 +598,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="bottomleft" left="0" name="view_profile_btn_lp" - user_resize="false" auto_resize="true" width="68"> <button @@ -623,7 +618,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="bottomleft" left_pad="3" name="im_btn_lp" - user_resize="false" auto_resize="true" width="41"> <button @@ -644,7 +638,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="bottomleft" left_pad="3" name="call_btn_lp" - user_resize="false" auto_resize="true" width="52"> <button @@ -665,7 +658,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="bottomleft" left_pad="3" name="share_btn_lp" - user_resize="false" auto_resize="true" width="66"> <button @@ -686,7 +678,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="bottomleft" left_pad="3" name="teleport_btn_lp" - user_resize="false" auto_resize="true" width="77"> <button @@ -720,7 +711,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left="0" mouse_opaque="false" name="group_info_btn_lp" - user_resize="false" auto_resize="true" width="108"> <button @@ -743,7 +733,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="3" mouse_opaque="false" name="chat_btn_lp" - user_resize="false" auto_resize="true" width="101"> <button @@ -766,7 +755,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="3" mouse_opaque="false" name="group_call_btn_lp" - user_resize="false" auto_resize="true" width="96"> <button diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml index 24046d5cca..79d190e1e0 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml @@ -139,7 +139,6 @@ layout="bottomleft" left="0" name="layout_panel1" - user_resize="false" auto_resize="true" width="101"> <button @@ -158,7 +157,6 @@ layout="bottomleft" left_pad="3" name="show_on_map_btn_lp" - user_resize="false" auto_resize="true" width="100"> <button @@ -177,7 +175,6 @@ layout="bottomleft" left_pad="3" name="edit_btn_lp" - user_resize="false" auto_resize="true" width="101"> <button diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index 85f402dfa2..8def96cada 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -102,7 +102,6 @@ bg_opaque_color="DkGray2" layout="bottomleft" left="0" name="gear_menu_btn" - user_resize="false" auto_resize="true" width="51"> <button @@ -124,7 +123,6 @@ bg_opaque_color="DkGray2" height="18" layout="bottomleft" name="trash_btn_lp" - user_resize="false" auto_resize="true" width="18"> <button @@ -170,7 +168,6 @@ bg_opaque_color="DkGray2" layout="topleft" left="0" name="info_btn_lp" - user_resize="false" auto_resize="true" top="0" width="95"> @@ -192,7 +189,6 @@ bg_opaque_color="DkGray2" layout="bottomleft" left_pad="2" name="teleport_btn_lp" - user_resize="false" auto_resize="true" width="117"> <button @@ -212,7 +208,6 @@ bg_opaque_color="DkGray2" height="28" layout="bottomleft" name="show_on_map_btn_lp" - user_resize="false" auto_resize="true" left_pad="2" width="90"> diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index e280115bda..308acf0c0c 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -238,7 +238,6 @@ mouse_opaque="false" name="here_panel" top="0" - user_resize="false" width="60"> <icon follows="top|left" @@ -259,7 +258,6 @@ mouse_opaque="false" name="for_sale_panel" top="0" - user_resize="false" width="60"> <icon follows="top|left" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 670aa47313..f169dbb702 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -92,7 +92,6 @@ background_visible="true" left="0" mouse_opaque="false" name="lp1" - user_resize="false" auto_resize="true" width="193"> @@ -115,7 +114,6 @@ background_visible="true" left="0" mouse_opaque="false" name="teleport_btn_lp" - user_resize="false" auto_resize="true" width="109"> <button @@ -137,7 +135,6 @@ background_visible="true" left_pad="3" mouse_opaque="false" name="chat_btn_lp" - user_resize="false" auto_resize="true" width="86"> <button @@ -161,7 +158,6 @@ background_visible="true" left_pad="0" mouse_opaque="false" name="lp2" - user_resize="false" auto_resize="true" width="116"> @@ -185,7 +181,6 @@ background_visible="true" left_pad="0" mouse_opaque="false" name="edit_btn_lp" - user_resize="false" auto_resize="true" width="84"> <button @@ -208,7 +203,6 @@ background_visible="true" left_pad="0" mouse_opaque="false" name="overflow_btn_lp" - user_resize="false" auto_resize="true" width="24"> <menu_button @@ -246,7 +240,6 @@ background_visible="true" left_pad="3" mouse_opaque="false" name="profile_btn_lp" - user_resize="false" auto_resize="true" width="102"> <button @@ -283,7 +276,6 @@ background_visible="true" mouse_opaque="false" name="close_btn_lp" top="0" - user_resize="false" auto_resize="true" width="51"> <button @@ -324,7 +316,6 @@ background_visible="true" mouse_opaque="false" name="save_btn_lp" top="0" - user_resize="false" auto_resize="true" width="153"> <button @@ -347,7 +338,6 @@ background_visible="true" mouse_opaque="false" name="cancel_btn_lp" top="0" - user_resize="false" auto_resize="true" width="154"> <button diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml index 2e0bb88f53..e9427a2388 100644 --- a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -50,7 +50,6 @@ layout="topleft" left="0" name="postcard_image_size_lp" - user_resize="false" auto_resize="false" top="0" right="-1" @@ -99,7 +98,6 @@ layout="topleft" left="0" name="postcard_image_format_quality_lp" - user_resize="false" auto_resize="true" top="0" right="-1" 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 47236c1a48..587c461bee 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -59,7 +59,6 @@ top_pad="30" width="350" /> <check_box - enabled_control="EnableVoiceChat" control_name="VoiceCallsFriendsOnly" height="16" label="Only friends and groups can call or IM me" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_spellcheck.xml b/indra/newview/skins/default/xui/en/panel_preferences_spellcheck.xml index 9b5d429846..f1b16c5d0d 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_spellcheck.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_spellcheck.xml @@ -86,6 +86,7 @@ Active </text> <scroll_list + enabled_control="SpellCheck" follows="top|left" height="155" layout="topleft" @@ -96,6 +97,7 @@ sort_ascending="true" width="175" /> <button + enabled_control="SpellCheck" follows="top|left" height="26" image_overlay="Arrow_Right" @@ -107,6 +109,7 @@ width="25"> </button> <button + enabled_control="SpellCheck" follows="top|left" height="26" image_overlay="Arrow_Left" @@ -117,6 +120,7 @@ width="25"> </button> <scroll_list + enabled_control="SpellCheck" follows="top|left" height="155" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index 273c252474..198ccd6e2f 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -31,8 +31,7 @@ width="0" name="left_bookend_bottom" mouse_opaque="false" - layout="topleft" - user_resize="false" /> + layout="topleft"/> <layout_panel name="media_progress_indicator" mouse_opaque="false" @@ -41,7 +40,6 @@ left="0" top="0" auto_resize="false" - user_resize="false" min_width="100" width="200"> <progress_bar @@ -59,8 +57,7 @@ name="right_bookend_bottom" width="0" mouse_opaque="false" - layout="topleft" - user_resize="false" /> + layout="topleft"/> </layout_stack> <layout_stack name="media_controls" @@ -79,13 +76,11 @@ top="0" width="0" mouse_opaque="false" - layout="topleft" - user_resize="false" /> + layout="topleft"/> <layout_panel name="back" top="0" auto_resize="false" - user_resize="false" layout="topleft" mouse_opaque="false" min_width="22" @@ -114,7 +109,6 @@ name="fwd" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" min_width="22" top="0" @@ -142,7 +136,6 @@ name="home" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -170,7 +163,6 @@ name="media_stop" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -198,7 +190,6 @@ name="reload" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -226,7 +217,6 @@ name="stop" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -254,7 +244,6 @@ name="play" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="22" @@ -282,7 +271,6 @@ name="pause" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="22" @@ -310,7 +298,6 @@ name="media_address" mouse_opaque="false" auto_resize="true" - user_resize="false" height="24" follows="left|right|bottom" layout="topleft" @@ -343,8 +330,7 @@ layout="topleft" width="16" mouse_opaque="false" - auto_resize="false" - user_resize="false"> + auto_resize="false"> <icon name="media_whitelist_flag" follows="top|right" @@ -358,8 +344,7 @@ layout="topleft" width="16" mouse_opaque="false" - auto_resize="false" - user_resize="false"> + auto_resize="false"> <icon name="media_secure_lock_flag" height="16" @@ -374,7 +359,6 @@ name="media_play_position" mouse_opaque="false" auto_resize="true" - user_resize="false" follows="left|right" layout="topleft" top="0" @@ -399,7 +383,6 @@ name="skip_back" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="22" @@ -428,7 +411,6 @@ name="skip_forward" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="22" @@ -455,7 +437,6 @@ name="media_volume" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="72" @@ -511,7 +492,6 @@ name="zoom_frame" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" height="28" @@ -539,7 +519,6 @@ name="close" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="21" @@ -567,7 +546,6 @@ name="new_window" mouse_opaque="false" auto_resize="false" - user_resize="false" layout="topleft" top="0" min_width="22" @@ -596,8 +574,7 @@ mouse_opaque="false" top="0" width="0" - layout="topleft" - user_resize="false" /> + layout="topleft"/> </layout_stack> <panel name="media_region" diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml index 4535c56339..860caf2d21 100644 --- a/indra/newview/skins/default/xui/en/panel_progress.xml +++ b/indra/newview/skins/default/xui/en/panel_progress.xml @@ -12,45 +12,43 @@ height="768" layout="topleft" left="0" - name="stack1" + name="horizontal_centering" orientation="horizontal" top="0" width="1024"> <layout_panel layout="topleft" min_width="10" - name="panel1" - user_resize="false" + name="left" width="150" /> <layout_panel height="768" layout="topleft" - min_width="640" - name="panel2" - user_resize="false" - width="640"> + min_width="670" + name="center" + width="670"> <layout_stack follows="left|right|top|bottom" height="768" layout="topleft" left="0" orientation="vertical" - name="stack2" + name="vertical_centering" top="0" - width="640"> + width="670"> <layout_panel height="200" layout="topleft" min_height="10" name="panel3" - width="640" /> + width="670" /> <layout_panel auto_resize="false" height="250" layout="topleft" min_height="250" name="panel4" - width="640"> + width="670"> <icon color="LoginProgressBoxCenterColor" follows="left|right|bottom|top" @@ -59,7 +57,7 @@ layout="topleft" left="0" top="0" - width="640" /> + width="670" /> <text follows="left|right|top" font="SansSerifHuge" @@ -71,7 +69,7 @@ name="title_text" text_color="LoginProgressBoxTextColor" top_delta="50" - width="593" /> + right="-47"/> <text follows="left|right|top" font="SansSerif" @@ -83,7 +81,7 @@ name="progress_text" text_color="LoginProgressBoxTextColor" top_pad="5" - width="593" + right="-47" word_wrap="true"/> <progress_bar bottom="115" @@ -106,7 +104,7 @@ name="message_text" text_color="LoginProgressBoxTextColor" top="145" - width="550" + right="-90" word_wrap="true"/> </layout_panel> <layout_panel @@ -114,14 +112,13 @@ layout="topleft" min_width="10" name="panel5" - width="640" /> + width="670" /> </layout_stack> </layout_panel> <layout_panel layout="topleft" min_width="10" - name="panel6" - user_resize="false" + name="right" width="150" /> </layout_stack> <button diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index 6b28639a77..bfd796a62b 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -134,26 +134,26 @@ name="Only Allow" top_delta="-30" width="278"> - Restrict Access to accounts verified by: + Allow access only to Residents who: </text> <check_box follows="top|left" height="16" - label="Payment Information on File" + label="Have payment information on file" layout="topleft" left_delta="0" name="limit_payment" - tool_tip="Ban unidentified Residents" + tool_tip="Residents must have payment information on file to access this estate. See the [SUPPORT_SITE] for more information." top_pad="2" width="278" /> <check_box follows="top|left" height="16" - label="Age Verification" + label="Have been age-verified" layout="topleft" left_delta="0" name="limit_age_verified" - tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information." + tool_tip="Residents must be age verified to access this estate. See the [SUPPORT_SITE] for more information." top_pad="2" width="278" /> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml index ae0215a578..b966358f18 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -96,7 +96,6 @@ layout="topleft" left="0" name="local_image_size_lp" - user_resize="false" auto_resize="false" top="0" right="-1" @@ -145,7 +144,6 @@ layout="topleft" left="0" name="local_image_format_quality_lp" - user_resize="false" auto_resize="true" top="0" right="-1" diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml index 91ac9ad658..5bd383b81e 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -84,7 +84,6 @@ layout="topleft" left="0" name="profile_image_size_lp" - user_resize="false" auto_resize="false" top="0" right="-1" @@ -132,7 +131,6 @@ layout="topleft" left="0" name="profile_image_metadata_lp" - user_resize="false" auto_resize="true" top="0" right="-1" diff --git a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml index 3c69a0cb6c..58911bed56 100644 --- a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml +++ b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml @@ -20,7 +20,6 @@ mouse_opaque="false"> <layout_panel name="vertical_toolbar_panel" auto_resize="true" - user_resize="false" width="1024" height="500" mouse_opaque="false"> @@ -34,7 +33,6 @@ mouse_opaque="false"> <layout_panel name="left_toolbar_panel" auto_resize="false" - user_resize="false" height="500" width="30" mouse_opaque="false"> @@ -61,7 +59,6 @@ </layout_panel> <layout_panel name="non_toolbar_panel" auto_resize="true" - user_resize="false" mouse_opaque="false" height="100" width="200"> @@ -102,7 +99,6 @@ </layout_panel> <layout_panel name="right_toolbar_panel" auto_resize="false" - user_resize="false" height="500" width="30" mouse_opaque="false"> @@ -132,7 +128,6 @@ </layout_panel> <layout_panel name="bottom_toolbar_panel" auto_resize="false" - user_resize="false" height="30" width="1024" mouse_opaque="false"> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index b52784d6bc..29aa6d1039 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_visible="true" follows="all" height="570" label="Things" @@ -30,11 +29,12 @@ width="330"> <layout_panel name="main_inventory_layout_panel" - layout="topleft" + layout="topleft" + auto_resize="true" + user_resize="true" min_dim="150" width="330" follows="bottom|left|right" - user_resize="false" height="300"> <panel class="panel_main_inventory" @@ -48,41 +48,18 @@ height="300" width="330" /> </layout_panel> - <layout_panel - width="330" - layout="topleft" - auto_resize="true" - user_resize="false" - follows="bottom|left|right" - name="inbox_outbox_layout_panel" - visible="false" - min_dim="35" - max_dim="235" - expanded_min_dim="125" - height="235"> - <layout_stack - follows="left|right|top|bottom" - layout="topleft" - left="0" - top="0" - orientation="vertical" - name="inbox_outbox_layout_stack" - open_time_constant="0.02" - close_time_constant="0.02" - height="235" - width="330"> - <layout_panel + <layout_panel width="330" - layout="topleft" + layout="topleft" auto_resize="true" - user_resize="false" + user_resize="true" follows="left|right|top" name="inbox_layout_panel" visible="false" min_dim="35" - max_dim="200" + max_dim="235" expanded_min_dim="90" - height="200"> + height="235"> <panel follows="all" layout="topleft" @@ -91,13 +68,13 @@ class="panel_marketplace_inbox" top="0" label="" - height="200" + height="235" width="330"> <string name="InboxLabelWithArg">Received items ([NUM])</string> <string name="InboxLabelNoArg">Received items</string> <button label="Received items" - font="SansSerifMedium" + font="SansSerifMedium" name="inbox_btn" height="35" width="308" @@ -129,13 +106,13 @@ <panel follows="all" left="10" - bottom="200" + bottom="235" width="308" top="35" bg_opaque_color="InventoryBackgroundColor" background_visible="true" background_opaque="true" - tool_tip="Drag and drop items to your inventory to manage and use them" + tool_tip="Drag and drop items to your inventory to use them" > <text name="inbox_inventory_placeholder" @@ -145,7 +122,7 @@ top="0" left="0" width="308" - height="165" + height="200" wrap="true" halign="center"> Purchases from the marketplace will be delivered here. @@ -153,139 +130,6 @@ </panel> </panel> </layout_panel> - <layout_panel - width="330" - layout="topleft" - auto_resize="true" - user_resize="false" - follows="all" - name="outbox_layout_panel" - visible="false" - min_dim="35" - max_dim="200" - expanded_min_dim="90" - height="200"> - <panel - follows="all" - layout="topleft" - left="0" - name="marketplace_outbox" - class="panel_marketplace_outbox" - top="0" - label="" - height="200" - width="330"> - <string name="OutboxLabelWithArg">Merchant outbox ([NUM])</string> - <string name="OutboxLabelNoArg">Merchant outbox</string> - <button - label="Merchant outbox" - font="SansSerifMedium" - name="outbox_btn" - height="35" - width="308" - image_unselected="MarketplaceBtn_Off" - image_selected="MarketplaceBtn_Selected" - halign="left" - handle_right_mouse="false" - follows="top|left|right" - is_toggle="true" - tab_stop="false" - pad_left="35" - top="0" - left="10" /> - <button - image_unselected="OutboxPush_Off" - image_selected="OutboxPush_Selected" - image_hover_selected="OutboxPush_Selected_Over" - image_hover_unselected="OutboxPush_Over" - image_disabled_selected="OutboxPush_Selected_Disabled" - image_disabled="OutboxPush_Disabled" - image_pressed="OutboxPush_Press" - image_pressed_selected="OutboxPush_Selected_Press" - label="" - tool_tip="Push to my Marketplace Storefront" - is_toggle="false" - name="outbox_sync_btn" - follows="top|right" - tab_stop="false" - halign="center" - top="6" - left="-50" - height="23" - width="32" - enabled="false" /> - <loading_indicator - follows="top|right" - name="outbox_sync_indicator" - top="6" - left="-50" - height="23" - width="32" - images_per_sec="1.15" - tab_stop="false" - visible="false"> - <images> - <image name="OutboxPush_Progress_1"/> - <image name="OutboxPush_Progress_2"/> - <image name="OutboxPush_Progress_3"/> - <image name="OutboxPush_Progress_4"/> - <image name="OutboxPush_Progress_5"/> - <image name="OutboxPush_Progress_6"/> - </images> - </loading_indicator> - <panel - follows="all" - left="10" - bottom="200" - width="308" - top="35" - bg_opaque_color="InventoryBackgroundColor" - background_visible="true" - background_opaque="true" - > - <panel - name="outbox_inventory_placeholder_panel" - follows="all" - layout="topleft" - top="0" - left="0" - width="308" - height="165" - bg_opaque_color="InventoryBackgroundColor" - background_visible="true" - background_opaque="true" - > - <text - name="outbox_inventory_placeholder_title" - type="string" - follows="all" - layout="topleft" - top="10" - left="0" - width="308" - height="25" - wrap="true" - halign="center" - font="SansSerifBold"> - Loading... - </text> - <text - name="outbox_inventory_placeholder_text" - type="string" - follows="all" - layout="topleft" - top="35" - left="0" - width="308" - height="130" - wrap="true" - halign="left" /> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> - </layout_panel> </layout_stack> <panel follows="bottom|left|right" @@ -312,7 +156,6 @@ left="0" mouse_opaque="false" name="info_btn_lp" - user_resize="false" auto_resize="true" width="101"> <button @@ -334,7 +177,6 @@ left_pad="1" mouse_opaque="false" name="share_btn_lp" - user_resize="false" auto_resize="true" width="100"> <button @@ -356,7 +198,6 @@ left_pad="1" mouse_opaque="false" name="shop_btn_lp" - user_resize="false" auto_resize="true" width="100"> <button @@ -406,8 +247,7 @@ </layout_stack> </panel> </panel> - -<panel + <panel follows="all" layout="topleft" left="0" @@ -420,8 +260,7 @@ visible="false" width="330"> </panel> - -<panel + <panel follows="all" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2b0dcdfeca..4bc72be49b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -18,7 +18,7 @@ <string name="StartupClearingCache">Clearing cache...</string> <string name="StartupInitializingTextureCache">Initializing texture cache...</string> <string name="StartupInitializingVFS">Initializing VFS...</string> - <string name="StartupRequireDriverUpdate">Graphics initialization failed. Please update your graphics driver!</string> + <string name="StartupRequireDriverUpdate">Graphics initialization failed. Please update your graphics driver!</string> <!-- progress --> <string name="ProgressRestoring">Restoring...</string> @@ -35,9 +35,9 @@ <string name="LoginAttempt">Previous login attempt failed. Logging in, attempt [NUMBER]</string> <string name="LoginPrecaching">Loading world...</string> <string name="LoginInitializingBrowser">Initializing embedded web browser...</string> - <string name="LoginInitializingMultimedia">Initializing multimedia...</string> - <string name="LoginInitializingFonts">Loading fonts...</string> - <string name="LoginVerifyingCache">Verifying cache files (can take 60-90 seconds)...</string> + <string name="LoginInitializingMultimedia">Initializing multimedia...</string> + <string name="LoginInitializingFonts">Loading fonts...</string> + <string name="LoginVerifyingCache">Verifying cache files (can take 60-90 seconds)...</string> <string name="LoginProcessingResponse">Processing response...</string> <string name="LoginInitializingWorld">Initializing world...</string> <string name="LoginDecodingImages">Decoding images...</string> @@ -49,12 +49,12 @@ <string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string> <string name="LoginConnectingToRegion">Connecting to region...</string> <string name="LoginDownloadingClothing">Downloading clothing...</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.</string> - <string name="CertExpired">The certificate returned by the Grid appears to be expired. Please check your system clock, or contact your Grid administrator.</string> - <string name="CertKeyUsage">The certificate returned by the server could not be used for SSL. Please contact your Grid administrator.</string> - <string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain. Please contact your Grid administrator.</string> - <string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified. Please contact your Grid administrator.</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.</string> + <string name="CertExpired">The certificate returned by the Grid appears to be expired. Please check your system clock, or contact your Grid administrator.</string> + <string name="CertKeyUsage">The certificate returned by the server could not be used for SSL. Please contact your Grid administrator.</string> + <string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain. Please contact your Grid administrator.</string> + <string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified. Please contact your Grid administrator.</string> <string name="LoginFailedNoNetwork">Network error: Could not establish connection, please check your network connection.</string> <string name="LoginFailed">Login failed.</string> @@ -164,11 +164,19 @@ Please try logging in again in a minute.</string> <string name="TooltipLand">Land:</string> <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> <string name="TooltipPrice" value="L$[AMOUNT]: "/> - <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred to another user.</string> - <string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string> - <string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string> - <string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string> + <string name="TooltipOutboxDragToWorld">You can not rez items in your merchant outbox</string> + <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string> + <string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string> + <string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string> + <string name="TooltipOutboxCallingCard">You can not put calling cards into your merchant outbox</string> + <string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds 3</string> + <string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string> + <string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string> + + <string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string> + <string name="TooltipDragOntoSelf">You can't move a folder into itself</string> + <!-- tooltips for Urls --> <string name="TooltipHttpUrl">Click to view this web page</string> <string name="TooltipSLURL">Click to view this location's information</string> @@ -2029,24 +2037,28 @@ Returns a string with the requested data about the region <string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string> <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string> - <string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string> - <string name="MarketplaceURL">http://marketplace.[DOMAIN_NAME]</string> - <string name="MarketplaceURL_CreateStore">http://marketplace.[DOMAIN_NAME]/create_store</string> - <string name="MarketplaceURL_LearnMore">http://marketplace.[DOMAIN_NAME]/learn_more</string> - <string name="InventoryOutboxCreationErrorTitle">Your Merchant Outbox is not properly configured</string> - <string name="InventoryOutboxCreationErrorTooltip">Merchant Outbox configuration error</string> - <string name="InventoryOutboxCreationError">Please contact Customer Service to correct the problem.</string> - <string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace</string> - <string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string> - <string name="InventoryOutboxNotMerchant">[[MARKETPLACE_URL] The Second Life Marketplace] offers more than one million virtual products for sale, all of them created by Residents. You, too, can sell items you create, as well as some of the items you have purchased. It’s easy and setup is free. [[LEARN_MORE_URL] Learn more] or [[CREATE_STORE_URL] create a store] on the Marketplace to get started.</string> - <string name="InventoryOutboxNoItemsTitle">A new way to send items to the Marketplace</string> - <string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string> - <string name="InventoryOutboxNoItems">Drag items or folders that you wish to sell into this area. A copy of the item will appear, leaving your inventory unchanged, unless you have dragged a no-copy item. When you are ready to send the items to the Marketplace, click the Upload button. Once your items have been moved to your Marketplace Inventory, they will disappear from this folder.</string> + <string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string> + <string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> + <string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> + <string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string> + <string name="MarketplaceURL_Imports">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports</string> + <string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string> + <string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string> + <string name="InventoryOutboxNotMerchantTooltip"></string> + <string name="InventoryOutboxNotMerchant"> +If you'd like to become a merchant, you'll need to [[MARKETPLACE_CREATE_STORE_URL] create a Marketplace store]. + </string> + <string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string> + <string name="InventoryOutboxNoItemsTooltip"></string> + <string name="InventoryOutboxNoItems"> +Drag folders to this area and click "Send to Marketplace" to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> <string name="Marketplace Error None">No errors</string> <string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> <string name="Marketplace Error Empty Folder">Error: This folder has no contents.</string> - <string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, login to the marketplace website and reduce your unassociated item count.</string> + <string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, log in to the marketplace website and reduce your unassociated item count.</string> + <string name="Marketplace Error Object Limit">Error: This item contains too many objects. Fix this error by placing objects together in boxes to reduce the total count to less than 200.</string> <string name="Marketplace Error Folder Depth">Error: This item contains too many levels of nested folders. Reorganize it to a maximum of 3 levels of nested folders.</string> <string name="Marketplace Error Unsellable Item">Error: This item can not be sold on the marketplace.</string> @@ -3681,6 +3693,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Marketplace_Label">Marketplace</string> <string name="Command_MiniMap_Label">Mini-map</string> <string name="Command_Move_Label">Walk / run / fly</string> + <string name="Command_Outbox_Label">Merchant outbox</string> <string name="Command_People_Label">People</string> <string name="Command_Picks_Label">Picks</string> <string name="Command_Places_Label">Places</string> @@ -3706,6 +3719,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Marketplace_Tooltip">Go shopping</string> <string name="Command_MiniMap_Tooltip">Show nearby people</string> <string name="Command_Move_Tooltip">Moving your avatar</string> + <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string> <string name="Command_People_Tooltip">Friends, groups, and nearby people</string> <string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string> <string name="Command_Places_Tooltip">Places you've saved</string> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml index 0792996107..d19c47f54f 100644 --- a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml +++ b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml @@ -6,14 +6,4 @@ item_top_pad="4" selection_image="Rounded_Square" > - <error_badge - label=" " - label_offset_horiz="-1" - location="right" - padding_horiz="12.5" - padding_vert="2" - location_offset_hcenter="-23" - image="Error_Tag_Background" - image_color="Black" - /> </outbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml index e3f2072819..3964569da2 100644 --- a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel show_load_status="false" /> +<outbox_inventory_panel show_empty_message="false" show_load_status="false" /> diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml index c072ea9b5a..24c961fa26 100644 --- a/indra/newview/skins/default/xui/pl/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml @@ -20,8 +20,6 @@ <menu_item_call label="Tryb oddalenia" name="Set Away"/> <menu_item_call label="Tryb pracy" name="Set Busy"/> </menu> - <menu_item_call label="Zażądaj statusu administratora" name="Request Admin Options"/> - <menu_item_call label="Wyłącz atatus administratora" name="Leave Admin Options"/> <menu_item_call label="Wyłącz [APP_NAME]" name="Quit"/> </menu> <menu label="Komunikacja" name="Communicate"> @@ -36,11 +34,10 @@ <menu_item_check label="Szukaj" name="Search"/> <menu_item_call label="Zrób zdjęcie" name="Take Snapshot"/> <menu_item_call label="Zapamiętaj to miejsce (LM)" name="Create Landmark Here"/> - <menu label="Miejsce" name="Land"> - <menu_item_call label="Profil miejsca" name="Place Profile"/> - <menu_item_call label="O posiadłości" name="About Land"/> - <menu_item_call label="Region/Majątek" name="Region/Estate"/> - </menu> + <menu_item_separator/> + <menu_item_call label="Profil miejsca" name="Place Profile"/> + <menu_item_call label="O posiadłości" name="About Land"/> + <menu_item_call label="Region/Majątek" name="Region/Estate"/> <menu_item_call label="Kup posiadłość" name="Buy Land"/> <menu_item_call label="Moje posiadłości" name="My Land"/> <menu label="Pokaż" name="LandShow"> @@ -56,7 +53,7 @@ </menu> <menu_item_call label="Teleportuj do Miejsca Startu" name="Teleport Home"/> <menu_item_call label="Ustaw Miejsce Startu" name="Set Home to Here"/> - <menu label="Słońce" name="Environment Settings"> + <menu label="Słońce" name="Sun"> <menu_item_call label="Wschód Słońca" name="Sunrise"/> <menu_item_call label="Południe" name="Noon"/> <menu_item_call label="Zachód Słońca" name="Sunset"/> @@ -153,22 +150,22 @@ <menu_item_check label="Pokaż celownik myszki" name="ShowCrosshairs"/> </menu> <menu label="Rodzaje renderowania" name="Rendering Types"> - <menu_item_check label="Podstawowe" name="Simple"/> - <menu_item_check label="Maska alpha" name="Alpha"/> - <menu_item_check label="Drzewo" name="Tree"/> - <menu_item_check label="Awatary" name="Character"/> - <menu_item_check label="Płaszczyzna powierzchni" name="SurfacePath"/> - <menu_item_check label="Niebo" name="Sky"/> - <menu_item_check label="Woda" name="Water"/> - <menu_item_check label="Ziemia" name="Ground"/> - <menu_item_check label="Głośność" name="Volume"/> - <menu_item_check label="Trawa" name="Grass"/> - <menu_item_check label="Chmury" name="Clouds"/> - <menu_item_check label="Cząsteczki" name="Particles"/> - <menu_item_check label="Zderzenie" name="Bump"/> + <menu_item_check label="Podstawowe" name="Rendering Type Simple"/> + <menu_item_check label="Maska alpha" name="Rendering Type Alpha"/> + <menu_item_check label="Drzewo" name="Rendering Type Tree"/> + <menu_item_check label="Awatary" name="Rendering Type Character"/> + <menu_item_check label="Płaszczyzna powierzchni" name="Rendering Type Surface Patch"/> + <menu_item_check label="Niebo" name="Rendering Type Sky"/> + <menu_item_check label="Woda" name="Rendering Type Water"/> + <menu_item_check label="Ziemia" name="Rendering Type Ground"/> + <menu_item_check label="Głośność" name="Rendering Type Volume"/> + <menu_item_check label="Trawa" name="Rendering Type Grass"/> + <menu_item_check label="Chmury" name="Rendering Type Clouds"/> + <menu_item_check label="Cząsteczki" name="Rendering Type Particles"/> + <menu_item_check label="Zderzenie" name="Rendering Type Bump"/> </menu> <menu label="Opcje renderowania" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="Zaznaczone" name="Selected"/> <menu_item_check label="Podświetlenie" name="Highlighted"/> <menu_item_check label="Tekstury dynamiczne" name="Dynamic Textures"/> @@ -180,10 +177,7 @@ <menu_item_call label="Wyczyść bufor danych grupy" name="ClearGroupCache"/> <menu_item_check label="Wygładzanie ruchu myszki" name="Mouse Smoothing"/> <menu label="Skróty" name="Shortcuts"> - <menu_item_call label="Obraz (L$[COST])..." name="Upload Image"/> - <menu_item_check label="Szukaj" name="Search"/> <menu_item_call label="Zwolnij klawisze" name="Release Keys"/> - <menu_item_call label="Domyślne ustawienia rozmiaru interfejsu" name="Set UI Size to Default"/> <menu_item_check label="Pokaż menu Zaawansowane - skrót" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Zamknij okno" name="Close Window"/> <menu_item_call label="Zamknij wszystkie okna" name="Close All Windows"/> @@ -192,13 +186,6 @@ <menu_item_check label="Wolna kamera" name="Joystick Flycam"/> <menu_item_call label="Reset widoku" name="Reset View"/> <menu_item_call label="Zobacz ostatniego rozmówcę" name="Look at Last Chatter"/> - <menu label="Wybierz narzędzie budowania" name="Select Tool"> - <menu_item_call label="Narzędzie ogniskowej" name="Focus"/> - <menu_item_call label="Narzędzie ruchu" name="Move"/> - <menu_item_call label="Narzędzie edycji" name="Edit"/> - <menu_item_call label="Stwórz narzędzie" name="Create"/> - <menu_item_call label="Narzędzia posiadłości" name="Land"/> - </menu> <menu_item_call label="Przybliż" name="Zoom In"/> <menu_item_call label="Domyślne przybliżenie" name="Zoom Default"/> <menu_item_call label="Oddal" name="Zoom Out"/> @@ -267,9 +254,8 @@ <menu_item_call label="Upuść pakiet pamięci" name="Drop a Packet"/> </menu> <menu_item_call label="Zderzenia, popchnięcia & uderzenia" name="Bumps, Pushes &amp; Hits"/> - <menu label="Świat" name="World"> + <menu label="Świat" name="DevelopWorld"> <menu_item_check label="Domyślne ustawienia środowiska Regionu" name="Sim Sun Override"/> - <menu_item_check label="Efekty emiterów" name="Cheesy Beacon"/> <menu_item_check label="Ustalona pogoda" name="Fixed Weather"/> <menu_item_call label="Zachowaj bufor pamięci obiektów regionu" name="Dump Region Object Cache"/> </menu> @@ -291,11 +277,11 @@ </menu> <menu label="Awatar" name="Character"> <menu label="Przesuń bakowaną teksturę" name="Grab Baked Texture"> - <menu_item_call label="Tęczówka oka" name="Iris"/> - <menu_item_call label="Głowa" name="Head"/> - <menu_item_call label="Górna część ciała" name="Upper Body"/> - <menu_item_call label="Dolna część ciała" name="Lower Body"/> - <menu_item_call label="Spódnica" name="Skirt"/> + <menu_item_call label="Tęczówka oka" name="Grab Iris"/> + <menu_item_call label="Głowa" name="Grab Head"/> + <menu_item_call label="Górna część ciała" name="Grab Upper Body"/> + <menu_item_call label="Dolna część ciała" name="Grab Lower Body"/> + <menu_item_call label="Spódnica" name="Grab Skirt"/> </menu> <menu label="Testy postaci" name="Character Tests"> <menu_item_call label="Przesuń geometrię postaci" name="Toggle Character Geometry"/> @@ -316,8 +302,8 @@ <menu_item_check label="Pokaż menu administratora" name="View Admin Options"/> </menu> <menu label="Administrator" name="Admin"> - <menu label="Object"> - <menu_item_call label="Weź kopię" name="Take Copy"/> + <menu label="Object" name="AdminObject"> + <menu_item_call label="Weź kopię" name="Admin Take Copy"/> <menu_item_call label="Reset właściciela" name="Force Owner To Me"/> <menu_item_call label="Reset przyzwolenia właściciela" name="Force Owner Permissive"/> <menu_item_call label="Usuń" name="Delete"/> diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml index f7be781cac..b6bb79bcbc 100644 --- a/indra/newview/skins/default/xui/zh/menu_viewer.xml +++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml @@ -20,8 +20,6 @@ <menu_item_call label="離開" name="Set Away"/> <menu_item_call label="忙碌" name="Set Busy"/> </menu> - <menu_item_call label="要求 Admin 狀態" name="Request Admin Options"/> - <menu_item_call label="離開 Admin 狀態" name="Leave Admin Options"/> <menu_item_call label="結束退出 [APP_NAME]" name="Quit"/> </menu> <menu label="溝通" name="Communicate"> @@ -36,11 +34,10 @@ <menu_item_check label="搜尋" name="Search"/> <menu_item_call label="拍攝快照" name="Take Snapshot"/> <menu_item_call label="將此處記下地標" name="Create Landmark Here"/> - <menu label="地點檔案" name="Land"> - <menu_item_call label="地點檔案" name="Place Profile"/> - <menu_item_call label="關於土地" name="About Land"/> - <menu_item_call label="地區 / 領地" name="Region/Estate"/> - </menu> + <menu_item_separator/> + <menu_item_call label="地點檔案" name="Place Profile"/> + <menu_item_call label="關於土地" name="About Land"/> + <menu_item_call label="地區 / 領地" name="Region/Estate"/> <menu_item_call label="購買這塊土地" name="Buy Land"/> <menu_item_call label="我的土地" name="My Land"/> <menu label="顯示" name="LandShow"> @@ -56,7 +53,7 @@ </menu> <menu_item_call label="瞬間瞬間傳送回家" name="Teleport Home"/> <menu_item_call label="設定家在此處" name="Set Home to Here"/> - <menu label="太陽" name="Environment Settings"> + <menu label="太陽" name="Sun"> <menu_item_call label="日出" name="Sunrise"/> <menu_item_call label="中午" name="Noon"/> <menu_item_call label="日落" name="Sunset"/> @@ -154,22 +151,22 @@ <menu_item_check label="顯示第一人稱視角準星" name="ShowCrosshairs"/> </menu> <menu label="Rendering Types" name="Rendering Types"> - <menu_item_check label="簡單" name="Simple"/> - <menu_item_check label="半透明" name="Alpha"/> - <menu_item_check label="樹木" name="Tree"/> - <menu_item_check label="化身" name="Character"/> - <menu_item_check label="地表" name="SurfacePath"/> - <menu_item_check label="天空" name="Sky"/> - <menu_item_check label="水文" name="Water"/> - <menu_item_check label="地面" name="Ground"/> - <menu_item_check label="體積" name="Volume"/> - <menu_item_check label="草地" name="Grass"/> - <menu_item_check label="雲彩" name="Clouds"/> - <menu_item_check label="粒子效果" name="Particles"/> - <menu_item_check label="碰撞" name="Bump"/> + <menu_item_check label="簡單" name="Rendering Type Simple"/> + <menu_item_check label="半透明" name="Rendering Type Alpha"/> + <menu_item_check label="樹木" name="Rendering Type Tree"/> + <menu_item_check label="化身" name="Rendering Type Character"/> + <menu_item_check label="地表" name="Rendering Type Surface Patch"/> + <menu_item_check label="天空" name="Rendering Type Sky"/> + <menu_item_check label="水文" name="Rendering Type Water"/> + <menu_item_check label="地面" name="Rendering Type Ground"/> + <menu_item_check label="體積" name="Rendering Type Volume"/> + <menu_item_check label="草地" name="Rendering Type Grass"/> + <menu_item_check label="雲彩" name="Rendering Type Clouds"/> + <menu_item_check label="粒子效果" name="Rendering Type Particles"/> + <menu_item_check label="碰撞" name="Rendering Type Bump"/> </menu> <menu label="Rendering Features" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="Selected" name="Selected"/> <menu_item_check label="Highlighted" name="Highlighted"/> <menu_item_check label="Dynamic Textures" name="Dynamic Textures"/> @@ -182,10 +179,7 @@ <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="顯示進階選單 - 舊版捷徑" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="關閉視窗" name="Close Window"/> <menu_item_call label="關閉全部視窗" name="Close All Windows"/> @@ -194,13 +188,6 @@ <menu_item_check label="Joystick Flycam" name="Joystick Flycam"/> <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"/> - <menu_item_call label="編輯工具" name="Edit"/> - <menu_item_call label="創造工具" name="Create"/> - <menu_item_call label="土地工具" name="Land"/> - </menu> <menu_item_call label="Zoom In" name="Zoom In"/> <menu_item_call label="Zoom Default" name="Zoom Default"/> <menu_item_call label="Zoom Out" name="Zoom Out"/> @@ -306,9 +293,8 @@ <menu_item_call label="開始錄製" name="Start Record"/> <menu_item_call label="停止錄製" name="Stop Record"/> </menu> - <menu label="世界" name="World"> + <menu label="世界" name="DevelopWorld"> <menu_item_check label="模擬器太陽設定覆蓋" name="Sim Sun Override"/> - <menu_item_check label="Cheesy Beacon" name="Cheesy Beacon"/> <menu_item_check label="固定天氣" name="Fixed Weather"/> <menu_item_call label="傾印地區物件快取" name="Dump Region Object Cache"/> </menu> @@ -340,11 +326,11 @@ </menu> <menu label="化身" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> - <menu_item_call label="Iris" name="Iris"/> - <menu_item_call label="頭部" name="Head"/> - <menu_item_call label="Upper Body" name="Upper Body"/> - <menu_item_call label="Lower Body" name="Lower Body"/> - <menu_item_call label="裙子" name="Skirt"/> + <menu_item_call label="Iris" name="Grab Iris"/> + <menu_item_call label="頭部" name="Grab Head"/> + <menu_item_call label="Upper Body" name="Grab Upper Body"/> + <menu_item_call label="Lower Body" name="Grab Lower Body"/> + <menu_item_call label="裙子" name="Grab Skirt"/> </menu> <menu label="Character Tests" name="Character Tests"> <menu_item_call label="Appearance To XML" name="Appearance To XML"/> @@ -378,8 +364,8 @@ <menu_item_check label="Show Admin Menu" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="取得副本" name="Take Copy"/> + <menu label="Object" name="AdminObject"> + <menu_item_call label="取得副本" name="Admin Take Copy"/> <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"/> @@ -415,7 +401,7 @@ <menu_item_call label="身體物理" name="Physics"/> <menu_item_call label="全部衣服" name="All Clothes"/> </menu> - <menu label="幫助" name="Help"> + <menu label="幫助" name="DeprecatedHelp"> <menu_item_call label="林登官方部落格" name="Official Linden Blog"/> <menu_item_call label="Scripting Portal" name="Scripting Portal"/> <menu label="臭蟲回報" name="Bug Reporting"> diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index e88d1bf811..19ac418e9e 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -39,7 +39,7 @@ #include "llsdserialize.h" #include "llthread.h" #include "llupdaterservice.h" - +#include "llcurl.h" class LLUpdateDownloader::Implementation: public LLThread @@ -198,13 +198,19 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & LLUpdateDownloader::Implementation::~Implementation() { - if(isDownloading()) { + if(isDownloading()) + { cancel(); shutdown(); - } else { + } + else + { ; // No op. } - if(mCurl) curl_easy_cleanup(mCurl); + if(mCurl) + { + LLCurl::deleteEasyHandle(mCurl); + } } @@ -406,9 +412,12 @@ void LLUpdateDownloader::Implementation::run(void) void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) { - if(mCurl == 0) { - mCurl = curl_easy_init(); - } else { + if(mCurl == 0) + { + mCurl = LLCurl::newEasyHandle(); + } + else + { curl_easy_reset(mCurl); } |