diff options
152 files changed, 3130 insertions, 1514 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index 86b42a5ff0..5ead9daaec 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -401,6 +401,7 @@ Cinder Roxley      STORM-2127      STORM-2144      SL-3404 +    SL-17634  Clara Young  Coaldust Numbers      VWR-1095 @@ -1123,6 +1124,7 @@ Nicky Dasmijn  	SL-16438  	SL-17218  	SL-17238 +	SL-17585  Nicky Perian  	OPEN-1  	STORM-1087 diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2d6d2a10d2..f0df3e1474 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -927,6 +927,9 @@ BOOL LLAvatarAppearance::loadAvatar()  		return FALSE;  	} +	// initialize mJointAliasMap +	getJointAliases(); +  	// avatar_lad.xml : <skeleton>  	if( !loadSkeletonNode() )  	{ @@ -1047,7 +1050,6 @@ BOOL LLAvatarAppearance::loadAvatar()  			return FALSE;  		}  	} -  	return TRUE;  } diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 0a7a8d27bb..3892e4ce43 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -612,14 +612,16 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName )                                          // we reached the end of the morphs                                          break;                                  } -                                LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName)); +                                std::string morph_name(morphName); +                                LLPolyMorphData* morph_data = new LLPolyMorphData(morph_name);                                  BOOL result = morph_data->loadBinary(fp, this);                                  if (!result)                                  { -                                        delete morph_data; -                                        continue; +                                    LL_WARNS() << "Failure loading " << morph_name << " from " << fileName << LL_ENDL; +                                    delete morph_data; +                                    continue;                                  }                                  mMorphData.insert(morph_data); diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 16b5f1e204..84dd6156a9 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -156,7 +156,9 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh)  		if (mVertexIndices[v] > 10000)  		{ -			LL_ERRS() << "Bad morph index: " << mVertexIndices[v] << LL_ENDL; +            // Bad install? These are usually .llm files from 'character' fodler +			LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; +            return FALSE;  		} diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index ff0aa6e76e..38a6b41afe 100644..100755 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -35,6 +35,8 @@  #include "llendianswizzle.h"  #include "llassetstorage.h"  #include "llrefcount.h" +#include "threadpool.h" +#include "workqueue.h"  #include "llvorbisencode.h" @@ -45,15 +47,13 @@  extern LLAudioEngine *gAudiop; -LLAudioDecodeMgr *gAudioDecodeMgrp = NULL; -  static const S32 WAV_HEADER_SIZE = 44;  ////////////////////////////////////////////////////////////////////////////// -class LLVorbisDecodeState : public LLRefCount +class LLVorbisDecodeState : public LLThreadSafeRefCount  {  public:  	class WriteResponder : public LLLFSThread::Responder @@ -532,146 +532,254 @@ void LLVorbisDecodeState::flushBadFile()  class LLAudioDecodeMgr::Impl  { -	friend class LLAudioDecodeMgr; -public: -	Impl() {}; -	~Impl() {}; +    friend class LLAudioDecodeMgr; +    Impl(); +  public: -	void processQueue(const F32 num_secs = 0.005); +    void processQueue(); -protected: -	std::deque<LLUUID> mDecodeQueue; -	LLPointer<LLVorbisDecodeState> mCurrentDecodep; +    void startMoreDecodes(); +    void enqueueFinishAudio(const LLUUID &decode_id, LLPointer<LLVorbisDecodeState>& decode_state); +    void checkDecodesFinished(); + +  protected: +    std::deque<LLUUID> mDecodeQueue; +    std::map<LLUUID, LLPointer<LLVorbisDecodeState>> mDecodes;  }; +LLAudioDecodeMgr::Impl::Impl() +{ +} + +// Returns the in-progress decode_state, which may be an empty LLPointer if +// there was an error and there is no more work to be done. +LLPointer<LLVorbisDecodeState> beginDecodingAndWritingAudio(const LLUUID &decode_id); -void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) +// Return true if finished +bool tryFinishAudio(const LLUUID &decode_id, LLPointer<LLVorbisDecodeState> decode_state); + +void LLAudioDecodeMgr::Impl::processQueue()  { -	LLUUID uuid; +    // First, check if any audio from in-progress decodes are ready to play. If +    // so, mark them ready for playback (or errored, in case of error). +    checkDecodesFinished(); -	LLTimer decode_timer; +    // Second, start as many decodes from the queue as permitted +    startMoreDecodes(); +} -	BOOL done = FALSE; -	while (!done) -	{ -		if (mCurrentDecodep) -		{ -			BOOL res; +void LLAudioDecodeMgr::Impl::startMoreDecodes() +{ +    llassert_always(gAudiop); + +    LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); +    // *NOTE: main_queue->postTo casts this refcounted smart pointer to a weak +    // pointer +    LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); +    const LL::ThreadPool::ptr_t general_thread_pool = LL::ThreadPool::getInstance("General"); +    llassert_always(main_queue); +    llassert_always(general_queue); +    llassert_always(general_thread_pool); +    // Set max decodes to double the thread count of the general work queue. +    // This ensures the general work queue is full, but prevents theoretical +    // buildup of buffers in memory due to disk writes once the +    // LLVorbisDecodeState leaves the worker thread (see +    // LLLFSThread::sLocal->write). This is probably as fast as we can get it +    // without modifying/removing LLVorbisDecodeState, at which point we should +    // consider decoding the audio during the asset download process. +    // -Cosmic,2022-05-11 +    const size_t max_decodes = general_thread_pool->getWidth() * 2; + +    while (!mDecodeQueue.empty() && mDecodes.size() < max_decodes) +    { +        const LLUUID decode_id = mDecodeQueue.front(); +        mDecodeQueue.pop_front(); + +        // Don't decode the same file twice +        if (mDecodes.find(decode_id) != mDecodes.end()) +        { +            continue; +        } +        if (gAudiop->hasDecodedFile(decode_id)) +        { +            continue; +        } + +        // Kick off a decode +        mDecodes[decode_id] = LLPointer<LLVorbisDecodeState>(NULL); +        try +        { +            main_queue->postTo( +                general_queue, +                [decode_id]() // Work done on general queue +                { +                    LLPointer<LLVorbisDecodeState> decode_state = beginDecodingAndWritingAudio(decode_id); + +                    if (!decode_state) +                    { +                        // Audio decode has errored +                        return decode_state; +                    } + +                    // Disk write of decoded audio is now in progress off-thread +                    return decode_state; +                }, +                [decode_id, this](LLPointer<LLVorbisDecodeState> decode_state) // Callback to main thread +                mutable { +                    if (!gAudiop) +                    { +                        // There is no LLAudioEngine anymore. This might happen if +                        // an audio decode is enqueued just before shutdown. +                        return; +                    } + +                    // At this point, we can be certain that the pointer to "this" +                    // is valid because the lifetime of "this" is dependent upon +                    // the lifetime of gAudiop. + +                    enqueueFinishAudio(decode_id, decode_state); +                }); +        } +        catch (const LLThreadSafeQueueInterrupt&) +        { +            // Shutdown +            // Consider making processQueue() do a cleanup instead +            // of starting more decodes +            LL_WARNS() << "Tried to start decoding on shutdown" << LL_ENDL; +        } +    } +} -			// Decode in a loop until we're done or have run out of time. -			while(!(res = mCurrentDecodep->decodeSection()) && (decode_timer.getElapsedTimeF32() < num_secs)) -			{ -				// decodeSection does all of the work above -			} +LLPointer<LLVorbisDecodeState> beginDecodingAndWritingAudio(const LLUUID &decode_id) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; + +    LL_DEBUGS() << "Decoding " << decode_id << " from audio queue!" << LL_ENDL; + +    std::string                    d_path       = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, decode_id.asString()) + ".dsf"; +    LLPointer<LLVorbisDecodeState> decode_state = new LLVorbisDecodeState(decode_id, d_path); + +    if (!decode_state->initDecode()) +    { +        return NULL; +    } + +    // Decode in a loop until we're done +    while (!decode_state->decodeSection()) +    { +        // decodeSection does all of the work above +    } + +    if (!decode_state->isDone()) +    { +        // Decode stopped early, or something bad happened to the file +        // during decoding. +        LL_WARNS("AudioEngine") << decode_id << " has invalid vorbis data or decode has been canceled, aborting decode" << LL_ENDL; +        decode_state->flushBadFile(); +        return NULL; +    } + +    if (!decode_state->isValid()) +    { +        // We had an error when decoding, abort. +        LL_WARNS("AudioEngine") << decode_id << " has invalid vorbis data, aborting decode" << LL_ENDL; +        decode_state->flushBadFile(); +        return NULL; +    } + +    // Kick off the writing of the decoded audio to the disk cache. +    // The receiving thread can then cheaply call finishDecode() again to check +    // if writing has finished. Someone has to hold on to the refcounted +    // decode_state to prevent it from getting destroyed during write. +    decode_state->finishDecode(); + +    return decode_state; +} -			if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid()) -			{ -				// We had an error when decoding, abort. -				LL_WARNS("AudioEngine") << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL; -				mCurrentDecodep->flushBadFile(); - -				if (gAudiop) -				{ -					LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); -					adp->setHasValidData(false); -					adp->setHasCompletedDecode(true); -				} - -				mCurrentDecodep = NULL; -				done = TRUE; -			} +void LLAudioDecodeMgr::Impl::enqueueFinishAudio(const LLUUID &decode_id, LLPointer<LLVorbisDecodeState>& decode_state) +{ +    // Assumed fast +    if (tryFinishAudio(decode_id, decode_state)) +    { +        // Done early! +        auto decode_iter = mDecodes.find(decode_id); +        llassert(decode_iter != mDecodes.end()); +        mDecodes.erase(decode_iter); +        return; +    } + +    // Not done yet... enqueue it +    mDecodes[decode_id] = decode_state; +} -			if (!res) -			{ -				// We've used up out time slice, bail... -				done = TRUE; -			} -			else if (mCurrentDecodep) -			{ -				if (gAudiop && mCurrentDecodep->finishDecode()) -				{ -					// We finished! -					LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); -					if (!adp) -					{ -						LL_WARNS("AudioEngine") << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << LL_ENDL; -					} -					else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) -					{ -						adp->setHasCompletedDecode(true); -						adp->setHasDecodedData(true); -						adp->setHasValidData(true); - -						// At this point, we could see if anyone needs this sound immediately, but -						// I'm not sure that there's a reason to - we need to poll all of the playing -						// sounds anyway. -						//LL_INFOS("AudioEngine") << "Finished the vorbis decode, now what?" << LL_ENDL; -					} -					else -					{ -						adp->setHasCompletedDecode(true); -						LL_INFOS("AudioEngine") << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << LL_ENDL; -					} -					mCurrentDecodep = NULL; -				} -				done = TRUE; // done for now -			} -		} +void LLAudioDecodeMgr::Impl::checkDecodesFinished() +{ +    auto decode_iter = mDecodes.begin(); +    while (decode_iter != mDecodes.end()) +    { +        const LLUUID& decode_id = decode_iter->first; +        const LLPointer<LLVorbisDecodeState>& decode_state = decode_iter->second; +        if (tryFinishAudio(decode_id, decode_state)) +        { +            decode_iter = mDecodes.erase(decode_iter); +        } +        else +        { +            ++decode_iter; +        } +    } +} -		if (!done) -		{ -			if (mDecodeQueue.empty()) -			{ -				// Nothing else on the queue. -				done = TRUE; -			} -			else -			{ -				LLUUID uuid; -				uuid = mDecodeQueue.front(); -				mDecodeQueue.pop_front(); -				if (!gAudiop || gAudiop->hasDecodedFile(uuid)) -				{ -					// This file has already been decoded, don't decode it again. -					continue; -				} - -				LL_DEBUGS() << "Decoding " << uuid << " from audio queue!" << LL_ENDL; - -				std::string uuid_str; -				std::string d_path; - -				LLTimer timer; -				timer.reset(); - -				uuid.toString(uuid_str); -				d_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf"; - -				mCurrentDecodep = new LLVorbisDecodeState(uuid, d_path); -				if (!mCurrentDecodep->initDecode()) -				{ -					mCurrentDecodep = NULL; -				} -			} -		} -	} +bool tryFinishAudio(const LLUUID &decode_id, LLPointer<LLVorbisDecodeState> decode_state) +{ +    // decode_state is a file write in progress unless finished is true +    bool finished = decode_state && decode_state->finishDecode(); +    if (!finished) +    { +        return false; +    } + +    llassert_always(gAudiop); + +    LLAudioData *adp = gAudiop->getAudioData(decode_id); +    if (!adp) +    { +        LL_WARNS("AudioEngine") << "Missing LLAudioData for decode of " << decode_id << LL_ENDL; +        return true; +    } + +    bool valid = decode_state && decode_state->isValid(); +    // Mark current decode finished regardless of success or failure +    adp->setHasCompletedDecode(true); +    // Flip flags for decoded data +    adp->setHasDecodeFailed(!valid); +    adp->setHasDecodedData(valid); +    // When finished decoding, there will also be a decoded wav file cached on +    // disk with the .dsf extension +    if (valid) +    { +        adp->setHasWAVLoadFailed(false); +    } + +    return true;  }  //////////////////////////////////////////////////////////////////////////////  LLAudioDecodeMgr::LLAudioDecodeMgr()  { -	mImpl = new Impl; +    mImpl = new Impl();  }  LLAudioDecodeMgr::~LLAudioDecodeMgr()  { -	delete mImpl; +    delete mImpl; +    mImpl = nullptr;  } -void LLAudioDecodeMgr::processQueue(const F32 num_secs) +void LLAudioDecodeMgr::processQueue()  { -	mImpl->processQueue(num_secs); +    mImpl->processQueue();  }  BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid) @@ -687,7 +795,7 @@ BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)  	{  		// Just put it on the decode queue.  		LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has local asset file already" << LL_ENDL; -		mImpl->mDecodeQueue.push_back(uuid); +        mImpl->mDecodeQueue.push_back(uuid);  		return TRUE;  	} diff --git a/indra/llaudio/llaudiodecodemgr.h b/indra/llaudio/llaudiodecodemgr.h index ceaff3f2d8..4c17b46156 100644 --- a/indra/llaudio/llaudiodecodemgr.h +++ b/indra/llaudio/llaudiodecodemgr.h @@ -32,24 +32,23 @@  #include "llassettype.h"  #include "llframetimer.h" +#include "llsingleton.h" +template<class T> class LLPointer;  class LLVorbisDecodeState; -class LLAudioDecodeMgr +class LLAudioDecodeMgr : public LLSingleton<LLAudioDecodeMgr>  { +    LLSINGLETON(LLAudioDecodeMgr); +    ~LLAudioDecodeMgr();  public: -	LLAudioDecodeMgr(); -	~LLAudioDecodeMgr(); - -	void processQueue(const F32 num_secs = 0.005); +	void processQueue();  	BOOL addDecodeRequest(const LLUUID &uuid);  	void addAudioRequest(const LLUUID &uuid);  protected:  	class Impl; -	Impl* mImpl; +    Impl* mImpl;  }; -extern LLAudioDecodeMgr *gAudioDecodeMgrp; -  #endif diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 9e897a7ce8..008e1827c5 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -83,18 +83,10 @@ void LLAudioEngine::setDefaults()  	mLastStatus = 0; -	mNumChannels = 0;  	mEnableWind = false; -	S32 i; -	for (i = 0; i < MAX_CHANNELS; i++) -	{ -		mChannels[i] = NULL; -	} -	for (i = 0; i < MAX_BUFFERS; i++) -	{ -		mBuffers[i] = NULL; -	} +	mChannels.fill(nullptr); +	mBuffers.fill(nullptr);  	mMasterGain = 1.f;  	// Setting mInternalGain to an out of range value fixes the issue reported in STORM-830. @@ -111,18 +103,14 @@ void LLAudioEngine::setDefaults()  } -bool LLAudioEngine::init(const S32 num_channels, void* userdata, const std::string &app_title) +bool LLAudioEngine::init(void* userdata, const std::string &app_title)  {  	setDefaults(); -	mNumChannels = num_channels;  	mUserData = userdata;  	allocateListener(); -	// Initialize the decode manager -	gAudioDecodeMgrp = new LLAudioDecodeMgr; -  	LL_INFOS("AudioEngine") << "LLAudioEngine::init() AudioEngine successfully initialized" << LL_ENDL;  	return true; @@ -131,10 +119,6 @@ bool LLAudioEngine::init(const S32 num_channels, void* userdata, const std::stri  void LLAudioEngine::shutdown()  { -	// Clean up decode manager -	delete gAudioDecodeMgrp; -	gAudioDecodeMgrp = NULL; -  	// Clean up wind source  	cleanupWind(); @@ -156,14 +140,14 @@ void LLAudioEngine::shutdown()  	// Clean up channels  	S32 i; -	for (i = 0; i < MAX_CHANNELS; i++) +	for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		delete mChannels[i];  		mChannels[i] = NULL;  	}  	// Clean up buffers -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		delete mBuffers[i];  		mBuffers[i] = NULL; @@ -229,7 +213,7 @@ std::string LLAudioEngine::getInternetStreamURL()  void LLAudioEngine::updateChannels()  {  	S32 i; -	for (i = 0; i < MAX_CHANNELS; i++) +	for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		if (mChannels[i])  		{ @@ -240,20 +224,14 @@ void LLAudioEngine::updateChannels()  	}  } -static const F32 default_max_decode_time = .002f; // 2 ms -void LLAudioEngine::idle(F32 max_decode_time) +void LLAudioEngine::idle()  { -	if (max_decode_time <= 0.f) -	{ -		max_decode_time = default_max_decode_time; -	} -	  	// "Update" all of our audio sources, clean up dead ones.  	// Primarily does position updating, cleanup of unused audio sources.  	// Also does regeneration of the current priority of each audio source.  	S32 i; -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		if (mBuffers[i])  		{ @@ -473,7 +451,7 @@ void LLAudioEngine::idle(F32 max_decode_time)  	commitDeferredChanges();  	// Flush unused buffers that are stale enough -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		if (mBuffers[i])  		{ @@ -489,7 +467,7 @@ void LLAudioEngine::idle(F32 max_decode_time)  	// Clear all of the looped flags for the channels -	for (i = 0; i < MAX_CHANNELS; i++) +	for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		if (mChannels[i])  		{ @@ -498,7 +476,7 @@ void LLAudioEngine::idle(F32 max_decode_time)  	}  	// Decode audio files -	gAudioDecodeMgrp->processQueue(max_decode_time); +    LLAudioDecodeMgr::getInstance()->processQueue();  	// Call this every frame, just in case we somehow  	// missed picking it up in all the places that can add @@ -532,7 +510,7 @@ bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uu  		{  			if (audio_uuid.notNull())  			{ -				gAudioDecodeMgrp->addDecodeRequest(audio_uuid); +                LLAudioDecodeMgr::getInstance()->addDecodeRequest(audio_uuid);  			}  		}  		else @@ -561,7 +539,7 @@ void LLAudioEngine::enableWind(bool enable)  LLAudioBuffer * LLAudioEngine::getFreeBuffer()  {  	S32 i; -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		if (!mBuffers[i])  		{ @@ -574,7 +552,7 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()  	// Grab the oldest unused buffer  	F32 max_age = -1.f;  	S32 buffer_id = -1; -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		if (mBuffers[i])  		{ @@ -605,7 +583,7 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()  LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)  {  	S32 i; -	for (i = 0; i < mNumChannels; i++) +    for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		if (!mChannels[i])  		{ @@ -633,7 +611,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)  	F32 min_priority = 10000.f;  	LLAudioChannel *min_channelp = NULL; -	for (i = 0; i < mNumChannels; i++) +    for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		LLAudioChannel *channelp = mChannels[i];  		LLAudioSource *sourcep = channelp->getSource(); @@ -660,7 +638,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)  void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)  {  	S32 i; -	for (i = 0; i < MAX_BUFFERS; i++) +	for (i = 0; i < LL_MAX_AUDIO_BUFFERS; i++)  	{  		if (mBuffers[i] == bufferp)  		{ @@ -678,7 +656,7 @@ bool LLAudioEngine::preloadSound(const LLUUID &uuid)  	getAudioData(uuid);	// We don't care about the return value, this is just to make sure  									// that we have an entry, which will mean that the audio engine knows about this -	if (gAudioDecodeMgrp->addDecodeRequest(uuid)) +    if (LLAudioDecodeMgr::getInstance()->addDecodeRequest(uuid))  	{  		// This means that we do have a local copy, and we're working on decoding it.  		return true; @@ -954,6 +932,7 @@ LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id)  LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid)  { +	LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA;  	data_map::iterator iter;  	iter = mAllData.find(audio_uuid);  	if (iter == mAllData.end()) @@ -1040,7 +1019,7 @@ void LLAudioEngine::startNextTransfer()  	// Check all channels for currently playing sounds.  	F32 max_pri = -1.f; -	for (i = 0; i < MAX_CHANNELS; i++) +	for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  	{  		if (!mChannels[i])  		{ @@ -1068,7 +1047,7 @@ void LLAudioEngine::startNextTransfer()  			continue;  		} -		if (!adp->hasLocalData() && adp->hasValidData()) +        if (!adp->hasLocalData() && !adp->hasDecodeFailed())  		{  			asset_id = adp->getID();  			max_pri = asp->getPriority(); @@ -1079,7 +1058,7 @@ void LLAudioEngine::startNextTransfer()  	if (asset_id.isNull())  	{  		max_pri = -1.f; -		for (i = 0; i < MAX_CHANNELS; i++) +		for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  		{  			if (!mChannels[i])  			{ @@ -1104,7 +1083,7 @@ void LLAudioEngine::startNextTransfer()  				continue;  			} -			if (!adp->hasLocalData() && adp->hasValidData()) +            if (!adp->hasLocalData() && !adp->hasDecodeFailed())  			{  				asset_id = adp->getID();  				max_pri = asp->getPriority(); @@ -1116,7 +1095,7 @@ void LLAudioEngine::startNextTransfer()  	if (asset_id.isNull())  	{  		max_pri = -1.f; -		for (i = 0; i < MAX_CHANNELS; i++) +		for (i = 0; i < LL_MAX_AUDIO_CHANNELS; i++)  		{  			if (!mChannels[i])  			{ @@ -1144,7 +1123,7 @@ void LLAudioEngine::startNextTransfer()  					continue;  				} -				if (!adp->hasLocalData() && adp->hasValidData()) +                if (!adp->hasLocalData() && !adp->hasDecodeFailed())  				{  					asset_id = adp->getID();  					max_pri = asp->getPriority(); @@ -1172,7 +1151,7 @@ void LLAudioEngine::startNextTransfer()  			}  			adp = asp->getCurrentData(); -			if (adp && !adp->hasLocalData() && adp->hasValidData()) +            if (adp && !adp->hasLocalData() && !adp->hasDecodeFailed())  			{  				asset_id = adp->getID();  				max_pri = asp->getPriority(); @@ -1180,7 +1159,7 @@ void LLAudioEngine::startNextTransfer()  			}  			adp = asp->getQueuedData(); -			if (adp && !adp->hasLocalData() && adp->hasValidData()) +            if (adp && !adp->hasLocalData() && !adp->hasDecodeFailed())  			{  				asset_id = adp->getID();  				max_pri = asp->getPriority(); @@ -1195,7 +1174,7 @@ void LLAudioEngine::startNextTransfer()  					continue;  				} -				if (!adp->hasLocalData() && adp->hasValidData()) +                if (!adp->hasLocalData() && !adp->hasDecodeFailed())  				{  					asset_id = adp->getID();  					max_pri = asp->getPriority(); @@ -1236,7 +1215,7 @@ void LLAudioEngine::assetCallback(const LLUUID &uuid, LLAssetType::EType type, v  		LLAudioData *adp = gAudiop->getAudioData(uuid);  		if (adp)          {	// Make sure everything is cleared -			adp->setHasValidData(false); +            adp->setHasDecodeFailed(true);  			adp->setHasLocalData(false);  			adp->setHasDecodedData(false);  			adp->setHasCompletedDecode(true); @@ -1253,9 +1232,9 @@ void LLAudioEngine::assetCallback(const LLUUID &uuid, LLAssetType::EType type, v  		else  		{  			// LL_INFOS() << "Got asset callback with good audio data for " << uuid << ", making decode request" << LL_ENDL; -			adp->setHasValidData(true); +            adp->setHasDecodeFailed(false);  		    adp->setHasLocalData(true); -		    gAudioDecodeMgrp->addDecodeRequest(uuid); +            LLAudioDecodeMgr::getInstance()->addDecodeRequest(uuid);  		}  	}  	gAudiop->mCurrentTransfer = LLUUID::null; @@ -1325,11 +1304,15 @@ void LLAudioSource::update()  		{  			// Hack - try and load the sound.  Will do this as a callback  			// on decode later. -			if (adp->load() && adp->getBuffer()) +            if (adp->getBuffer())  			{  				play(adp->getID());  			} -			else if (adp->hasCompletedDecode())		// Only mark corrupted after decode is done +            else if (adp->hasDecodedData() && !adp->hasWAVLoadFailed()) +            { +                adp->load(); +            } +            else if (adp->hasCompletedDecode() && adp->hasDecodeFailed()) // Only mark corrupted after decode is done  			{  				LL_WARNS() << "Marking LLAudioSource corrupted for " << adp->getID() << LL_ENDL;  				mCorrupted = true ; @@ -1625,12 +1608,12 @@ bool LLAudioSource::hasPendingPreloads() const  	{  		LLAudioData *adp = iter->second;  		// note: a bad UUID will forever be !hasDecodedData() -		// but also !hasValidData(), hence the check for hasValidData() +        // but also hasDecodeFailed(), hence the check for hasDecodeFailed()  		if (!adp)  		{  			continue;  		} -		if (!adp->hasDecodedData() && adp->hasValidData()) +        if (!adp->hasDecodedData() && !adp->hasDecodeFailed())  		{  			// This source is still waiting for a preload  			return true; @@ -1787,7 +1770,8 @@ LLAudioData::LLAudioData(const LLUUID &uuid) :  	mHasLocalData(false),  	mHasDecodedData(false),  	mHasCompletedDecode(false), -	mHasValidData(true) +    mHasDecodeFailed(false), +    mHasWAVLoadFailed(false)  {  	if (uuid.isNull())  	{ @@ -1822,12 +1806,14 @@ bool LLAudioData::load()  	{  		// We already have this sound in a buffer, don't do anything.  		LL_INFOS() << "Already have a buffer for this sound, don't bother loading!" << LL_ENDL; +        mHasWAVLoadFailed = false;  		return true;  	}  	if (!gAudiop)  	{  		LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +        mHasWAVLoadFailed = true;  		return false;  	} @@ -1836,6 +1822,8 @@ bool LLAudioData::load()  	{  		// No free buffers, abort.  		LL_INFOS() << "Not able to allocate a new audio buffer, aborting." << LL_ENDL; +        // *TODO: Mark this failure differently so the audio engine could retry loading this buffer in the future +        mHasWAVLoadFailed = true;  		return true;  	} @@ -1844,7 +1832,8 @@ bool LLAudioData::load()  	mID.toString(uuid_str);  	wav_path= gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf"; -	if (!mBufferp->loadWAV(wav_path)) +    mHasWAVLoadFailed = !mBufferp->loadWAV(wav_path); +    if (mHasWAVLoadFailed)  	{  		// Hrm.  Right now, let's unset the buffer, since it's empty.  		gAudiop->cleanupBuffer(mBufferp); diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index e12fb970ca..0fe8b3d756 100644..100755 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -47,8 +47,8 @@ const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;  const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;  const F32 DEFAULT_MIN_DISTANCE = 2.0f; -#define MAX_CHANNELS 30 -#define MAX_BUFFERS 40	// Some extra for preloading, maybe? +#define LL_MAX_AUDIO_CHANNELS 30 +#define LL_MAX_AUDIO_BUFFERS 40 // Some extra for preloading, maybe?  class LLAudioSource;  class LLAudioData; @@ -88,7 +88,7 @@ public:  	virtual ~LLAudioEngine();  	// initialization/startup/shutdown -	virtual bool init(const S32 num_channels, void *userdata, const std::string &app_title); +	virtual bool init(void *userdata, const std::string &app_title);  	virtual std::string getDriverName(bool verbose) = 0;  	virtual void shutdown(); @@ -96,7 +96,7 @@ public:  	//virtual void processQueue(const LLUUID &sound_guid);  	virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at);  	virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0; -	virtual void idle(F32 max_decode_time = 0.f); +	virtual void idle();  	virtual void updateChannels();  	// @@ -209,7 +209,6 @@ protected:  	S32 mLastStatus; -	S32 mNumChannels;  	bool mEnableWind;  	LLUUID mCurrentTransfer; // Audio file currently being transferred by the system @@ -224,11 +223,11 @@ protected:  	source_map mAllSources;  	data_map mAllData; -	LLAudioChannel *mChannels[MAX_CHANNELS]; +    std::array<LLAudioChannel*, LL_MAX_AUDIO_CHANNELS> mChannels;  	// Buffers needs to change into a different data structure, as the number of buffers  	// that we have active should be limited by RAM usage, not count. -	LLAudioBuffer *mBuffers[MAX_BUFFERS]; +    std::array<LLAudioBuffer*, LL_MAX_AUDIO_BUFFERS> mBuffers;  	F32 mMasterGain;  	F32 mInternalGain;			// Actual gain set; either mMasterGain or 0 when mMuted is true. @@ -360,32 +359,36 @@ protected:  class LLAudioData  { -public: -	LLAudioData(const LLUUID &uuid); -	bool load(); - -	LLUUID getID() const				{ return mID; } -	LLAudioBuffer *getBuffer() const	{ return mBufferp; } - -	bool	hasLocalData() const		{ return mHasLocalData; } -	bool	hasDecodedData() const		{ return mHasDecodedData; } -	bool	hasCompletedDecode() const	{ return mHasCompletedDecode; } -	bool	hasValidData() const		{ return mHasValidData; } - -	void	setHasLocalData(const bool hld)		{ mHasLocalData = hld; } -	void	setHasDecodedData(const bool hdd)	{ mHasDecodedData = hdd; } -	void	setHasCompletedDecode(const bool hcd)	{ mHasCompletedDecode = hcd; } -	void	setHasValidData(const bool hvd)		{ mHasValidData = hvd; } - -	friend class LLAudioEngine; // Severe laziness, bad. - -protected: -	LLUUID mID; -	LLAudioBuffer *mBufferp;	// If this data is being used by the audio system, a pointer to the buffer will be set here. -	bool mHasLocalData;			// Set true if the sound asset file is available locally -	bool mHasDecodedData;		// Set true if the sound file has been decoded -	bool mHasCompletedDecode;	// Set true when the sound is decoded -	bool mHasValidData;			// Set false if decoding failed, meaning the sound asset is bad +  public: +    LLAudioData(const LLUUID &uuid); +    bool load(); + +    LLUUID         getID() const { return mID; } +    LLAudioBuffer *getBuffer() const { return mBufferp; } + +    bool hasLocalData() const { return mHasLocalData; } +    bool hasDecodedData() const { return mHasDecodedData; } +    bool hasCompletedDecode() const { return mHasCompletedDecode; } +    bool hasDecodeFailed() const { return mHasDecodeFailed; } +    bool hasWAVLoadFailed() const { return mHasWAVLoadFailed; } + +    void setHasLocalData(const bool hld) { mHasLocalData = hld; } +    void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } +    void setHasCompletedDecode(const bool hcd) { mHasCompletedDecode = hcd; } +    void setHasDecodeFailed(const bool hdf) { mHasDecodeFailed = hdf; } +    void setHasWAVLoadFailed(const bool hwlf) { mHasWAVLoadFailed = hwlf; } + +    friend class LLAudioEngine;  // Severe laziness, bad. + +  protected: +    LLUUID         mID; +    LLAudioBuffer *mBufferp;             // If this data is being used by the audio system, a pointer to the buffer will be set here. +    bool           mHasLocalData;        // Set true if the encoded sound asset file is available locally +    bool           mHasDecodedData;      // Set true if the decoded sound file is available on disk +    bool           mHasCompletedDecode;  // Set true when the sound is decoded +    bool           mHasDecodeFailed;     // Set true if decoding failed, meaning the sound asset is bad +    bool mHasWAVLoadFailed;  // Set true if loading the decoded WAV file failed, meaning the sound asset should be decoded instead if +                             // possible  }; diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp index e5752d3dad..ba743020b5 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.cpp +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -74,7 +74,7 @@ static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)      return true;  } -bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, const std::string &app_title) +bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title)  {      U32 version;      FMOD_RESULT result; @@ -86,7 +86,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons          return false;      //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. -    LLAudioEngine::init(num_channels, userdata, app_title); +    LLAudioEngine::init(userdata, app_title);      result = mSystem->getVersion(&version);      Check_FMOD_Error(result, "FMOD::System::getVersion"); @@ -98,7 +98,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons      }      // In this case, all sounds, PLUS wind and stream will be software. -    result = mSystem->setSoftwareChannels(num_channels + 2); +    result = mSystem->setSoftwareChannels(LL_MAX_AUDIO_CHANNELS + 2);      Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels");      FMOD_ADVANCEDSETTINGS settings; @@ -127,7 +127,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons          {              LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;              if (mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && -                (result = mSystem->init(num_channels + 2, fmod_flags, const_cast<char*>(app_title.c_str()))) == FMOD_OK) +                (result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, const_cast<char*>(app_title.c_str()))) == FMOD_OK)              {                  LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL;                  audio_ok = true; @@ -149,7 +149,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons          {              LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;              if (mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && -                (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) +                (result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0)) == FMOD_OK)              {                  LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;                  audio_ok = true; @@ -190,7 +190,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons      // initialize the FMOD engine      // number of channel in this case looks to be identiacal to number of max simultaneously      // playing objects and we can set practically any number -    result = mSystem->init(num_channels + 2, fmod_flags, 0); +    result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0);      if (Check_FMOD_Error(result, "Error initializing FMOD Studio with default settins, retrying with other format"))      {          result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0/*- ignore*/); @@ -198,7 +198,7 @@ bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, cons          {              return false;          } -        result = mSystem->init(num_channels + 2, fmod_flags, 0); +        result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0);      }      if (Check_FMOD_Error(result, "Error initializing FMOD Studio"))      { diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h index f2361df1b6..d3d6d69685 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -51,7 +51,7 @@ public:  	virtual ~LLAudioEngine_FMODSTUDIO();  	// initialization/startup/shutdown -	virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title); +	virtual bool init(void *user_data, const std::string &app_title);  	virtual std::string getDriverName(bool verbose);  	virtual void allocateListener(); diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index 305aa1ecb5..0a79614424 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -52,10 +52,10 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()  }  // virtual -bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata, const std::string &app_title) +bool LLAudioEngine_OpenAL::init(void* userdata, const std::string &app_title)  {  	mWindGen = NULL; -	LLAudioEngine::init(num_channels, userdata, app_title); +	LLAudioEngine::init(userdata, app_title);  	if(!alutInit(NULL, NULL))  	{ diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h index 366f9259e3..a3cab97cd2 100644 --- a/indra/llaudio/llaudioengine_openal.h +++ b/indra/llaudio/llaudioengine_openal.h @@ -40,7 +40,7 @@ class LLAudioEngine_OpenAL : public LLAudioEngine  		LLAudioEngine_OpenAL();  		virtual ~LLAudioEngine_OpenAL(); -        virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title); +        virtual bool init(void *user_data, const std::string &app_title);          virtual std::string getDriverName(bool verbose);  		virtual void allocateListener(); diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index a25ff16786..ebf7454a61 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1222,8 +1222,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8  //-----------------------------------------------------------------------------  // deserialize() +// +// allow_invalid_joints should be true when handling existing content, to avoid breakage. +// During upload, we should be more restrictive and reject such animations.  //----------------------------------------------------------------------------- -BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) +BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, bool allow_invalid_joints)  {  	BOOL old_version = FALSE;  	mJointMotionList = new LLKeyframeMotion::JointMotionList; @@ -1344,6 +1347,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id)  		return FALSE;  	} +	//SL-17206 hack to alter Female_land loop setting, while current behavior won't be changed serverside +	LLUUID const female_land_anim("ca1baf4d-0a18-5a1f-0330-e4bd1e71f09e"); +	LLUUID const formal_female_land_anim("6a9a173b-61fa-3ad5-01fa-a851cfc5f66a"); +	if (female_land_anim == asset_id || formal_female_land_anim == asset_id) +	{ +		LL_WARNS() << "Animation(" << asset_id << ") won't be looped." << LL_ENDL; +		mJointMotionList->mLoop = FALSE; +	} +  	//-------------------------------------------------------------------------  	// get easeIn and easeOut  	//------------------------------------------------------------------------- @@ -1443,6 +1455,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id)  		if (joint)  		{              S32 joint_num = joint->getJointNum(); +			joint_name = joint->getName(); // canonical name in case this is an alias.  //			LL_INFOS() << "  joint: " << joint_name << LL_ENDL;              if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0))              { @@ -1457,7 +1470,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id)  		{  			LL_WARNS() << "invalid joint name: " << joint_name                         << " for animation " << asset_id << LL_ENDL; -			//return FALSE; +			if (!allow_invalid_joints) +			{ +				return FALSE; +			}  		}  		joint_motion->mJointName = joint_name; @@ -2096,8 +2112,9 @@ U32	LLKeyframeMotion::getFileSize()  //-----------------------------------------------------------------------------  // dumpToFile()  //----------------------------------------------------------------------------- -void LLKeyframeMotion::dumpToFile(const std::string& name) +bool LLKeyframeMotion::dumpToFile(const std::string& name)  { +	bool succ = false;      if (isLoaded())      {          std::string outfile_base; @@ -2114,10 +2131,24 @@ void LLKeyframeMotion::dumpToFile(const std::string& name)              const LLUUID& id = getID();              outfile_base = id.asString();          } -        std::string outfilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfile_base + ".anim"); + +		if (gDirUtilp->getExtension(outfile_base).empty()) +		{ +			outfile_base += ".anim"; +		} +		std::string outfilename; +		if (gDirUtilp->getDirName(outfile_base).empty()) +		{ +			outfilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfile_base); +		} +		else +		{ +			outfilename = outfile_base; +		}          if (LLFile::isfile(outfilename))          { -            return; +			LL_WARNS() << outfilename << " already exists, write failed" << LL_ENDL; +            return false;          }          S32 file_size = getFileSize(); @@ -2131,11 +2162,13 @@ void LLKeyframeMotion::dumpToFile(const std::string& name)              outfile.open(outfilename, LL_APR_WPB);              if (outfile.getFileHandle())              { -                outfile.write(buffer, file_size); +                S32 wrote_bytes = outfile.write(buffer, file_size); +				succ = (wrote_bytes == file_size);              }          }          delete [] buffer;      } +	return succ;  }  //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index 9a927ede9a..96746f57c9 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -156,9 +156,9 @@ public:  public:  	U32		getFileSize();  	BOOL	serialize(LLDataPacker& dp) const; -	BOOL	deserialize(LLDataPacker& dp, const LLUUID& asset_id); +	BOOL	deserialize(LLDataPacker& dp, const LLUUID& asset_id, bool allow_invalid_joints = true);  	BOOL	isLoaded() { return mJointMotionList != NULL; } -    void	dumpToFile(const std::string& name); +    bool	dumpToFile(const std::string& name);  	// setters for modifying a keyframe animation @@ -432,6 +432,9 @@ protected:  	F32								mLastUpdateTime;  	F32								mLastLoopedTime;  	AssetStatus						mAssetStatus; + +public: +	void setCharacter(LLCharacter* character) { mCharacter = character; }  };  class LLKeyframeDataCache diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 56939584bb..5770b319f7 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -253,6 +253,11 @@ set(llcommon_HEADER_FILES      workqueue.h      StackWalker.h      ) +     +if (DARWIN) +  list(APPEND llcommon_HEADER_FILES llsys_objc.h) +  list(APPEND llcommon_SOURCE_FILES llsys_objc.mm) +endif (DARWIN)  list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) @@ -270,8 +275,8 @@ target_link_libraries(          ll::tracy      ) -target_include_directories( llcommon  INTERFACE   ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories( llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) +target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})  add_dependencies(llcommon stage_third_party_libs) diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 849867586a..d6ae1284d3 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -212,11 +212,9 @@ U64 LLMemory::getCurrentRSS()  	mach_msg_type_number_t  basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;  	if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)  	{ -//		residentSize = basicInfo.resident_size; -		// Although this method is defined to return the "resident set size," -		// in fact what callers want from it is the total virtual memory -		// consumed by the application. -		residentSize = basicInfo.virtual_size; +        residentSize = basicInfo.resident_size; +        // 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size. +        // basicInfo.virtual_size is not what we want.  	}  	else  	{ diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 5cbd346411..6852b5536a 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -30,7 +30,7 @@  #include "llerror.h"  // maximum reference count before sounding memory leak alarm -const S32 gMaxRefCount = 65536; +const S32 gMaxRefCount = S32_MAX;  LLRefCount::LLRefCount(const LLRefCount& other)  :	mRef(0) diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 26a0fa1b1c..a8b5c7b3a8 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -64,6 +64,7 @@ using namespace llsd;  #   include <psapi.h>               // GetPerformanceInfo() et al.  #	include <VersionHelpers.h>  #elif LL_DARWIN +#   include "llsys_objc.h"  #	include <errno.h>  #	include <sys/sysctl.h>  #	include <sys/utsname.h> @@ -74,12 +75,6 @@ using namespace llsd;  #	include <mach/mach_host.h>  #	include <mach/task.h>  #	include <mach/task_info.h> - -// disable warnings about Gestalt calls being deprecated -// until Apple get's on the ball and provides an alternative -// -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -  #elif LL_LINUX  #	include <errno.h>  #	include <sys/utsname.h> @@ -278,12 +273,9 @@ LLOSInfo::LLOSInfo() :  	{  		const char * DARWIN_PRODUCT_NAME = "Mac OS X"; -		SInt32 major_version, minor_version, bugfix_version; -		OSErr r1 = Gestalt(gestaltSystemVersionMajor, &major_version); -		OSErr r2 = Gestalt(gestaltSystemVersionMinor, &minor_version); -		OSErr r3 = Gestalt(gestaltSystemVersionBugFix, &bugfix_version); +		S32 major_version, minor_version, bugfix_version = 0; -		if((r1 == noErr) && (r2 == noErr) && (r3 == noErr)) +		if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))  		{  			mMajorVer = major_version;  			mMinorVer = minor_version; @@ -1410,10 +1402,3 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)  	if (dst != NULL) gzclose(dst);  	return retval;  } - -#if LL_DARWIN -// disable warnings about Gestalt calls being deprecated -// until Apple get's on the ball and provides an alternative -// -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif diff --git a/indra/llcommon/llsys_objc.h b/indra/llcommon/llsys_objc.h new file mode 100644 index 0000000000..35599a574b --- /dev/null +++ b/indra/llcommon/llsys_objc.h @@ -0,0 +1,33 @@ +/** + * @file llsys_objc.h + * @brief Header file for llsys_objc.mm + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LLSYS_OBJC_H +#define LL_LLSYS_OBJC_H + +bool LLGetDarwinOSInfo(int &major, int &minor, int &patch); + + +#endif // LL_LLSYS_OBJC_H diff --git a/indra/llcommon/llsys_objc.mm b/indra/llcommon/llsys_objc.mm new file mode 100644 index 0000000000..cdb1e320d5 --- /dev/null +++ b/indra/llcommon/llsys_objc.mm @@ -0,0 +1,64 @@ +/** + * @file llsys_objc.mm + * @brief obj-c implementation of the system information functions + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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$ + */ + +#import "llsys_objc.h" +#import <AppKit/AppKit.h> + +static int intAtStringIndex(NSArray *array, int index) +{ +    return [(NSString *)[array objectAtIndex:index] integerValue]; +} + +bool LLGetDarwinOSInfo(int &major, int &minor, int &patch) +{ +    if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8) +    { +        NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; +        major = osVersion.majorVersion; +        minor = osVersion.minorVersion; +        patch = osVersion.patchVersion; +    } +    else +    { +        NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile: +                                    @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]; +        NSArray* versions = [versionString componentsSeparatedByString:@"."]; +        NSUInteger count = [versions count]; +        if (count > 0) +        { +            major = intAtStringIndex(versions, 0); +            if (count > 1) +            { +                minor = intAtStringIndex(versions, 1); +                if (count > 2) +                { +                    patch = intAtStringIndex(versions, 2); +                } +            } +        } +    } +    return true; +} diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ba914035e2..d5adf11264 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -22,6 +22,7 @@  #include "stringize.h"  LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): +    super(name),      mQueue(name, capacity),      mName("ThreadPool:" + name),      mThreadCount(threads) diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b79c9b9090..f8eec3b457 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -22,8 +22,10 @@  namespace LL  { -    class ThreadPool +    class ThreadPool: public LLInstanceTracker<ThreadPool, std::string>      { +    private: +        using super = LLInstanceTracker<ThreadPool, std::string>;      public:          /**           * Pass ThreadPool a string name. This can be used to look up the diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 96574a18b9..70fd65bd0c 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -403,7 +403,7 @@ namespace LL                  [result = std::forward<CALLABLE>(callable)(),                   callback = std::move(callback)]                  () -                { callback(std::move(result)); }; +                mutable { callback(std::move(result)); };          }      }; @@ -449,7 +449,7 @@ namespace LL               callable = std::move(callable),               callback = std::move(callback)]              () -            { +            mutable {                  // Use postMaybe() below in case this originating WorkQueue                  // has been closed or destroyed. Remember, the outer lambda is                  // now running on a thread servicing the target WorkQueue, and @@ -513,7 +513,7 @@ namespace LL                  // We dare to bind a reference to Promise because it's                  // specifically designed for cross-thread communication.                  [&promise, callable = std::move(callable)]() -                { +                mutable {                      try                      {                          // call the caller's callable and trigger promise with result @@ -542,7 +542,7 @@ namespace LL                  time,                  // &promise is designed for cross-thread access                  [&promise, callable = std::move(callable)]() -                { +                mutable {                      try                      {                          callable(); diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index 01144d8b0d..6de99dfbff 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -131,28 +131,44 @@ void LLDiskCache::purge()      LL_INFOS() << "Purging cache to a maximum of " << mMaxSizeBytes << " bytes" << LL_ENDL; +    std::vector<bool> file_removed; +    if (mEnableCacheDebugInfo) +    { +        file_removed.reserve(file_info.size()); +    }      uintmax_t file_size_total = 0;      for (file_info_t& entry : file_info)      {          file_size_total += entry.second.first; -        std::string action = ""; -        if (file_size_total > mMaxSizeBytes) +        bool should_remove = file_size_total > mMaxSizeBytes; +        if (mEnableCacheDebugInfo) +        { +            file_removed.push_back(should_remove); +        } +        if (should_remove)          { -            action = "DELETE:";              boost::filesystem::remove(entry.second.second, ec);              if (ec.failed())              {                  LL_WARNS() << "Failed to delete cache file " << entry.second.second << ": " << ec.message() << LL_ENDL;              }          } -        else -        { -            action = "  KEEP:"; -        } +    } -        if (mEnableCacheDebugInfo) +    if (mEnableCacheDebugInfo) +    { +        auto end_time = std::chrono::high_resolution_clock::now(); +        auto execute_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count(); + +        // Log afterward so it doesn't affect the time measurement +        // Logging thousands of file results can take hundreds of milliseconds +        for (size_t i = 0; i < file_info.size(); ++i)          { +            const file_info_t& entry = file_info[i]; +            const bool removed = file_removed[i]; +            const std::string action = removed ? "DELETE:" : "KEEP:"; +              // have to do this because of LL_INFO/LL_END weirdness              std::ostringstream line; @@ -163,12 +179,7 @@ void LLDiskCache::purge()              line << " (" << file_size_total << "/" << mMaxSizeBytes << ")";              LL_INFOS() << line.str() << LL_ENDL;          } -    } -    if (mEnableCacheDebugInfo) -    { -        auto end_time = std::chrono::high_resolution_clock::now(); -        auto execute_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();          LL_INFOS() << "Total dir size after purge is " << dirFileSize(mCacheDir) << LL_ENDL;          LL_INFOS() << "Cache purge took " << execute_time << " ms to execute for " << file_info.size() << " files" << LL_ENDL;      } diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index a9a54a8113..318ee65cc0 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -48,52 +48,59 @@ extern float gOctreeMinSize;  #define LL_OCTREE_MAX_CAPACITY 128  #endif*/ -template <class T> class LLOctreeNode; - -template <class T> +// T is the type of the element referenced by the octree node. +// T_PTR determines how pointers to elements are stored internally. +// LLOctreeNode<T, LLPointer<T>> assumes ownership of inserted elements and +// deletes elements removed from the tree. +// LLOctreeNode<T, T*> doesn't take ownership of inserted elements, so the API +// user is responsible for managing the storage lifecycle of elements added to +// the tree. +template <class T, typename T_PTR> class LLOctreeNode; + +template <class T, typename T_PTR>  class LLOctreeListener: public LLTreeListener<T>  {  public:  	typedef LLTreeListener<T> BaseType; -	typedef LLOctreeNode<T> oct_node; +    typedef LLOctreeNode<T, T_PTR> oct_node;  	virtual void handleChildAddition(const oct_node* parent, oct_node* child) = 0;  	virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;  }; -template <class T> +template <class T, typename T_PTR>  class LLOctreeTraveler  {  public: -	virtual void traverse(const LLOctreeNode<T>* node); -	virtual void visit(const LLOctreeNode<T>* branch) = 0; +    virtual void traverse(const LLOctreeNode<T, T_PTR>* node); +    virtual void visit(const LLOctreeNode<T, T_PTR>* branch) = 0;  }; -template <class T> -class LLOctreeTravelerDepthFirst : public LLOctreeTraveler<T> +template <class T, typename T_PTR> +class LLOctreeTravelerDepthFirst : public LLOctreeTraveler<T, T_PTR>  {  public: -	virtual void traverse(const LLOctreeNode<T>* node) override; +	virtual void traverse(const LLOctreeNode<T, T_PTR>* node) override;  }; -template <class T> +template <class T, typename T_PTR>  class alignas(16) LLOctreeNode : public LLTreeNode<T>  {      LL_ALIGN_NEW  public: -	typedef LLOctreeTraveler<T>									oct_traveler; -	typedef LLTreeTraveler<T>									tree_traveler; -	typedef std::vector< LLPointer<T> >							element_list;		// note:  don't remove the whitespace between "> >" -	typedef LLPointer<T>*										element_iter; -	typedef const LLPointer<T>*									const_element_iter; +    typedef LLOctreeTraveler<T, T_PTR>                          oct_traveler; +    typedef LLTreeTraveler<T>                                   tree_traveler; +    typedef std::vector<T_PTR>                                  element_list; +    typedef typename element_list::iterator                     element_iter; +    typedef typename element_list::const_iterator               const_element_iter;  	typedef typename std::vector<LLTreeListener<T>*>::iterator	tree_listener_iter; -	typedef LLOctreeNode<T>**									child_list; -	typedef LLOctreeNode<T>**									child_iter; +    typedef LLOctreeNode<T, T_PTR>**                            child_list; +    typedef LLOctreeNode<T, T_PTR>**                            child_iter; -	typedef LLTreeNode<T>		BaseType; -	typedef LLOctreeNode<T>		oct_node; -	typedef LLOctreeListener<T>	oct_listener; +    typedef LLTreeNode<T>               BaseType; +    typedef LLOctreeNode<T, T_PTR>      oct_node; +    typedef LLOctreeListener<T, T_PTR>  oct_listener;      enum      { @@ -108,9 +115,6 @@ public:  		mOctant(octant)   	{   		llassert(size[0] >= gOctreeMinSize*0.5f); -		//always keep a NULL terminated list to avoid out of bounds exceptions in debug builds -		mData.push_back(NULL); -		mDataEnd = &mData[0];  		mCenter = center;  		mSize = size; @@ -121,8 +125,6 @@ public:  			mOctant = ((oct_node*) mParent)->getOctant(mCenter);  		} -		mElementCount = 0; -  		clearChildren();  	} @@ -130,15 +132,14 @@ public:  	{   		BaseType::destroyListeners(); -		for (U32 i = 0; i < mElementCount; ++i) +        const U32 element_count = getElementCount(); +        for (U32 i = 0; i < element_count; ++i)  		{  			mData[i]->setBinIndex(-1);  			mData[i] = NULL;  		}  		mData.clear(); -		mData.push_back(NULL); -		mDataEnd = &mData[0];  		for (U32 i = 0; i < getChildCount(); i++)  		{ @@ -238,14 +239,12 @@ public:  	void accept(oct_traveler* visitor)				{ visitor->visit(this); }  	virtual bool isLeaf() const						{ return mChildCount == 0; } -	U32 getElementCount() const						{ return mElementCount; } -	bool isEmpty() const							{ return mElementCount == 0; } -	element_list& getData()							{ return mData; } -	const element_list& getData() const				{ return mData; } -	element_iter getDataBegin()						{ return &mData[0]; } -	element_iter getDataEnd()						{ return mDataEnd; } -	const_element_iter getDataBegin() const			{ return &mData[0]; } -	const_element_iter getDataEnd() const			{ return mDataEnd; } +    U32 getElementCount() const                     { return (U32)mData.size(); } +    bool isEmpty() const                            { return mData.empty(); } +    element_iter getDataBegin()                     { return mData.begin(); } +    element_iter getDataEnd()                       { return mData.end(); } +    const_element_iter getDataBegin() const         { return mData.cbegin(); } +    const_element_iter getDataEnd() const           { return mData.cend(); }  	U32 getChildCount()	const						{ return mChildCount; }  	oct_node* getChild(U32 index)					{ return mChild[index]; } @@ -263,7 +262,7 @@ public:  			U8 idx = mChildMap[i];  			if (idx != NO_CHILD_NODES)  			{ -				LLOctreeNode<T>* child = mChild[idx]; +                oct_node* child = mChild[idx];  				if (child->getOctant() != i)  				{ @@ -281,7 +280,7 @@ public:  	oct_node* getNodeAt(const LLVector4a& pos, const F32& rad)  	{  -		LLOctreeNode<T>* node = this; +        oct_node* node = this;  		if (node->isInside(pos, rad))  		{ @@ -303,7 +302,7 @@ public:  		}  		else if (!node->contains(rad) && node->getParent())  		{ //if we got here, data does not exist in this node -			return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(pos, rad); +            return ((oct_node*) node->getParent())->getNodeAt(pos, rad);  		}  		return node; @@ -318,7 +317,7 @@ public:  			OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << LL_ENDL;  			return false;  		} -		LLOctreeNode<T>* parent = getOctParent(); +        oct_node* parent = getOctParent();  		//is it here?  		if (isInside(data->getPositionGroup())) @@ -326,11 +325,8 @@ public:  			if ((((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius())) ||  				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity)))   			{ //it belongs here -				mData.push_back(NULL); -				mData[mElementCount] = data; -				mElementCount++; -				mDataEnd = &mData[mElementCount]; -				data->setBinIndex(mElementCount-1); +                mData.push_back(data); +                data->setBinIndex(getElementCount() - 1);  				BaseType::insert(data);  				return true;  			} @@ -354,7 +350,7 @@ public:  				size.mul(0.5f);  				//push center in direction of data -				LLOctreeNode<T>::pushCenter(center, size, data); +                oct_node::pushCenter(center, size, data);  				// handle case where floating point number gets too small  				LLVector4a val; @@ -366,11 +362,8 @@ public:  				if( lt == 0x7 )  				{ -					mData.push_back(NULL); -					mData[mElementCount] = data; -					mElementCount++; -					mDataEnd = &mData[mElementCount]; -					data->setBinIndex(mElementCount-1); +                    mData.push_back(data); +                    data->setBinIndex(getElementCount() - 1);  					BaseType::insert(data);  					return true;  				} @@ -396,7 +389,7 @@ public:  				llassert(size[0] >= gOctreeMinSize*0.5f);  				//make the new kid -				child = new LLOctreeNode<T>(center, size, this); +                child = new oct_node(center, size, this);  				addChild(child);  				child->insert(data); @@ -429,28 +422,25 @@ public:  	}  	void _remove(T* data, S32 i) -	{ //precondition -- mElementCount > 0, idx is in range [0, mElementCount) +    { //precondition -- getElementCount() > 0, idx is in range [0, getElementCount()) -		mElementCount--;  		data->setBinIndex(-1);  -		if (mElementCount > 0) +        const U32 new_element_count = getElementCount() - 1; +		if (new_element_count > 0)  		{ -			if (mElementCount != i) +			if (new_element_count != i)  			{ -				mData[i] = mData[mElementCount]; //might unref data, do not access data after this point +				mData[i] = mData[new_element_count]; //might unref data, do not access data after this point  				mData[i]->setBinIndex(i);  			} -			mData[mElementCount] = NULL; +			mData[new_element_count] = NULL;  			mData.pop_back(); -			mDataEnd = &mData[mElementCount];  		}  		else  		{  			mData.clear(); -			mData.push_back(NULL); -			mDataEnd = &mData[0];  		}  		this->notifyRemoval(data); @@ -463,7 +453,7 @@ public:  		S32 i = data->getBinIndex(); -		if (i >= 0 && i < mElementCount) +        if (i >= 0 && i < getElementCount())  		{  			if (mData[i] == data)  			{ //found it @@ -506,7 +496,8 @@ public:  	void removeByAddress(T* data)  	{ -        for (U32 i = 0; i < mElementCount; ++i) +        const U32 element_count = getElementCount(); +        for (U32 i = 0; i < element_count; ++i)  		{  			if (mData[i] == data)  			{ //we have data @@ -518,7 +509,7 @@ public:  		for (U32 i = 0; i < getChildCount(); i++)  		{	//we don't contain data, so pass this guy down -			LLOctreeNode<T>* child = (LLOctreeNode<T>*) getChild(i); +            oct_node* child = (oct_node*) getChild(i);  			child->removeByAddress(data);  		}  	} @@ -672,22 +663,20 @@ protected:  	oct_node* mParent;  	U8 mOctant; -	LLOctreeNode<T>* mChild[8]; +    oct_node* mChild[8];  	U8 mChildMap[8];  	U32 mChildCount;  	element_list mData; -	element_iter mDataEnd; -	U32 mElementCount;  };   //just like a regular node, except it might expand on insert and compress on balance -template <class T> -class LLOctreeRoot : public LLOctreeNode<T> +template <class T, typename T_PTR> +class LLOctreeRoot : public LLOctreeNode<T, T_PTR>  {  public: -	typedef LLOctreeNode<T>	BaseType; -	typedef LLOctreeNode<T>	oct_node; +    typedef LLOctreeNode<T, T_PTR> BaseType; +    typedef LLOctreeNode<T, T_PTR> oct_node;  	LLOctreeRoot(const LLVector4a& center,   				 const LLVector4a& size,  @@ -768,7 +757,7 @@ public:  			oct_node* node = this->getNodeAt(data);  			if (node == this)  			{ -				LLOctreeNode<T>::insert(data); +                oct_node::insert(data);  			}  			else if (node->isInside(data->getPositionGroup()))  			{ @@ -788,13 +777,13 @@ public:  				LLVector4a center, size;  				center = this->getCenter();  				size = this->getSize(); -				LLOctreeNode<T>::pushCenter(center, size, data); +                oct_node::pushCenter(center, size, data);  				this->setCenter(center);  				size.mul(2.f);  				this->setSize(size);  				this->updateMinMax();  			} -			LLOctreeNode<T>::insert(data); +            oct_node::insert(data);  		}  		else  		{ @@ -806,7 +795,7 @@ public:  				//expand this node  				LLVector4a newcenter(center); -				LLOctreeNode<T>::pushCenter(newcenter, size, data); +                oct_node::pushCenter(newcenter, size, data);  				this->setCenter(newcenter);  				LLVector4a size2 = size;  				size2.mul(2.f); @@ -816,11 +805,11 @@ public:  				llassert(size[0] >= gOctreeMinSize);  				//copy our children to a new branch -				LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this); +                oct_node* newnode = new oct_node(center, size, this);  				for (U32 i = 0; i < this->getChildCount(); i++)  				{ -					LLOctreeNode<T>* child = this->getChild(i); +                    oct_node* child = this->getChild(i);  					newnode->addChild(child);  				} @@ -846,8 +835,8 @@ public:  //========================  //		LLOctreeTraveler  //======================== -template <class T> -void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node) +template <class T, typename T_PTR> +void LLOctreeTraveler<T, T_PTR>::traverse(const LLOctreeNode<T, T_PTR>* node)  {  	node->accept(this);  	for (U32 i = 0; i < node->getChildCount(); i++) @@ -856,8 +845,8 @@ void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node)  	}  } -template <class T> -void LLOctreeTravelerDepthFirst<T>::traverse(const LLOctreeNode<T>* node) +template <class T, typename T_PTR> +void LLOctreeTravelerDepthFirst<T, T_PTR>::traverse(const LLOctreeNode<T, T_PTR>* node)  {  	for (U32 i = 0; i < node->getChildCount(); i++)  	{ diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 762c0f74f3..f43d07ce5e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -371,7 +371,7 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons  	}  } -class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle> +class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle, LLVolumeTriangle*>  {  public:  	const LLVolumeFace* mFace; @@ -381,7 +381,7 @@ public:  		mFace = face;  	} -	virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) +    virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)  	{ //this is a depth first traversal, so it's safe to assum all children have complete  		//bounding data  	LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME @@ -399,8 +399,7 @@ public:  			min = *(tri->mV[0]);  			max = *(tri->mV[0]); -			for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter =  -				branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) +            for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter)  			{ //for each triangle in node  				//stretch by triangles in node @@ -2423,6 +2422,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			//copy out indices              S32 num_indices = idx.size() / 2; +            const S32 indices_to_discard = num_indices % 3; +            if (indices_to_discard > 0) +            { +                // Invalid number of triangle indices +                LL_WARNS() << "Incomplete triangle discarded from face! Indices count " << num_indices << " was not divisible by 3. face index: " << i << " Total: " << face_count << LL_ENDL; +                num_indices -= indices_to_discard; +            }              face.resizeIndices(num_indices);              if (num_indices > 2 && !face.mIndices) @@ -2438,8 +2444,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			}  			U16* indices = (U16*) &(idx[0]); -			U32 count = idx.size()/2; -			for (U32 j = 0; j < count; ++j) +            for (U32 j = 0; j < num_indices; ++j)  			{  				face.mIndices[j] = indices[j];  			} @@ -3831,8 +3836,8 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,  #if DEBUG_SILHOUETTE_EDGE_MAP  			//for each triangle -			U32 count = face.mNumIndices; -			for (U32 j = 0; j < count/3; j++) { +            U32 tri_count = face.mNumIndices / 3; +            for (U32 j = 0; j < tri_count; j++) {  				//get vertices  				S32 v1 = face.mIndices[j*3+0];  				S32 v2 = face.mIndices[j*3+1]; @@ -3850,7 +3855,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,  						continue;  					} -					if (nIndex >= (S32) count/3) { +                    if (nIndex >= (S32)tri_count) {  						continue;  					}  					//get neighbor vertices @@ -4142,13 +4147,13 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en  			}  			else  			{ -				if (!face.mOctree) +                if (!face.getOctree())  				{  					face.createOctree();  				}  				LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); -				intersect.traverse(face.mOctree); +                intersect.traverse(face.getOctree());  				if (intersect.mHitFace)  				{  					hit_face = i; @@ -4703,6 +4708,7 @@ LLVolumeFace::LLVolumeFace() :  #endif      mWeightsScrubbed(FALSE),  	mOctree(NULL), +    mOctreeTriangles(NULL),  	mOptimized(FALSE)  {  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); @@ -4732,8 +4738,9 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)      mJointIndices(NULL),  #endif      mWeightsScrubbed(FALSE), -	mOctree(NULL) -{  +    mOctree(NULL), +    mOctreeTriangles(NULL) +{  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);  	mCenter = mExtents+2;  	*this = src; @@ -4873,8 +4880,7 @@ void LLVolumeFace::freeData()  	mJustWeights = NULL;  #endif -	delete mOctree; -	mOctree = NULL; +    destroyOctree();  }  BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) @@ -4882,8 +4888,7 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)  	LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME  	//tree for this face is no longer valid -	delete mOctree; -	mOctree = NULL; +    destroyOctree();  	LL_CHECK_MEMORY  	BOOL ret = FALSE ; @@ -5596,21 +5601,27 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe  {  	LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME -	if (mOctree) +    if (getOctree())  	{  		return;  	} -	mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL); +    llassert(mNumIndices % 3 == 0); + +    mOctree = new LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, NULL);  	new LLVolumeOctreeListener(mOctree); +    const U32 num_triangles = mNumIndices / 3; +    // Initialize all the triangles we need +    mOctreeTriangles = new LLVolumeTriangle[num_triangles]; -	for (U32 i = 0; i < mNumIndices; i+= 3) +    for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index)  	{ //for each triangle -		LLPointer<LLVolumeTriangle> tri = new LLVolumeTriangle(); +        const U32 index = triangle_index * 3; +        LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; -		const LLVector4a& v0 = mPositions[mIndices[i]]; -		const LLVector4a& v1 = mPositions[mIndices[i+1]]; -		const LLVector4a& v2 = mPositions[mIndices[i+2]]; +		const LLVector4a& v0 = mPositions[mIndices[index]]; +		const LLVector4a& v1 = mPositions[mIndices[index + 1]]; +		const LLVector4a& v2 = mPositions[mIndices[index + 2]];  		//store pointers to vertex data  		tri->mV[0] = &v0; @@ -5618,9 +5629,9 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe  		tri->mV[2] = &v2;  		//store indices -		tri->mIndex[0] = mIndices[i]; -		tri->mIndex[1] = mIndices[i+1]; -		tri->mIndex[2] = mIndices[i+2]; +		tri->mIndex[0] = mIndices[index]; +		tri->mIndex[1] = mIndices[index + 1]; +		tri->mIndex[2] = mIndices[index + 2];  		//get minimum point  		LLVector4a min = v0; @@ -5663,6 +5674,19 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe  	}  } +void LLVolumeFace::destroyOctree() +{ +    delete mOctree; +    mOctree = NULL; +    delete[] mOctreeTriangles; +    mOctreeTriangles = NULL; +} + +const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* LLVolumeFace::getOctree() const +{ +    return mOctree; +} +  void LLVolumeFace::swapData(LLVolumeFace& rhs)  { @@ -6534,6 +6558,7 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts)  void LLVolumeFace::resizeIndices(S32 num_indices)  {  	ll_aligned_free_16(mIndices); +    llassert(num_indices % 3 == 0);  	if (num_indices)  	{ diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 9697952f5b..3ccaed47f1 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -35,7 +35,8 @@ class LLVolumeParams;  class LLProfile;  class LLPath; -template <class T> class LLOctreeNode; +template<class T> class LLPointer; +template <class T, typename T_PTR> class LLOctreeNode;  class LLVolumeFace;  class LLVolume; @@ -910,6 +911,9 @@ public:  	bool cacheOptimize();  	void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); +    void destroyOctree(); +    // Get a reference to the octree, which may be null +    const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* getOctree() const;  	enum  	{ @@ -977,13 +981,14 @@ public:      // Which joints are rigged to, and the bounding box of any rigged      // vertices per joint.      LLJointRiggingInfoTab mJointRiggingInfoTab; -     -	LLOctreeNode<LLVolumeTriangle>* mOctree;  	//whether or not face has been cache optimized  	BOOL mOptimized;  private: +    LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* mOctree; +    LLVolumeTriangle* mOctreeTriangles; +  	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);  	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);  	BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE); diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index fb232d5f6c..6894d04d3c 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -75,7 +75,7 @@ BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, c  } -LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node) +LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node)  {  	node->addListener(this);  } @@ -85,13 +85,12 @@ LLVolumeOctreeListener::~LLVolumeOctreeListener()  } -void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTriangle>* parent,  -	LLOctreeNode<LLVolumeTriangle>* child) +void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent,  +    LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child)  {  	new LLVolumeOctreeListener(child);  } -  LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,   							   const LLVolumeFace* face, F32* closest_t,  							   LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) @@ -108,7 +107,7 @@ LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& sta  	mEnd.setAdd(mStart, mDir);  } -void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>* node) +void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node)  {  	LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); @@ -122,9 +121,9 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>  	}  } -void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* node) +void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node)  { -	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter =  +    for (typename LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter =  			node->getDataBegin(); iter != node->getDataEnd(); ++iter)  	{  		const LLVolumeTriangle* tri = *iter; @@ -219,7 +218,7 @@ const F32& LLVolumeTriangle::getBinRadius() const  //TEST CODE -void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch) +void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)  {  	LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); @@ -256,7 +255,7 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch)  	}  	//children fit, check data -	for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin();  +    for (typename LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin();  			iter != branch->getDataEnd(); ++iter)  	{  		const LLVolumeTriangle* tri = *iter; @@ -273,4 +272,3 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch)  	}  } - diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index b2bc440368..d65bca5e52 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -77,11 +77,11 @@ public:  }; -class alignas(16) LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> +class alignas(16) LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle, LLVolumeTriangle*>  {      LL_ALIGN_NEW  public: -	LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node); +    LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node);  	~LLVolumeOctreeListener();  	LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) @@ -96,11 +96,9 @@ public:  	}  	 //LISTENER FUNCTIONS -	virtual void handleChildAddition(const LLOctreeNode<LLVolumeTriangle>* parent,  -		LLOctreeNode<LLVolumeTriangle>* child); +    virtual void handleChildAddition(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child);  	virtual void handleStateChange(const LLTreeNode<LLVolumeTriangle>* node) { } -	virtual void handleChildRemoval(const LLOctreeNode<LLVolumeTriangle>* parent,  -			const LLOctreeNode<LLVolumeTriangle>* child) {	} +    virtual void handleChildRemoval(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child) { }  	virtual void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { }  	virtual void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { }  	virtual void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) { } @@ -111,7 +109,7 @@ public:  	LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children  }; -class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle> +class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*>  {  public:  	const LLVolumeFace* mFace; @@ -129,14 +127,14 @@ public:  								   const LLVolumeFace* face, F32* closest_t,  								   LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); -	void traverse(const LLOctreeNode<LLVolumeTriangle>* node); +    void traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node); -	virtual void visit(const LLOctreeNode<LLVolumeTriangle>* node); +    virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node);  }; -class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle> +class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*>  { -	virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch); +    virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch);  };  #endif diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index 53aa35c0f9..6664eb02dc 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -311,8 +311,9 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)  std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  {  	s << "Flags: " << std::hex << data.mFlags; -	s << " Pattern: " << std::hex << (U32) data.mPattern << "\n"; -	s << "Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n"; +	s << "Pattern: " << std::hex << (U32) data.mPattern << "\n"; +	s << "Source Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n"; +    s << "Particle Age: " << data.mPartData.mMaxAge << "\n";  	s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";  	s << "Burst Rate: " << data.mBurstRate << "\n";  	s << "Burst Radius: " << data.mBurstRadius << "\n"; diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index d53064dde0..805af55299 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -379,6 +379,8 @@ void LLModel::setVolumeFaceData(  	U32 num_verts,   	U32 num_indices)  { +    llassert(num_indices % 3 == 0); +  	LLVolumeFace& face = mVolumeFaces[f];  	face.resizeVertices(num_verts); @@ -889,7 +891,6 @@ LLSD LLModel::writeModel(  LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)  { -	  	std::string::size_type cur_offset = 0;  	LLSD header; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 2b7ce155f6..193cfa64b8 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -743,6 +743,14 @@ bool LLGLManager::initGL()  		LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_multitexture" << LL_ENDL;  		return false;  	} + +    if (!mHasFramebufferObject) +    { +        mHasRequirements = FALSE; + +        LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_framebuffer_object" << LL_ENDL; +        return false; +    }  	stop_glerror(); @@ -758,12 +766,6 @@ bool LLGLManager::initGL()  	//HACK always disable texture multisample, use FXAA instead  	mHasTextureMultisample = FALSE; -#if LL_WINDOWS -	if (mIsIntel && mGLVersion <= 3.f) -	{ //never try to use framebuffer objects on older intel drivers (crashy) -		mHasFramebufferObject = FALSE; -	} -#endif  	if (mHasFramebufferObject)  	{ diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index b9dc689d1a..9dc140b5b9 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2447,7 +2447,7 @@ void LLImageGLThread::run()      // We must perform setup on this thread before actually servicing our      // WorkQueue, likewise cleanup afterwards.      mWindow->makeContextCurrent(mContext); -    gGL.init(); +    gGL.init(false);      ThreadPool::run();      gGL.shutdown();      mWindow->destroySharedContext(mContext); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a03a27cf94..72cca1f2a2 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -869,7 +869,7 @@ LLRender::~LLRender()  	shutdown();  } -void LLRender::init() +void LLRender::init(bool needs_vertex_buffer)  {  #if LL_WINDOWS      if (gGLManager.mHasDebugOutput && gDebugGL) @@ -897,15 +897,27 @@ void LLRender::init()  #endif  	} +    if (needs_vertex_buffer) +    { +        initVertexBuffer(); +    } +} -	llassert_always(mBuffer.isNull()) ; -	stop_glerror(); -	mBuffer = new LLVertexBuffer(immediate_mask, 0); -	mBuffer->allocateBuffer(4096, 0, TRUE); -	mBuffer->getVertexStrider(mVerticesp); -	mBuffer->getTexCoord0Strider(mTexcoordsp); -	mBuffer->getColorStrider(mColorsp); -	stop_glerror(); +void LLRender::initVertexBuffer() +{ +    llassert_always(mBuffer.isNull()); +    stop_glerror(); +    mBuffer = new LLVertexBuffer(immediate_mask, 0); +    mBuffer->allocateBuffer(4096, 0, TRUE); +    mBuffer->getVertexStrider(mVerticesp); +    mBuffer->getTexCoord0Strider(mTexcoordsp); +    mBuffer->getColorStrider(mColorsp); +    stop_glerror(); +} + +void LLRender::resetVertexBuffer() +{ +    mBuffer = NULL;  }  void LLRender::shutdown() @@ -923,7 +935,7 @@ void LLRender::shutdown()  		delete mLightState[i];  	}  	mLightState.clear(); -	mBuffer = NULL ; +    resetVertexBuffer();  }  void LLRender::refreshState(void) @@ -1625,25 +1637,34 @@ void LLRender::flush()  		mCount = 0; -		if (mBuffer->useVBOs() && !mBuffer->isLocked()) -		{ //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata) -			mBuffer->getVertexStrider(mVerticesp, 0, count); -			mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count); -			mBuffer->getColorStrider(mColorsp, 0, count); -		} -		 -		mBuffer->flush(); -		mBuffer->setBuffer(immediate_mask); +        if (mBuffer) +        { +            if (mBuffer->useVBOs() && !mBuffer->isLocked()) +            { //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata) +                mBuffer->getVertexStrider(mVerticesp, 0, count); +                mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count); +                mBuffer->getColorStrider(mColorsp, 0, count); +            } + +            mBuffer->flush(); +            mBuffer->setBuffer(immediate_mask); + +            if (mMode == LLRender::QUADS && sGLCoreProfile) +            { +                mBuffer->drawArrays(LLRender::TRIANGLES, 0, count); +                mQuadCycle = 1; +            } +            else +            { +                mBuffer->drawArrays(mMode, 0, count); +            } +        } +        else +        { +            // mBuffer is present in main thread and not present in an image thread +            LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL; +        } -		if (mMode == LLRender::QUADS && sGLCoreProfile) -		{ -			mBuffer->drawArrays(LLRender::TRIANGLES, 0, count); -			mQuadCycle = 1; -		} -		else -		{ -			mBuffer->drawArrays(mMode, 0, count); -		}  		mVerticesp[0] = mVerticesp[count];  		mTexcoordsp[0] = mTexcoordsp[count]; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index e2489876e4..9c36c230fb 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -354,7 +354,9 @@ public:  	LLRender();  	~LLRender(); -	void init() ; +    void init(bool needs_vertex_buffer); +    void initVertexBuffer(); +    void resetVertexBuffer();  	void shutdown();  	// Refreshes renderer state to the cached values diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 0408010513..fffc15efc3 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -133,7 +133,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo  	mUsage = usage;  	mUseDepth = depth; -	if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) +	if (sUseFBO || use_fbo)  	{  		if (depth)  		{ diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index c100c182dd..c64f46f38a 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -665,7 +665,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  	if (file == NULL)  	{ -		LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL; +		LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL;  		return 0;  	} diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 6338cab96a..be3e6ddff0 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1055,7 +1055,7 @@ void LLVertexBuffer::releaseIndices()  bool LLVertexBuffer::createGLBuffer(U32 size)  { -	if (mGLBuffer) +	if (mGLBuffer || mMappedData)  	{  		destroyGLBuffer();  	} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index baf8407fc6..3b3fe44984 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -265,7 +265,6 @@ public:  	bool getTangentStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getTangentStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); -	bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index dbab58c5de..ca08e38f77 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -169,5 +169,17 @@ endif (llwindow_HEADER_FILES)      ${viewer_SOURCE_FILES}      ) -target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) -target_include_directories( llwindow  INTERFACE   ${CMAKE_CURRENT_SOURCE_DIR}) +if (SDL_FOUND) +  set_property(TARGET llwindow +    PROPERTY COMPILE_DEFINITIONS LL_SDL=1 +    ) +endif (SDL_FOUND) + +  target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) +  target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +   +if (DARWIN) +  include(CMakeFindFrameworks) +  find_library(CARBON_LIBRARY Carbon) +  target_link_libraries(llwindow ${CARBON_LIBRARY}) +endif (DARWIN) diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 22a5462c7f..f7050bb588 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1713,6 +1713,10 @@ void LLSplashScreenMacOSX::showImpl()  void LLSplashScreenMacOSX::updateImpl(const std::string& mesg)  { +	if(mWindow != NULL) +	{ +		CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); +	}  } diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4c3aeb4695..c487877caf 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -874,21 +874,20 @@ void LLWindowWin32::close()  	// Restore gamma to the system values.  	restoreGamma(); -	if (mhDC) -	{ -		if (!ReleaseDC(mWindowHandle, mhDC)) -		{ -			LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL; -		} -		mhDC = NULL; -	} -  	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;      mWindowThread->post([=]()          {              if (IsWindow(mWindowHandle))              { +                if (mhDC) +                { +                    if (!ReleaseDC(mWindowHandle, mhDC)) +                    { +                        LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL; +                    } +                } +                  // Make sure we don't leave a blank toolbar button.                  ShowWindow(mWindowHandle, SW_HIDE); @@ -914,6 +913,7 @@ void LLWindowWin32::close()      // Even though the above lambda might not yet have run, we've already      // bound mWindowHandle into it by value, which should suffice for the      // operations we're asking. That's the last time WE should touch it. +    mhDC = NULL;      mWindowHandle = NULL;      mWindowThread->close();  } @@ -1506,12 +1506,10 @@ const	S32   max_format  = (S32)num_formats - 1;  			{  				wglDeleteContext (mhRC);							// Release The Rendering Context  				mhRC = 0;										// Zero The Rendering Context -  			} -			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context -			mhDC = 0;											// Zero The Device Context  		} +        // will release and recreate mhDC, mWindowHandle  		recreateWindow(window_rect, dw_ex_style, dw_style);          RECT rect; @@ -1661,7 +1659,8 @@ const	S32   max_format  = (S32)num_formats - 1;  void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style)  { -    auto oldHandle = mWindowHandle; +    auto oldWindowHandle = mWindowHandle; +    auto oldDCHandle = mhDC;      // zero out mWindowHandle and mhDC before destroying window so window      // thread falls back to peekmessage @@ -1673,7 +1672,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw      auto window_work =          [this,           self=mWindowThread, -         oldHandle, +         oldWindowHandle, +         oldDCHandle,           // bind CreateWindowEx() parameters by value instead of           // back-referencing LLWindowWin32 members           windowClassName=mWindowClassName, @@ -1689,11 +1689,20 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw              self->mWindowHandle = 0;              self->mhDC = 0; -            // important to call DestroyWindow() from the window thread -            if (oldHandle && !destroy_window_handler(oldHandle)) +            if (oldWindowHandle)              { -                LL_WARNS("Window") << "Failed to properly close window before recreating it!" -                                   << LL_ENDL; +                if (oldDCHandle && !ReleaseDC(oldWindowHandle, oldDCHandle)) +                { +                    LL_WARNS("Window") << "Failed to ReleaseDC" << LL_ENDL; +                } + +                // important to call DestroyWindow() from the window thread +                if (!destroy_window_handler(oldWindowHandle)) +                { + +                    LL_WARNS("Window") << "Failed to properly close window before recreating it!" +                        << LL_ENDL; +                }              }              auto handle = CreateWindowEx(dw_ex_style, @@ -1731,7 +1740,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw          };      // But how we pass window_work to the window thread depends on whether we      // already have a window handle. -    if (! oldHandle) +    if (!oldWindowHandle)      {          // Pass window_work using the WorkQueue: without an existing window          // handle, the window thread can't call GetMessage(). @@ -1744,7 +1753,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw          // PostMessage(oldHandle) because oldHandle won't be destroyed until          // the window thread has retrieved and executed window_work.          LL_DEBUGS("Window") << "posting window_work to message queue" << LL_ENDL; -        mWindowThread->Post(oldHandle, window_work); +        mWindowThread->Post(oldWindowHandle, window_work);      }      auto future = promise.get_future(); diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 5dbe61b99e..10abd6ae5b 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.5 +6.6.6 diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 55babc88bc..8d5349550f 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -85,7 +85,6 @@      <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>      <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> -    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>      <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>    </third_person> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b70b3f4ef7..6861153d43 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1360,7 +1360,7 @@        <key>Type</key>        <string>F32</string>        <key>Value</key> -      <real>20.0</real> +      <real>40.0</real>      </map>      <key>DiskCacheDirName</key>      <map> @@ -6808,6 +6808,9 @@        <key>Type</key>        <string>Boolean</string>        <key>Value</key> +      <!-- *HACK: On first run, set this to 0 for new users, +           otherwise the default is 1 to maintain consistent experience +           for existing users. Hardcoded in llnetmap.cpp -->        <integer>1</integer>      </map>      <key>MiniMapScale</key> @@ -6821,6 +6824,17 @@        <key>Value</key>        <real>128.0</real>      </map> +    <key>MiniMapShowPropertyLines</key> +    <map> +      <key>Comment</key> +      <string>Whether or not to show parcel borders on the MiniMap.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <real>1</real> +    </map>      <key>MouseSensitivity</key>      <map>        <key>Comment</key> @@ -7099,13 +7113,13 @@      <key>NonvisibleObjectsInMemoryTime</key>      <map>        <key>Comment</key> -      <string>Number of frames non-visible objects stay in memory before being removed. 0 means never to remove.</string> +      <string>Number of frames non-visible objects stay in memory before being removed. 0 means max.</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key>        <string>U32</string>        <key>Value</key> -			<integer>300</integer> +			<integer>64</integer>      </map>      <key>NoPreload</key>      <map> @@ -11022,7 +11036,7 @@        <key>Type</key>        <string>U32</string>        <key>Value</key> -      <integer>1024</integer> +      <integer>2048</integer>      </map>      <key>SceneLoadLowMemoryBound</key>      <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 02d83925ea..b26194f278 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -202,7 +202,7 @@ VARYING vec2 vary_texcoord2;  uniform float env_intensity;  uniform vec4 specular_color;  // specular color RGB and specular exponent (glossiness) in alpha -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) +#ifdef HAS_ALPHA_MASK  uniform float minimum_alpha;  #endif @@ -227,11 +227,12 @@ void main()      vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);  	diffcol.rgb *= vertex_color.rgb; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) - -    // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points -    float bias = 0.001953125; // 1/512, or half an 8-bit quantization -    if (diffcol.a < minimum_alpha-bias) +#ifdef HAS_ALPHA_MASK +#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND +    if (diffcol.a*vertex_color.a < minimum_alpha) +#else +    if (diffcol.a < minimum_alpha) +#endif      {          discard;      } diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 2241a12545..6cfc0b0be2 100644 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -2,15 +2,15 @@     <bone aliases="hip avatar_mPelvis" connected="false" end="0.000 0.000 0.084" group="Torso" name="mPelvis" pivot="0.000000 0.000000 1.067015" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">        <collision_volume end="0.030 0.000 0.095" group="Collision" name="PELVIS" pos="-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17" support="base"/>        <collision_volume end="-0.100 0.000 0.000" group="Collision" name="BUTT" pos="-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1" support="base"/> -      <bone connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> -         <bone connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> +      <bone aliases="avatar_mSpine1" connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> +         <bone aliases="avatar_mSpine2" connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">              <bone aliases="abdomen avatar_mTorso" connected="true" end="-0.015 0.000 0.205" group="Torso" name="mTorso" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">                 <collision_volume end="0.028 0.000 0.094" group="Collision" name="BELLY" pos="0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>                 <collision_volume end="0.000 0.100 0.000" group="Collision" name="LEFT_HANDLE" pos="0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>                 <collision_volume end="0.000 -0.100 0.000" group="Collision" name="RIGHT_HANDLE" pos="0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>                 <collision_volume end="-0.100 0.000 0.000" group="Collision" name="LOWER_BACK" pos="0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/> -               <bone connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> -                  <bone connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> +               <bone aliases="avatar_mSpine3" connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> +                  <bone aliases="avatar_mSpine4" connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">                       <bone aliases="chest avatar_mChest" connected="true" end="-0.010 0.000 0.250" group="Torso" name="mChest" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">                          <collision_volume end="-0.096 0.000 0.152" group="Collision" name="CHEST" pos="0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2" support="base"/>                          <collision_volume end="0.080 0.000 -0.006" group="Collision" name="LEFT_PEC" pos="0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/> @@ -23,58 +23,58 @@                                <bone aliases="figureHair avatar_mSkull" connected="false" end="0.000 0.000 0.033" group="Extra" name="mSkull" pivot="0.000000 0.000000 0.079000" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>                                <bone aliases="avatar_mEyeRight" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeRight" pivot="0.098466 -0.036000 0.079000" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" support="base"/>                                <bone aliases="avatar_mEyeLeft" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeLeft" pivot="0.098461 0.036000 0.079000" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/> -                              <bone connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> -                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                              <bone aliases="avatar_mFaceRoot" connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> +                                 <bone aliases="avatar_mFaceEyeAltRight" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyeAltLeft" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceForeheadLeft" connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceForeheadRight" connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowOuterLeft" connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowCenterLeft" connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowInnerLeft" connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowOuterRight" connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowCenterRight" connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyebrowInnerRight" connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyeLidUpperLeft" connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyeLidLowerLeft" connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyeLidUpperRight" connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyeLidLowerRight" connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEar1Left" connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mFaceEar2Left" connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                   </bone> -                                 <bone connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEar1Right" connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mFaceEar2Right" connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                   </bone> -                                 <bone connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                       <bone connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                       <bone connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                       <bone connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceNoseLeft" connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceNoseCenter" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceNoseRight" connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceCheekLowerLeft" connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceCheekUpperLeft" connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceCheekLowerRight" connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceCheekUpperRight" connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceJaw" connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mFaceChin" connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mFaceTeethLower" connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mFaceLipLowerLeft" connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                       <bone aliases="avatar_mFaceLipLowerRight" connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                       <bone aliases="avatar_mFaceLipLowerCenter" connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                       <bone aliases="avatar_mFaceTongueBase" connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mFaceTongueTip" connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone>                                   </bone> -                                 <bone connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceJawShaper" connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceForeheadCenter" connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceNoseBase" connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceTeethUpper" connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mFaceLipUpperLeft" connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mFaceLipUpperRight" connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mFaceLipCornerLeft" connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mFaceLipCornerRight" connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mFaceLipUpperCenter" connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                   </bone> -                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                 <bone connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyecornerInnerLeft" connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceEyecornerInnerRight" connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                 <bone aliases="avatar_mFaceNoseBridge" connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                </bone>                             </bone>                          </bone> @@ -86,29 +86,29 @@                                   <collision_volume end="0.000 0.100 -0.001" group="Collision" name="L_LOWER_ARM" pos="0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>                                   <bone aliases="lHand avatar_mWristLeft" connected="true" end="0.000 0.060 0.000" group="Arms" name="mWristLeft" pivot="-0.000000 0.204846 0.000000" pos="-0.000 0.205 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">                                      <collision_volume end="0.005 0.049 -0.001" group="Collision" name="L_HAND" pos="0.01 0.05 0.0" rot="-3.000000 0.00000 -10.000000" scale="0.05 0.08 0.03" support="base"/> -                                    <bone connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.001 0.049 -0.008" group="Hand" name="mHandMiddle2Left" pivot="-0.001 0.040 -0.006" pos="-0.001 0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.002 0.033 -0.006" group="Hand" name="mHandMiddle3Left" pivot="-0.001 0.049 -0.008" pos="-0.001 0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandMiddle1Left" connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandMiddle2Left" connected="true" end="-0.001 0.049 -0.008" group="Hand" name="mHandMiddle2Left" pivot="-0.001 0.040 -0.006" pos="-0.001 0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandMiddle3Left" connected="true" end="-0.002 0.033 -0.006" group="Hand" name="mHandMiddle3Left" pivot="-0.001 0.049 -0.008" pos="-0.001 0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="0.017 0.036 -0.006" group="Hand" name="mHandIndex1Left" pivot="0.038 0.097 0.015" pos="0.038 0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="0.014 0.032 -0.006" group="Hand" name="mHandIndex2Left" pivot="0.017 0.036 -0.006" pos="0.017 0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="0.011 0.025 -0.004" group="Hand" name="mHandIndex3Left" pivot="0.014 0.032 -0.006" pos="0.014 0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandIndex1Left" connected="false" end="0.017 0.036 -0.006" group="Hand" name="mHandIndex1Left" pivot="0.038 0.097 0.015" pos="0.038 0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandIndex2Left" connected="true" end="0.014 0.032 -0.006" group="Hand" name="mHandIndex2Left" pivot="0.017 0.036 -0.006" pos="0.017 0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandIndex3Left" connected="true" end="0.011 0.025 -0.004" group="Hand" name="mHandIndex3Left" pivot="0.014 0.032 -0.006" pos="0.014 0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="-0.013 0.038 -0.008" group="Hand" name="mHandRing1Left" pivot="-0.010 0.099 0.009" pos="-0.010 0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.013 0.040 -0.009" group="Hand" name="mHandRing2Left" pivot="-0.013 0.038 -0.008" pos="-0.013 0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.010 0.028 -0.006" group="Hand" name="mHandRing3Left" pivot="-0.013 0.040 -0.009" pos="-0.013 0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandRing1Left" connected="false" end="-0.013 0.038 -0.008" group="Hand" name="mHandRing1Left" pivot="-0.010 0.099 0.009" pos="-0.010 0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandRing2Left" connected="true" end="-0.013 0.040 -0.009" group="Hand" name="mHandRing2Left" pivot="-0.013 0.038 -0.008" pos="-0.013 0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandRing3Left" connected="true" end="-0.010 0.028 -0.006" group="Hand" name="mHandRing3Left" pivot="-0.013 0.040 -0.009" pos="-0.013 0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="-0.024 0.025 -0.006" group="Hand" name="mHandPinky1Left" pivot="-0.031 0.095 0.003" pos="-0.031 0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.015 0.018 -0.004" group="Hand" name="mHandPinky2Left" pivot="-0.024 0.025 -0.006" pos="-0.024 0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.013 0.016 -0.004" group="Hand" name="mHandPinky3Left" pivot="-0.015 0.018 -0.004" pos="-0.015 0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandPinky1Left" connected="false" end="-0.024 0.025 -0.006" group="Hand" name="mHandPinky1Left" pivot="-0.031 0.095 0.003" pos="-0.031 0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandPinky2Left" connected="true" end="-0.015 0.018 -0.004" group="Hand" name="mHandPinky2Left" pivot="-0.024 0.025 -0.006" pos="-0.024 0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandPinky3Left" connected="true" end="-0.013 0.016 -0.004" group="Hand" name="mHandPinky3Left" pivot="-0.015 0.018 -0.004" pos="-0.015 0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="0.028 0.032 0.000" group="Hand" name="mHandThumb1Left" pivot="0.031 0.026 0.004" pos="0.031 0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="0.023 0.031 0.000" group="Hand" name="mHandThumb2Left" pivot="0.028 0.032 -0.001" pos="0.028 0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="0.015 0.025 0.000" group="Hand" name="mHandThumb3Left" pivot="0.023 0.031 -0.001" pos="0.023 0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandThumb1Left" connected="false" end="0.028 0.032 0.000" group="Hand" name="mHandThumb1Left" pivot="0.031 0.026 0.004" pos="0.031 0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandThumb2Left" connected="true" end="0.023 0.031 0.000" group="Hand" name="mHandThumb2Left" pivot="0.028 0.032 -0.001" pos="0.028 0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandThumb3Left" connected="true" end="0.015 0.025 0.000" group="Hand" name="mHandThumb3Left" pivot="0.023 0.031 -0.001" pos="0.023 0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone>                                   </bone> @@ -123,49 +123,49 @@                                   <collision_volume end="0.000 -0.100 -0.001" group="Collision" name="R_LOWER_ARM" pos="0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>                                   <bone aliases="rHand avatar_mWristRight" connected="true" end="0.000 -0.060 0.000" group="Arms" name="mWristRight" pivot="-0.000000 -0.205000 -0.000000" pos="0.000 -0.205 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">                                      <collision_volume end="0.005 -0.049 -0.001" group="Collision" name="R_HAND" pos="0.01 -0.05 0.0" rot="3.000000 0.00000 10.000000" scale="0.05 0.08 0.03" support="base"/> -                                    <bone connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.001 -0.049 -0.008" group="Hand" name="mHandMiddle2Right" pivot="-0.001 -0.040 -0.006" pos="-0.001 -0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.002 -0.033 -0.006" group="Hand" name="mHandMiddle3Right" pivot="-0.001 -0.049 -0.008" pos="-0.001 -0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandMiddle1Right" connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandMiddle2Right" connected="true" end="-0.001 -0.049 -0.008" group="Hand" name="mHandMiddle2Right" pivot="-0.001 -0.040 -0.006" pos="-0.001 -0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandMiddle3Right" connected="true" end="-0.002 -0.033 -0.006" group="Hand" name="mHandMiddle3Right" pivot="-0.001 -0.049 -0.008" pos="-0.001 -0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="0.017 -0.036 -0.006" group="Hand" name="mHandIndex1Right" pivot="0.038 -0.097 0.015" pos="0.038 -0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="0.014 -0.032 -0.006" group="Hand" name="mHandIndex2Right" pivot="0.017 -0.036 -0.006" pos="0.017 -0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="0.011 -0.025 -0.004" group="Hand" name="mHandIndex3Right" pivot="0.014 -0.032 -0.006" pos="0.014 -0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandIndex1Right" connected="false" end="0.017 -0.036 -0.006" group="Hand" name="mHandIndex1Right" pivot="0.038 -0.097 0.015" pos="0.038 -0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandIndex2Right" connected="true" end="0.014 -0.032 -0.006" group="Hand" name="mHandIndex2Right" pivot="0.017 -0.036 -0.006" pos="0.017 -0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandIndex3Right" connected="true" end="0.011 -0.025 -0.004" group="Hand" name="mHandIndex3Right" pivot="0.014 -0.032 -0.006" pos="0.014 -0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="-0.013 -0.038 -0.008" group="Hand" name="mHandRing1Right" pivot="-0.010 -0.099 0.009" pos="-0.010 -0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.013 -0.040 -0.009" group="Hand" name="mHandRing2Right" pivot="-0.013 -0.038 -0.008" pos="-0.013 -0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.010 -0.028 -0.006" group="Hand" name="mHandRing3Right" pivot="-0.013 -0.040 -0.009" pos="-0.013 -0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandRing1Right" connected="false" end="-0.013 -0.038 -0.008" group="Hand" name="mHandRing1Right" pivot="-0.010 -0.099 0.009" pos="-0.010 -0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandRing2Right" connected="true" end="-0.013 -0.040 -0.009" group="Hand" name="mHandRing2Right" pivot="-0.013 -0.038 -0.008" pos="-0.013 -0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandRing3Right" connected="true" end="-0.010 -0.028 -0.006" group="Hand" name="mHandRing3Right" pivot="-0.013 -0.040 -0.009" pos="-0.013 -0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="-0.024 -0.025 -0.006" group="Hand" name="mHandPinky1Right" pivot="-0.031 -0.095 0.003" pos="-0.031 -0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="-0.015 -0.018 -0.004" group="Hand" name="mHandPinky2Right" pivot="-0.024 -0.025 -0.006" pos="-0.024 -0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="-0.013 -0.016 -0.004" group="Hand" name="mHandPinky3Right" pivot="-0.015 -0.018 -0.004" pos="-0.015 -0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandPinky1Right" connected="false" end="-0.024 -0.025 -0.006" group="Hand" name="mHandPinky1Right" pivot="-0.031 -0.095 0.003" pos="-0.031 -0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandPinky2Right" connected="true" end="-0.015 -0.018 -0.004" group="Hand" name="mHandPinky2Right" pivot="-0.024 -0.025 -0.006" pos="-0.024 -0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandPinky3Right" connected="true" end="-0.013 -0.016 -0.004" group="Hand" name="mHandPinky3Right" pivot="-0.015 -0.018 -0.004" pos="-0.015 -0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone> -                                    <bone connected="false" end="0.028 -0.032 0.000" group="Hand" name="mHandThumb1Right" pivot="0.031 -0.026 0.004" pos="0.031 -0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                       <bone connected="true" end="0.023 -0.031 0.000" group="Hand" name="mHandThumb2Right" pivot="0.028 -0.032 -0.001" pos="0.028 -0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                          <bone connected="true" end="0.015 -0.025 0.000" group="Hand" name="mHandThumb3Right" pivot="0.023 -0.031 -0.001" pos="0.023 -0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mHandThumb1Right" connected="false" end="0.028 -0.032 0.000" group="Hand" name="mHandThumb1Right" pivot="0.031 -0.026 0.004" pos="0.031 -0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                       <bone aliases="avatar_mHandThumb2Right" connected="true" end="0.023 -0.031 0.000" group="Hand" name="mHandThumb2Right" pivot="0.028 -0.032 -0.001" pos="0.028 -0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                          <bone aliases="avatar_mHandThumb3Right" connected="true" end="0.015 -0.025 0.000" group="Hand" name="mHandThumb3Right" pivot="0.023 -0.031 -0.001" pos="0.023 -0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                         </bone>                                      </bone>                                   </bone>                                </bone>                             </bone>                          </bone> -                        <bone connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                           <bone connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                              <bone connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                 <bone connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                        <bone aliases="avatar_mWingsRoot" connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                           <bone aliases="avatar_mWing1Left" connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                              <bone aliases="avatar_mWing2Left" connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                 <bone aliases="avatar_mWing3Left" connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mWing4Left" connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mWing4FanLeft" connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                   </bone>                                </bone>                             </bone> -                           <bone connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                              <bone connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                 <bone connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                                    <bone connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -                                    <bone connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                           <bone aliases="avatar_mWing1Right" connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                              <bone aliases="avatar_mWing2Right" connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                 <bone aliases="avatar_mWing3Right" connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                                    <bone aliases="avatar_mWing4Right" connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +                                    <bone aliases="avatar_mWing4FanRight" connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                                   </bone>                                </bone>                             </bone> @@ -200,30 +200,30 @@              </bone>           </bone>        </bone> -      <bone connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -         <bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -            <bone connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -               <bone connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                  <bone connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                     <bone connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +      <bone aliases="avatar_mTail1" connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +         <bone aliases="avatar_mTail2" connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +            <bone aliases="avatar_mTail3" connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +               <bone aliases="avatar_mTail4" connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                  <bone aliases="avatar_mTail5" connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                     <bone aliases="avatar_mTail6" connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                    </bone>                 </bone>              </bone>           </bone>        </bone> -      <bone connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> -      <bone connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -         <bone connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -            <bone connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -               <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                  <bone connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +      <bone aliases="avatar_mGroin" connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +      <bone aliases="avatar_mHindLimbsRoot" connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +         <bone aliases="avatar_mHindLimb1Left" connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +            <bone aliases="avatar_mHindLimb2Left" connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +               <bone aliases="avatar_mHindLimb3Left" connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                  <bone aliases="avatar_mHindLimb4Left" connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                 </bone>              </bone>           </bone> -         <bone connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -            <bone connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -               <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> -                  <bone connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> +         <bone aliases="avatar_mHindLimb1Right" connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +            <bone aliases="avatar_mHindLimb2Right" connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +               <bone aliases="avatar_mHindLimb3Right" connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> +                  <bone aliases="avatar_mHindLimb4Right" connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>                 </bone>              </bone>           </bone> diff --git a/indra/newview/cube.dae b/indra/newview/cube.dae new file mode 100644 index 0000000000..085b2c7309 --- /dev/null +++ b/indra/newview/cube.dae @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1"> + <asset> +  <contributor> +   modified from https://gist.github.com/wtsnz/bfa11c40e04594b260255b5dc7956f26 +  </contributor> +  <created>2018-10-25T16:29:03Z</created> +  <modified>2022-02-18T00:00:00Z</modified> +  <unit meter="1.000000"/> +  <up_axis>Y_UP</up_axis> + </asset> + + <library_materials> +  <material id="Blue" name="Blue"> +   <instance_effect url="#effect_Blue"/> +  </material> + </library_materials> + + + <library_effects> +  <effect id="effect_Blue"> +   <profile_COMMON> +    <technique sid="common"> +     <phong> +      <ambient> +       <color>0 0 0 1</color> +      </ambient> +      <diffuse> +       <color>0.137255 0.403922 0.870588 1</color> +      </diffuse> +      <specular> +       <color>0.5 0.5 0.5 1</color> +      </specular> +      <shininess> +       <float>16</float> +      </shininess> +      <transparent opaque="A_ONE"> +       <color>0 0 0 1</color> +      </transparent> +      <transparency> +       <float>1</float> +      </transparency> +      <index_of_refraction> +       <float>1</float> +      </index_of_refraction> +     </phong> +    </technique> +   </profile_COMMON> +  </effect> + </library_effects> + + + <library_geometries> +  <geometry id="F1" name="default_physics_shape"> +   <mesh> + +    <source id="cube-vertex-positions"> +     <float_array id="ID2-array" count="72">-0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 -0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 -0.5 0.5 -0.5 0.5 -0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 </float_array> +     <technique_common> +      <accessor source="#ID2-array" count="24" stride="3"> +       <param name="X" type="float"/> +       <param name="Y" type="float"/> +       <param name="Z" type="float"/> +      </accessor> +     </technique_common> +    </source> + +    <vertices id="cube-vertices"> +     <input semantic="POSITION" source="#cube-vertex-positions"/> +    </vertices> + +    <triangles count="12" material="geometryElement5"> +     <input semantic="VERTEX" offset="0" source="#cube-vertices"/> +     <p>0 1 2 0 2 3 4 5 6 4 6 7 8 9 10 8 10 11 12 13 14 12 14 15 16 17 18 16 18 19 20 21 22 20 22 23 </p> +    </triangles> +     +   </mesh> +  </geometry> + </library_geometries> + <library_visual_scenes> + + +  <visual_scene id="reportScene"> +  <!-- No Spaces allowed in Name --> +   <node id="F1" name="Face1"> +    <instance_geometry url="#F1"> +     <bind_material> +      <technique_common> +       <instance_material symbol="geometryElement5" target="#Blue"/> +      </technique_common> +     </bind_material> +    </instance_geometry> +   </node> +  </visual_scene> + </library_visual_scenes> + + + <scene> +  <instance_visual_scene url="#reportScene"/> + </scene> + + +</COLLADA> diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 7513908cb4..60e26274cb 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -351,11 +351,29 @@ DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp"  DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "NoStartPage"
  ClearErrors
 +INSTALL_FILES_START:
 +
  Call RemoveProgFilesOnInst		# Remove existing files to prevent certain errors when running the new version of the viewer
  # This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py
  %%INSTALL_FILES%%
 +IfErrors 0 INSTALL_FILES_DONE
 +  StrCmp $SKIP_DIALOGS "true" INSTALL_FILES_DONE
 +	MessageBox MB_ABORTRETRYIGNORE $(ErrorSecondLifeInstallRetry) IDABORT INSTALL_FILES_CANCEL IDRETRY INSTALL_FILES_START
 +    # MB_ABORTRETRYIGNORE does not accept IDIGNORE
 +    Goto INSTALL_FILES_DONE
 +
 +INSTALL_FILES_CANCEL:
 +  # We are quiting, cleanup.
 +  # Silence warnings from RemoveProgFilesOnInst.
 +  StrCpy $SKIP_DIALOGS "true"
 +  Call RemoveProgFilesOnInst
 +  MessageBox MB_OK $(ErrorSecondLifeInstallSupport)
 +  Quit
 +
 +INSTALL_FILES_DONE:
 +
  # Pass the installer's language to the client to use as a default
  StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
 @@ -622,7 +640,9 @@ Function RemoveProgFilesOnInst  Push $0
  StrCpy $0 0
 -PREINSTALLREMOVE:
 +ClearErrors
 +
 +PREINSTALL_REMOVE:
  # Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
  Delete "$INSTDIR\$INSTEXE"
 @@ -642,17 +662,17 @@ RMDir /r "$INSTDIR\llplugin"  IntOp $0 $0 + 1
 -IfErrors 0 PREINSTALLDONE
 -  IntCmp $0 1 PREINSTALLREMOVE #try again once
 -    StrCmp $SKIP_DIALOGS "true" PREINSTALLDONE
 -      MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALLFAIL IDRETRY PREINSTALLREMOVE
 +IfErrors 0 PREINSTALL_DONE
 +  IntCmp $0 1 PREINSTALL_REMOVE #try again once
 +    StrCmp $SKIP_DIALOGS "true" PREINSTALL_DONE
 +      MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALL_FAIL IDRETRY PREINSTALL_REMOVE
        # MB_ABORTRETRYIGNORE does not accept IDIGNORE
 -      Goto PREINSTALLDONE
 +      Goto PREINSTALL_DONE
 -PREINSTALLFAIL:
 +PREINSTALL_FAIL:
      Quit
 -PREINSTALLDONE:
 +PREINSTALL_DONE:
  # We are no longer including release notes with the viewer, so remove them.
  Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk"
 diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsiBinary files differ index 648ddbfb85..73f23086be 100644 --- a/indra/newview/installers/windows/lang_da.nsi +++ b/indra/newview/installers/windows/lang_da.nsi diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi index 188c30197a..7cc70e4c76 100755 --- a/indra/newview/installers/windows/lang_de.nsi +++ b/indra/newview/installers/windows/lang_de.nsi @@ -73,6 +73,10 @@ LangString CloseSecondLifeUnInstMB ${LANG_GERMAN} "Second Life kann nicht entfer  ; CheckNetworkConnection
  LangString CheckNetworkConnectionDP ${LANG_GERMAN} "Prüfe Netzwerkverbindung..."
 +; error during installation
 +LangString ErrorSecondLifeInstallRetry ${LANG_GERMAN} "Second Life konnte nicht korrekt installiert werden, einige Dateien wurden eventuell nicht korrekt von der Installationroutine kopiert."
 +LangString ErrorSecondLifeInstallSupport ${LANG_GERMAN} "Bitte laden Sie den Viewer erneut von https://secondlife.com/support/downloads/ und versuchen Sie die Installation erneut. Sollte das Problem weiterhin bestehen, dann kontaktieren Sie unseren Support unter https://support.secondlife.com."
 +
  ; ask to remove user's data files
  LangString RemoveDataFilesMB ${LANG_GERMAN} "Möchten Sie alle anderen zu Second Life gehörigen Dateien ebenfalls ENTFERNEN?$\n$\nWir empfehlen, die Einstellungen und Cache-Dateien zu behalten, wenn Sie andere Versionen von Second Life installiert haben oder eine Deinstallation durchführen, um Second Life auf eine neuere Version zu aktualisieren."
 diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsiBinary files differ index 0639d51e10..2eaf97d023 100644 --- a/indra/newview/installers/windows/lang_en-us.nsi +++ b/indra/newview/installers/windows/lang_en-us.nsi diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsiBinary files differ index ee30651a38..364cc9f67e 100755 --- a/indra/newview/installers/windows/lang_es.nsi +++ b/indra/newview/installers/windows/lang_es.nsi diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsiBinary files differ index 7cd90ec314..2f34c0c87a 100755 --- a/indra/newview/installers/windows/lang_fr.nsi +++ b/indra/newview/installers/windows/lang_fr.nsi diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsiBinary files differ index 194062da9a..51214d3a9c 100755 --- a/indra/newview/installers/windows/lang_it.nsi +++ b/indra/newview/installers/windows/lang_it.nsi diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsiBinary files differ index a54005ba14..296703d1a3 100755 --- a/indra/newview/installers/windows/lang_ja.nsi +++ b/indra/newview/installers/windows/lang_ja.nsi diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsiBinary files differ index 355d806866..299645bbb7 100644 --- a/indra/newview/installers/windows/lang_pl.nsi +++ b/indra/newview/installers/windows/lang_pl.nsi diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsiBinary files differ index 97f5d2b44a..542c8654b5 100755 --- a/indra/newview/installers/windows/lang_pt-br.nsi +++ b/indra/newview/installers/windows/lang_pt-br.nsi diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsiBinary files differ index 65a9f4846d..4e53a4957d 100755 --- a/indra/newview/installers/windows/lang_ru.nsi +++ b/indra/newview/installers/windows/lang_ru.nsi diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsiBinary files differ index e71886cc66..bae5029ad1 100755 --- a/indra/newview/installers/windows/lang_tr.nsi +++ b/indra/newview/installers/windows/lang_tr.nsi diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsiBinary files differ index f5f0c6cbdf..7922d9df52 100755 --- a/indra/newview/installers/windows/lang_zh.nsi +++ b/indra/newview/installers/windows/lang_zh.nsi diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 999f4a9f20..5250369813 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -96,6 +96,7 @@  #include "stringize.h"  #include "boost/foreach.hpp"  #include "llcorehttputil.h" +#include "lluiusage.h"  using namespace LLAvatarAppearanceDefines; @@ -574,6 +575,8 @@ void LLAgent::ageChat()  //-----------------------------------------------------------------------------  void LLAgent::moveAt(S32 direction, bool reset)  { +	LLUIUsage::instance().logCommand("Agent.MoveAt"); +	  	mMoveTimer.reset();  	LLFirstUse::notMoving(false); @@ -4026,6 +4029,7 @@ void LLAgent::startTeleportRequest()      }  	if (hasPendingTeleportRequest())  	{ +		LLUIUsage::instance().logCommand("Agent.StartTeleportRequest");          mTeleportCanceled.reset();  		if  (!isMaturityPreferenceSyncedWithServer())  		{ diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 39c9fa1bca..909f32cd21 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -60,6 +60,7 @@  #include "llappviewer.h"  #include "llcoros.h"  #include "lleventcoro.h" +#include "lluiusage.h"  #include "llavatarpropertiesprocessor.h" @@ -1426,6 +1427,9 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,                                          bool replace,                                          LLPointer<LLInventoryCallback> cb)  { +	LL_DEBUGS("UIUsage") << "wearItemsOnAvatar" << LL_ENDL; +	LLUIUsage::instance().logCommand("Avatar.WearItem"); +      bool first = true;      LLInventoryObject::const_object_list_t items_to_link; @@ -2761,6 +2765,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego  	LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName()  			 << "'" << LL_ENDL; +	LLUIUsage::instance().logCommand("Avatar.WearCategory");  	if (gAgentCamera.cameraCustomizeAvatar())  	{ @@ -3968,6 +3973,8 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo  {  	if (!isAgentAvatarValid()) return; +	LLUIUsage::instance().logCommand("Avatar.CreateNewOutfit"); +  	LL_DEBUGS("Avatar") << "creating new outfit" << LL_ENDL;  	gAgentWearables.notifyLoadingStarted(); @@ -4006,6 +4013,9 @@ void LLAppearanceMgr::wearBaseOutfit()  void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)  { +	LL_DEBUGS("UIUsage") << "removeItemsFromAvatar" << LL_ENDL; +	LLUIUsage::instance().logCommand("Avatar.RemoveItem"); +  	if (ids_to_remove.empty())  	{  		LL_WARNS() << "called with empty list, nothing to do" << LL_ENDL; @@ -4485,6 +4495,8 @@ public:  																			  "Quick Appearance");  			if ( gInventory.getCategory( folder_uuid ) != NULL )  			{ +				// Assume this is coming from the predefined avatars web floater +				LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance");  				LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);  				// *TODOw: This may not be necessary if initial outfit is chosen already -- josh diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e7cb17ddd9..a7f213a034 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -557,7 +557,7 @@ static void settings_to_globals()  	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");  	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); -	LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); +    LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));  #if LL_DARWIN  	gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); @@ -2487,10 +2487,24 @@ bool LLAppViewer::initConfiguration()  	//Load settings files list  	std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");  	LLXMLNodePtr root; -	BOOL success  = LLXMLNode::parseFile(settings_file_list, root, NULL); +	BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);  	if (!success)  	{ -        LL_ERRS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; +        LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; +        if (gDirUtilp->fileExists(settings_file_list)) +        { +            LL_ERRS() << "Cannot load default configuration file settings_files.xml. " +                << "Please reinstall viewer from https://secondlife.com/support/downloads/ " +                << "and contact https://support.secondlife.com if issue persists after reinstall." +                << LL_ENDL; +        } +        else +        { +            LL_ERRS() << "Default configuration file settings_files.xml not found. " +                << "Please reinstall viewer from https://secondlife.com/support/downloads/ " +                << "and contact https://support.secondlife.com if issue persists after reinstall." +                << LL_ENDL; +        }  	}  	mSettingsLocationList = new SettingsFiles(); @@ -3492,7 +3506,7 @@ void LLAppViewer::cleanupSavedSettings()  		}  	} -	gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale ); +    gSavedSettings.setF32("MapScale", LLWorldMapView::getScaleSetting());  	// Some things are cached in LLAgent.  	if (gAgent.isInitialized()) @@ -4291,12 +4305,17 @@ bool LLAppViewer::initCache()  	// initialize the new disk cache using saved settings  	const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName"); +	const U32 MB = 1024 * 1024; +    const uintmax_t MIN_CACHE_SIZE = 256 * MB; +	const uintmax_t MAX_CACHE_SIZE = 9984ll * MB; +    const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB; +    const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); +    const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal"); +    const F64 texture_cache_percent = 100.0 - disk_cache_percent; +      // note that the maximum size of this cache is defined as a percentage of the       // total cache size - the 'CacheSize' pref - for all caches.  -    const unsigned int cache_total_size_mb = gSavedSettings.getU32("CacheSize"); -    const double disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal"); -    const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100; -    const uintmax_t disk_cache_bytes = disk_cache_mb * 1024 * 1024; +    const uintmax_t disk_cache_size = uintmax_t(cache_total_size * disk_cache_percent / 100);  	const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");  	bool texture_cache_mismatch = false; @@ -4351,7 +4370,7 @@ bool LLAppViewer::initCache()  	}  	const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); -	LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); +    LLDiskCache::initParamSingleton(cache_dir, disk_cache_size, enable_cache_debug_info);  	if (!read_only)  	{ @@ -4386,22 +4405,14 @@ bool LLAppViewer::initCache()  	LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));  	// Init the texture cache -	// Allocate 80% of the cache size for textures -	const S32 MB = 1024 * 1024; -	const S64 MIN_CACHE_SIZE = 256 * MB; -	const S64 MAX_CACHE_SIZE = 9984ll * MB; - -	S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; -	cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); +    // Allocate the remaining percent which is not allocated to the disk cache +    const S64 texture_cache_size = S64(cache_total_size * texture_cache_percent / 100); -	S64 texture_cache_size = cache_size; - -	S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); -	texture_cache_size -= extra; +    LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);  	LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); -		return true; +    return true;  }  void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) @@ -5087,8 +5098,7 @@ void LLAppViewer::idle()  			audio_update_wind(false);  			// this line actually commits the changes we've made to source positions, etc. -			const F32 max_audio_decode_time = 0.002f; // 2 ms decode time -			gAudiop->idle(max_audio_decode_time); +			gAudiop->idle();  		}  	} diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 25ba7c365f..3e450e6dec 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -78,6 +78,7 @@  #include "llsidepanelinventory.h"  #include "llavatarname.h"  #include "llagentui.h" +#include "lluiusage.h"  // Flags for kick message  const U32 KICK_FLAGS_DEFAULT	= 0x0; @@ -113,7 +114,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin  	payload["id"] = id;  	payload["name"] = name; -    	LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); +	LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);  	// add friend to recent people list  	LLRecentPeople::instance().add(id); @@ -1418,6 +1419,8 @@ bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& respo  void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)  {  	const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); +	LLUIUsage::instance().logCommand("Agent.SendFriendRequest"); +  	send_improved_im(target_id,  					 target_name,  					 message, diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index fa7d5139ae..1ad2157df0 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -53,6 +53,7 @@  #include "llviewerobjectlist.h"  #include "llvoavatar.h"  #include "llavataractions.h" +#include "lluiusage.h"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs @@ -294,6 +295,8 @@ void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const  void LLAvatarTracker::terminateBuddy(const LLUUID& id)  {  	LL_DEBUGS() << "LLAvatarTracker::terminateBuddy()" << LL_ENDL; +	LLUIUsage::instance().logCommand("Agent.TerminateFriendship"); +  	LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id);  	if(!buddy) return;  	mBuddyInfo.erase(id); diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index e400609a74..72f667a0b8 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -568,8 +568,6 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL  	// how to chat  	gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE); -	LLUIUsage::instance().logCommand("Chat.Send"); // Pseudo-command -	  	// Look for "/20 foo" channel chats.  	S32 channel = 0;  	LLWString out_text = stripChannelNumber(wtext, &channel); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 80d810d159..036ff17074 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -290,9 +290,14 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )  									pickerp->getCurG (),   									pickerp->getCurB (),   									subject->mColor.mV[VALPHA] ); // keep current alpha -			subject->mColor = updatedColor; -			subject->setControlValue(updatedColor.getValue()); -			pickerp->setRevertOnCancel(TRUE); + +            bool color_changed = subject->mColor != updatedColor; +            if (color_changed) +            { +                subject->mColor = updatedColor; +                subject->setControlValue(updatedColor.getValue()); +            } +  			if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback)  			{  				subject->mOnCancelCallback( subject, LLSD()); @@ -306,6 +311,13 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )  				// just commit change  				subject->onCommit ();  			} + +            if (pick_op == COLOR_CANCEL || pick_op == COLOR_SELECT) +            { +                // both select and cancel close LLFloaterColorPicker +                // but COLOR_CHANGE does not +                subject->setFocus(TRUE); +            }  		}  	}  } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 2372ea01a6..2a0f4c93ac 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -133,6 +133,7 @@ public:  	inline LLFace*      getFace(const S32 i) const;  	inline S32			getNumFaces()      	 const;      face_list_t& getFaces() { return mFaces; } +    const face_list_t& getFaces() const { return mFaces; }  	//void                removeFace(const S32 i); // SJB: Avoid using this, it's slow  	LLFace*				addFace(LLFacePool *poolp, LLViewerTexture *texturep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index e674707c01..6c1abb24c9 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -58,6 +58,7 @@ static BOOL deferred_render = FALSE;  // minimum alpha before discarding a fragment  static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255 +  // minimum alpha before discarding a fragment when rendering impostors  static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f; @@ -147,6 +148,10 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)          (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;      prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) +    for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) +    { +        prepare_alpha_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], false, false); // note: bindDeferredShader will get called during render loop for materials +    }      // first pass, render rigged objects only and render to depth buffer      forwardRender(true); @@ -215,9 +220,15 @@ void LLDrawPoolAlpha::render(S32 pass)      {          minimum_alpha = MINIMUM_IMPOSTOR_ALPHA;      } +      prepare_forward_shader(fullbright_shader, minimum_alpha);      prepare_forward_shader(simple_shader, minimum_alpha); +    for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) +    { +        prepare_forward_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], minimum_alpha); +    } +      //first pass -- rigged only and drawn to depth buffer      forwardRender(true); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 63e7887d81..361a7666fa 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -125,7 +125,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth)  		llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight()));  	} -	if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD) +	if (gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD)  	{ //using offscreen render target, just use the bottom left corner  		mOrigin.set(0, 0);  	} @@ -212,7 +212,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()  		return TRUE;  	} -	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; +	bool use_fbo = gPipeline.mBake.isComplete() && !gGLManager.mIsAMD;  	if (use_fbo)  	{ diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index b76dc6a961..1300cf3658 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -2641,7 +2641,7 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F3      if (!water.isUndefined())      { -        environment->injectWaterSettings(sky, experience_id, LLSettingsBase::Seconds(transition_time)); +        environment->injectWaterSettings(water, experience_id, LLSettingsBase::Seconds(transition_time));      }      if (updateenvironment) diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4f2769a507..cdce6f7156 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -471,7 +471,25 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  			}  			// check if we are dragging an existing item from the favorites bar -			if (item && mDragItemId == item->getUUID()) +            bool existing_drop = false; +            if (item && mDragItemId == item->getUUID()) +            { +                // There is a chance of mDragItemId being obsolete +                // ex: can happen if something interrupts viewer, which +                // results in viewer not geting a 'mouse up' signal +                for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) +                { +                    LLViewerInventoryItem* currItem = *i; + +                    if (currItem->getUUID() == mDragItemId) +                    { +                        existing_drop = true; +                        break; +                    } +                } +            } + +            if (existing_drop)  			{  				*accept = ACCEPT_YES_SINGLE; @@ -500,6 +518,7 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  					if (mItems.empty())  					{  						setLandingTab(NULL); +                        mLastTab = NULL;  					}  					handleNewFavoriteDragAndDrop(item, favorites_id, x, y);  				} @@ -515,6 +534,12 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)  { +    if (mItems.empty()) +    { +        // Isn't supposed to be empty +        return; +    } +  	// Identify the button hovered and the side to drop  	LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);  	bool insert_before = true;	 @@ -787,6 +812,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)  	if(mItems.empty())  	{  		mBarLabel->setVisible(TRUE); +        mLastTab = NULL;  	}  	else  	{ @@ -833,6 +859,10 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)  					dynamic_cast<LLFavoriteLandmarkButton*> (*cur_it);  			if (button)  			{ +                if (mLastTab == button) +                { +                    mLastTab = NULL; +                }  				removeChild(button);  				delete button;  			} @@ -873,6 +903,17 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)  			mLastTab = last_new_button;  		} +        if (!mLastTab && mItems.size() > 0) +        { +            // mMoreTextBox was removed, so LLFavoriteLandmarkButtons +            // should be the only ones in the list +            LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (childs->back()); +            if (button) +            { +                mLastTab = button; +            } +        } +  		mFirstDropDownItem = j;  		// Chevron button  		if (mFirstDropDownItem < mItems.size()) diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 392633bd7d..ed3dc37043 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -294,7 +294,7 @@ BOOL LLFloaterBvhPreview::postBuild()  		loaderp->serialize(dp);  		dp.reset();  		LL_INFOS("BVH") << "Deserializing motionp" << LL_ENDL; -		BOOL success = motionp && motionp->deserialize(dp, mMotionID); +		BOOL success = motionp && motionp->deserialize(dp, mMotionID, false);  		LL_INFOS("BVH") << "Done" << LL_ENDL;  		delete []buffer; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 1a784223c2..ba91277c79 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -173,7 +173,6 @@ void LLFloaterColorPicker::showUI ()  	openFloater(getKey());  	setVisible ( TRUE );  	setFocus ( TRUE ); -	setRevertOnCancel(FALSE);  	// HACK: if system color picker is required - close the SL one we made and use default system dialog  	if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) ) @@ -185,15 +184,23 @@ void LLFloaterColorPicker::showUI ()  		// code that will get switched in for default system color picker  		if ( swatch )  		{ +            // Todo: this needs to be threaded for viewer not to timeout  			LLColor4 curCol = swatch->get ();  			send_agent_pause(); -			getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); +			bool commit = getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );  			send_agent_resume(); -			setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] ); -			setCurRgb( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] ); - -			LLColorSwatchCtrl::onColorChanged ( swatch, LLColorSwatchCtrl::COLOR_CHANGE ); +            if (commit) +            { +                setOrigRgb(curCol[0], curCol[1], curCol[2]); +                setCurRgb(curCol[0], curCol[1], curCol[2]); + +                LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_SELECT); +            } +            else +            { +                LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_CANCEL); +            }  		}  		closeFloater(); @@ -391,10 +398,7 @@ void LLFloaterColorPicker::onClickCancel ( void* data )  		if ( self )  		{ -		    if(self->getRevertOnCancel()) -		    { -		        self->cancelSelection (); -		    } +		    self->cancelSelection();  			self->closeFloater();  		}  	} diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index 16974a872e..39dbc5b763 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -104,9 +104,6 @@ class LLFloaterColorPicker  		void setMouseDownInSwatch (BOOL mouse_down_in_swatch);  		BOOL getMouseDownInSwatch () { return mMouseDownInSwatch; } -		void setRevertOnCancel (BOOL revertOnCancel) { mRevertOnCancel = revertOnCancel; }; -		BOOL getRevertOnCancel () { return mRevertOnCancel; } -  		BOOL isColorChanged ();  		// called when text entries (RGB/HSL etc.) are changed by user @@ -149,8 +146,6 @@ class LLFloaterColorPicker  		BOOL mMouseDownInHueRegion;  		BOOL mMouseDownInSwatch; -		BOOL mRevertOnCancel; -  		const S32 mRGBViewerImageLeft;  		const S32 mRGBViewerImageTop;  		const S32 mRGBViewerImageWidth; diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 6b1d9306fb..7def855d83 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -46,19 +46,60 @@  typedef std::pair<LLUUID, std::string> folder_pair_t; -class LLLandmarksInventoryObserver : public LLInventoryAddedObserver +class LLLandmarksInventoryObserver : public LLInventoryObserver  {  public:  	LLLandmarksInventoryObserver(LLFloaterCreateLandmark* create_landmark_floater) :  		mFloater(create_landmark_floater)  	{} +    void changed(U32 mask) override +    { +        if (mFloater->getItem()) +        { +            checkChanged(mask); +        } +        else +        { +            checkCreated(mask); +        } +    } +  protected: -	/*virtual*/ void done() +	void checkCreated(U32 mask)  	{ +        if (gInventory.getAddedIDs().empty()) +        { +            return; +        } + +        if (!(mask & LLInventoryObserver::ADD) || +            !(mask & LLInventoryObserver::CREATE) || +            !(mask & LLInventoryObserver::UPDATE_CREATE)) +        { +            return; +        } +  		mFloater->setItem(gInventory.getAddedIDs());  	} +    void checkChanged(U32 mask) +    { +        if (gInventory.getChangedIDs().empty()) +        { +            return; +        } + +        if ((mask & LLInventoryObserver::LABEL) || +            (mask & LLInventoryObserver::INTERNAL) || +            (mask & LLInventoryObserver::REMOVE) || +            (mask & LLInventoryObserver::STRUCTURE) || +            (mask & LLInventoryObserver::REBUILD)) +        { +            mFloater->updateItem(gInventory.getChangedIDs(), mask); +        } +    } +  private:  	LLFloaterCreateLandmark* mFloater;  }; @@ -85,6 +126,9 @@ BOOL LLFloaterCreateLandmark::postBuild()  	getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onSaveClicked, this));  	getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCancelClicked, this)); +    mLandmarkTitleEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTextChanges(); }); +    mNotesEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTextChanges(); }); +  	mLandmarksID = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);  	return TRUE; @@ -204,6 +248,33 @@ void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id)  	}  } +void LLFloaterCreateLandmark::onCommitTextChanges() +{ +    if (mItem.isNull()) +    { +        return; +    } +    std::string current_title_value = mLandmarkTitleEditor->getText(); +    std::string item_title_value = mItem->getName(); +    std::string current_notes_value = mNotesEditor->getText(); +    std::string item_notes_value = mItem->getDescription(); + +    LLStringUtil::trim(current_title_value); +    LLStringUtil::trim(current_notes_value); + +    if (!current_title_value.empty() && +        (item_title_value != current_title_value || item_notes_value != current_notes_value)) +    { +        LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem); +        new_item->rename(current_title_value); +        new_item->setDescription(current_notes_value); +        LLPointer<LLInventoryCallback> cb; +        LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0); +        gInventory.accountForUpdate(up); +        update_inventory_item(new_item, cb); +    } +} +  void LLFloaterCreateLandmark::onCreateFolderClicked()  {  	LLNotificationsUtil::add("CreateLandmarkFolder", LLSD(), LLSD(), @@ -278,6 +349,8 @@ void LLFloaterCreateLandmark::onSaveClicked()  		new_item->updateParentOnServer(FALSE);  	} +    removeObserver(); +  	gInventory.updateItem(new_item);  	gInventory.notifyObservers(); @@ -286,6 +359,7 @@ void LLFloaterCreateLandmark::onSaveClicked()  void LLFloaterCreateLandmark::onCancelClicked()  { +    removeObserver();  	if (!mItem.isNull())  	{  		LLUUID item_id = mItem->getUUID(); @@ -314,10 +388,59 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items)  		{  			if(!getItem())  			{ -				removeObserver();  				mItem = item; +                mAssetID = mItem->getAssetUUID(); +                setVisibleAndFrontmost(true);  				break;  			}  		}  	}  } + +void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask) +{ +    if (!getItem()) +    { +        return; +    } + +    LLUUID landmark_id = getItem()->getUUID(); + +    for (uuid_set_t::const_iterator item_iter = items.begin(); +        item_iter != items.end(); +        ++item_iter) +    { +        const LLUUID& item_id = (*item_iter); +        if (landmark_id == item_id) +        { +            if (getItem() != gInventory.getItem(item_id)) +            { +                // item is obsolete or removed +                closeFloater(); +            } + +            LLUUID folder_id = mFolderCombo->getValue().asUUID(); +            if (folder_id != mItem->getParentUUID()) +            { +                // user moved landmark in inventory, +                // assume that we are done all other changes should already be commited +                closeFloater(); +            } + +            if ((mask & LLInventoryObserver::INTERNAL) && mAssetID != mItem->getAssetUUID()) +            { +                closeFloater(); +            } + +            if (mask & LLInventoryObserver::LABEL) +            { +                mLandmarkTitleEditor->setText(mItem->getName()); +            } + +            if (mask & LLInventoryObserver::INTERNAL) +            { +                mNotesEditor->setText(mItem->getDescription()); +            } +        } +    } +} diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h index 74ac5e651c..d84f5ae1fc 100644 --- a/indra/newview/llfloatercreatelandmark.h +++ b/indra/newview/llfloatercreatelandmark.h @@ -49,6 +49,7 @@ public:  	void onOpen(const LLSD& key);  	void setItem(const uuid_set_t& items); +    void updateItem(const uuid_set_t& items, U32 mask);  	LLInventoryItem* getItem() { return mItem; } @@ -56,6 +57,7 @@ private:  	void setLandmarkInfo(const LLUUID &folder_id);  	void removeObserver();  	void populateFoldersList(const LLUUID &folder_id = LLUUID::null); +    void onCommitTextChanges();  	void onCreateFolderClicked();  	void onSaveClicked();  	void onCancelClicked(); @@ -66,6 +68,7 @@ private:  	LLLineEditor*	mLandmarkTitleEditor;  	LLTextEditor*	mNotesEditor;  	LLUUID			mLandmarksID; +    LLUUID			mAssetID;  	LLLandmarksInventoryObserver*	mInventoryObserver;  	LLPointer<LLInventoryItem>		mItem; diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 24673d5a7c..297ad24359 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -665,6 +665,7 @@ void LLFloaterEditExtDayCycle::onButtonApply(LLUICtrl *ctrl, const LLSD &data)      if (ctrl_action == ACTION_SAVE)      {          doApplyUpdateInventory(dayclone); +        clearDirtyFlag();      }      else if (ctrl_action == ACTION_SAVEAS)      { diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index fec218ca3b..aa9a2c164a 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -296,6 +296,7 @@ void LLFloaterFixedEnvironment::onButtonApply(LLUICtrl *ctrl, const LLSD &data)      if (ctrl_action == ACTION_SAVE)      {          doApplyUpdateInventory(setting_clone); +        clearDirtyFlag();      }      else if (ctrl_action == ACTION_SAVEAS)      { diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp index 42c5e40761..a00fc4aa84 100644 --- a/indra/newview/llfloaterhoverheight.cpp +++ b/indra/newview/llfloaterhoverheight.cpp @@ -100,11 +100,14 @@ void LLFloaterHoverHeight::onClose(bool app_quitting)  // static  void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData)  { -	LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); -	F32 value = sldrCtrl->getValueF32(); -	LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z)); -	LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL; -	gAgentAvatarp->setHoverOffset(offset, false); +    if (isAgentAvatarValid()) +    { +        LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); +        F32 value = sldrCtrl->getValueF32(); +        LLVector3 offset(0.0, 0.0, llclamp(value, MIN_HOVER_Z, MAX_HOVER_Z)); +        LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL; +        gAgentAvatarp->setHoverOffset(offset, false); +    }  }  // Do send-to-the-server work when slider drag completes, or new diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 3a850d4b68..4cceddeefb 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -698,7 +698,6 @@ void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, ECha  void LLFloaterIMNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)  { -	LLUIUsage::instance().logCommand("Chat.Send"); // pseuo-command  	// Look for "/20 foo" channel chats.  	S32 channel = 0;  	LLWString out_text = stripChannelNumber(wtext, &channel); @@ -858,6 +857,12 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32*  void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)  { +	LL_DEBUGS("UIUsage") << "Nearby chat, text " << utf8_out_text << " type " << type << " channel " << channel << LL_ENDL; +	if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) // prune back some redundant logging +	{ +		LLUIUsage::instance().logCommand("Chat.SendNearby"); // pseuo-command +	} +      LLMessageSystem* msg = gMessageSystem;      if (channel >= 0) diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index d78f80ad12..1a98ab9d76 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -3056,7 +3056,8 @@ BOOL LLPanelLandCovenant::postBuild()  {  	mLastRegionID = LLUUID::null;  	mNextUpdateTime = 0; - +    mTextEstateOwner = getChild<LLTextBox>("estate_owner_text"); +    mTextEstateOwner->setIsFriendCallback(LLAvatarActions::isFriend);  	return TRUE;  } @@ -3164,8 +3165,7 @@ void LLPanelLandCovenant::updateEstateOwnerName(const std::string& name)  	LLPanelLandCovenant* self = LLFloaterLand::getCurrentPanelLandCovenant();  	if (self)  	{ -		LLTextBox* editor = self->getChild<LLTextBox>("estate_owner_text"); -		if (editor) editor->setText(name); +		self->mTextEstateOwner->setText(name);  	}  } diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 5d9b411f04..684950d88b 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -413,6 +413,7 @@ protected:  private:  	LLUUID mLastRegionID;  	F64 mNextUpdateTime; //seconds since client start +    LLTextBox* mTextEstateOwner;  };  #endif diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index fc2da772f3..fd1af7ccc0 100644..100755 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -51,7 +51,7 @@  // The minor cardinal direction labels are hidden if their height is more  // than this proportion of the map. -const F32 MAP_MINOR_DIR_THRESHOLD = 0.07f; +const F32 MAP_MINOR_DIR_THRESHOLD = 0.035f;  //  // Member functions @@ -77,35 +77,44 @@ LLFloaterMap::~LLFloaterMap()  BOOL LLFloaterMap::postBuild()  { -	mMap = getChild<LLNetMap>("Net Map"); -	if (gSavedSettings.getBOOL("DoubleClickTeleport")) -	{ -		mMap->setToolTipMsg(getString("AltToolTipMsg")); -	} -	else if (gSavedSettings.getBOOL("DoubleClickShowWorldMap")) -	{ -		mMap->setToolTipMsg(getString("ToolTipMsg")); -	} -	sendChildToBack(mMap); -	 -	mTextBoxNorth = getChild<LLTextBox> ("floater_map_north"); -	mTextBoxEast = getChild<LLTextBox> ("floater_map_east"); -	mTextBoxWest = getChild<LLTextBox> ("floater_map_west"); -	mTextBoxSouth = getChild<LLTextBox> ("floater_map_south"); -	mTextBoxSouthEast = getChild<LLTextBox> ("floater_map_southeast"); -	mTextBoxNorthEast = getChild<LLTextBox> ("floater_map_northeast"); -	mTextBoxSouthWest = getChild<LLTextBox> ("floater_map_southwest"); -	mTextBoxNorthWest = getChild<LLTextBox> ("floater_map_northwest"); - -	updateMinorDirections(); - -	// Get the drag handle all the way in back -	sendChildToBack(getDragHandle()); - -	// keep onscreen -	gFloaterView->adjustToFitScreen(this, FALSE); - -	return TRUE; +    mMap = getChild<LLNetMap>("Net Map"); +    mMap->setToolTipMsg(getString("ToolTipMsg")); +    mMap->setParcelNameMsg(getString("ParcelNameMsg")); +    mMap->setParcelSalePriceMsg(getString("ParcelSalePriceMsg")); +    mMap->setParcelSaleAreaMsg(getString("ParcelSaleAreaMsg")); +    mMap->setParcelOwnerMsg(getString("ParcelOwnerMsg")); +    mMap->setRegionNameMsg(getString("RegionNameMsg")); +    mMap->setToolTipHintMsg(getString("ToolTipHintMsg")); +    mMap->setAltToolTipHintMsg(getString("AltToolTipHintMsg")); +    sendChildToBack(mMap); + +    mTextBoxNorth     = getChild<LLTextBox>("floater_map_north"); +    mTextBoxEast      = getChild<LLTextBox>("floater_map_east"); +    mTextBoxWest      = getChild<LLTextBox>("floater_map_west"); +    mTextBoxSouth     = getChild<LLTextBox>("floater_map_south"); +    mTextBoxSouthEast = getChild<LLTextBox>("floater_map_southeast"); +    mTextBoxNorthEast = getChild<LLTextBox>("floater_map_northeast"); +    mTextBoxSouthWest = getChild<LLTextBox>("floater_map_southwest"); +    mTextBoxNorthWest = getChild<LLTextBox>("floater_map_northwest"); + +    mTextBoxNorth->reshapeToFitText(); +    mTextBoxEast->reshapeToFitText(); +    mTextBoxWest->reshapeToFitText(); +    mTextBoxSouth->reshapeToFitText(); +    mTextBoxSouthEast->reshapeToFitText(); +    mTextBoxNorthEast->reshapeToFitText(); +    mTextBoxSouthWest->reshapeToFitText(); +    mTextBoxNorthWest->reshapeToFitText(); + +    updateMinorDirections(); + +    // Get the drag handle all the way in back +    sendChildToBack(getDragHandle()); + +    // keep onscreen +    gFloaterView->adjustToFitScreen(this, false); + +    return true;  }  BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -138,23 +147,44 @@ BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask)  	return TRUE;  } -void LLFloaterMap::setDirectionPos( LLTextBox* text_box, F32 rotation ) +void LLFloaterMap::setDirectionPos(LLTextBox *text_box, F32 rotation)  { -	// Rotation is in radians. -	// Rotation of 0 means x = 1, y = 0 on the unit circle. - -	F32 map_half_height = (F32)(getRect().getHeight() / 2) - getHeaderHeight()/2; -	F32 map_half_width = (F32)(getRect().getWidth() / 2) ; -	F32 text_half_height = (F32)(text_box->getRect().getHeight() / 2); -	F32 text_half_width = (F32)(text_box->getRect().getWidth() / 2); -	F32 radius = llmin( map_half_height - text_half_height, map_half_width - text_half_width ); - -	// Inset by a little to account for position display. -	radius -= 8.f; - -	text_box->setOrigin(  -		ll_round(map_half_width - text_half_width + radius * cos( rotation )), -		ll_round(map_half_height - text_half_height + radius * sin( rotation )) ); +    // Rotation is in radians. +    // Rotation of 0 means x = 1, y = 0 on the unit circle. + +    F32 map_half_height  = (F32) (getRect().getHeight() / 2) - (getHeaderHeight() / 2); +    F32 map_half_width   = (F32) (getRect().getWidth() / 2); +    F32 text_half_height = (F32) (text_box->getRect().getHeight() / 2); +    F32 text_half_width  = (F32) (text_box->getRect().getWidth() / 2); +    F32 extra_padding    = (F32) (mTextBoxNorth->getRect().getWidth() / 2); +    F32 pos_half_height  = map_half_height - text_half_height - extra_padding; +    F32 pos_half_width   = map_half_width - text_half_width - extra_padding; + +    F32 corner_angle               = atan2(pos_half_height, pos_half_width); +    F32 rotation_mirrored_into_top = abs(fmodf(rotation, F_PI)); +    if (rotation < 0) +    { +        rotation_mirrored_into_top = F_PI - rotation_mirrored_into_top; +    } +    F32  rotation_mirrored_into_top_right = (F_PI_BY_TWO - abs(rotation_mirrored_into_top - F_PI_BY_TWO)); +    bool at_left_right_edge               = rotation_mirrored_into_top_right < corner_angle; + +    F32 part_x = cos(rotation); +    F32 part_y = sin(rotation); +    F32 y; +    F32 x; +    if (at_left_right_edge) +    { +        x = std::copysign(pos_half_width, part_x); +        y = x * part_y / part_x; +    } +    else +    { +        y = std::copysign(pos_half_height, part_y); +        x = y * part_x / part_y; +    } + +    text_box->setOrigin(ll_round(map_half_width + x - text_half_width), ll_round(map_half_height + y - text_half_height));  }  void LLFloaterMap::updateMinorDirections() @@ -218,32 +248,6 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)  	updateMinorDirections();  } -void LLFloaterMap::handleZoom(const LLSD& userdata) -{ -	std::string level = userdata.asString(); -	 -	F32 scale = 0.0f; -	if (level == std::string("default")) -	{ -		LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale"); -		if(pvar) -		{ -			pvar->resetToDefault(); -			scale = gSavedSettings.getF32("MiniMapScale"); -		} -	} -	else if (level == std::string("close")) -		scale = LLNetMap::MAP_SCALE_MAX; -	else if (level == std::string("medium")) -		scale = LLNetMap::MAP_SCALE_MID; -	else if (level == std::string("far")) -		scale = LLNetMap::MAP_SCALE_MIN; -	if (scale != 0.0f) -	{ -		mMap->setScale(scale); -	} -} -  LLFloaterMap* LLFloaterMap::getInstance()  {  	return LLFloaterReg::getTypedInstance<LLFloaterMap>("mini_map"); diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h index ff2fb20535..929b1795aa 100644 --- a/indra/newview/llfloatermap.h +++ b/indra/newview/llfloatermap.h @@ -48,7 +48,6 @@ public:  	/*virtual*/ void	draw();  private: -	void handleZoom(const LLSD& userdata);  	void setDirectionPos( LLTextBox* text_box, F32 rotation );  	void updateMinorDirections(); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 90390de52a..66a245b779 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -467,22 +467,25 @@ void LLFloaterModelPreview::loadHighLodModel()  	loadModel(3);  } -void LLFloaterModelPreview::loadModel(S32 lod) +void LLFloaterModelPreview::prepareToLoadModel(S32 lod)  {  	mModelPreview->mLoading = true;  	if (lod == LLModel::LOD_PHYSICS)  	{  		// loading physics from file  		mModelPreview->mPhysicsSearchLOD = lod; +		mModelPreview->mWarnOfUnmatchedPhyicsMeshes = false;  	} - +} +void LLFloaterModelPreview::loadModel(S32 lod) +{ +	prepareToLoadModel(lod);  	(new LLMeshFilePicker(mModelPreview, lod))->getFile();  }  void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name, bool force_disable_slm)  { -	mModelPreview->mLoading = true; - +	prepareToLoadModel(lod);  	mModelPreview->loadModel(file_name, lod, force_disable_slm);  } @@ -1072,11 +1075,18 @@ void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)  	}  	S32 file_mode = iface->getItemCount() - 1; -	if (which_mode < file_mode) +	S32 cube_mode = file_mode - 1; +	if (which_mode < cube_mode)  	{  		S32 which_lod = num_lods - which_mode;  		sInstance->mModelPreview->setPhysicsFromLOD(which_lod);  	} +	else if (which_mode == cube_mode) +	{ +		std::string path = gDirUtilp->getAppRODataDir(); +		gDirUtilp->append(path, "cube.dae"); +		sInstance->loadModel(LLModel::LOD_PHYSICS, path); +	}  	LLModelPreview *model_preview = sInstance->mModelPreview;  	if (model_preview) @@ -1671,15 +1681,15 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL  void LLFloaterModelPreview::setCtrlLoadFromFile(S32 lod)  {      if (lod == LLModel::LOD_PHYSICS) -    { +	{          LLComboBox* lod_combo = findChild<LLComboBox>("physics_lod_combo");          if (lod_combo)          { -            lod_combo->setCurrentByIndex(5); +            lod_combo->setCurrentByIndex(lod_combo->getItemCount() - 1);          }      }      else -{ +	{          LLComboBox* lod_combo = findChild<LLComboBox>("lod_source_" + lod_name[lod]);          if (lod_combo)  	{ diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 1e147cd555..bda042186b 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -221,6 +221,7 @@ private:  	void resetUploadOptions();  	void clearLogTab(); +	void prepareToLoadModel(S32 lod);  	void createSmoothComboBox(LLComboBox* combo_box, float min, float max); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index dcd96d1f7d..273810e8d4 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1199,7 +1199,6 @@ void LLFloaterPreference::refreshEnabledState()  	BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&  						bumpshiny &&  						shaders &&  -						gGLManager.mHasFramebufferObject &&  						(ctrl_wind_light->get()) ? TRUE : FALSE;  	ctrl_deferred->setEnabled(enabled); @@ -1250,7 +1249,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()      BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&                          ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && -                        gGLManager.mHasFramebufferObject &&                          (ctrl_wind_light->get()) ? TRUE : FALSE;      ctrl_deferred->setEnabled(enabled); @@ -1384,8 +1382,7 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()  	}  	// disabled deferred -	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") || -		!gGLManager.mHasFramebufferObject) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"))  	{  		ctrl_shadows->setEnabled(FALSE);  		ctrl_shadows->setValue(0); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 65decbcd77..64f84cbe4f 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -47,6 +47,7 @@  #include "llagent.h"  #include "llappviewer.h" +#include "llavataractions.h"  #include "llavatarname.h"  #include "llfloateravatarpicker.h"  #include "llbutton.h"  @@ -1827,7 +1828,7 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)  	setCtrlsEnabled(god || owner || manager);  	getChildView("apply_btn")->setEnabled(FALSE); - +    getChildView("estate_owner")->setEnabled(TRUE);  	getChildView("message_estate_btn")->setEnabled(god || owner || manager);  	getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); @@ -1889,6 +1890,8 @@ BOOL LLPanelEstateInfo::postBuild()  	getChild<LLUICtrl>("externally_visible_radio")->setFocus(TRUE); +    getChild<LLTextBox>("estate_owner")->setIsFriendCallback(LLAvatarActions::isFriend); +  	return LLPanelRegionInfo::postBuild();  } @@ -2135,6 +2138,7 @@ BOOL LLPanelEstateCovenant::postBuild()  {  	mEstateNameText = getChild<LLTextBox>("estate_name_text");  	mEstateOwnerText = getChild<LLTextBox>("estate_owner_text"); +    mEstateOwnerText->setIsFriendCallback(LLAvatarActions::isFriend);  	mLastModifiedText = getChild<LLTextBox>("covenant_timestamp_text");  	mEditor = getChild<LLViewerTextEditor>("covenant_editor");  	LLButton* reset_button = getChild<LLButton>("reset_covenant"); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 977023cfe4..01bfae8934 100644..100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -82,7 +82,6 @@  //---------------------------------------------------------------------------  // Constants  //--------------------------------------------------------------------------- -static const F32 MAP_ZOOM_TIME = 0.2f;  // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed  // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across @@ -285,7 +284,7 @@ void* LLFloaterWorldMap::createWorldMapView(void* data)  BOOL LLFloaterWorldMap::postBuild()  { -	mPanel = getChild<LLPanel>("objects_mapview"); +    mMapView = dynamic_cast<LLWorldMapView*>(getChild<LLPanel>("objects_mapview"));  	LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");  	avatar_combo->selectFirstItem(); @@ -306,15 +305,13 @@ BOOL LLFloaterWorldMap::postBuild()  	landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );  	mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo); -	mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f); -	getChild<LLUICtrl>("zoom slider")->setValue(mCurZoomVal); - +    F32 slider_zoom = mMapView->getZoom(); +    getChild<LLUICtrl>("zoom slider")->setValue(slider_zoom); +          getChild<LLPanel>("expand_btn_panel")->setMouseDownCallback(boost::bind(&LLFloaterWorldMap::onExpandCollapseBtn, this));  	setDefaultBtn(NULL); -	mZoomTimer.stop(); -	  	onChangeMaturity();  	return TRUE; @@ -324,7 +321,7 @@ BOOL LLFloaterWorldMap::postBuild()  LLFloaterWorldMap::~LLFloaterWorldMap()  {  	// All cleaned up by LLView destructor -	mPanel = NULL; +    mMapView = NULL;  	// Inventory deletes all observers on shutdown  	mInventory = NULL; @@ -362,17 +359,15 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)  	mIsClosing = FALSE; -	LLWorldMapView* map_panel; -	map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; -	map_panel->clearLastClick(); +    mMapView->clearLastClick();  	{  		// reset pan on show, so it centers on you again  		if (!center_on_target)  		{ -			LLWorldMapView::setPan(0, 0, TRUE); +            mMapView->setPan(0, 0, true);  		} -		map_panel->updateVisibleBlocks(); +        mMapView->updateVisibleBlocks();  		// Reload items as they may have changed  		LLWorldMap::getInstance()->reloadItems(); @@ -420,18 +415,21 @@ BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)  BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)  { -	if (!isMinimized() && isFrontmost()) -	{ -		if(mPanel->pointInView(x, y)) -		{ -			F32 slider_value = (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(); -			slider_value += ((F32)clicks * -0.3333f); -			getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_value)); -			return TRUE; -		} -	} -	 -	return LLFloater::handleScrollWheel(x, y, clicks); +    if (!isMinimized() && isFrontmost()) +    { +        S32 map_x = x - mMapView->getRect().mLeft; +        S32 map_y = y - mMapView->getRect().mBottom; +        if (mMapView->pointInView(map_x, map_y)) +        { +            F32 old_slider_zoom = (F32) getChild<LLUICtrl>("zoom slider")->getValue().asReal(); +            F32 slider_zoom     = old_slider_zoom + ((F32) clicks * -0.3333f); +            getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_zoom)); +            mMapView->zoomWithPivot(slider_zoom, map_x, map_y); +            return true; +        } +    } + +    return LLFloater::handleScrollWheel(x, y, clicks);  } @@ -510,26 +508,13 @@ void LLFloaterWorldMap::draw()  	setMouseOpaque(TRUE);  	getDragHandle()->setMouseOpaque(TRUE); -	 -	//RN: snaps to zoom value because interpolation caused jitter in the text rendering -	if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal()) -	{ -		mZoomTimer.start(); -	} -	F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; -	if (interp > 1.f) -	{ -		interp = 1.f; -		mZoomTimer.stop(); -	} -	mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp); -	F32 map_scale = 256.f*pow(2.f, mCurZoomVal); -	LLWorldMapView::setScale( map_scale ); + +    mMapView->zoom((F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal());  	// Enable/disable checkboxes depending on the zoom level  	// If above threshold level (i.e. low res) -> Disable all checkboxes  	// If under threshold level (i.e. high res) -> Enable all checkboxes -	bool enable = LLWorldMapView::showRegionInfo(); +    bool enable = mMapView->showRegionInfo();  	getChildView("people_chk")->setEnabled(enable);  	getChildView("infohub_chk")->setEnabled(enable);  	getChildView("telehub_chk")->setEnabled(enable); @@ -1028,9 +1013,7 @@ void LLFloaterWorldMap::adjustZoomSliderBounds()  	S32 world_height_regions = MAX_VISIBLE_REGIONS;  	// Find how much space we have to display the world -	LLWorldMapView* map_panel; -	map_panel = (LLWorldMapView*)mPanel; -	LLRect view_rect = map_panel->getRect(); +    LLRect view_rect = mMapView->getRect();  	// View size in pixels  	S32 view_width = view_rect.getWidth(); @@ -1298,9 +1281,9 @@ void LLFloaterWorldMap::onShowTargetBtn()  void LLFloaterWorldMap::onShowAgentBtn()  { -	LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate -	// Set flag so user's location will be displayed if not tracking anything else -	mSetToUserPosition = TRUE;	 +    mMapView->setPanWithInterpTime(0, 0, false, 0.1f);  // false == animate +    // Set flag so user's location will be displayed if not tracking anything else +    mSetToUserPosition = true;  }  void LLFloaterWorldMap::onClickTeleportBtn() @@ -1368,9 +1351,10 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)  		pos_global.clearVec();  	} -	LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),  -						   -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), -						   !animate); +    F64 map_scale = (F64)mMapView->getScale(); +    mMapView->setPanWithInterpTime(-llfloor((F32)(pos_global.mdV[VX] * map_scale / REGION_WIDTH_METERS)), +                           -llfloor((F32)(pos_global.mdV[VY] * map_scale / REGION_WIDTH_METERS)), +                           !animate, 0.1f);  	mWaitingForTracker = FALSE;  } @@ -1600,7 +1584,7 @@ void LLFloaterWorldMap::onTeleportFinished()  {      if(isInVisibleChain())      { -        LLWorldMapView::setPan(0, 0, TRUE); +        mMapView->setPan(0, 0, TRUE);      }  } @@ -1675,9 +1659,8 @@ void LLFloaterWorldMap::onChangeMaturity()  void LLFloaterWorldMap::onFocusLost()  { -	gViewerWindow->showCursor(); -	LLWorldMapView* map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; -	map_panel->mPanning = FALSE; +    gViewerWindow->showCursor(); +    mMapView->mPanning = false;  }  LLPanelHideBeacon::LLPanelHideBeacon() : diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index fcb55e9666..3702226d23 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -44,6 +44,7 @@ class LLInventoryObserver;  class LLItemInfo;  class LLLineEditor;  class LLTabContainer; +class LLWorldMapView;  class LLFloaterWorldMap : public LLFloater  { @@ -156,11 +157,7 @@ protected:      void            onTeleportFinished();  private: -	LLPanel*			mPanel;		// Panel displaying the map - -	// Ties to LLWorldMapView::sMapScale, in pixels per region -	F32						mCurZoomVal; -	LLFrameTimer			mZoomTimer; +    LLWorldMapView* mMapView; // Panel displaying the map  	// update display of teleport destination coordinates - pos is in global coordinates  	void updateTeleportCoordsDisplay( const LLVector3d& pos ); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 7f65153879..a9e5e55451 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -53,6 +53,7 @@  #include "llviewerregion.h"  #include <boost/regex.hpp>  #include "llcorehttputil.h" +#include "lluiusage.h"  #if LL_MSVC @@ -1859,6 +1860,9 @@ void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)  //static  void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id)  { + +	LLUIUsage::instance().logCommand("Group.Join"); +  	LLMessageSystem *msg = gMessageSystem;  	msg->newMessageFast(_PREHASH_JoinGroupRequest); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 98c1d65f92..4d6ebf9cbb 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -69,7 +69,7 @@  #include "message.h"  #include "llviewerregion.h"  #include "llcorehttputil.h" - +#include "lluiusage.h"  const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -770,6 +770,23 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f  	message["index"] = (LLSD::Integer)mMsgs.size();   	message["is_history"] = is_history; +	LL_DEBUGS("UIUsage") << "addMessage " << " from " << from << " from_id " << from_id << " utf8_text " << utf8_text << " time " << time << " is_history " << is_history << " session mType " << mType << LL_ENDL; +	if (from_id == gAgent.getID()) +	{ +		if (mType == IM_SESSION_GROUP_START) +		{ +			LLUIUsage::instance().logCommand("Chat.SendGroup"); +		} +		else if (mType == IM_NOTHING_SPECIAL) +		{ +			LLUIUsage::instance().logCommand("Chat.SendIM"); +		} +		else +		{ +			LLUIUsage::instance().logCommand("Chat.SendOther"); +		} +	} +  	mMsgs.push_front(message);   	if (mSpeakers && from_id.notNull()) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f42c954185..a0bc1035bf 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3814,7 +3814,20 @@ void LLFolderBridge::perform_pasteFromClipboard()  				{  					if (item && can_move_to_landmarks(item))  					{ -						dropToFavorites(item); +                        if (LLClipboard::instance().isCutMode()) +                        { +                            LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); +                            llassert(viitem); +                            if (viitem) +                            { +                                //changeItemParent() implicity calls dirtyFilter +                                changeItemParent(model, viitem, parent_id, FALSE); +                            } +                        } +                        else +                        { +                            dropToFavorites(item); +                        }  					}  				}  				else if (LLClipboard::instance().isCutMode()) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b0859060ba..3ed75cb98e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -4587,7 +4587,6 @@ void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore:  	{  		gInventory.updateItem(*it);  	} -  	gInventory.notifyObservers();  	gViewerWindow->getWindow()->decBusyCount();  } diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp index bbbde0711f..a34dafb19a 100644 --- a/indra/newview/lllegacyatmospherics.cpp +++ b/indra/newview/lllegacyatmospherics.cpp @@ -482,8 +482,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in)  	{          LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();  		F32 depth = water_height - camera_height; -		 -		// get the water param manager variables  		LLColor4 water_fog_color(pwater->getWaterFogColor());  		// adjust the color based on depth.  We're doing linear approximations diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 14c039a0a2..a15a61429b 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2058,7 +2058,6 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_  		if (volume->unpackVolumeFaces(stream, data_size))  		{ -			//load volume faces into decomposition buffer  			d->mPhysicsShapeMesh.clear();  			std::vector<LLVector3>& pos = d->mPhysicsShapeMesh.mPositions; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index ae5dd6ec54..642df7f931 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -86,6 +86,7 @@ static const LLColor4 PREVIEW_DEG_FILL_COL(1.f, 0.f, 0.f, 0.5f);  static const F32 PREVIEW_DEG_EDGE_WIDTH(3.f);  static const F32 PREVIEW_DEG_POINT_SIZE(8.f);  static const F32 PREVIEW_ZOOM_LIMIT(10.f); +static const std::string DEFAULT_PHYSICS_MESH_NAME = "default_physics_shape";  const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f; @@ -432,6 +433,20 @@ void LLModelPreview::rebuildUploadData()                          LLFloaterModelPreview::addStringToLog(out, false);                      }                  } +                if (mWarnOfUnmatchedPhyicsMeshes && !lod_model && (i == LLModel::LOD_PHYSICS)) +                { +                    // Despite the various strategies above, if we don't now have a physics model, we're going to end up with decomposition. +                    // That's ok, but might not what they wanted. Use default_physics_shape if found. +                    std::ostringstream out; +                    out << "No physics model specified for " << instance.mLabel; +                    if (mDefaultPhysicsShapeP) +                    { +                        out << " - using: " << DEFAULT_PHYSICS_MESH_NAME; +                        lod_model = mDefaultPhysicsShapeP; +                    } +                    LL_WARNS() << out.str() << LL_ENDL; +                    LLFloaterModelPreview::addStringToLog(out, !mDefaultPhysicsShapeP); // Flash log tab if no default. +                }                  if (lod_model)                  { @@ -1034,6 +1049,13 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)          }          else          { +            if (loaded_lod == LLModel::LOD_PHYSICS) +            {   // Explicitly loading physics. See if there is a default mesh. +                LLMatrix4 ignored_transform; // Each mesh that uses this will supply their own. +                mDefaultPhysicsShapeP = nullptr; +                FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), mDefaultPhysicsShapeP, ignored_transform); +                mWarnOfUnmatchedPhyicsMeshes = true; +            }              BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");              if (!legacyMatching)              { @@ -1104,7 +1126,6 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)                                      LL_WARNS() << out.str() << LL_ENDL;                                      LLFloaterModelPreview::addStringToLog(out, false);                                  } -                                  mModel[loaded_lod][idx]->mLabel = name;                              }                          } @@ -2815,7 +2836,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)              mVertexBuffer[lod][mdl].push_back(vb);              ++mesh_count; -          }      }  } diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 7cb5fd6845..df7320768c 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -226,6 +226,21 @@ private:      static U32 countRootModels(LLModelLoader::model_list models);      LLVector3   mGroundPlane[4];  	void		renderGroundPlane(float z_offset = 0.0f); +    /// Indicates whether we should warn of high-lod meshes that do not have a corresponding physics mesh. +    /// Reset when resetting the modelpreview (i.e., when the uploader dialog is created or reset), and when +    /// about to process a physics file. Set to true immediately after the file is loaded (before rebuildUploadData()). +    /// +    /// (The rules for mapping the correspondence of high-lod meshes to physics meshes are complex. When +    /// lod rendering meshes are used, there is never an unmatched mesh. Nor is there a mismatch when +    /// the high-lod file and physics file have ony one mesh each. In these cases, this value is moot. +    /// When there are multiple meshes in each file, they are matched by name or order, and some meshes +    /// are broken up by limitations into multiple objects, and thus there can be mismatches.) +    bool mWarnOfUnmatchedPhyicsMeshes{false}; +    /// A mesh to use as the default physics shape in only those cases where the physics shape is not otherwise specified. +    /// It is set only when the user chooses a physics shape file that contains a mesh with a name that matches DEFAULT_PHYSICS_MESH_NAME. +    /// It is reset when such a name is not found, and when resetting the modelpreview. +    /// Not read unless mWarnOfUnmatchedPhyicsMeshes is true. +    LLModel* mDefaultPhysicsShapeP{};      typedef enum      { diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 2dd7cfab27..f5ee1171d9 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -451,9 +451,9 @@ void LLNavigationBar::onLocationSelection()  			if(value.has("AssetUUID"))  			{ -				  				gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString())); -				mSaveToLocationHistory = true; +                // user teleported by manually inputting inventory landmark's name +				mSaveToLocationHistory = false;  				return;  			}  			else diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 1240ce7c0f..b34be80b07 100644..100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -37,6 +37,7 @@  #include "llfocusmgr.h"  #include "lllocalcliprect.h"  #include "llrender.h" +#include "llresmgr.h"  #include "llui.h"  #include "lltooltip.h" @@ -47,11 +48,16 @@  #include "llagentcamera.h"  #include "llappviewer.h" // for gDisconnected  #include "llcallingcard.h" // LLAvatarTracker +#include "llfloaterland.h"  #include "llfloaterworldmap.h" +#include "llparcel.h"  #include "lltracker.h"  #include "llsurface.h" +#include "llurlmatch.h" +#include "llurlregistry.h"  #include "llviewercamera.h"  #include "llviewercontrol.h" +#include "llviewerparcelmgr.h"  #include "llviewertexture.h"  #include "llviewertexturelist.h"  #include "llviewermenu.h" @@ -64,7 +70,10 @@  static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map");  const F32 LLNetMap::MAP_SCALE_MIN = 32; -const F32 LLNetMap::MAP_SCALE_MID = 1024; +const F32 LLNetMap::MAP_SCALE_FAR = 32; +const F32 LLNetMap::MAP_SCALE_MEDIUM = 128; +const F32 LLNetMap::MAP_SCALE_CLOSE = 256; +const F32 LLNetMap::MAP_SCALE_VERY_CLOSE = 1024;  const F32 LLNetMap::MAP_SCALE_MAX = 4096;  const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%) @@ -78,13 +87,13 @@ const F64 COARSEUPDATE_MAX_Z = 1020.0f;  LLNetMap::LLNetMap (const Params & p)  :	LLUICtrl (p),  	mBackgroundColor (p.bg_color()), -	mScale( MAP_SCALE_MID ), -	mPixelsPerMeter( MAP_SCALE_MID / REGION_WIDTH_METERS ), +    mScale( MAP_SCALE_MEDIUM ), +    mPixelsPerMeter( MAP_SCALE_MEDIUM / REGION_WIDTH_METERS ),  	mObjectMapTPM(0.f),  	mObjectMapPixels(0.f), -	mTargetPan(0.f, 0.f),  	mCurPan(0.f, 0.f),  	mStartPan(0.f, 0.f), +    mPopupWorldPos(0.f, 0.f, 0.f),  	mMouseDown(0, 0),  	mPanning(false),  	mUpdateNow(false), @@ -97,6 +106,13 @@ LLNetMap::LLNetMap (const Params & p)  	mPopupMenu(NULL)  {  	mScale = gSavedSettings.getF32("MiniMapScale"); +    if (gAgent.isFirstLogin()) +    { +        // *HACK: On first run, set this to false for new users, otherwise the +        // default is true to maintain consistent experience for existing +        // users. +        gSavedSettings.setBOOL("MiniMapRotate", false); +    }  	mPixelsPerMeter = mScale / REGION_WIDTH_METERS;  	mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);  } @@ -107,13 +123,22 @@ LLNetMap::~LLNetMap()  BOOL LLNetMap::postBuild()  { -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	 -	registrar.add("Minimap.Zoom", boost::bind(&LLNetMap::handleZoom, this, _2)); -	registrar.add("Minimap.Tracker", boost::bind(&LLNetMap::handleStopTracking, this, _2)); - -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	return TRUE; +    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commitRegistrar; +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enableRegistrar; + +    enableRegistrar.add("Minimap.Zoom.Check", boost::bind(&LLNetMap::isZoomChecked, this, _2)); +    commitRegistrar.add("Minimap.Zoom.Set", boost::bind(&LLNetMap::setZoom, this, _2)); +    commitRegistrar.add("Minimap.Tracker", boost::bind(&LLNetMap::handleStopTracking, this, _2)); +    commitRegistrar.add("Minimap.Center.Activate", boost::bind(&LLNetMap::activateCenterMap, this, _2)); +    enableRegistrar.add("Minimap.MapOrientation.Check", boost::bind(&LLNetMap::isMapOrientationChecked, this, _2)); +    commitRegistrar.add("Minimap.MapOrientation.Set", boost::bind(&LLNetMap::setMapOrientation, this, _2)); +    commitRegistrar.add("Minimap.AboutLand", boost::bind(&LLNetMap::popupShowAboutLand, this, _2)); + +    mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, +                                                                          LLViewerMenuHolderGL::child_registry_t::instance()); +    mPopupMenu->setItemEnabled("Re-center map", false); + +    return true;  }  void LLNetMap::setScale( F32 scale ) @@ -158,18 +183,32 @@ void LLNetMap::draw()  	static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);  	//static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white);  	static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white); -	static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white); +	static LLUIColor map_parcel_outline_color = LLUIColorTable::instance().getColor("MapParcelOutlineColor", LLColor4(LLColor3(LLColor4::yellow), 0.5f));  	if (mObjectImagep.isNull())  	{  		createObjectImage();  	} -	static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); -	if (auto_center) +    static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); +    bool auto_centering = auto_center && !mPanning; +    mCentering = mCentering && !mPanning; + +    if (auto_centering || mCentering)  	{ -		mCurPan = lerp(mCurPan, mTargetPan, LLSmoothInterpolation::getInterpolant(0.1f)); +        mCurPan = lerp(mCurPan, LLVector2(0.0f, 0.0f) , LLSmoothInterpolation::getInterpolant(0.1f));  	} +    bool centered = abs(mCurPan.mV[VX]) < 0.5f && abs(mCurPan.mV[VY]) < 0.5f; +    if (centered) +    { +        mCurPan.mV[0] = 0.0f; +        mCurPan.mV[1] = 0.0f; +        mCentering = false; +    } + +    bool can_recenter_map = !(centered || mCentering || auto_centering); +    mPopupMenu->setItemEnabled("Re-center map", can_recenter_map); +    updateAboutLandPopupButton();  	// Prepare a scissor region  	F32 rotation = 0; @@ -216,7 +255,8 @@ void LLNetMap::draw()  		}  		// figure out where agent is -		S32 region_width = ll_round(LLWorld::getInstance()->getRegionWidthInMeters()); +		const S32 region_width = ll_round(LLWorld::getInstance()->getRegionWidthInMeters()); +        const F32 scale_pixels_per_meter = mScale / region_width;  		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();  			 iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -225,8 +265,8 @@ void LLNetMap::draw()  			// Find x and y position relative to camera's center.  			LLVector3 origin_agent = regionp->getOriginAgent();  			LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent(); -			F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale; -			F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale; +			F32 relative_x = rel_region_pos.mV[0] * scale_pixels_per_meter; +			F32 relative_y = rel_region_pos.mV[1] * scale_pixels_per_meter;  			// background region rectangle  			F32 bottom =	relative_y; @@ -249,6 +289,7 @@ void LLNetMap::draw()  			} +  			// Draw using texture.  			gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture());  			gGL.begin(LLRender::QUADS); @@ -310,8 +351,8 @@ void LLNetMap::draw()  		LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);  		LLVector3 camera_position = gAgentCamera.getCameraPositionAgent();  		map_center_agent -= camera_position; -		map_center_agent.mV[VX] *= mScale/region_width; -		map_center_agent.mV[VY] *= mScale/region_width; +		map_center_agent.mV[VX] *= scale_pixels_per_meter; +		map_center_agent.mV[VY] *= scale_pixels_per_meter;  		gGL.getTexUnit(0)->bind(mObjectImagep);  		F32 image_half_width = 0.5f*mObjectMapPixels; @@ -327,6 +368,13 @@ void LLNetMap::draw()  			gGL.texCoord2f(1.f, 1.f);  			gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]);  		gGL.end(); +         +		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); +			 iter != LLWorld::getInstance()->getRegionList().end(); ++iter) +		{ +			LLViewerRegion* regionp = *iter; +            regionp->renderPropertyLinesOnMinimap(scale_pixels_per_meter, map_parcel_outline_color.get().mV); +        }  		gGL.popMatrix(); @@ -451,41 +499,34 @@ void LLNetMap::draw()  		F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();  		F32 far_clip_meters = LLViewerCamera::getInstance()->getFar();  		F32 far_clip_pixels = far_clip_meters * meters_to_pixels; - -		F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); -		F32 half_width_pixels = half_width_meters * meters_to_pixels; -		F32 ctr_x = (F32)center_sw_left; -		F32 ctr_y = (F32)center_sw_bottom; - - -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - -		if( rotate_map ) -		{ -			gGL.color4fv((map_frustum_color()).mV); - -			gGL.begin( LLRender::TRIANGLES  ); -				gGL.vertex2f( ctr_x, ctr_y ); -				gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels ); -				gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels ); -			gGL.end(); -		} -		else -		{ -			gGL.color4fv((map_frustum_rotating_color()).mV); -			 -			// If we don't rotate the map, we have to rotate the frustum. -			gGL.pushMatrix(); -				gGL.translatef( ctr_x, ctr_y, 0 ); -				gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); -				gGL.begin( LLRender::TRIANGLES  ); -					gGL.vertex2f( 0, 0 ); -					gGL.vertex2f( -half_width_pixels, far_clip_pixels ); -					gGL.vertex2f(  half_width_pixels, far_clip_pixels ); -				gGL.end(); -			gGL.popMatrix(); -		} +        F32 ctr_x = (F32)center_sw_left; +        F32 ctr_y = (F32)center_sw_bottom; + +        const F32 steps_per_circle = 40.0f; +        const F32 steps_per_radian = steps_per_circle / F_TWO_PI; +        const F32 arc_start = -(horiz_fov / 2.0f) + F_PI_BY_TWO; +        const F32 arc_end = (horiz_fov / 2.0f) + F_PI_BY_TWO; +        const S32 steps = llmax(1, (S32)((horiz_fov * steps_per_radian) + 0.5f)); + +        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + +        if( rotate_map ) +        { +            gGL.pushMatrix(); +                gGL.translatef( ctr_x, ctr_y, 0 ); +                gl_washer_segment_2d(far_clip_pixels, 0, arc_start, arc_end, steps, map_frustum_color(), map_frustum_color()); +            gGL.popMatrix(); +        } +        else +        { +            gGL.pushMatrix(); +                gGL.translatef( ctr_x, ctr_y, 0 ); +                // If we don't rotate the map, we have to rotate the frustum. +                gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); +                gl_washer_segment_2d(far_clip_pixels, 0, arc_start, arc_end, steps, map_frustum_color(), map_frustum_color()); +            gGL.popMatrix(); +        }  	}  	gGL.popMatrix(); @@ -552,6 +593,65 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,  	}  } +bool LLNetMap::isMouseOnPopupMenu() +{ +    if (!mPopupMenu->isOpen()) +    { +        return false; +    } + +    S32 popup_x; +    S32 popup_y; +    LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y); +    // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain +    // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22 +    constexpr S32 tolerance = 10; +    // Test tolerance from all four corners, as the popup menu can appear from a different direction if there's not enough space. +    // Assume the size of the popup menu is much larger than the provided tolerance. +    // In practice, this is a [tolerance]px margin around the popup menu. +    for (S32 sign_x = -1; sign_x <= 1; sign_x += 2) +    { +        for (S32 sign_y = -1; sign_y <= 1; sign_y += 2) +        { +            if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) +            { +                return true; +            } +        } +    } +    return false; +} + +void LLNetMap::updateAboutLandPopupButton() +{ +    if (!mPopupMenu->isOpen()) +    { +        return; +    } + +    LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos); +    if (!region) +    { +        mPopupMenu->setItemEnabled("About Land", false); +    } +    else +    { +        // Check if the mouse is in the bounds of the popup. If so, it's safe to assume no other hover function will be called, so the hover +        // parcel can be used to check if location-sensitive tooltip options are available. +        if (isMouseOnPopupMenu()) +        { +            LLViewerParcelMgr::getInstance()->setHoverParcel(mPopupWorldPos); +            LLParcel *hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); +            bool      valid_parcel = false; +            if (hover_parcel) +            { +                valid_parcel = hover_parcel->getOwnerID().notNull(); +            } +            mPopupMenu->setItemEnabled("About Land", valid_parcel); +        } +    } +} +  LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )  {  	x -= ll_round(getRect().getWidth() / 2 + mCurPan.mV[VX]); @@ -579,66 +679,152 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )  BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)  { -	// note that clicks are reversed from what you'd think: i.e. > 0  means zoom out, < 0 means zoom in -	F32 new_scale = mScale * pow(MAP_SCALE_ZOOM_FACTOR, -clicks); +    // note that clicks are reversed from what you'd think: i.e. > 0  means zoom out, < 0 means zoom in +    F32 new_scale = mScale * pow(MAP_SCALE_ZOOM_FACTOR, -clicks);  	F32 old_scale = mScale; -	setScale(new_scale); +    setScale(new_scale); -	static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); -	if (!auto_center) -	{ -		// Adjust pan to center the zoom on the mouse pointer -		LLVector2 zoom_offset; -		zoom_offset.mV[VX] = x - getRect().getWidth() / 2; -		zoom_offset.mV[VY] = y - getRect().getHeight() / 2; -		mCurPan -= zoom_offset * mScale / old_scale - zoom_offset; -	} +    static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); +    if (!auto_center) +    { +        // Adjust pan to center the zoom on the mouse pointer +        LLVector2 zoom_offset; +        zoom_offset.mV[VX] = x - getRect().getWidth() / 2; +        zoom_offset.mV[VY] = y - getRect().getHeight() / 2; +        mCurPan -= zoom_offset * mScale / old_scale - zoom_offset; +    } -	return TRUE; +    return true;  } -BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleToolTip(S32 x, S32 y, MASK mask)  { -	if (gDisconnected) -	{ -		return FALSE; -	} +    if (gDisconnected) +    { +        return false; +    } -	// If the cursor is near an avatar on the minimap, a mini-inspector will be -	// shown for the avatar, instead of the normal map tooltip. -	if (handleToolTipAgent(mClosestAgentToCursor)) -	{ -		return TRUE; -	} +    // If the cursor is near an avatar on the minimap, a mini-inspector will be +    // shown for the avatar, instead of the normal map tooltip. +    if (handleToolTipAgent(mClosestAgentToCursor)) +    { +        return true; +    } -	LLRect sticky_rect; -	std::string region_name; -	LLViewerRegion*	region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) ); -	if(region) -	{ -		// set sticky_rect -		S32 SLOP = 4; -		localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect.mLeft), &(sticky_rect.mBottom)); -		sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; -		sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP; - -		region_name = region->getName(); -		if (!region_name.empty()) -		{ -			region_name += "\n"; -		} -	} +    // The popup menu uses the hover parcel when it is open and the mouse is on +    // top of it, with some additional tolerance. Returning early here prevents +    // fighting over that hover parcel when getting tooltip info in the +    // tolerance region. +    if (isMouseOnPopupMenu()) +    { +        return false; +    } -	LLStringUtil::format_map_t args; -	args["[REGION]"] = region_name; -	std::string msg = mToolTipMsg; -	LLStringUtil::format(msg, args); -	LLToolTipMgr::instance().show(LLToolTip::Params() -		.message(msg) -		.sticky_rect(sticky_rect)); -		 -	return TRUE; +    LLRect sticky_rect; +    S32 SLOP = 4; +    localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect.mLeft), &(sticky_rect.mBottom)); +    sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; +    sticky_rect.mTop   = sticky_rect.mBottom + 2 * SLOP; + +    std::string parcel_name_msg; +    std::string parcel_sale_price_msg; +    std::string parcel_sale_area_msg; +    std::string parcel_owner_msg; +    std::string region_name_msg; + +    LLVector3d      posGlobal = viewPosToGlobal(x, y); +    LLViewerRegion *region    = LLWorld::getInstance()->getRegionFromPosGlobal(posGlobal); +    if (region) +    { +        std::string region_name = region->getName(); +        if (!region_name.empty()) +        { +            region_name_msg = mRegionNameMsg; +            LLStringUtil::format(region_name_msg, {{"[REGION_NAME]", region_name}}); +        } + +        // Only show parcel information in the tooltip if property lines are visible. Otherwise, the parcel the tooltip is referring to is +        // ambiguous. +        if (gSavedSettings.getBOOL("MiniMapShowPropertyLines")) +        { +            LLViewerParcelMgr::getInstance()->setHoverParcel(posGlobal); +            LLParcel *hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); +            if (hover_parcel) +            { +                std::string parcel_name = hover_parcel->getName(); +                if (!parcel_name.empty()) +                { +                    parcel_name_msg = mParcelNameMsg; +                    LLStringUtil::format(parcel_name_msg, {{"[PARCEL_NAME]", parcel_name}}); +                } + +                const LLUUID      parcel_owner          = hover_parcel->getOwnerID(); +                std::string       parcel_owner_name_url = LLSLURL("agent", parcel_owner, "inspect").getSLURLString(); +                static LLUrlMatch parcel_owner_name_url_match; +                LLUrlRegistry::getInstance()->findUrl(parcel_owner_name_url, parcel_owner_name_url_match); +                if (!parcel_owner_name_url_match.empty()) +                { +                    parcel_owner_msg              = mParcelOwnerMsg; +                    std::string parcel_owner_name = parcel_owner_name_url_match.getLabel(); +                    LLStringUtil::format(parcel_owner_msg, {{"[PARCEL_OWNER]", parcel_owner_name}}); +                } + +                if (hover_parcel->getForSale()) +                { +                    const LLUUID auth_buyer_id = hover_parcel->getAuthorizedBuyerID(); +                    const LLUUID agent_id      = gAgent.getID(); +                    bool         show_for_sale = auth_buyer_id.isNull() || auth_buyer_id == agent_id || parcel_owner == agent_id; +                    if (show_for_sale) +                    { +                        S32 price        = hover_parcel->getSalePrice(); +                        S32 area         = hover_parcel->getArea(); +                        F32 cost_per_sqm = 0.0f; +                        if (area > 0) +                        { +                            cost_per_sqm = F32(price) / area; +                        } +                        std::string formatted_price          = LLResMgr::getInstance()->getMonetaryString(price); +                        std::string formatted_cost_per_meter = llformat("%.1f", cost_per_sqm); +                        parcel_sale_price_msg                = mParcelSalePriceMsg; +                        LLStringUtil::format(parcel_sale_price_msg, +                                             {{"[PRICE]", formatted_price}, {"[PRICE_PER_SQM]", formatted_cost_per_meter}}); +                        std::string formatted_area = llformat("%d", area); +                        parcel_sale_area_msg       = mParcelSaleAreaMsg; +                        LLStringUtil::format(parcel_sale_area_msg, {{"[AREA]", formatted_area}}); +                    } +                } +            } +        } +    } + +    std::string tool_tip_hint_msg; +    if (gSavedSettings.getBOOL("DoubleClickTeleport")) +    { +        tool_tip_hint_msg = mAltToolTipHintMsg; +    } +    else if (gSavedSettings.getBOOL("DoubleClickShowWorldMap")) +    { +        tool_tip_hint_msg = mToolTipHintMsg; +    } + +    LLStringUtil::format_map_t args; +    args["[PARCEL_NAME_MSG]"]       = parcel_name_msg.empty() ? "" : parcel_name_msg + '\n'; +    args["[PARCEL_SALE_PRICE_MSG]"] = parcel_sale_price_msg.empty() ? "" : parcel_sale_price_msg + '\n'; +    args["[PARCEL_SALE_AREA_MSG]"]  = parcel_sale_area_msg.empty() ? "" : parcel_sale_area_msg + '\n'; +    args["[PARCEL_OWNER_MSG]"]      = parcel_owner_msg.empty() ? "" : parcel_owner_msg + '\n'; +    args["[REGION_NAME_MSG]"]       = region_name_msg.empty() ? "" : region_name_msg + '\n'; +    args["[TOOL_TIP_HINT_MSG]"]     = tool_tip_hint_msg.empty() ? "" : tool_tip_hint_msg + '\n'; + +    std::string msg                 = mToolTipMsg; +    LLStringUtil::format(msg, args); +    if (msg.back() == '\n') +    { +        msg.resize(msg.size() - 1); +    } +    LLToolTipMgr::instance().show(LLToolTip::Params().message(msg).sticky_rect(sticky_rect)); + +    return true;  }  BOOL LLNetMap::handleToolTipAgent(const LLUUID& avatar_id) @@ -811,59 +997,58 @@ void LLNetMap::createObjectImage()  	mUpdateNow = true;  } -BOOL LLNetMap::handleMouseDown( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleMouseDown(S32 x, S32 y, MASK mask)  { -	if (!(mask & MASK_SHIFT)) return FALSE; - -	// Start panning -	gFocusMgr.setMouseCapture(this); +    // Start panning +    gFocusMgr.setMouseCapture(this); -	mStartPan = mCurPan; -	mMouseDown.mX = x; -	mMouseDown.mY = y; -	return TRUE; +    mStartPan     = mCurPan; +    mMouseDown.mX = x; +    mMouseDown.mY = y; +    return true;  } -BOOL LLNetMap::handleMouseUp( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleMouseUp(S32 x, S32 y, MASK mask)  { -	if(abs(mMouseDown.mX-x)<3 && abs(mMouseDown.mY-y)<3) -		handleClick(x,y,mask); +    if (abs(mMouseDown.mX - x) < 3 && abs(mMouseDown.mY - y) < 3) +    { +        handleClick(x, y, mask); +    } -	if (hasMouseCapture()) -	{ -		if (mPanning) -		{ -			// restore mouse cursor -			S32 local_x, local_y; -			local_x = mMouseDown.mX + llfloor(mCurPan.mV[VX] - mStartPan.mV[VX]); -			local_y = mMouseDown.mY + llfloor(mCurPan.mV[VY] - mStartPan.mV[VY]); -			LLRect clip_rect = getRect(); -			clip_rect.stretch(-8); -			clip_rect.clipPointToRect(mMouseDown.mX, mMouseDown.mY, local_x, local_y); -			LLUI::getInstance()->setMousePositionLocal(this, local_x, local_y); - -			// finish the pan -			mPanning = false; - -			mMouseDown.set(0, 0); - -			// auto centre -			mTargetPan.setZero(); -		} -		gViewerWindow->showCursor(); -		gFocusMgr.setMouseCapture(NULL); -		return TRUE; -	} -	return FALSE; +    if (hasMouseCapture()) +    { +        if (mPanning) +        { +            // restore mouse cursor +            S32 local_x, local_y; +            local_x          = mMouseDown.mX + llfloor(mCurPan.mV[VX] - mStartPan.mV[VX]); +            local_y          = mMouseDown.mY + llfloor(mCurPan.mV[VY] - mStartPan.mV[VY]); +            LLRect clip_rect = getRect(); +            clip_rect.stretch(-8); +            clip_rect.clipPointToRect(mMouseDown.mX, mMouseDown.mY, local_x, local_y); +            LLUI::getInstance()->setMousePositionLocal(this, local_x, local_y); + +            // finish the pan +            mPanning = false; + +            mMouseDown.set(0, 0); +        } +        gViewerWindow->showCursor(); +        gFocusMgr.setMouseCapture(NULL); +        return true; +    } + +    return false;  }  BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	if (mPopupMenu)  	{ +        mPopupWorldPos = viewPosToGlobal(x, y);  		mPopupMenu->buildDrawLabels();  		mPopupMenu->updateParent(LLMenuGL::sMenuContainer); -		mPopupMenu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); +		mPopupMenu->setItemEnabled("Stop tracking", LLTracker::isTracking(0));  		LLMenuGL::showPopup(this, mPopupMenu, x, y);  	}  	return TRUE; @@ -911,6 +1096,27 @@ BOOL LLNetMap::handleDoubleClick(S32 x, S32 y, MASK mask)  	return TRUE;  } +F32 LLNetMap::getScaleForName(std::string scale_name) +{ +    if (scale_name == "very close") +    { +        return LLNetMap::MAP_SCALE_VERY_CLOSE; +    } +    else if (scale_name == "close") +    { +        return LLNetMap::MAP_SCALE_CLOSE; +    } +    else if (scale_name == "medium") +    { +        return LLNetMap::MAP_SCALE_MEDIUM; +    } +    else if (scale_name == "far") +    { +        return LLNetMap::MAP_SCALE_FAR; +    } +    return 0.0f; +} +  // static  bool LLNetMap::outsideSlop( S32 x, S32 y, S32 start_x, S32 start_y, S32 slop )  { @@ -928,7 +1134,7 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask )  		{  			if (!mPanning)  			{ -				// just started panning, so hide cursor +                // Just started panning. Hide cursor.  				mPanning = true;  				gViewerWindow->hideCursor();  			} @@ -938,61 +1144,89 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask )  			// Set pan to value at start of drag + offset  			mCurPan += delta; -			mTargetPan = mCurPan;  			gViewerWindow->moveCursorToCenter();  		} - -		// Doesn't really matter, cursor should be hidden -		gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); -	} -	else -	{ -		if (mask & MASK_SHIFT) -		{ -			// If shift is held, change the cursor to hint that the map can be dragged -			gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); -		} -		else -		{ -			gViewerWindow->setCursor( UI_CURSOR_CROSS ); -		}  	} +    if (mask & MASK_SHIFT) +    { +        // If shift is held, change the cursor to hint that the map can be +        // dragged. However, holding shift is not required to drag the map. +        gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); +    } +    else +    { +        gViewerWindow->setCursor( UI_CURSOR_CROSS ); +    } +  	return TRUE;  } -void LLNetMap::handleZoom(const LLSD& userdata) +bool LLNetMap::isZoomChecked(const LLSD &userdata)  { -	std::string level = userdata.asString(); -	 -	F32 scale = 0.0f; -	if (level == std::string("default")) -	{ -		LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale"); -		if(pvar) -		{ -			pvar->resetToDefault(); -			scale = gSavedSettings.getF32("MiniMapScale"); -		} -	} -	else if (level == std::string("close")) -		scale = LLNetMap::MAP_SCALE_MAX; -	else if (level == std::string("medium")) -		scale = LLNetMap::MAP_SCALE_MID; -	else if (level == std::string("far")) -		scale = LLNetMap::MAP_SCALE_MIN; -	if (scale != 0.0f) -	{ -		setScale(scale); -	} +    std::string level = userdata.asString(); +    F32         scale = getScaleForName(level); +    return scale == mScale; +} + +void LLNetMap::setZoom(const LLSD &userdata) +{ +    std::string level = userdata.asString(); +    F32         scale = getScaleForName(level); +    if (scale != 0.0f) +    { +        setScale(scale); +    }  }  void LLNetMap::handleStopTracking (const LLSD& userdata)  {  	if (mPopupMenu)  	{ -		mPopupMenu->setItemEnabled ("Stop Tracking", false); +		mPopupMenu->setItemEnabled ("Stop tracking", false);  		LLTracker::stopTracking (LLTracker::isTracking(NULL));  	}  } + +void LLNetMap::activateCenterMap(const LLSD &userdata) { mCentering = true; } + +bool LLNetMap::isMapOrientationChecked(const LLSD &userdata) +{ +    const std::string command_name = userdata.asString(); +    const bool        rotate_map   = gSavedSettings.getBOOL("MiniMapRotate"); +    if (command_name == "north_at_top") +    { +        return !rotate_map; +    } + +    if (command_name == "camera_at_top") +    { +        return rotate_map; +    } + +    return false; +} + +void LLNetMap::setMapOrientation(const LLSD &userdata) +{ +    const std::string command_name = userdata.asString(); +    if (command_name == "north_at_top") +    { +        gSavedSettings.setBOOL("MiniMapRotate", false); +    } +    else if (command_name == "camera_at_top") +    { +        gSavedSettings.setBOOL("MiniMapRotate", true); +    } +} + +void LLNetMap::popupShowAboutLand(const LLSD &userdata) +{ +    // Update parcel selection. It's important to deselect land first so the "About Land" floater doesn't refresh with the old selection. +    LLViewerParcelMgr::getInstance()->deselectLand(); +    LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt(mPopupWorldPos); +    gMenuHolder->setParcelSelection(selection); + +    LLFloaterReg::showInstance("about_land", LLSD(), false); +} diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 1f7e7d68c6..fe1aca65a9 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -62,9 +62,12 @@ protected:  public:  	virtual ~LLNetMap(); -	static const F32 MAP_SCALE_MIN; -	static const F32 MAP_SCALE_MID; -	static const F32 MAP_SCALE_MAX; +    static const F32 MAP_SCALE_MIN; +    static const F32 MAP_SCALE_FAR; +    static const F32 MAP_SCALE_MEDIUM; +    static const F32 MAP_SCALE_CLOSE; +    static const F32 MAP_SCALE_VERY_CLOSE; +    static const F32 MAP_SCALE_MAX;  	/*virtual*/ void	draw();  	/*virtual*/ BOOL	handleScrollWheel(S32 x, S32 y, S32 clicks); @@ -79,8 +82,17 @@ public:  	/*virtual*/ BOOL	handleClick(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL	handleDoubleClick( S32 x, S32 y, MASK mask ); -	void			setScale( F32 scale ); -	void			setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; } +    void            setScale(F32 scale); + +    void            setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; } +    void            setParcelNameMsg(const std::string& msg) { mParcelNameMsg = msg; } +    void            setParcelSalePriceMsg(const std::string& msg) { mParcelSalePriceMsg = msg; } +    void            setParcelSaleAreaMsg(const std::string& msg) { mParcelSaleAreaMsg = msg; } +    void            setParcelOwnerMsg(const std::string& msg) { mParcelOwnerMsg = msg; } +    void            setRegionNameMsg(const std::string& msg) { mRegionNameMsg = msg; } +    void            setToolTipHintMsg(const std::string& msg) { mToolTipHintMsg = msg; } +    void            setAltToolTipHintMsg(const std::string& msg) { mAltToolTipHintMsg = msg; } +  	void			renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius );  private: @@ -94,11 +106,14 @@ private:  	void			drawTracking( const LLVector3d& pos_global,   								  const LLColor4& color,  								  BOOL draw_arrow = TRUE); +    bool            isMouseOnPopupMenu(); +    void            updateAboutLandPopupButton();  	BOOL			handleToolTipAgent(const LLUUID& avatar_id);  	static void		showAvatarInspector(const LLUUID& avatar_id);  	void			createObjectImage(); +    F32             getScaleForName(std::string scale_name);  	static bool		outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y, S32 slop);  private: @@ -112,11 +127,12 @@ private:  	F32				mObjectMapPixels;		// Width of object map in pixels  	F32				mDotRadius;				// Size of avatar markers -	bool			mPanning;			// map is being dragged -	LLVector2		mTargetPan; -	LLVector2		mCurPan; -	LLVector2		mStartPan;		// pan offset at start of drag -	LLCoordGL		mMouseDown;			// pointer position at start of drag +    bool            mPanning; // map is being dragged +    bool            mCentering; // map is being re-centered around the agent +    LLVector2       mCurPan; +    LLVector2       mStartPan; // pan offset at start of drag +    LLVector3d      mPopupWorldPos; // world position picked under mouse when context menu is opened +    LLCoordGL       mMouseDown; // pointer position at start of drag  	LLVector3d		mObjectImageCenterGlobal;  	LLPointer<LLImageRaw> mObjectRawImagep; @@ -125,14 +141,26 @@ private:  	LLUUID			mClosestAgentToCursor;  	LLUUID			mClosestAgentAtLastRightClick; -	std::string		mToolTipMsg; +    std::string     mToolTipMsg; +    std::string     mParcelNameMsg; +    std::string     mParcelSalePriceMsg; +    std::string     mParcelSaleAreaMsg; +    std::string     mParcelOwnerMsg; +    std::string     mRegionNameMsg; +    std::string     mToolTipHintMsg; +    std::string     mAltToolTipHintMsg;  public:  	void			setSelected(uuid_vec_t uuids) { gmSelected=uuids; };  private: -	void handleZoom(const LLSD& userdata); -	void handleStopTracking (const LLSD& userdata); +    bool isZoomChecked(const LLSD& userdata); +    void setZoom(const LLSD& userdata); +    void handleStopTracking(const LLSD& userdata); +    void activateCenterMap(const LLSD& userdata); +    bool isMapOrientationChecked(const LLSD& userdata); +    void setMapOrientation(const LLSD& userdata); +    void popupShowAboutLand(const LLSD& userdata);  	LLMenuGL*		mPopupMenu;  	uuid_vec_t		gmSelected; diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp index 5bfe5c9941..9603ee6329 100644 --- a/indra/newview/llphysicsshapebuilderutil.cpp +++ b/indra/newview/llphysicsshapebuilderutil.cpp @@ -29,7 +29,7 @@  #include "llphysicsshapebuilderutil.h"  /* static */ -void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut ) +void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut)  {  	const LLProfileParams& profile_params = volume_params.getProfileParams();  	const LLPathParams& path_params = volume_params.getPathParams(); @@ -191,6 +191,7 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara  	if ( volume_params.shouldForceConvex() )  	{ +        // Server distinguishes between convex of a prim vs isSculpt, but we don't care.  		specOut.mType = PhysicsShapeSpecification::USER_CONVEX;  	}	  	// Make a simpler convex shape if we can. @@ -199,6 +200,16 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara  	{  		specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX;  	} +    else if (volume_params.isMeshSculpt() && +             // Check overall dimensions, not individual triangles. +             (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || +              scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || +              scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE +              ) ) +    { +        // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't. +        specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; +    }  	else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy)  	{  		specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT; diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h index bd5b7d799c..b3b100296f 100644 --- a/indra/newview/llphysicsshapebuilderutil.h +++ b/indra/newview/llphysicsshapebuilderutil.h @@ -47,6 +47,7 @@ const F32 SHAPE_BUILDER_ENTRY_SNAP_SCALE_BIN_SIZE = 0.15f;  const F32 SHAPE_BUILDER_ENTRY_SNAP_PARAMETER_BIN_SIZE = 0.010f;  const F32 SHAPE_BUILDER_CONVEXIFICATION_SIZE = 2.f * COLLISION_TOLERANCE;  const F32 SHAPE_BUILDER_MIN_GEOMETRY_SIZE = 0.5f * COLLISION_TOLERANCE; +const F32 SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE = 0.5f;  class LLPhysicsVolumeParams : public LLVolumeParams  { diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 0d53950889..42cd1133a2 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1567,6 +1567,62 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)  	}  } +// return false if drawable is rigged and: +//  - a linked rigged drawable has a different spatial group +//  - a linked rigged drawable face has the wrong draw order index +bool check_rigged_group(LLDrawable* drawable) +{ +    if (drawable->isState(LLDrawable::RIGGED)) +    { +        LLSpatialGroup* group = drawable->getSpatialGroup(); +        LLDrawable* root = drawable->getRoot(); + +        if (root->isState(LLDrawable::RIGGED) && root->getSpatialGroup() != group) +        { +            llassert(false); +            return false; +        } + +        S32 last_draw_index = -1; +        if (root->isState(LLDrawable::RIGGED)) +        { +            for (auto& face : root->getFaces()) +            { +                if ((S32) face->getDrawOrderIndex() <= last_draw_index) +                { +                    llassert(false); +                    return false; +                } +                last_draw_index = face->getDrawOrderIndex(); +            } +        } + +        for (auto& child : root->getVObj()->getChildren()) +        { +            if (child->mDrawable->isState(LLDrawable::RIGGED)) +            { +                for (auto& face : child->mDrawable->getFaces()) +                { +                    if ((S32) face->getDrawOrderIndex() <= last_draw_index) +                    { +                        llassert(false); +                        return false; +                    } +                    last_draw_index = face->getDrawOrderIndex(); +                } +            } +             +            if (child->mDrawable->getSpatialGroup() != group) +            { +                llassert(false); +                return false; +            } +        } +    } + +    return true; +} +  void renderOctree(LLSpatialGroup* group)  {  	//render solid object bounding box, color @@ -1611,6 +1667,9 @@ void renderOctree(LLSpatialGroup* group)  				{  					continue;  				} + +                llassert(check_rigged_group(drawable)); +  				if (!group->getSpatialPartition()->isBridge())  				{  					gGL.pushMatrix(); @@ -3028,7 +3087,7 @@ public:  	} -	void visit(const LLOctreeNode<LLVolumeTriangle>* branch) +    void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)  	{  		LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); @@ -3070,7 +3129,7 @@ public:  			}  			gGL.begin(LLRender::TRIANGLES); -			for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); +            for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin();  					iter != branch->getDataEnd();  					++iter)  			{ @@ -3164,14 +3223,14 @@ void renderRaycast(LLDrawable* drawablep)  					{  						F32 t = 1.f; -						if (!face.mOctree) +                        if (!face.getOctree())  						{  							((LLVolumeFace*) &face)->createOctree();   						}  						LLRenderOctreeRaycast render(start, dir, &t); -						render.traverse(face.mOctree); +                        render.traverse(face.getOctree());  					}  					gGL.popMatrix();		 @@ -3787,7 +3846,7 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v)  }  LL_ALIGN_PREFIX(16) -class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry> +class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>>  {  public:  	LL_ALIGN_16(LLVector4a mStart); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6d3ef33801..f7bc9fb644 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -264,7 +264,7 @@ public:                  return lhs->mAvatarp < rhs->mAvatarp;              } -            return lhs->mRenderOrder > rhs->mRenderOrder; +            return lhs->mRenderOrder < rhs->mRenderOrder;          }      }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 43e808f8aa..054e9530d4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -662,7 +662,7 @@ bool idle_startup()  #else  				void* window_handle = NULL;  #endif -				bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle, LLAppViewer::instance()->getSecondLifeTitle()); +				bool init = gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle());  				if(init)  				{  					gAudiop->setMuted(TRUE); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d4fc6f3de2..9403e73b87 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1042,7 +1042,8 @@ void LLTextureCache::setReadOnly(BOOL read_only)  	mReadOnly = read_only ;  } -//called in the main thread. +// Called in the main thread. +// Returns the unused amount of max_size if any  S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache_mismatch)  {  	llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index f76a2f7f90..b16b26b96e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -60,6 +60,7 @@  #include "llvoavatarself.h"  #include "llworld.h"  #include "llpanelface.h" +#include "lluiusage.h"  // syntactic sugar  #define callMemberFunction(object,ptrToMember)  ((object).*(ptrToMember)) @@ -1305,10 +1306,12 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,  	LLMessageSystem* msg = gMessageSystem;  	if (mSource == SOURCE_NOTECARD)  	{ +		LLUIUsage::instance().logCommand("Object.RezObjectFromNotecard");  		msg->newMessageFast(_PREHASH_RezObjectFromNotecard);  	}  	else  	{ +		LLUIUsage::instance().logCommand("Object.RezObject");  		msg->newMessageFast(_PREHASH_RezObject);  	}  	msg->nextBlockFast(_PREHASH_AgentData); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 43deac60d9..5fb83bf08e 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -71,6 +71,7 @@  #include "llui.h"  #include "llweb.h"  #include "pipeline.h"	// setHighlightObject +#include "lluiusage.h"  extern BOOL gDebugClicks; @@ -568,6 +569,8 @@ bool LLToolPie::walkToClickedLocation()          return false;      } +	LLUIUsage::instance().logCommand("Agent.WalkToClickedLocation"); +	      LLPickInfo saved_pick = mPick;      if (gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)      { diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 814bade56a..7cdd7cc5c8 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -62,6 +62,7 @@  #include "llprimitive.h"  #include "llwindow.h"			// incBusyCount()  #include "material_codes.h" +#include "lluiusage.h"  const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f); @@ -227,6 +228,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )  							   gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);  	} +	LLUIUsage::instance().logCommand("Build.ObjectAdd");  	gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);  	gMessageSystem->nextBlockFast(_PREHASH_AgentData);  	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 3f7e8531fb..14fae8d035 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -50,6 +50,10 @@  #include "llpreviewnotecard.h"  #include "llpreviewgesture.h"  #include "llcoproceduremanager.h" +#include "llthread.h" +#include "llkeyframemotion.h" +#include "lldatapacker.h" +#include "llvoavatarself.h"  void dialog_refresh_all(); @@ -450,9 +454,62 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()          errorLabel = "DoNotSupportBulkAnimationUpload";          error = true;      } -    else if (assetType == LLAssetType::AT_ANIMATION) +    else if (exten == "anim") +    { +		// Default unless everything succeeds +		errorLabel = "ProblemWithFile"; +		error = true; + +        // read from getFileName() +		LLAPRFile infile; +		infile.open(getFileName(),LL_APR_RB); +		if (!infile.getFileHandle()) +		{ +			LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL; +			errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str()); +		} +		else +		{ +			S32 size = LLAPRFile::size(getFileName()); +			U8* buffer = new U8[size]; +			S32 size_read = infile.read(buffer,size); +			if (size_read != size) +			{ +				errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read); +			} +			else +			{ +				LLDataPackerBinaryBuffer dp(buffer, size); +				LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId()); +				motionp->setCharacter(gAgentAvatarp); +				if (motionp->deserialize(dp, getAssetId(), false)) +				{ +					// write to temp file +					bool succ = motionp->dumpToFile(filename); +					if (succ) +					{ +						assetType = LLAssetType::AT_ANIMATION; +						errorLabel = ""; +						error = false; +					} +					else +					{ +						errorMessage = "Failed saving temporary animation file"; +					} +				} +				else +				{ +					errorMessage = "Failed reading animation file"; +				} +			} +		} +    } +    else      { -        filename = getFileName(); +        // Unknown extension +        errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str()); +        errorLabel = "ErrorMessage"; +        error = TRUE;;      }      if (error) @@ -863,6 +920,7 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res      {          args["FILE"] = uploadInfo->getDisplayName();          args["REASON"] = reason; +        args["ERROR"] = reason;      }      LLNotificationsUtil::add(label, args); diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index 782285ce36..febae36ae8 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -33,8 +33,6 @@  // comment out to turn off wind  #define kAUDIO_ENABLE_WIND   //#define kAUDIO_ENABLE_WATER 1	// comment out to turn off water -#define kAUDIO_NUM_BUFFERS 30 -#define kAUDIO_NUM_SOURCES 30   void init_audio();  void audio_update_volume(bool force_update = true); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 9036e87514..bc46a61fb0 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -639,157 +639,186 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)  void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value);  //////////////////////////////////////////////////////////////////////////// +LLPointer<LLControlVariable> setting_get_control(LLControlGroup& group, const std::string& setting) +{ +    LLPointer<LLControlVariable> cntrl_ptr = group.getControl(setting); +    if (cntrl_ptr.isNull()) +    { +        LL_ERRS() << "Unable to set up setting listener for " << setting +            << ". Please reinstall viewer from  https ://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." +            << LL_ENDL; +    } +    return cntrl_ptr; +} + +void setting_setup_signal_listener(LLControlGroup& group, const std::string& setting, std::function<void(const LLSD& newvalue)> callback) +{ +    setting_get_control(group, setting)->getSignal()->connect([callback](LLControlVariable* control, const LLSD& new_val, const LLSD& old_val) +    { +        callback(new_val); +    }); +} + +void setting_setup_signal_listener(LLControlGroup& group, const std::string& setting, std::function<void()> callback) +{ +    setting_get_control(group, setting)->getSignal()->connect([callback](LLControlVariable* control, const LLSD& new_val, const LLSD& old_val) +    { +        callback(); +    }); +} +  void settings_setup_listeners()  { -	gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2)); -	gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2)); -	gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2)); -	gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); -	gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); -	gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); -	gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); -	gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); -	gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleWindowResized, _2)); -	gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); -	gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); -	gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); -	gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2)); -	gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleShadowsResized, _2)); -	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); -	gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); -	gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); -	gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); -	gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _2)); -	gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _2)); -	gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _2)); -	gSavedSettings.getControl("RenderFogRatio")->getSignal()->connect(boost::bind(&handleFogRatioChanged, _2)); -	gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _2)); -	gSavedSettings.getControl("RenderDynamicLOD")->getSignal()->connect(boost::bind(&handleRenderDynamicLODChanged, _2)); -	gSavedSettings.getControl("RenderLocalLights")->getSignal()->connect(boost::bind(&handleRenderLocalLightsChanged, _2)); -	gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2)); -	gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -    gSavedSettings.getControl("RenderVSyncEnable")->getSignal()->connect(boost::bind(&handleVSyncChanged, _2)); -	gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2)); -	gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2)); -	gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2)); -	gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -	gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); -	gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); -	gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); -	gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); -	gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _2)); -	gSavedSettings.getControl("UseOcclusion")->getSignal()->connect(boost::bind(&handleUseOcclusionChanged, _2)); -	gSavedSettings.getControl("AudioLevelMaster")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelSFX")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("AudioLevelUnderwaterRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); -	gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderUseVAO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderPreferStreamDraw")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2)); -	gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("JoystickAxis6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisScale6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("FlycamAxisDeadZone6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("AvatarAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("BuildAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); -	gSavedSettings.getControl("DebugViews")->getSignal()->connect(boost::bind(&handleDebugViewsChanged, _2)); -	gSavedSettings.getControl("UserLogFile")->getSignal()->connect(boost::bind(&handleLogFileChanged, _2)); -	gSavedSettings.getControl("RenderHideGroupTitle")->getSignal()->connect(boost::bind(handleHideGroupTitleChanged, _2)); -	gSavedSettings.getControl("HighResSnapshot")->getSignal()->connect(boost::bind(handleHighResSnapshotChanged, _2)); -	gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("PTTCurrentlyEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("PushToTalkButton")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("PushToTalkToggle")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("VoiceEarLocation")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); -	gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2));	 -	gSavedSettings.getControl("VelocityInterpolate")->getSignal()->connect(boost::bind(&handleVelocityInterpolate, _2)); -	gSavedSettings.getControl("QAMode")->getSignal()->connect(boost::bind(&show_debug_menus)); -	gSavedSettings.getControl("UseDebugMenus")->getSignal()->connect(boost::bind(&show_debug_menus)); -	gSavedSettings.getControl("AgentPause")->getSignal()->connect(boost::bind(&toggle_agent_pause, _2)); -	gSavedSettings.getControl("ShowNavbarNavigationPanel")->getSignal()->connect(boost::bind(&toggle_show_navigation_panel, _2)); -	gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2)); -	gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2)); -	gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); -	gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); -	gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); -	gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); -	gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); -	gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); -	gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2)); -	gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&handleAvatarHoverOffsetChanged, _2)); +    setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); +	setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); +	setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); +	setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); +	setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition); +	setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition); +	setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized); +	setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); +	setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAvatarCloth", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAvatarPhysicsLODFactor", handleAvatarPhysicsLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderTerrainLODFactor", handleTerrainLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderTreeLODFactor", handleTreeLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderFlexTimeFactor", handleFlexLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderGamma", handleGammaChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderFogRatio", handleFogRatioChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderLocalLights", handleRenderLocalLightsChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged); +    setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); +	setting_setup_signal_listener(gSavedSettings, "TextureMemory", handleVideoMemoryChanged); +	setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged); +	setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged); +	setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged); +	setting_setup_signal_listener(gSavedSettings, "UploadBakedTexOld", handleUploadBakedTexOldChanged); +	setting_setup_signal_listener(gSavedSettings, "UseOcclusion", handleUseOcclusionChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelMaster", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelSFX", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelUI", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelAmbient", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelMusic", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelMedia", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelVoice", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelDoppler", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelRolloff", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelUnderwaterRolloff", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteAudio", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteMusic", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteMedia", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderVBOEnable", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderUseVAO", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderVBOMappingDisable", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderUseStreamVBO", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderPreferStreamDraw", handleResetVertexBuffersChanged); +	setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "JoystickAxis6", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale6", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone6", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisScale5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone0", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone1", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone2", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone3", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone4", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone5", handleJoystickChanged); +	setting_setup_signal_listener(gSavedSettings, "DebugViews", handleDebugViewsChanged); +	setting_setup_signal_listener(gSavedSettings, "UserLogFile", handleLogFileChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderHideGroupTitle", handleHideGroupTitleChanged); +	setting_setup_signal_listener(gSavedSettings, "HighResSnapshot", handleHighResSnapshotChanged); +	setting_setup_signal_listener(gSavedSettings, "EnableVoiceChat", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "PTTCurrentlyEnabled", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "PushToTalkButton", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "PushToTalkToggle", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "VoiceEarLocation", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "VoiceInputAudioDevice", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "VoiceOutputAudioDevice", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "AudioLevelMic", handleVoiceClientPrefsChanged); +	setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged);	 +	setting_setup_signal_listener(gSavedSettings, "VelocityInterpolate", handleVelocityInterpolate); +	setting_setup_signal_listener(gSavedSettings, "QAMode", show_debug_menus); +	setting_setup_signal_listener(gSavedSettings, "UseDebugMenus", show_debug_menus); +	setting_setup_signal_listener(gSavedSettings, "AgentPause", toggle_agent_pause); +	setting_setup_signal_listener(gSavedSettings, "ShowNavbarNavigationPanel", toggle_show_navigation_panel); +	setting_setup_signal_listener(gSavedSettings, "ShowMiniLocationPanel", toggle_show_mini_location_panel); +	setting_setup_signal_listener(gSavedSettings, "ShowObjectRenderingCost", toggle_show_object_render_cost); +	setting_setup_signal_listener(gSavedSettings, "ForceShowGrid", handleForceShowGrid); +	setting_setup_signal_listener(gSavedSettings, "RenderTransparentWater", handleRenderTransparentWaterChanged); +	setting_setup_signal_listener(gSavedSettings, "SpellCheck", handleSpellCheckChanged); +	setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged); +	setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged); +	setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged); +	setting_setup_signal_listener(gSavedSettings, "RenderAutoMuteByteLimit", handleRenderAutoMuteByteLimitChanged); + +    setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged);  }  #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 636909e6f2..a1cb152e1e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -3883,7 +3883,7 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const  //  bool LLViewerMediaImpl::isObscured() const  { -    if (getUsedInUI() || isParcelMedia()) return false; +    if (getUsedInUI() || isParcelMedia() || isAttachedToHUD()) return false;      LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();      if (!agent_parcel) @@ -3899,6 +3899,20 @@ bool LLViewerMediaImpl::isObscured() const      return false;  } +bool LLViewerMediaImpl::isAttachedToHUD() const +{ +    std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin(); +    std::list< LLVOVolume* >::const_iterator end = mObjectList.end(); +    for ( ; iter != end; iter++) +    { +        if ((*iter)->isHUDAttachment()) +        { +            return true; +        } +    } +    return false; +} +  //////////////////////////////////////////////////////////////////////////////////////////  //  bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index b95cfd4c68..f1f42afd81 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -411,6 +411,8 @@ public:  	void cancelMimeTypeProbe(); +    bool isAttachedToHUD() const; +  	// Is this media attached to an avatar *not* self  	bool isAttachedToAnotherAvatar() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f76031953d..3573af40cb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -54,6 +54,7 @@  #include "llcompilequeue.h"  #include "llconsole.h"  #include "lldebugview.h" +#include "lldiskcache.h"  #include "llenvironment.h"  #include "llfilepicker.h"  #include "llfirstuse.h" @@ -2102,6 +2103,32 @@ class LLAdvancedDropPacket : public view_listener_t  	}  }; +////////////////////// +// PURGE DISK CACHE // +////////////////////// + + +class LLAdvancedPurgeDiskCache : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +        LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); +        LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); +        llassert_always(main_queue); +        llassert_always(general_queue); +        main_queue->postTo( +            general_queue, +            []() // Work done on general queue +            { +                LLDiskCache::getInstance()->purge(); +                // Nothing needed to return +            }, +            [](){}); // Callback to main thread is empty as there is nothing left to do + +		return true; +	} +}; +  ////////////////////  // EVENT Recorder // @@ -2326,25 +2353,13 @@ class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t  };  ///////////////////////////////////// -// Enable Framebuffer Objects	  /// -///////////////////////////////////// -class LLAdvancedEnableRenderFBO: public view_listener_t -{ -	bool handleEvent(const LLSD& userdata) -	{ -		bool new_value = gGLManager.mHasFramebufferObject; -		return new_value; -	} -}; - -/////////////////////////////////////  // Enable Deferred Rendering	  ///  /////////////////////////////////////  class LLAdvancedEnableRenderDeferred: public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{ -		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && +		bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&  			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;  		return new_value;  	} @@ -2357,7 +2372,7 @@ class LLAdvancedEnableRenderDeferredOptions: public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{ -		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && +		bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&  			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");  		return new_value;  	} @@ -9406,7 +9421,6 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");  	// Develop > Render  	view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion"); -	view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO");  	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred");  	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions");  	view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate"); @@ -9505,6 +9519,9 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");  	view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket"); +    // Advanced > Cache +    view_listener_t::addMenu(new LLAdvancedPurgeDiskCache(), "Advanced.PurgeDiskCache"); +  	// Advanced > Recorder  	view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");  	view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5f82f1c44f..d97ed61e11 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -33,6 +33,7 @@  #include "llavataractions.h"  #include "llavatarnamecache.h"		// IDEVO HACK  #include "lleventtimer.h" +#include "llfloatercreatelandmark.h"  #include "llfloaterreg.h"  #include "llfolderview.h"  #include "llfollowcamparams.h" @@ -122,6 +123,7 @@  #include "llexperiencecache.h"  #include "llexperiencecache.h" +#include "lluiusage.h"  extern void on_new_message(const LLSD& msg); @@ -261,6 +263,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	    {  	    case 0:  	    { +			LLUIUsage::instance().logCommand("Agent.AcceptFriendship");  		    // accept  		    LLAvatarTracker::formFriendship(payload["from_id"]); @@ -303,6 +306,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	    // fall-through  	    case 2: // Send IM - decline and start IM session  		    { +				LLUIUsage::instance().logCommand("Agent.DeclineFriendship");  			    // decline  			    // We no longer notify other viewers, but we DO still send                  // the rejection to the simulator to delete the pending userop. @@ -833,6 +837,11 @@ void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accep          EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE; +		if (accept_invite) +		{ +			LLUIUsage::instance().logCommand("Group.Join"); +		} +          send_improved_im(group_id,              std::string("name"),              std::string("message"), @@ -1560,6 +1569,17 @@ bool highlight_offered_object(const LLUUID& obj_id)  		}  	} +    if (obj->getType() == LLAssetType::AT_LANDMARK) +    { +        LLFloaterCreateLandmark *floater = LLFloaterReg::findTypedInstance<LLFloaterCreateLandmark>("add_landmark"); +        if (floater && floater->getItem() && floater->getItem()->getUUID() == obj_id) +        { +            // LLFloaterCreateLandmark is supposed to handle this, +            // keep landmark creation floater at the front +            return false; +        } +    } +  	return true;  } diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index e6974b0f84..7666062f99 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -45,11 +45,11 @@ class LLViewerOctreeGroup;  class LLViewerOctreeEntry;  class LLViewerOctreePartition; -typedef LLOctreeListener<LLViewerOctreeEntry>	OctreeListener; -typedef LLTreeNode<LLViewerOctreeEntry>			TreeNode; -typedef LLOctreeNode<LLViewerOctreeEntry>		OctreeNode; -typedef LLOctreeRoot<LLViewerOctreeEntry>		OctreeRoot; -typedef LLOctreeTraveler<LLViewerOctreeEntry>	OctreeTraveler; +typedef LLOctreeListener<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeListener; +typedef LLTreeNode<LLViewerOctreeEntry> TreeNode; +typedef LLOctreeNode<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeNode; +typedef LLOctreeRoot<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeRoot; +typedef LLOctreeTraveler<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeTraveler;  #if LL_OCTREE_PARANOIA_CHECK  #define assert_octree_valid(x) x->validate() @@ -179,7 +179,7 @@ protected:  //defines an octree group for an octree node, which contains multiple entries.  //LL_ALIGN_PREFIX(16)  class LLViewerOctreeGroup -:	public LLOctreeListener<LLViewerOctreeEntry> +:	public OctreeListener  {      LL_ALIGN_NEW  	friend class LLViewerOctreeCull; @@ -198,8 +198,8 @@ public:  	};  public: -	typedef LLOctreeNode<LLViewerOctreeEntry>::element_iter element_iter; -	typedef LLOctreeNode<LLViewerOctreeEntry>::element_list element_list; +	typedef OctreeNode::element_iter element_iter; +	typedef OctreeNode::element_list element_list;  	LLViewerOctreeGroup(OctreeNode* node);  	LLViewerOctreeGroup(const LLViewerOctreeGroup& rhs) @@ -245,7 +245,6 @@ public:  	const LLVector4a* getObjectExtents() const {return mObjectExtents;}  	//octree wrappers to make code more readable -	element_list& getData() { return mOctreeNode->getData(); }  	element_iter getDataBegin() { return mOctreeNode->getDataBegin(); }  	element_iter getDataEnd() { return mOctreeNode->getDataEnd(); }  	U32 getElementCount() const { return mOctreeNode->getElementCount(); } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index f58eac2ed9..75eb16c085 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1592,6 +1592,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use      else if (sequence_id == 0 || sequence_id > parcel_mgr.mAgentParcelSequenceID)      {          // new agent parcel +        // *TODO: Does it really make sense to set the agent parcel to this +        // parcel if the client doesn't know what kind of parcel data this is?          parcel_mgr.mAgentParcelSequenceID = sequence_id;          parcel = parcel_mgr.mAgentParcel;      } @@ -1887,8 +1889,13 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use  	}  	else  	{ -		// Check for video -		LLViewerParcelMedia::getInstance()->update(parcel); +        if (gNonInteractive) +        { +            return; +        } +     +        // Check for video +        LLViewerParcelMedia::getInstance()->update(parcel);  		// Then check for music  		if (gAudiop) diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 02f7bbeed8..785c84c38d 100644..100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -264,7 +264,7 @@ BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const  {  	S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);  	S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS); -	return PARCEL_SOUND_LOCAL & mOwnership[row * mParcelGridsPerEdge + column]; +    return parcelFlags(row, column, PARCEL_SOUND_LOCAL);  }  U8 LLViewerParcelOverlay::ownership( const LLVector3& pos) const @@ -278,12 +278,19 @@ U8 LLViewerParcelOverlay::parcelLineFlags(const LLVector3& pos) const  {      S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);      S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS); -    return parcelLineFlags(row, column); +    return parcelFlags(row, column, PARCEL_WEST_LINE | PARCEL_SOUTH_LINE);  }  U8 LLViewerParcelOverlay::parcelLineFlags(S32 row, S32 col) const  { -    U8 flags = PARCEL_WEST_LINE | PARCEL_SOUTH_LINE; -    if (row > mParcelGridsPerEdge || col > mParcelGridsPerEdge) +    return parcelFlags(row, col, PARCEL_WEST_LINE | PARCEL_SOUTH_LINE); +} + +U8 LLViewerParcelOverlay::parcelFlags(S32 row, S32 col, U8 flags) const +{ +    if (row >= mParcelGridsPerEdge +        || col >= mParcelGridsPerEdge +        || row < 0 +        || col < 0)      {          LL_WARNS() << "Attempted to get ownership out of region's overlay, row: " << row << " col: " << col << LL_ENDL;          return flags; @@ -908,8 +915,8 @@ S32 LLViewerParcelOverlay::renderPropertyLines	()  	// Always fudge a little vertically.  	pull_toward_camera.mV[VZ] += 0.01f; -	gGL.matrixMode(LLRender::MM_MODELVIEW); -	gGL.pushMatrix(); +    gGL.matrixMode(LLRender::MM_MODELVIEW); +    gGL.pushMatrix();  	// Move to appropriate region coords  	LLVector3 origin = mRegion->getOriginAgent(); @@ -1014,7 +1021,66 @@ S32 LLViewerParcelOverlay::renderPropertyLines	()  	} -	gGL.popMatrix(); +    gGL.popMatrix();  	return drawn;  } + +// Draw half of a single cell (no fill) in a grid drawn from left to right and from bottom to top +void grid_2d_part_lines(const F32 left, const F32 top, const F32 right, const F32 bottom, bool has_left, bool has_bottom) +{ +    gGL.begin(LLRender::LINES); + +    if (has_left) +    { +        gGL.vertex2f(left, bottom); +        gGL.vertex2f(left, top); +    } +    if (has_bottom) +    { +        gGL.vertex2f(left, bottom); +        gGL.vertex2f(right, bottom); +    } + +    gGL.end(); +} + +void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) +{ +    if (!mOwnership) +    { +        return; +    } +    if (!gSavedSettings.getBOOL("MiniMapShowPropertyLines")) +    { +        return; +    } + +    LLVector3 origin_agent     = mRegion->getOriginAgent(); +    LLVector3 rel_region_pos   = origin_agent - gAgentCamera.getCameraPositionAgent(); +    F32       region_left      = rel_region_pos.mV[0] * scale_pixels_per_meter; +    F32       region_bottom    = rel_region_pos.mV[1] * scale_pixels_per_meter; +    F32       map_parcel_width = PARCEL_GRID_STEP_METERS * scale_pixels_per_meter; +    const S32 GRIDS_PER_EDGE   = mParcelGridsPerEdge; + +    gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +    glLineWidth(1.0f); +    gGL.color4fv(parcel_outline_color); +    for (S32 i = 0; i < GRIDS_PER_EDGE + 1; i++) +    { +        const F32 bottom = region_bottom + (i * map_parcel_width); +        const F32 top    = bottom + map_parcel_width; +        for (S32 j = 0; j < GRIDS_PER_EDGE + 1; j++) +        { +            const F32  left               = region_left + (j * map_parcel_width); +            const F32  right              = left + map_parcel_width; +            const bool is_region_boundary = i == GRIDS_PER_EDGE || j == GRIDS_PER_EDGE; +            const U8   overlay            = is_region_boundary ? 0 : mOwnership[(i * GRIDS_PER_EDGE) + j]; +            // The property line vertices are three-dimensional, but here we only care about the x and y coordinates, as we are drawing on a +            // 2D map +            const bool has_left   = i != GRIDS_PER_EDGE && (j == GRIDS_PER_EDGE || (overlay & PARCEL_WEST_LINE)); +            const bool has_bottom = j != GRIDS_PER_EDGE && (i == GRIDS_PER_EDGE || (overlay & PARCEL_SOUTH_LINE)); +            grid_2d_part_lines(left, top, right, bottom, has_left, has_bottom); +        } +    } +} diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index e30dbf17b3..c466cc3b6b 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -69,6 +69,7 @@ public:  	// Returns the number of vertices drawn  	S32				renderPropertyLines(); +    void			renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color);  	U8				ownership( const LLVector3& pos) const;  	U8				parcelLineFlags( const LLVector3& pos) const; @@ -82,12 +83,14 @@ public:  	void	idleUpdate(bool update_now = false);  	void	updateGL(); - +      private:  	// This is in parcel rows and columns, not grid rows and columns  	// Stored in bottom three bits.  	U8		ownership(S32 row, S32 col) const	 -				{ return 0x7 & mOwnership[row * mParcelGridsPerEdge + col]; } +				{ return parcelFlags(row, col, (U8)0x7); } + +    U8		parcelFlags(S32 row, S32 col, U8 flags) const;  	void	addPropertyLine(std::vector<LLVector3>& vertex_array,  				std::vector<LLColor4U>& color_array, diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index fb55c5e816..ad7321ca4b 100644..100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -324,6 +324,23 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              return;          } +        if (!LLWorld::instanceExists()) +        { +            LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL; +            return; +        } + +        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); +        if (!regionp) //region was removed +        { +            LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; +            return; // this error condition is not recoverable. +        } + +        impl = regionp->getRegionImplNC(); + +        ++(impl->mSeedCapAttempts); +          if (!result.isMap() || result.has("error"))          {              LL_WARNS("AppInit", "Capabilities") << "Malformed response" << LL_ENDL; @@ -343,23 +360,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)          // remove the http_result from the llsd          result.erase("http_result"); -        if (!LLWorld::instanceExists()) -        { -            LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL; -            return; -        } - -        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); -        if (!regionp) //region was removed -        { -            LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; -            return; // this error condition is not recoverable. -        } - -        impl = regionp->getRegionImplNC(); - -        ++(impl->mSeedCapAttempts); -          if (id != impl->mHttpResponderID) // region is no longer referring to this request          {              LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL; @@ -1068,6 +1068,15 @@ S32 LLViewerRegion::renderPropertyLines()  	}  } +void LLViewerRegion::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) +{ +    if (mParcelOverlay) +    { +        mParcelOverlay->renderPropertyLinesOnMinimap(scale_pixels_per_meter, parcel_outline_color); +    } +} + +  // This gets called when the height field changes.  void LLViewerRegion::dirtyHeights()  { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index d0fa9fea01..6548e8d372 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -154,6 +154,8 @@ public:  	// Draw lines in the dirt showing ownership. Return number of   	// vertices drawn.  	S32 renderPropertyLines(); +    void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); +  	// Call this whenever you change the height data in the region.  	// (Automatically called by LLSurfacePatch's update routine) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 086b433c72..1c9360a843 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -556,15 +556,14 @@ void LLViewerShaderMgr::setShaders()      mShaderLevel[SHADER_DEFERRED] = deferred_class;      mShaderLevel[SHADER_TRANSFORM] = transform_class; -    BOOL loaded = loadBasicShaders(); -    if (loaded) +    std::string shader_name = loadBasicShaders(); +    if (shader_name.empty())      {          LL_INFOS() << "Loaded basic shaders." << LL_ENDL;      }      else      { -        LL_ERRS() << "Unable to load basic shaders, verify graphics driver installed and current." << LL_ENDL; -        llassert(loaded); +        LL_ERRS() << "Unable to load basic shader " << shader_name << ", verify graphics driver installed and current." << LL_ENDL;          reentrance = false; // For hygiene only, re-try probably helps nothing           return;      } @@ -572,7 +571,7 @@ void LLViewerShaderMgr::setShaders()      gPipeline.mShadersLoaded = true;      // Load all shaders to set max levels -    loaded = loadShadersEnvironment(); +    BOOL loaded = loadShadersEnvironment();      if (loaded)      { @@ -859,7 +858,7 @@ void LLViewerShaderMgr::unloadShaders()  	gPipeline.mShadersLoaded = false;  } -BOOL LLViewerShaderMgr::loadBasicShaders() +std::string LLViewerShaderMgr::loadBasicShaders()  {  	// Load basic dependency shaders first  	// All of these have to load for any shaders to function @@ -945,8 +944,8 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  		// Note usage of GL_VERTEX_SHADER_ARB  		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0)  		{ -			LL_SHADER_LOADING_WARNS() << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; -			return FALSE; +			LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; +			return shaders[i].first;  		}  	} @@ -1005,12 +1004,12 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  		// Note usage of GL_FRAGMENT_SHADER_ARB  		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0)  		{ -			LL_SHADER_LOADING_WARNS() << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; -			return FALSE; +			LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; +			return shaders[i].first;  		}  	} -	return TRUE; +	return std::string();  }  BOOL LLViewerShaderMgr::loadShadersEnvironment() @@ -1484,6 +1483,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()              gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); +            if (alpha_mode != 0) +            { +                gDeferredMaterialProgram[i].mFeatures.hasAlphaMask = true; +                gDeferredMaterialProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); +            } +              if (use_sun_shadow)              {                  gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); @@ -1542,6 +1547,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()              }              gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); +            if (alpha_mode != 0) +            { +                gDeferredMaterialWaterProgram[i].mFeatures.hasAlphaMask = true; +                gDeferredMaterialWaterProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); +            } +              if (use_sun_shadow)              {                  gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 93bb29a355..f8a261805b 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -49,7 +49,11 @@ public:  	void setShaders();  	void unloadShaders();      S32  getShaderLevel(S32 type); -	BOOL loadBasicShaders(); + +    // loadBasicShaders in case of a failure returns +    // name of a file error happened at, otherwise +    // returns an empty string +    std::string loadBasicShaders();  	BOOL loadShadersEffects();  	BOOL loadShadersDeferred();  	BOOL loadShadersObject(); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 815d8e9486..441648d4e9 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1155,7 +1155,8 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)  		 iter3 != entries.end(); )  	{  		LLViewerFetchedTexture* imagep = *iter3++; -		imagep->updateFetch(); +        imagep->updateFetch(); +  		if (min_count <= min_update_count)  		{  			mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5ce46b143a..8a7d5f12d0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2005,7 +2005,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	}  	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));  	LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; -	gGL.init() ; +	gGL.init(true);  	if (LLFeatureManager::getInstance()->isSafe()  		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) @@ -2518,10 +2518,11 @@ void LLViewerWindow::reshape(S32 width, S32 height)  		//glViewport(0, 0, width, height ); -		if (height > 0) +        LLViewerCamera * camera = LLViewerCamera::getInstance(); // simpleton, might not exist +		if (height > 0 && camera)  		{  -			LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); -			LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); +            camera->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); +            camera->setAspect( getWorldViewAspectRatio() );  		}  		calcDisplayScale(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6543081bd8..42550ed48d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2813,6 +2813,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)  	if (detailed_update)  	{          U32 draw_order = 0; +        S32 attachment_selected = LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment();  		for (attachment_map_t::iterator iter = mAttachmentPoints.begin();   			 iter != mAttachmentPoints.end();  			 ++iter) @@ -2852,7 +2853,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)                      }                      // if selecting any attachments, update all of them as non-damped -                    if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment()) +                    if (attachment_selected)                      {                          gPipeline.updateMoveNormalAsync(attached_object->mDrawable);                      } @@ -6155,7 +6156,21 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )  	if (iter == mJointMap.end() || iter->second == NULL)  	{   //search for joint and cache found joint in lookup table -		jointp = mRoot->findJoint(name); +		if (mJointAliasMap.empty()) +		{ +			getJointAliases(); +		} +		joint_alias_map_t::const_iterator alias_iter = mJointAliasMap.find(name); +		std::string canonical_name; +		if (alias_iter != mJointAliasMap.end()) +		{ +			canonical_name = alias_iter->second; +		} +		else +		{ +			canonical_name = name; +		} +		jointp = mRoot->findJoint(canonical_name);  		mJointMap[name] = jointp;  	}  	else diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 60a69a4ac4..8fc1dcd81f 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -67,6 +67,7 @@  #include "llsdserialize.h"  #include "llcallstack.h"  #include "llcorehttputil.h" +#include "lluiusage.h"  #if LL_MSVC  // disable boost::lexical_cast warning @@ -2663,6 +2664,7 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch)  {  	if (isAgentAvatarValid())  	{ +		LLUIUsage::instance().logCommand("Avatar.CustomizeStart");  		if (!gAgentAvatarp->mEndCustomizeCallback.get())  		{  			gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index db8ad183f0..55fc663496 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -366,15 +366,6 @@ void LLVOCacheEntry::updateDebugSettings()  	}  	timer.reset(); -	//the number of frames invisible objects stay in memory -	static LLCachedControl<U32> inv_obj_time(gSavedSettings,"NonvisibleObjectsInMemoryTime"); -	sMinFrameRange = inv_obj_time - 1; //make 0 to be the maximum  - -	//min radius: all objects within this radius remain loaded in memory -	static LLCachedControl<F32> min_radius(gSavedSettings,"SceneLoadMinRadius"); -	sNearRadius = llmin((F32)min_radius, gAgentCamera.mDrawDistance); //can not exceed the draw distance -	sNearRadius = llmax(sNearRadius, 1.f); //minimum value is 1.0m -  	//objects within the view frustum whose visible area is greater than this threshold will be loaded  	static LLCachedControl<F32> front_pixel_threshold(gSavedSettings,"SceneLoadFrontPixelThreshold");  	sFrontPixelThreshold = front_pixel_threshold; @@ -384,29 +375,38 @@ void LLVOCacheEntry::updateDebugSettings()  	sRearPixelThreshold = rear_pixel_threshold;  	sRearPixelThreshold = llmax(sRearPixelThreshold, sFrontPixelThreshold); //can not be smaller than sFrontPixelThreshold. -	// a percentage of draw distance beyond which all objects outside of view frustum will be unloaded, regardless of pixel threshold -	static LLCachedControl<F32> rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction"); -	sRearFarRadius = llmax(rear_max_radius_frac * gAgentCamera.mDrawDistance / 100.f, 1.0f); //minimum value is 1.0m -	sRearFarRadius = llmax(sRearFarRadius, (F32)min_radius); //can not be less than "SceneLoadMinRadius". -	sRearFarRadius = llmin(sRearFarRadius, gAgentCamera.mDrawDistance); //can not be more than the draw distance. - -	//make the above parameters adaptive to memory usage +	//make parameters adaptive to memory usage  	//starts to put restrictions from low_mem_bound_MB, apply tightest restrictions when hits high_mem_bound_MB  	static LLCachedControl<U32> low_mem_bound_MB(gSavedSettings,"SceneLoadLowMemoryBound");  	static LLCachedControl<U32> high_mem_bound_MB(gSavedSettings,"SceneLoadHighMemoryBound");  	LLMemory::updateMemoryInfo() ;  	U32 allocated_mem = LLMemory::getAllocatedMemKB().value(); -	allocated_mem /= 1024; //convert to MB. -	if(allocated_mem < low_mem_bound_MB) -	{ -		return;  -	} -	F32 adjust_factor = llmax(0.f, (F32)(high_mem_bound_MB - allocated_mem) / (high_mem_bound_MB - low_mem_bound_MB)); - -	sRearFarRadius = llmin(adjust_factor * sRearFarRadius, 96.f);  //[0.f, 96.f] -	sMinFrameRange = (U32)llclamp(adjust_factor * sMinFrameRange, 10.f, 64.f);  //[10, 64] -	sNearRadius    = llmax(adjust_factor * sNearRadius, 1.0f); +    static const F32 KB_to_MB = 1.f / 1024.f; +	U32 clamped_memory = llclamp(allocated_mem * KB_to_MB, (F32) low_mem_bound_MB, (F32) high_mem_bound_MB); +    const F32 adjust_range = high_mem_bound_MB - low_mem_bound_MB; +    const F32 adjust_factor = (high_mem_bound_MB - clamped_memory) / adjust_range; // [0, 1] + +    //min radius: all objects within this radius remain loaded in memory +    static LLCachedControl<F32> min_radius(gSavedSettings,"SceneLoadMinRadius"); +    static const F32 MIN_RADIUS = 1.0f; +    const F32 draw_radius = gAgentCamera.mDrawDistance; +    const F32 clamped_min_radius = llclamp((F32) min_radius, MIN_RADIUS, draw_radius); // [1, mDrawDistance] +    sNearRadius = MIN_RADIUS + ((clamped_min_radius - MIN_RADIUS) * adjust_factor); + +    // a percentage of draw distance beyond which all objects outside of view frustum will be unloaded, regardless of pixel threshold +    static LLCachedControl<F32> rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction"); +    const F32 min_radius_plus_one = sNearRadius + 1.f; +    const F32 max_radius = rear_max_radius_frac * gAgentCamera.mDrawDistance; +    const F32 clamped_max_radius = llclamp(max_radius, min_radius_plus_one, draw_radius); // [sNearRadius, mDrawDistance] +    sRearFarRadius = min_radius_plus_one + ((clamped_max_radius - min_radius_plus_one) * adjust_factor); + +    //the number of frames invisible objects stay in memory +    static LLCachedControl<U32> inv_obj_time(gSavedSettings,"NonvisibleObjectsInMemoryTime"); +    static const U32 MIN_FRAMES = 10; +    static const U32 MAX_FRAMES = 64; +    const U32 clamped_frames = inv_obj_time ? llclamp((U32) inv_obj_time, MIN_FRAMES, MAX_FRAMES) : MAX_FRAMES; // [10, 64], with zero => 64 +    sMinFrameRange = MIN_FRAMES + ((clamped_frames - MIN_FRAMES) * adjust_factor);  }  //static  diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index d8b8b8749f..2ef2d66f18 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -37,6 +37,7 @@  #include "llui.h"  #include "llkeyboard.h"  #include "llagent.h" +#include "lluiusage.h"  const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; @@ -603,6 +604,10 @@ void LLVoiceClient::setMuteMic(bool muted)  void LLVoiceClient::setUserPTTState(bool ptt)  { +	if (ptt) +	{ +		LLUIUsage::instance().logCommand("Agent.EnableMicrophone"); +	}  	mUserPTTState = ptt;  	updateMicMuteLogic();  	mMicroChangedSignal(); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 735bb4ad94..ac6369e4e2 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1610,13 +1610,33 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo()          }          else          { -            LL_WARNS("Voice") << "No voice channel credentials" << LL_ENDL; - +            LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); +            if (channel != NULL) +            { +                if (channel->getSessionName().empty() && channel->getSessionID().isNull()) +                { +                    if (LLViewerParcelMgr::getInstance()->allowAgentVoice()) +                    { +                        LL_WARNS("Voice") << "No channel credentials for default channel" << LL_ENDL; +                    } +                } +                else +                { +                    LL_WARNS("Voice") << "No voice channel credentials" << LL_ENDL; +                } +            }          }      }      else      { -        LL_WARNS("Voice") << "No voice credentials" << LL_ENDL; +        if (LLViewerParcelMgr::getInstance()->allowAgentVoice()) +        { +            LL_WARNS("Voice") << "No voice credentials" << LL_ENDL; +        } +        else +        { +            LL_DEBUGS("Voice") << "No voice credentials" << LL_ENDL; +        }      }      // set the spatial channel.  If no voice credentials or uri are  diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f4a938e57d..e923115c43 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1715,7 +1715,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds)          // updates needed, set REBUILD_RIGGED accordingly.          // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. -        updateRiggedVolume(); +        updateRiggedVolume(false);      }      LLVolume* volume = mRiggedVolume; @@ -2009,7 +2009,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  	if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))  	{ -		updateRiggedVolume(); +        updateRiggedVolume(false);  		genBBoxes(FALSE);  		mDrawable->clearState(LLDrawable::REBUILD_RIGGED);  	} @@ -4615,7 +4615,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  	{  		if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools))))  		{ -			updateRiggedVolume(true); +            updateRiggedVolume(true, LLRiggedVolume::DO_NOT_UPDATE_FACES);  			volume = mRiggedVolume;  			transform = false;  		} @@ -4690,6 +4690,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  				continue;  			} +            // This calculates the bounding box of the skinned mesh from scratch. It's actually quite expensive, but not nearly as expensive as building a full octree. +            // rebuild_face_octrees = false because an octree for this face will be built later only if needed for narrow phase picking. +            updateRiggedVolume(true, i, false);  			face_hit = volume->lineSegmentIntersect(local_start, local_end, i,  													&p, &tc, &n, &tn); @@ -4813,13 +4816,13 @@ void LLVOVolume::clearRiggedVolume()  	}  } -void LLVOVolume::updateRiggedVolume(bool force_update) +void LLVOVolume::updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index, bool rebuild_face_octrees)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;  	//Update mRiggedVolume to match current animation frame of avatar.   	//Also update position/size in octree.   -	if ((!force_update) && (!treatAsRigged())) +    if ((!force_treat_as_rigged) && (!treatAsRigged()))  	{  		clearRiggedVolume(); @@ -4848,10 +4851,10 @@ void LLVOVolume::updateRiggedVolume(bool force_update)  		updateRelativeXform();  	} -	mRiggedVolume->update(skin, avatar, volume); +    mRiggedVolume->update(skin, avatar, volume, face_index, rebuild_face_octrees);  } -void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume, FaceIndex face_index, bool rebuild_face_octrees)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;  	bool copy = false; @@ -4882,7 +4885,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  		if (is_paused)  		{              S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); -            if (frames_paused > 2) +            if (frames_paused > 1)              {                  return;              } @@ -4901,7 +4904,24 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons      S32 rigged_vert_count = 0;      S32 rigged_face_count = 0;      LLVector4a box_min, box_max; -	for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) +    S32 face_begin; +    S32 face_end; +    if (face_index == DO_NOT_UPDATE_FACES) +    { +        face_begin = 0; +        face_end = 0; +    } +    else if (face_index == UPDATE_ALL_FACES) +    { +        face_begin = 0; +        face_end = volume->getNumVolumeFaces(); +    } +    else +    { +        face_begin = face_index; +        face_end = face_begin + 1; +    } +    for (S32 i = face_begin; i < face_end; ++i)  	{  		const LLVolumeFace& vol_face = volume->getVolumeFace(i); @@ -4986,15 +5006,10 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  			} +            if (rebuild_face_octrees)  			{ -    			delete dst_face.mOctree; -				dst_face.mOctree = NULL; - -				LLVector4a size; -				size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); -				size.splat(size.getLength3().getF32()*0.5f); -			 -				dst_face.createOctree(1.f); +                dst_face.destroyOctree(); +                dst_face.createOctree();  			}  		}  	} @@ -5500,7 +5515,7 @@ static inline void add_face(T*** list, U32* count, T* face)      {          if (count[1] < MAX_FACE_COUNT)          { -            face->setDrawOrderIndex(count[1]); +            //face->setDrawOrderIndex(count[1]);              list[1][count[1]++] = face;          }      } @@ -5508,15 +5523,40 @@ static inline void add_face(T*** list, U32* count, T* face)      {          if (count[0] < MAX_FACE_COUNT)          { -            face->setDrawOrderIndex(count[0]); +            //face->setDrawOrderIndex(count[0]);              list[0][count[0]++] = face;          }      }  } +// return index into linkset for given object (0 for root prim) +U32 get_linkset_index(LLVOVolume* vobj) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; +    if (vobj->isRootEdit()) +    { +        return 0; +    } + +    LLViewerObject* root = vobj->getRootEdit(); +    U32 idx = 1; +    for (const auto& child : root->getChildren()) +    { +        if (child == vobj) +        { +            return idx; +        } +        ++idx; +    } + +    llassert(false); +    return idx; //should never get here +} +  void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; +  	if (group->changeLOD())  	{  		group->mLastUpdateDistance = group->mDistance; @@ -5675,6 +5715,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)                  avatar->addAttachmentOverridesForObject(vobj, NULL, false);              } +            U32 linkset_index = get_linkset_index(vobj); +              // Standard rigged mesh attachments:   			bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment();              // Animated objects. Have to check for isRiggedMesh() to @@ -5694,6 +5736,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					continue;  				} +                // order by linkset index first and face index second +                facep->setDrawOrderIndex(linkset_index * 100 + i); +  				//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render  				// batch, it will recover its vertex buffer reference from the spatial group  				facep->setVertexBuffer(NULL); @@ -5718,11 +5763,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)                      if (facep->isState(LLFace::RIGGED))                      {                           //face is not rigged but used to be, remove from rigged face pool -                        LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); -                        if (pool) -                        { -                            pool->removeFace(facep); -                        }                          facep->clearState(LLFace::RIGGED);                          facep->mAvatar = NULL;                          facep->mSkinInfo = NULL; @@ -5904,7 +5944,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  			else  			{  				drawablep->clearState(LLDrawable::RIGGED); -                vobj->updateRiggedVolume(); +                vobj->updateRiggedVolume(false);  			}  		}  	} @@ -6014,7 +6054,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			{  				LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); -				if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) +				if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL))  				{  					LLVOVolume* vobj = drawablep->getVOVolume(); @@ -6048,8 +6088,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  							LLVertexBuffer* buff = face->getVertexBuffer();  							if (buff)  							{ -								llassert(!face->isState(LLFace::RIGGED)); -  								if (!face->getGeometryVolume(*volume, face->getTEOffset(),   									vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()))  								{ //something's gone wrong with the vertex buffer accounting, rebuild this group  @@ -6178,6 +6216,13 @@ struct CompareBatchBreakerRigged      }  }; +struct CompareDrawOrder +{ +    bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) +    { +        return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex(); +    } +};  U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL rigged)  { @@ -6222,6 +6267,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace                  //sort faces by things that break batches, including avatar and mesh id                  std::sort(faces, faces + face_count, CompareBatchBreakerRigged());              } +            else +            { +                // preserve legacy draw order for rigged faces +                std::sort(faces, faces + face_count, CompareDrawOrder()); +            }          }          else if (!distance_sort)          { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4136c13315..01ad40274b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -65,7 +65,10 @@ public:  	{  	} -	void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume); +    using FaceIndex = S32; +    static const FaceIndex UPDATE_ALL_FACES = -1; +    static const FaceIndex DO_NOT_UPDATE_FACES = -2; +    void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume, FaceIndex face_index = UPDATE_ALL_FACES, bool rebuild_face_octrees = true);      std::string mExtraDebugText;  }; @@ -362,8 +365,9 @@ public:  	S32 getMDCImplCount() { return mMDCImplCount; } -	//rigged volume update (for raycasting) -	void updateRiggedVolume(bool force_update = false); +    // Rigged volume update (for raycasting) +    // By default, this updates the bounding boxes of all the faces and builds an octree for precise per-triangle raycasting +    void updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index = LLRiggedVolume::UPDATE_ALL_FACES, bool rebuild_face_octrees = true);  	LLRiggedVolume* getRiggedVolume();  	//returns true if volume should be treated as a rigged volume diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 59ac4554d7..6e994b4e68 100644..100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -58,9 +58,15 @@  #include "llglheaders.h" +// # Constants +static const F32 MAP_DEFAULT_SCALE = 128.f; +static const F32 MAP_ITERP_TIME_CONSTANT = 0.75f; +static const F32 MAP_ZOOM_ACCELERATION_TIME = 0.3f; +static const F32 MAP_ZOOM_MAX_INTERP = 0.5f; +static const F32 MAP_SCALE_SNAP_THRESHOLD = 0.005f; +  // Basically a C++ implementation of the OCEAN_COLOR defined in mapstitcher.py   // Please ensure consistency between those 2 files (TODO: would be better to get that color from an asset source...) -// # Constants  // OCEAN_COLOR = "#1D475F"  const F32 OCEAN_RED   = (F32)(0x1D)/255.f;  const F32 OCEAN_GREEN = (F32)(0x47)/255.f; @@ -92,14 +98,12 @@ LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL;  LLUIImagePtr LLWorldMapView::sForSaleImage = NULL;  LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL; -F32 LLWorldMapView::sPanX = 0.f; -F32 LLWorldMapView::sPanY = 0.f; -F32 LLWorldMapView::sTargetPanX = 0.f; -F32 LLWorldMapView::sTargetPanY = 0.f;  S32 LLWorldMapView::sTrackingArrowX = 0;  S32 LLWorldMapView::sTrackingArrowY = 0;  bool LLWorldMapView::sVisibleTilesLoaded = false; -F32 LLWorldMapView::sMapScale = 128.f; +F32 LLWorldMapView::sMapScaleSetting = MAP_DEFAULT_SCALE; +LLVector2 LLWorldMapView::sZoomPivot = LLVector2(0.0f, 0.0f); +LLFrameTimer LLWorldMapView::sZoomTimer = LLFrameTimer();  std::map<std::string,std::string> LLWorldMapView::sStringsMap; @@ -166,20 +170,27 @@ void LLWorldMapView::cleanupClass()  	sForSaleAdultImage = NULL;  } -LLWorldMapView::LLWorldMapView() -:	LLPanel(), -	mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ), -	mItemPicked(FALSE), -	mPanning( FALSE ), -	mMouseDownPanX( 0 ), -	mMouseDownPanY( 0 ), -	mMouseDownX( 0 ), -	mMouseDownY( 0 ), -	mSelectIDStart(0) +LLWorldMapView::LLWorldMapView() : +    LLPanel(), +    mBackgroundColor(LLColor4(OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f)), +    mItemPicked(FALSE), +    mPanX(0.f), +    mPanY(0.f), +    mTargetPanX(0.f), +    mTargetPanY(0.f), +    mPanning(FALSE), +    mMouseDownPanX(0), +    mMouseDownPanY(0), +    mMouseDownX(0), +    mMouseDownY(0), +    mSelectIDStart(0), +    mMapScale(0.f), +    mTargetMapScale(0.f), +    mMapIterpTime(MAP_ITERP_TIME_CONSTANT)  { -	//LL_INFOS("WorldMap") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; +    // LL_INFOS("WorldMap") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; -	clearLastClick(); +    clearLastClick();  }  BOOL LLWorldMapView::postBuild() @@ -210,6 +221,9 @@ BOOL LLWorldMapView::postBuild()  	mTextBoxNorthEast ->reshapeToFitText();  	mTextBoxSouthWest->reshapeToFitText();  	mTextBoxNorthWest ->reshapeToFitText(); +     +    sZoomTimer.stop(); +    setScale(sMapScaleSetting, true);  	return true;  } @@ -227,59 +241,111 @@ void LLWorldMapView::cleanupTextures()  {  } +void LLWorldMapView::zoom(F32 zoom) +{ +    mTargetMapScale = scaleFromZoom(zoom); +    if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) +    { +        sZoomPivot = LLVector2(0, 0); +        sZoomTimer.start(); +    } +} -// static -void LLWorldMapView::setScale( F32 scale ) +void LLWorldMapView::zoomWithPivot(F32 zoom, S32 x, S32 y)  { -	if (scale != sMapScale) -	{ -		F32 old_scale = sMapScale; +    mTargetMapScale = scaleFromZoom(zoom); +    sZoomPivot      = LLVector2(x, y); +    if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) +    { +        sZoomTimer.start(); +    } +} -		sMapScale = scale; -		if (sMapScale <= 0.f) -		{ -			sMapScale = 0.1f; -		} +F32 LLWorldMapView::getZoom() { return LLWorldMapView::zoomFromScale(mMapScale); } -		F32 ratio = (scale / old_scale); -		sPanX *= ratio; -		sPanY *= ratio; -		sTargetPanX = sPanX; -		sTargetPanY = sPanY; -		sVisibleTilesLoaded = false; -	} -} +F32 LLWorldMapView::getScale() { return mMapScale; } +// static +void LLWorldMapView::setScaleSetting(F32 scaleSetting) { sMapScaleSetting = scaleSetting; } + +// static +F32 LLWorldMapView::getScaleSetting() { return sMapScaleSetting; } + +void LLWorldMapView::setScale(F32 scale, bool snap) +{ +    if (scale != mMapScale) +    { +        F32 old_scale = mMapScale; + +        mMapScale = scale; +        // Set the scale used when saving the setting +        sMapScaleSetting = scale; +        if (mMapScale <= 0.f) +        { +            mMapScale = 0.1f; +        } +        mMapIterpTime = MAP_ITERP_TIME_CONSTANT; +        F32 ratio = (scale / old_scale); +        mPanX *= ratio; +        mPanY *= ratio; +        mTargetPanX         = mPanX; +        mTargetPanY         = mPanY; +        sVisibleTilesLoaded = false; + +        // If we are zooming relative to somewhere else rather than the center of the map, compensate for the difference in panning here +        if (!sZoomPivot.isExactlyZero()) +        { +            LLVector2 relative_pivot; +            relative_pivot.mV[VX]     = sZoomPivot.mV[VX] - (getRect().getWidth() / 2.0); +            relative_pivot.mV[VY]     = sZoomPivot.mV[VY] - (getRect().getHeight() / 2.0); +            LLVector2 zoom_pan_offset = relative_pivot - (relative_pivot * scale / old_scale); +            mPanX += zoom_pan_offset.mV[VX]; +            mPanY += zoom_pan_offset.mV[VY]; +            mTargetPanX += zoom_pan_offset.mV[VX]; +            mTargetPanY += zoom_pan_offset.mV[VY]; +        } +    } + +    if (snap) +    { +        mTargetMapScale = scale; +    } +}  // static -void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y ) +void LLWorldMapView::translatePan(S32 delta_x, S32 delta_y)  { -	sPanX += delta_x; -	sPanY += delta_y; -	sTargetPanX = sPanX; -	sTargetPanY = sPanY; -	sVisibleTilesLoaded = false; +    mPanX += delta_x; +    mPanY += delta_y; +    mTargetPanX         = mPanX; +    mTargetPanY         = mPanY; +    sVisibleTilesLoaded = false;  }  // static -void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) +void LLWorldMapView::setPan(S32 x, S32 y, BOOL snap)  { -	sTargetPanX = (F32)x; -	sTargetPanY = (F32)y; -	if (snap) -	{ -		sPanX = sTargetPanX; -		sPanY = sTargetPanY; -	} -	sVisibleTilesLoaded = false; +    mMapIterpTime = MAP_ITERP_TIME_CONSTANT; +    mTargetPanX = (F32) x; +    mTargetPanY = (F32) y; +    if (snap) +    { +        mPanX = mTargetPanX; +        mPanY = mTargetPanY; +    } +    sVisibleTilesLoaded = false;  } -bool LLWorldMapView::showRegionInfo() +// static +void LLWorldMapView::setPanWithInterpTime(S32 x, S32 y, BOOL snap, F32 interp_time)  { -	return (LLWorldMipmap::scaleToLevel(sMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); +    setPan(x, y, snap); +    mMapIterpTime = interp_time;  } +bool LLWorldMapView::showRegionInfo() { return (LLWorldMipmap::scaleToLevel(mMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); } +  ///////////////////////////////////////////////////////////////////////////////////  // HELPERS @@ -300,9 +366,28 @@ void LLWorldMapView::draw()  	mVisibleRegions.clear(); -	// animate pan if necessary -	sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(0.1f)); -	sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(0.1f)); +    // animate pan if necessary +    mPanX = lerp(mPanX, mTargetPanX, LLSmoothInterpolation::getInterpolant(mMapIterpTime)); +    mPanY = lerp(mPanY, mTargetPanY, LLSmoothInterpolation::getInterpolant(mMapIterpTime)); +     +    //RN: snaps to zoom value because interpolation caused jitter in the text rendering +    if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) +    { +        sZoomTimer.start(); +    } +    bool snap_scale = false; +    F32 interp = llmin(MAP_ZOOM_MAX_INTERP, sZoomTimer.getElapsedTimeF32() / MAP_ZOOM_ACCELERATION_TIME); +    F32 current_zoom_val = zoomFromScale(mMapScale); +    F32 target_zoom_val = zoomFromScale(mTargetMapScale); +    F32 new_zoom_val = lerp(current_zoom_val, target_zoom_val, interp); +    if (abs(new_zoom_val - current_zoom_val) < MAP_SCALE_SNAP_THRESHOLD) +    { +        sZoomTimer.stop(); +        snap_scale = true; +        new_zoom_val = target_zoom_val; +    } +    F32 map_scale = scaleFromZoom(new_zoom_val); +    setScale(map_scale, snap_scale);  	const S32 width = getRect().getWidth();  	const S32 height = getRect().getHeight(); @@ -310,7 +395,7 @@ void LLWorldMapView::draw()  	const F32 half_height = F32(height) / 2.0f;  	LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); -	S32 level = LLWorldMipmap::scaleToLevel(sMapScale); +	S32 level = LLWorldMipmap::scaleToLevel(mMapScale);  	LLLocalClipRect clip(getLocalRect());  	{ @@ -347,15 +432,15 @@ void LLWorldMapView::draw()  		// Find x and y position relative to camera's center.  		LLVector3d rel_region_pos = origin_global - camera_global; -		F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; -		F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; +		F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * mMapScale; +		F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * mMapScale;  		// Coordinates of the sim in pixels in the UI panel  		// When the view isn't panned, 0,0 = center of rectangle -		F32 bottom =    sPanY + half_height + relative_y; -		F32 left =      sPanX + half_width + relative_x; -		F32 top =       bottom + sMapScale ; -		F32 right =     left + sMapScale ; +		F32 bottom =    mPanY + half_height + relative_y; +		F32 left =      mPanX + half_width + relative_x; +		F32 top =       bottom + mMapScale ; +		F32 right =     left + mMapScale ;  		// Discard if region is outside the screen rectangle (not visible on screen)  		if ((top < 0.f)   || (bottom > height) || @@ -416,7 +501,7 @@ void LLWorldMapView::draw()  			if (overlayimage)  			{  				// Inform the fetch mechanism of the size we need -				S32 draw_size = ll_round(sMapScale); +				S32 draw_size = ll_round(mMapScale);  				overlayimage->setKnownDrawSize(ll_round(draw_size * LLUI::getScaleFactor().mV[VX]), ll_round(draw_size * LLUI::getScaleFactor().mV[VY]));  				// Draw something whenever we have enough info  				if (overlayimage->hasGLTexture()) @@ -444,7 +529,7 @@ void LLWorldMapView::draw()  		}  		// Draw the region name in the lower left corner -		if (sMapScale >= DRAW_TEXT_THRESHOLD) +		if (mMapScale >= DRAW_TEXT_THRESHOLD)  		{  			LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD));  			std::string mesg; @@ -464,7 +549,7 @@ void LLWorldMapView::draw()  					LLColor4::white,  					LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW,  					S32_MAX, //max_chars -					sMapScale, //max_pixels +					mMapScale, //max_pixels  					NULL,  					TRUE); //use ellipses  			} @@ -591,7 +676,7 @@ void LLWorldMapView::setVisible(BOOL visible)  void LLWorldMapView::drawMipmap(S32 width, S32 height)  {  	// Compute the level of the mipmap to use for the current scale level -	S32 level = LLWorldMipmap::scaleToLevel(sMapScale); +	S32 level = LLWorldMipmap::scaleToLevel(mMapScale);  	// Set the tile boost level so that unused tiles get to 0  	LLWorldMap::getInstance()->equalizeBoostLevels(); @@ -874,7 +959,7 @@ void LLWorldMapView::drawAgents()  void LLWorldMapView::drawFrustum()  {  	// Draw frustum -	F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; +	F32 meters_to_pixels = mMapScale/ REGION_WIDTH_METERS;  	F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();  	F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); @@ -884,8 +969,8 @@ void LLWorldMapView::drawFrustum()  	F32 half_width_pixels = half_width_meters * meters_to_pixels;  	// Compute the frustum coordinates. Take the UI scale into account. -    F32 ctr_x = ((getLocalRect().getWidth() * 0.5f + sPanX)  * LLUI::getScaleFactor().mV[VX]); -    F32 ctr_y = ((getLocalRect().getHeight() * 0.5f + sPanY) * LLUI::getScaleFactor().mV[VY]); +    F32 ctr_x = ((getLocalRect().getWidth() * 0.5f + mPanX)  * LLUI::getScaleFactor().mV[VX]); +    F32 ctr_y = ((getLocalRect().getHeight() * 0.5f + mPanY) * LLUI::getScaleFactor().mV[VY]);  	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -942,13 +1027,13 @@ LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos )  	LLVector3 pos_local;  	pos_local.setVec(relative_pos_global);  // convert to floats from doubles -	pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS; -	pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS; +	pos_local.mV[VX] *= mMapScale / REGION_WIDTH_METERS; +	pos_local.mV[VY] *= mMapScale / REGION_WIDTH_METERS;  	// leave Z component in meters -	pos_local.mV[VX] += getRect().getWidth() / 2 + sPanX; -	pos_local.mV[VY] += getRect().getHeight() / 2 + sPanY; +	pos_local.mV[VX] += getRect().getWidth() / 2 + mPanX; +	pos_local.mV[VY] += getRect().getHeight() / 2 + mPanY;  	return pos_local;  } @@ -1019,12 +1104,12 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&  // If you change this, then you need to change LLTracker::getTrackedPositionGlobal() as well  LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )  { -	x -= llfloor((getRect().getWidth() / 2 + sPanX)); -	y -= llfloor((getRect().getHeight() / 2 + sPanY)); +	x -= llfloor((getRect().getWidth() / 2 + mPanX)); +	y -= llfloor((getRect().getHeight() / 2 + mPanY));  	LLVector3 pos_local( (F32)x, (F32)y, 0.f ); -	pos_local *= ( REGION_WIDTH_METERS / sMapScale ); +	pos_local *= ( REGION_WIDTH_METERS / mMapScale );  	LLVector3d pos_global;  	pos_global.setVec( pos_local ); @@ -1481,7 +1566,7 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,  	LLWorldMap::getInstance()->cancelTracking(); -	S32 level = LLWorldMipmap::scaleToLevel(sMapScale); +	S32 level = LLWorldMipmap::scaleToLevel(mMapScale);  	// If the zoom level is not too far out already, test hits  	if (level <= DRAW_SIMINFO_THRESHOLD)  	{ @@ -1598,8 +1683,8 @@ BOOL LLWorldMapView::handleMouseDown( S32 x, S32 y, MASK mask )  {  	gFocusMgr.setMouseCapture( this ); -	mMouseDownPanX = ll_round(sPanX); -	mMouseDownPanY = ll_round(sPanY); +	mMouseDownPanX = ll_round(mPanX); +	mMouseDownPanY = ll_round(mPanY);  	mMouseDownX = x;  	mMouseDownY = y;  	sHandledLastClick = TRUE; @@ -1614,8 +1699,8 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )  		{  			// restore mouse cursor  			S32 local_x, local_y; -			local_x = mMouseDownX + llfloor(sPanX - mMouseDownPanX); -			local_y = mMouseDownY + llfloor(sPanY - mMouseDownPanY); +			local_x = mMouseDownX + llfloor(mPanX - mMouseDownPanX); +			local_y = mMouseDownY + llfloor(mPanY - mMouseDownPanY);  			LLRect clip_rect = getRect();  			clip_rect.stretch(-8);  			clip_rect.clipPointToRect(mMouseDownX, mMouseDownY, local_x, local_y); @@ -1643,7 +1728,7 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )  void LLWorldMapView::updateVisibleBlocks()  { -	if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD) +	if (LLWorldMipmap::scaleToLevel(mMapScale) > DRAW_SIMINFO_THRESHOLD)  	{  		// If we're zoomed out too much, we just don't load all those sim info: too much!  		return; @@ -1659,16 +1744,16 @@ void LLWorldMapView::updateVisibleBlocks()  	const F32 half_height = F32(height) / 2.0f;  	// Compute center into sim grid coordinates -	S32 world_center_x = S32((-sPanX / sMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); -	S32 world_center_y = S32((-sPanY / sMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); +	S32 world_center_x = S32((-mPanX / mMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); +	S32 world_center_y = S32((-mPanY / mMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS));  	// Compute the boundaries into sim grid coordinates -	S32 world_left   = world_center_x - S32(half_width  / sMapScale) - 1; -	S32 world_right  = world_center_x + S32(half_width  / sMapScale) + 1; -	S32 world_bottom = world_center_y - S32(half_height / sMapScale) - 1; -	S32 world_top    = world_center_y + S32(half_height / sMapScale) + 1; +	S32 world_left   = world_center_x - S32(half_width  / mMapScale) - 1; +	S32 world_right  = world_center_x + S32(half_width  / mMapScale) + 1; +	S32 world_bottom = world_center_y - S32(half_height / mMapScale) - 1; +	S32 world_top    = world_center_y + S32(half_height / mMapScale) + 1; -	//LL_INFOS("WorldMap") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom  = " << world_bottom << ", top = " << world_top << LL_ENDL; +	//LL_INFOS("WorldMap") << "LLWorldMapView::updateVisibleBlocks() : mMapScale = " << mMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom  = " << world_bottom << ", top = " << world_top << LL_ENDL;  	LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top);  } @@ -1689,10 +1774,10 @@ BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask )  			F32 delta_y = (F32)(gViewerWindow->getCurrentMouseDY());  			// Set pan to value at start of drag + offset -			sPanX += delta_x; -			sPanY += delta_y; -			sTargetPanX = sPanX; -			sTargetPanY = sPanY; +			mPanX += delta_x; +			mPanY += delta_y; +			mTargetPanX = mPanX; +			mTargetPanY = mPanY;  			gViewerWindow->moveCursorToCenter();  		} @@ -1789,4 +1874,8 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )  	return FALSE;  } +// static +F32 LLWorldMapView::scaleFromZoom(F32 zoom) { return exp2(zoom) * 256.0f; } +// static +F32 LLWorldMapView::zoomFromScale(F32 scale) { return log2(scale / 256.f); } diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index a2a6dc53fb..ce8af76a82 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -67,12 +67,22 @@ public:  	bool			checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track);  	void			handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); -	// Scale and pan are shared across all instances! (i.e. Terrain and Objects maps are always registered) -	static void		setScale( F32 scale ); -	static void		translatePan( S32 delta_x, S32 delta_y ); -	static void		setPan( S32 x, S32 y, BOOL snap = TRUE ); +    // Scale, aka zoom, is shared across all instances! (i.e. Terrain and Objects maps are always registered) +    // Zoom is used for UI and will interpolate the map scale over multiple frames. +    void zoom(F32 zoom); +    void zoomWithPivot(F32 zoom, S32 x, S32 y); +    F32 getZoom(); +    // Scale is a linear scaling factor of in-world coordinates +    F32 getScale(); +    // setScaleSetting/getScaleSetting are for the default map setting on login +    static void setScaleSetting(F32 scaleSetting); +    static F32 getScaleSetting(); +    // Pan is in pixels relative to the center of the map. +	void translatePan( S32 delta_x, S32 delta_y ); +    void setPan( S32 x, S32 y, BOOL snap = TRUE ); +    void setPanWithInterpTime(S32 x, S32 y, BOOL snap, F32 interp_time);  	// Return true if the current scale level is above the threshold for accessing region info -	static bool		showRegionInfo(); +    bool showRegionInfo();  	LLVector3		globalPosToView(const LLVector3d& global_pos);  	LLVector3d		viewPosToGlobal(S32 x,S32 y); @@ -153,14 +163,12 @@ public:  	static LLUIImagePtr	sForSaleImage;  	static LLUIImagePtr	sForSaleAdultImage; -	static F32		sMapScale;				// scale = size of a region in pixels -  	BOOL			mItemPicked; -	static F32		sPanX;		// in pixels -	static F32		sPanY;		// in pixels -	static F32		sTargetPanX;		// in pixels -	static F32		sTargetPanY;		// in pixels +    F32 mPanX; // in pixels +    F32 mPanY; // in pixels +    F32 mTargetPanX; // in pixels +    F32 mTargetPanY; // in pixels  	static S32		sTrackingArrowX;  	static S32		sTrackingArrowY;  	static bool		sVisibleTilesLoaded; @@ -194,6 +202,19 @@ public:  private:  	void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right); + +    void setScale(F32 scale, bool snap = true); + +    static F32 scaleFromZoom(F32 zoom); +    static F32 zoomFromScale(F32 scale); + +    F32 mMapScale; +    F32 mTargetMapScale; +    static F32 sMapScaleSetting; +    static LLVector2 sZoomPivot; +    static LLFrameTimer sZoomTimer; + +    F32 mMapIterpTime;  };  #endif diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 54e6c6fc6e..96ba80dacc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7238,6 +7238,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)  	mResetVertexBuffers = false;  	mCubeVB = NULL; +    mDeferredVB = NULL;  	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();   			iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -7271,10 +7272,11 @@ void LLPipeline::doResetVertexBuffers(bool forced)  		LLPathingLib::getInstance()->cleanupVBOManager();  	}  	LLVOPartGroup::destroyGL(); +    gGL.resetVertexBuffer();  	SUBSYSTEM_CLEANUP(LLVertexBuffer); -	if (LLVertexBuffer::sGLCount > 0) +	if (LLVertexBuffer::sGLCount != 0)  	{  		LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL;  	} @@ -7295,6 +7297,10 @@ void LLPipeline::doResetVertexBuffers(bool forced)  	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");  	LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); +    gGL.initVertexBuffer(); + +    mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); +    mDeferredVB->allocateBuffer(8, 0, true);  	LLVOPartGroup::restoreGL();  } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 1085972d9e..c3ce83e834 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -514,8 +514,8 @@       name="MapFrustumColor"       reference="White_10" />      <color -     name="MapFrustumRotatingColor" -     value="1 1 1 0.2" /> +     name="MapParcelOutlineColor" +     value="1 1 0 0.5" />      <color       name="MapTrackColor"       reference="Red" /> @@ -607,10 +607,10 @@       value="0 0 0 1" />      <color       name="NetMapGroupOwnAboveWater" -     reference="Purple" /> +     value="0.85 0 0.85 1" />      <color       name="NetMapGroupOwnBelowWater" -     value="0.78 0 0.78 1" /> +     value="0.63 0 0.63 1" />      <color       name="NetMapOtherOwnAboveWater"       value="0.24 0.24 0.24 1" /> @@ -619,10 +619,10 @@       value="0.12 0.12 0.12 1" />      <color       name="NetMapYouOwnAboveWater" -     value="0 1 1 1" /> +     value="0 0.85 0.85 1" />      <color       name="NetMapYouOwnBelowWater" -     value="0 0.78 0.78 1" /> +     value="0 0.63 0.63 1" />      <color       name="NotifyBoxColor"       value="LtGray" /> diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml index bba30626b2..632daaec7e 100644 --- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml +++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml @@ -88,6 +88,7 @@       spellcheck="true"       text_readonly_color="white"       text_type="ascii_with_newline" +     commit_on_focus_lost="true"       top_pad="5"       width="290"       wrap="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index b8893e11d9..9639e70544 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -16,11 +16,35 @@   width="200">      <floater.string       name="ToolTipMsg"> -        [REGION](Double-click to open Map, shift-drag to pan) +        [PARCEL_NAME_MSG][PARCEL_SALE_PRICE_MSG][PARCEL_SALE_AREA_MSG][PARCEL_OWNER_MSG][REGION_NAME_MSG][TOOL_TIP_HINT_MSG] +    </floater.string> +    <floater.string +     name="ParcelNameMsg"> +        [PARCEL_NAME] +    </floater.string> +    <floater.string +     name="ParcelSalePriceMsg"> +        Price: L$[PRICE] (L$[PRICE_PER_SQM]/m²) +    </floater.string> +    <floater.string +     name="ParcelSaleAreaMsg"> +        Area: [AREA]m² +    </floater.string> +    <floater.string +     name="ParcelOwnerMsg"> +        Owner: [PARCEL_OWNER] +    </floater.string> +    <floater.string +     name="RegionNameMsg"> +        Region: [REGION_NAME]      </floater.string>  	<floater.string -     name="AltToolTipMsg"> -		[REGION](Double-click to teleport, shift-drag to pan) +     name="ToolTipHintMsg"> +        Double-click to open map +	</floater.string> +	<floater.string +     name="AltToolTipHintMsg"> +        Double-click to teleport  	</floater.string>  	<floater.string name="mini_map_caption">  	Mini-map @@ -37,105 +61,73 @@      <text       type="string"       length="1" -     bottom="218"       label="N"       layout="topleft" -     left="0"       name="floater_map_north" -     right="10" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          N      </text>      <text       type="string"       length="1" -     bottom="218"       label="E"       layout="topleft" -     left="0"       name="floater_map_east" -     right="10" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          E      </text>      <text       type="string"       length="1" -     bottom="205"       label="W"       layout="topleft" -     left="0"       name="floater_map_west" -     right="11" -     text_color="1 1 1 0.7" -     top="175"> +     text_color="1 1 1 0.7">          W      </text>      <text       type="string"       length="1" -     bottom="218"       label="S"       layout="topleft" -     left="0"       name="floater_map_south" -     right="10" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          S      </text>      <text       type="string"       length="1" -     bottom="218"       label="SE"       layout="topleft" -     left="0"       name="floater_map_southeast" -     right="20" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          SE      </text>      <text       type="string"       length="1" -     bottom="218"       label="NE"       layout="topleft" -     left="0"       name="floater_map_northeast" -     right="20" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          NE      </text>      <text       type="string"       length="1" -     bottom="218"       label="SW"       layout="topleft" -     left="0"       name="floater_map_southwest" -     right="20" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          SW      </text>      <text       type="string"       length="1" -     bottom="218"       label="NW"       layout="topleft" -     left="0"       name="floater_map_northwest" -     right="20" -     text_color="1 1 1 0.7" -     top="189"> +     text_color="1 1 1 0.7">          NW      </text>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index e499ddbc2f..21c894d3af 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -830,6 +830,7 @@                          <combo_item name="physics_medium"> Medium </combo_item>                          <combo_item name="physics_low">    Low    </combo_item>                          <combo_item name="physics_lowest"> Lowest </combo_item> +                        <combo_item name="physics_bounding_box"> Bounding Box </combo_item>                          <combo_item name="load_from_file"> From file   </combo_item>                      </combo_box>                      <line_editor diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 45e11fc836..c965a4427c 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -733,6 +733,7 @@       name="zoom_icon"       top_pad="7"       width="16" ></icon> +    <!-- NOTE: min_val for zoom slider is hardcoded for performance reasons -->      <slider       follows="left|bottom"       height="16" @@ -740,7 +741,7 @@       initial_value="-2"       left_pad="0"       layout="topleft" -     max_val="0" +     max_val="4"       min_val="-8"       name="zoom slider"       show_text="false" diff --git a/indra/newview/skins/default/xui/en/menu_mini_map.xml b/indra/newview/skins/default/xui/en/menu_mini_map.xml index ea263d05ce..2715c916d4 100644 --- a/indra/newview/skins/default/xui/en/menu_mini_map.xml +++ b/indra/newview/skins/default/xui/en/menu_mini_map.xml @@ -8,63 +8,109 @@   top="724"   visible="false"   width="128"> -	<menu_item_call -     label="Zoom Close" -     name="Zoom Close"> -        <menu_item_call.on_click -         function="Minimap.Zoom" +    <menu_item_check +     label="Zoom very close" +     name="Zoom very close"> +        <menu_item_check.on_check +         function="Minimap.Zoom.Check" +         parameter="very close" /> +        <menu_item_check.on_click +         function="Minimap.Zoom.Set" +         parameter="very close" /> +    </menu_item_check> +    <menu_item_check +     label="Zoom close" +     name="Zoom close"> +        <menu_item_check.on_check +         function="Minimap.Zoom.Check"           parameter="close" /> -    </menu_item_call> -    <menu_item_call -     label="Zoom Medium" -     name="Zoom Medium"> -        <menu_item_call.on_click -         function="Minimap.Zoom" +        <menu_item_check.on_click +         function="Minimap.Zoom.Set" +         parameter="close" /> +    </menu_item_check> +    <menu_item_check +     label="Zoom medium" +     name="Zoom medium"> +        <menu_item_check.on_check +         function="Minimap.Zoom.Check"           parameter="medium" /> -    </menu_item_call> -    <menu_item_call -     label="Zoom Far" -     name="Zoom Far"> -        <menu_item_call.on_click -         function="Minimap.Zoom" +        <menu_item_check.on_click +         function="Minimap.Zoom.Set" +         parameter="medium" /> +    </menu_item_check> +    <menu_item_check +     label="Zoom far" +     name="Zoom far"> +        <menu_item_check.on_check +         function="Minimap.Zoom.Check"           parameter="far" /> -    </menu_item_call> -	<menu_item_call -     label="Zoom Default" -     name="Zoom Default"> -		<menu_item_call.on_click -         function="Minimap.Zoom" -         parameter="default" /> -	</menu_item_call> +        <menu_item_check.on_click +         function="Minimap.Zoom.Set" +         parameter="far" /> +    </menu_item_check>  	<menu_item_separator />      <menu_item_check -       label="Rotate Map" -       name="Rotate Map"> +       label="North at top" +       name="North at top">            <menu_item_check.on_check -             control="MiniMapRotate" /> +             function="Minimap.MapOrientation.Check" +             parameter="north_at_top" />            <menu_item_check.on_click -             function="ToggleControl" -             parameter="MiniMapRotate" /> +             function="Minimap.MapOrientation.Set" +             parameter="north_at_top" />      </menu_item_check>      <menu_item_check -       label="Auto Center" -       name="Auto Center"> +       label="Camera at top" +       name="Camera at top">            <menu_item_check.on_check -             control="MiniMapAutoCenter" /> +             function="Minimap.MapOrientation.Check" +             parameter="camera_at_top" />            <menu_item_check.on_click -             function="ToggleControl" -             parameter="MiniMapAutoCenter" /> +             function="Minimap.MapOrientation.Set" +             parameter="camera_at_top" /> +    </menu_item_check> +	<menu_item_separator /> +    <menu_item_check +     label="Show parcel boundaries" +     name="Show parcel boundaries"> +        <menu_item_check.on_check +         control="MiniMapShowPropertyLines" /> +        <menu_item_check.on_click +         function="ToggleControl" +         parameter="MiniMapShowPropertyLines" />      </menu_item_check>      <menu_item_separator /> +    <menu_item_check +     label="Auto-center map" +     name="Auto-center map"> +        <menu_item_check.on_check +         control="MiniMapAutoCenter" /> +        <menu_item_check.on_click +         function="ToggleControl" +         parameter="MiniMapAutoCenter" /> +    </menu_item_check> +    <menu_item_separator /> +    <menu_item_call +     label="Re-center map" +     name="Re-center map"> +        <menu_item_call.on_click +         function="Minimap.Center.Activate" /> +    </menu_item_call>      <menu_item_call -     label="Stop Tracking" -     name="Stop Tracking"> +     label="Stop tracking" +     name="Stop tracking">          <menu_item_call.on_click           function="Minimap.Tracker"           parameter="task_properties" />      </menu_item_call>      <menu_item_separator />      <menu_item_call +     label="About Land" +     name="About Land"> +        <menu_item_call.on_click +         function="Minimap.AboutLand" /> +    </menu_item_call> +    <menu_item_call       label="World Map"       name="World Map">          <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 6c317f9995..58584345a9 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3333,6 +3333,18 @@ function="World.EnvPreset"                   function="Advanced.DropPacket" />              </menu_item_call>          </menu> +        <menu +         create_jump_keys="true" +         label="Cache" +         name="Cache" +         tear_off="true"> +            <menu_item_call +             label="Purge Disk Cache" +             name="Purge Disk Cache"> +                <menu_item_call.on_click +                 function="Advanced.PurgeDiskCache" /> +            </menu_item_call> +        </menu>          <menu_item_call           label="Dump Scripted Camera"           name="Dump Scripted Camera"> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index aa1b929412..54f038c24f 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -155,6 +155,7 @@       right="-3"       mouse_opaque="true"       name="speaking_indicator" +     tool_tip="Voice volume"       visible="true"       width="20" />  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml b/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml index 5e3de180f9..331ba889d8 100644 --- a/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml @@ -14,7 +14,7 @@  				<label name="favorites_bar_label" tool_tip="Перетаскивайте сюда закладки, чтобы было удобнее переходить в любимые места в Second Life!">  					Избранное  				</label> -				<more_button name=">>" tool_tip="Показать больше избранного"> +				<more_button name=">>" tool_tip="Показать больше избранного" width="60">  					Больше ▼  				</more_button>  			</favorites_bar> diff --git a/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml b/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml index 8d43e3fb5a..ae9bc33bfa 100644 --- a/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml @@ -14,7 +14,7 @@  				<label name="favorites_bar_label" tool_tip="Second Life içerisinde sık kullandığınız yerlere hızla erişmek için Yer İmlerini buraya sürükleyin!">  					Favoriler Çubuğu  				</label> -				<more_button name=">>" tool_tip="Favorilerimden daha çok göster"> +				<more_button name=">>" tool_tip="Favorilerimden daha çok göster" width="65">  					Daha Fazla ▼  				</more_button>  			</favorites_bar> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 3327ecfb56..be5c9bfcc5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -568,6 +568,7 @@ class WindowsManifest(ViewerManifest):          self.path(src="licenses-win32.txt", dst="licenses.txt")          self.path("featuretable.txt") +        self.path("cube.dae")          with self.prefix(src=pkgdir):              self.path("ca-bundle.crt") @@ -954,6 +955,7 @@ class DarwinManifest(ViewerManifest):                  self.path("licenses-mac.txt", dst="licenses.txt")                  self.path("featuretable_mac.txt") +                self.path("cube.dae")                  self.path("SecondLife.nib")                  with self.prefix(src=pkgdir,dst=""): @@ -1427,6 +1429,7 @@ class LinuxManifest(ViewerManifest):              print("Skipping llcommon.so (assuming llcommon was linked statically)")          self.path("featuretable_linux.txt") +        self.path("cube.dae")          with self.prefix(src=pkgdir):              self.path("ca-bundle.crt") diff --git a/scripts/content_tools/anim_tool.py b/scripts/content_tools/anim_tool.py index e7b86a88fa..4a0773951e 100644 --- a/scripts/content_tools/anim_tool.py +++ b/scripts/content_tools/anim_tool.py @@ -611,6 +611,7 @@ def main(*argv):      parser = argparse.ArgumentParser(description="process SL animations")      parser.add_argument("--verbose", help="verbose flag", action="store_true")      parser.add_argument("--dump", help="dump to stdout", action="store_true") +    parser.add_argument("--use_aliases", help="use alias names for bones", action="store_true")      parser.add_argument("--rot", help="specify sequence of rotations", type=float_triple, nargs="+")      parser.add_argument("--rand_pos", help="request NUM random positions (default %(default)s)",                          metavar="NUM", type=int, default=2) @@ -637,6 +638,7 @@ def main(*argv):      parser.add_argument("--no_hud", help="omit hud joints from list of attachments", action="store_true")      parser.add_argument("--base_priority", help="set base priority", type=int)      parser.add_argument("--joint_priority", help="set joint priority for all joints", type=int) +    parser.add_argument("--force_joints", help="don't check validity of joint names", action="store_true")      parser.add_argument("infilename", help="name of a .anim file to input")      parser.add_argument("outfilename", nargs="?", help="name of a .anim file to output")      args = parser.parse_args(argv) @@ -661,7 +663,12 @@ def main(*argv):          if lad_tree is None:              raise Error("failed to parse " + args.lad)      if args.joints: -        joints = resolve_joints(args.joints, skel_tree, lad_tree, args.no_hud) +        if args.force_joints: +            joints = args.joints +        else: +            joints = resolve_joints(args.joints, skel_tree, lad_tree, args.no_hud) +        if args.use_aliases: +            joints = map(lambda name: "avatar_" + name, joints)          if args.verbose:              print("joints resolved to",joints)          for name in joints: diff --git a/scripts/content_tools/skel_tool.py b/scripts/content_tools/skel_tool.py index 449ecd6a6c..696e4e2923 100644 --- a/scripts/content_tools/skel_tool.py +++ b/scripts/content_tools/skel_tool.py @@ -72,6 +72,22 @@ def check_symmetry(name, field, vec1, vec2):      if vec1[2] != vec2[2]:          print(name,field,"z match fail") +def enforce_alias_rules(tree, element, fix=False): +    if element.tag != "bone": +        return +    alias_lis = [] +    aliases = element.get("aliases") +    if aliases: +        alias_lis = aliases.split(" ") +    name = element.get("name") +    if name: +        std_alias = "avatar_" + name +        if not std_alias in alias_lis: +            print "missing expected alias",name,std_alias +        for alias in alias_lis: +            if alias.startswith("avatar_") and alias != std_alias: +                print "invalid avatar_ alias",name,alias +  def enforce_symmetry(tree, element, field, fix=False):      name = element.get("name")      if not name: @@ -209,6 +225,7 @@ def validate_skel_tree(tree, ogtree, reftree, fix=False):                              unfixable += 1          fix_name(element) +        enforce_alias_rules(tree, element, fix)          enforce_precision_rules(element)          for field in ["pos","pivot"]:              enforce_symmetry(tree, element, field, fix) | 
