diff options
56 files changed, 3056 insertions, 2313 deletions
| diff --git a/BuildParams b/BuildParams index ad2f71e336..58852110ef 100644..100755 --- a/BuildParams +++ b/BuildParams @@ -83,6 +83,26 @@ mesh-development.build_CYGWIN_Debug = false  mesh-development.build_viewer_update_version_manager = false  # ======================================== +# mesh-development-release-1-candidate +# ======================================== +mesh-development-release-1-candidate.viewer_channel = "Project Viewer - Mesh" +mesh-development-release-1-candidate.login_channel = "Project Viewer - Mesh" +mesh-development-release-1-candidate.viewer_grid = agni +mesh-development-release-1-candidate.build_debug_release_separately = true +mesh-development-release-1-candidate.build_CYGWIN_Debug = false +mesh-development-release-1-candidate.build_viewer_update_version_manager = false + +# ======================================== +# mesh-development-rc +# ======================================== +mesh-development-rc.viewer_channel = "Project Viewer - Mesh" +mesh-development-rc.login_channel = "Project Viewer - Mesh" +mesh-development-rc.viewer_grid = agni +mesh-development-rc.build_debug_release_separately = true +mesh-development-rc.build_CYGWIN_Debug = false +mesh-development-rc.build_viewer_update_version_manager = false + +# ========================================  # mesh-asset-deprecation  # ========================================  mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation" diff --git a/autobuild.xml b/autobuild.xml index d381035248..6872af0661 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -246,9 +246,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>d05be8fc196e9ce7b6636b931cf13dff</string> +              <string>be7321370b69b6d66938b82a9230a067</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/226716/arch/Linux/installer/colladadom-2.2-linux-20110415.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-colladadom/rev/233450/arch/Linux/installer/colladadom-2.2-linux-20110621.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -1110,9 +1110,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>6e45ad68506cd1ba49fd35a3201f0478</string> +              <string>0db10480362168f075c2af0ae302cb74</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110504.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110707.tar.bz2</string>              </map>              <key>name</key>              <string>darwin</string> @@ -1122,9 +1122,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>00ff5144612c2e261a0811a4503ce3ba</string> +              <string>f3c667dc159c0537a9122ce6e72e16db</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110504.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110707.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -1134,9 +1134,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>a4635dcbbe0915ce023dd41d3b848d4c</string> +              <string>46cac4d667446bbbc9b5023f2848a5ac</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/228821/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110504.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110707.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string> @@ -1148,7 +1148,7 @@          <key>license</key>          <string>lgpl</string>          <key>license_file</key> -        <string>LICENSES/lgpl.txt</string> +        <string>LICENSES/LLConvexDecompositionStubLicense.txt</string>          <key>name</key>          <string>llconvexdecompositionstub</string>          <key>platforms</key> diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 99c5412ae5..f2462ba426 100644..100755 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -32,7 +32,7 @@ const S32 LL_VERSION_MINOR = 8;  const S32 LL_VERSION_PATCH = 4;  const S32 LL_VERSION_BUILD = 0; -const char * const LL_CHANNEL = "Second Life Developer"; +const char * const LL_CHANNEL = "Project Viewer - Mesh";  #if LL_DARWIN  const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 93f3c910bd..331a1692ee 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -380,7 +380,7 @@ void LLCrashLogger::updateApplication(const std::string& message)  bool LLCrashLogger::init()  { -	LLCurl::initClass(); +	LLCurl::initClass(false);  	// We assume that all the logs we're looking for reside on the current drive  	gDirUtilp->initAppDirs("SecondLife"); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 21cc9b22f2..2893e746e9 100644..100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -32,6 +32,7 @@  #if !LL_WINDOWS  #include <stdint.h>  #endif +#include <cmath>  #include "llerror.h"  #include "llmemtype.h" @@ -2379,11 +2380,16 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co  bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const  {  	bool retval = false; -	if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord) + +	const F32 epsilon = 0.00001f; + +	if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) &&  +		fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && +		fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon)  	{  		if (angle_cutoff > 1.f)  		{ -			retval = (mData[NORMAL].equals3(rhs.mData[NORMAL])); +			retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon));  		}  		else  		{ @@ -2499,9 +2505,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			}  			{ -				U16* n = (U16*) &(norm[0]); -				if(n) +				if (!norm.empty())  				{ +					U16* n = (U16*) &(norm[0]);  					for (U32 j = 0; j < num_verts; ++j)  					{  						norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); @@ -2512,12 +2518,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  						n += 3;  					}  				} +				else +				{ +					memset(norm_out, 0, sizeof(LLVector4a)*num_verts); +				}  			}  			{ -				U16* t = (U16*) &(tc[0]); -				if(t) +				if (!tc.empty())  				{ +					U16* t = (U16*) &(tc[0]);  					for (U32 j = 0; j < num_verts; j+=2)  					{  						if (j < num_verts-1) @@ -2538,6 +2548,10 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  						tc_out++;  					}  				} +				else +				{ +					memset(tc_out, 0, sizeof(LLVector2)*num_verts); +				}  			}  			if (mdl[i].has("Weights")) @@ -2662,6 +2676,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  					min.setMin(min, face.mPositions[i]);  					max.setMax(max, face.mPositions[i]);  				} + +				if (face.mTexCoords) +				{ +					LLVector2& min_tc = face.mTexCoordExtents[0]; +					LLVector2& max_tc = face.mTexCoordExtents[1]; + +					min_tc = face.mTexCoords[0]; +					max_tc = face.mTexCoords[0]; + +					for (U32 j = 1; j < face.mNumVertices; ++j) +					{ +						update_min_max(min_tc, max_tc, face.mTexCoords[j]); +					} +				} +				else +				{ +					face.mTexCoordExtents[0].set(0,0); +					face.mTexCoordExtents[1].set(1,1); +				}  			}  		}  	} @@ -2741,11 +2774,13 @@ void LLVolume::makeTetrahedron()  	n[2] = cv[2].getNormal();  	n += 3; -	tc[0] = cv[0].mTexCoord; -	tc[1] = cv[1].mTexCoord; -	tc[2] = cv[2].mTexCoord; -	tc += 3; - +	if(tc) +	{ +		tc[0] = cv[0].mTexCoord; +		tc[1] = cv[1].mTexCoord; +		tc[2] = cv[2].mTexCoord; +		tc += 3; +	}  	//side 2  	cv[0].setPosition(p[3]); @@ -2764,11 +2799,14 @@ void LLVolume::makeTetrahedron()  	n[2] = cv[2].getNormal();  	n += 3; -	tc[0] = cv[0].mTexCoord; -	tc[1] = cv[1].mTexCoord; -	tc[2] = cv[2].mTexCoord; -	tc += 3; -	 +	if(tc) +	{ +		tc[0] = cv[0].mTexCoord; +		tc[1] = cv[1].mTexCoord; +		tc[2] = cv[2].mTexCoord; +		tc += 3; +	} +  	//side 3  	cv[0].setPosition(p[3]);  	cv[1].setPosition(p[1]); @@ -2786,10 +2824,13 @@ void LLVolume::makeTetrahedron()  	n[2] = cv[2].getNormal();  	n += 3; -	tc[0] = cv[0].mTexCoord; -	tc[1] = cv[1].mTexCoord; -	tc[2] = cv[2].mTexCoord; -	tc += 3; +	if(tc) +	{ +		tc[0] = cv[0].mTexCoord; +		tc[1] = cv[1].mTexCoord; +		tc[2] = cv[2].mTexCoord; +		tc += 3; +	}  	//side 4  	cv[0].setPosition(p[2]); @@ -2808,10 +2849,13 @@ void LLVolume::makeTetrahedron()  	n[2] = cv[2].getNormal();  	n += 3; -	tc[0] = cv[0].mTexCoord; -	tc[1] = cv[1].mTexCoord; -	tc[2] = cv[2].mTexCoord; -	tc += 3; +	if(tc) +	{ +		tc[0] = cv[0].mTexCoord; +		tc[1] = cv[1].mTexCoord; +		tc[2] = cv[2].mTexCoord; +		tc += 3; +	}  	//set index buffer  	for (U16 i = 0; i < 12; i++) @@ -5580,7 +5624,16 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);  		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); -		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + +		if(src.mTexCoords) +		{ +			LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); +		} +		else +		{ +			ll_aligned_free_16(mTexCoords) ; +			mTexCoords = NULL ; +		}  		if (src.mBinormals) @@ -5702,8 +5755,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)  void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv)  {  	cv.setPosition(mPositions[index]); -	cv.setNormal(mNormals[index]); -	cv.mTexCoord = mTexCoords[index]; +	if (mNormals) +	{ +		cv.setNormal(mNormals[index]); +	} +	else +	{ +		cv.getNormal().clear(); +	} + +	if (mTexCoords) +	{ +		cv.mTexCoord = mTexCoords[index]; +	} +	else +	{ +		cv.mTexCoord.clear(); +	}  }  bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const @@ -5733,7 +5801,10 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  	LLVolumeFace new_face;  	//map of points to vector of vertices at that point -	VertexMapData::PointMap point_map; +	std::map<U64, std::vector<VertexMapData> > point_map; + +	LLVector4a range; +	range.setSub(mExtents[1],mExtents[0]);  	//remove redundant vertices  	for (U32 i = 0; i < mNumIndices; ++i) @@ -5744,7 +5815,19 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  		getVertexData(index, cv);  		BOOL found = FALSE; -		VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + +		LLVector4a pos; +		pos.setSub(mPositions[index], mExtents[0]); +		pos.div(range); + +		U64 pos64 = 0; + +		pos64 = (U16) (pos[0]*65535); +		pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); +		pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); + +		std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64); +		  		if (point_iter != point_map.end())  		{ //duplicate point might exist  			for (U32 j = 0; j < point_iter->second.size(); ++j) @@ -5776,11 +5859,26 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  			}  			else  			{ -				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); +				point_map[pos64].push_back(d);  			}  		}  	} +	llassert(new_face.mNumIndices == mNumIndices); +	llassert(new_face.mNumVertices <= mNumVertices); + +	if (angle_cutoff > 1.f && !mNormals) +	{ +		ll_aligned_free_16(new_face.mNormals); +		new_face.mNormals = NULL; +	} + +	if (!mTexCoords) +	{ +		ll_aligned_free_16(new_face.mTexCoords); +		new_face.mTexCoords = NULL; +	} +  	swapData(new_face);  } diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 0735842dcd..1a86a69a04 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -26,6 +26,7 @@   * $/LicenseInfo$   */ +  #if LL_WINDOWS  #define SAFE_SSL 1  #elif LL_DARWIN @@ -74,6 +75,7 @@ static const S32 MULTI_PERFORM_CALL_REPEAT	= 5;  static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds  static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; +static   // DEBUG //  S32 gCurlEasyCount = 0;  S32 gCurlMultiCount = 0; @@ -85,6 +87,9 @@ std::vector<LLMutex*> LLCurl::sSSLMutex;  std::string LLCurl::sCAPath;  std::string LLCurl::sCAFile; +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; +  void check_curl_code(CURLcode code)  {  	if (code != CURLE_OK) @@ -244,7 +249,7 @@ public:  	U32 report(CURLcode);  	void getTransferInfo(LLCurl::TransferInfo* info); -	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); +	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false);  	const char* getErrorBuffer(); @@ -525,7 +530,7 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data  void LLCurl::Easy::prepRequest(const std::string& url,  							   const std::vector<std::string>& headers, -							   ResponderPtr responder, bool post) +							   ResponderPtr responder, S32 time_out, bool post)  {  	resetState(); @@ -558,7 +563,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	//don't verify host name so urls with scrubbed host names will work (improves DNS performance)  	setopt(CURLOPT_SSL_VERIFYHOST, 0); -	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); +	setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));  	setoptString(CURLOPT_URL, url); @@ -601,6 +606,7 @@ public:  	S32 process();  	void perform(); +	void doPerform();  	virtual void run(); @@ -613,6 +619,7 @@ public:  	LLCondition* mSignal;  	bool mQuitting; +	bool mThreaded;  private:  	void easyFree(Easy*); @@ -634,7 +641,16 @@ LLCurl::Multi::Multi()  	  mPerformState(PERFORM_STATE_READY)  {  	mQuitting = false; -	mSignal = new LLCondition(NULL); + +	mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; +	if (mThreaded) +	{ +		mSignal = new LLCondition(NULL); +	} +	else +	{ +		mSignal = NULL; +	}  	mCurlMultiHandle = curl_multi_init();  	if (!mCurlMultiHandle) @@ -681,39 +697,53 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)  void LLCurl::Multi::perform()  { -	if (mPerformState == PERFORM_STATE_READY) +	if (mThreaded) +	{ +		if (mPerformState == PERFORM_STATE_READY) +		{ +			mSignal->signal(); +		} +	} +	else  	{ -		mSignal->signal(); +		doPerform();  	}  }  void LLCurl::Multi::run()  { +	llassert(mThreaded); +  	while (!mQuitting)  	{  		mSignal->wait();  		mPerformState = PERFORM_STATE_PERFORMING;  		if (!mQuitting)  		{ -			S32 q = 0; -			for (S32 call_count = 0; -				 call_count < MULTI_PERFORM_CALL_REPEAT; -				 call_count += 1) -			{ -				CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); -				if (CURLM_CALL_MULTI_PERFORM != code || q == 0) -				{ -					check_curl_multi_code(code); -					break; -				} -	 -			} -			mQueued = q; -			mPerformState = PERFORM_STATE_COMPLETED; +			doPerform();  		}  	}  } +void LLCurl::Multi::doPerform() +{ +	S32 q = 0; +	for (S32 call_count = 0; +			call_count < MULTI_PERFORM_CALL_REPEAT; +			call_count += 1) +	{ +		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); +		if (CURLM_CALL_MULTI_PERFORM != code || q == 0) +		{ +			check_curl_multi_code(code); +			break; +		} +	 +	} +	mQueued = q; +	mPerformState = PERFORM_STATE_COMPLETED; +} +  S32 LLCurl::Multi::process()  {  	perform(); @@ -839,10 +869,13 @@ LLCurlRequest::~LLCurlRequest()  	{  		LLCurl::Multi* multi = *iter;  		multi->mQuitting = true; -		while (!multi->isStopped()) +		if (multi->mThreaded)  		{ -			multi->mSignal->signal(); -			apr_sleep(1000); +			while (!multi->isStopped()) +			{ +				multi->mSignal->signal(); +				apr_sleep(1000); +			}  		}  	}  	for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); @@ -852,7 +885,10 @@ void LLCurlRequest::addMulti()  {  	llassert_always(mThreadID == LLThread::currentID());  	LLCurl::Multi* multi = new LLCurl::Multi(); -	multi->start(); +	if (multi->mThreaded) +	{ +		multi->start(); +	}  	mMultiSet.insert(multi);  	mActiveMulti = multi;  	mActiveRequestCount = 0; @@ -914,14 +950,14 @@ bool LLCurlRequest::getByteRange(const std::string& url,  bool LLCurlRequest::post(const std::string& url,  						 const headers_t& headers,  						 const LLSD& data, -						 LLCurl::ResponderPtr responder) +						 LLCurl::ResponderPtr responder, S32 time_out)  {  	LLCurl::Easy* easy = allocEasy();  	if (!easy)  	{  		return false;  	} -	easy->prepRequest(url, headers, responder); +	easy->prepRequest(url, headers, responder, time_out);  	LLSDSerialize::toXML(data, easy->getInput());  	S32 bytes = easy->getInput().str().length(); @@ -941,14 +977,14 @@ bool LLCurlRequest::post(const std::string& url,  bool LLCurlRequest::post(const std::string& url,  						 const headers_t& headers,  						 const std::string& data, -						 LLCurl::ResponderPtr responder) +						 LLCurl::ResponderPtr responder, S32 time_out)  {  	LLCurl::Easy* easy = allocEasy();  	if (!easy)  	{  		return false;  	} -	easy->prepRequest(url, headers, responder); +	easy->prepRequest(url, headers, responder, time_out);  	easy->getInput().write(data.data(), data.size());  	S32 bytes = easy->getInput().str().length(); @@ -983,10 +1019,13 @@ S32 LLCurlRequest::process()  		{  			mMultiSet.erase(curiter);  			multi->mQuitting = true; -			while (!multi->isStopped()) +			if (multi->mThreaded)  			{ -				multi->mSignal->signal(); -				apr_sleep(1000); +				while (!multi->isStopped()) +				{ +					multi->mSignal->signal(); +					apr_sleep(1000); +				}  			}  			delete multi; @@ -1006,6 +1045,10 @@ S32 LLCurlRequest::getQueued()  		curlmulti_set_t::iterator curiter = iter++;  		LLCurl::Multi* multi = *curiter;  		queued += multi->mQueued; +		if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) +		{ +			++queued; +		}  	}  	return queued;  } @@ -1019,7 +1062,10 @@ LLCurlEasyRequest::LLCurlEasyRequest()  	  mResultReturned(false)  {  	mMulti = new LLCurl::Multi(); -	mMulti->start(); +	if (mMulti->mThreaded) +	{ +		mMulti->start(); +	}  	mEasy = mMulti->allocEasy();  	if (mEasy)  	{ @@ -1031,10 +1077,13 @@ LLCurlEasyRequest::LLCurlEasyRequest()  LLCurlEasyRequest::~LLCurlEasyRequest()  {  	mMulti->mQuitting = true; -	while (!mMulti->isStopped()) +	if (mMulti->mThreaded)  	{ -		mMulti->mSignal->signal(); -		apr_sleep(1000); +		while (!mMulti->isStopped()) +		{ +			mMulti->mSignal->signal(); +			apr_sleep(1000); +		}  	}  	delete mMulti;  } @@ -1230,8 +1279,10 @@ unsigned long LLCurl::ssl_thread_id(void)  }  #endif -void LLCurl::initClass() +void LLCurl::initClass(bool multi_threaded)  { +	sMainThreadID = LLThread::currentID(); +	sMultiThreaded = multi_threaded;  	// Do not change this "unless you are familiar with and mean to control   	// internal operations of libcurl"  	// - http://curl.haxx.se/libcurl/c/curl_global_init.html diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 2f951d6ab8..f7518c8e5c 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -41,6 +41,7 @@  #include "llbuffer.h"  #include "lliopipe.h"  #include "llsd.h" +#include "llthread.h"  class LLMutex; @@ -55,6 +56,8 @@ public:  	class Easy;  	class Multi; +	static bool sMultiThreaded; +  	struct TransferInfo  	{  		TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -159,7 +162,7 @@ public:  	/**  	 * @ brief Initialize LLCurl class  	 */ -	static void initClass(); +	static void initClass(bool multi_threaded = false);  	/**  	 * @ brief Cleanup LLCurl class @@ -201,8 +204,8 @@ public:  	void get(const std::string& url, LLCurl::ResponderPtr responder);  	bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); -	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); -	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); +	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0); +	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);  	S32  process();  	S32  getQueued(); diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 0463d5364b..434fb7650b 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -27,6 +27,7 @@  #include "linden_common.h"  #include "llmodel.h" +#include "llmemory.h"  #include "llconvexdecomposition.h"  #include "llsdserialize.h"  #include "llvector4a.h" @@ -71,88 +72,10 @@ LLModel::~LLModel()  	}  } -void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Array& inputs, U32 min_idx, U32 max_idx) -{ -	for (U32 j = 0; j < inputs.getCount(); ++j) -	{ -		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) -		{ //found vertex array -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			domVertices* vertices = (domVertices*) elem.cast(); - -			domInputLocal_Array& v_inp = vertices->getInput_array(); -			if (inputs[j]->getOffset() != 0) -			{ -				llerrs << "Vertex array offset MUST be zero." << llendl; -			} - -			for (U32 k = 0; k < v_inp.getCount(); ++k) -			{ -				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) -				{ -					const domURIFragmentType& uri = v_inp[k]->getSource(); -					 -					daeElementRef elem = uri.getElement(); -					domSource* src = (domSource*) elem.cast(); - -					if (src->getTechnique_common()->getAccessor()->getStride() != 3) -					{ -						llerrs << "Vertex array stride MUST be three." << llendl; -					} - -					domListOfFloats& v = src->getFloat_array()->getValue(); - -					LLVector4a min; -					min.set(v[min_idx], v[min_idx+1], v[min_idx+2]); -					LLVector4a max = min; - -					for (U32 j = min_idx; j <= max_idx; ++j) -					{ //copy vertex array -						face.mPositions[j-min_idx].set(v[j*3+0], v[j*3+1], v[j*3+2]); -						update_min_max(min, max, face.mPositions[j-min_idx]); -					} - -					face.mExtents[0] = min; -					face.mExtents[1] = max; -				} -			} -		} - -		if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) -		{ -			//found normal array for this triangle list -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			domSource* src = (domSource*) elem.cast(); -			domListOfFloats& n = src->getFloat_array()->getValue(); -			 -			for (U32 j = min_idx; j <= max_idx; ++j) -			{ -				LLVector4a* norm = (LLVector4a*) face.mNormals + (j-min_idx); -				norm->set(n[j*3+0], n[j*3+1], n[j*3+2]); -				norm->normalize3(); -			} -		} -		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) -		{ //found texCoords -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			domSource* src = (domSource*) elem.cast(); -			domListOfFloats& u = src->getFloat_array()->getValue(); -			 -			for (U32 j = min_idx; j <= max_idx; ++j) -			{ -				face.mTexCoords[j-min_idx].setVec(u[j*2+0], u[j*2+1]); -			} -		} -	} -}  bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,  					 domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)  { -	  	idx_stride = 0;  	for (U32 j = 0; j < inputs.getCount(); ++j) @@ -271,14 +194,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],  								tc[idx[i+tc_offset]*2+1]);  		} - +		  		if (norm_source)  		{  			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],  								n[idx[i+norm_offset]*3+1],  								n[idx[i+norm_offset]*3+2]));  		} -  		BOOL found = FALSE; @@ -329,10 +251,22 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  		{  			face_list.push_back(face);  			face_list.rbegin()->fillFromLegacyData(verts, indices); +			LLVolumeFace& new_face = *face_list.rbegin(); +			if (!norm_source) +			{ +				ll_aligned_free_16(new_face.mNormals); +				new_face.mNormals = NULL; +			} + +			if (!tc_source) +			{ +				ll_aligned_free_16(new_face.mTexCoords); +				new_face.mTexCoords = NULL; +			} +  			face = LLVolumeFace();  			point_map.clear();  		} -  	}  	if (!verts.empty()) @@ -348,6 +282,18 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  		face_list.push_back(face);  		face_list.rbegin()->fillFromLegacyData(verts, indices); +		LLVolumeFace& new_face = *face_list.rbegin(); +		if (!norm_source) +		{ +			ll_aligned_free_16(new_face.mNormals); +			new_face.mNormals = NULL; +		} + +		if (!tc_source) +		{ +			ll_aligned_free_16(new_face.mTexCoords); +			new_face.mTexCoords = NULL; +		}  	}  	return LLModel::NO_ERRORS ; @@ -433,14 +379,14 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],  									tc[idx[cur_idx+tc_offset]*2+1]);  			} - +			  			if (norm_source)  			{  				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],  									n[idx[cur_idx+norm_offset]*3+1],  									n[idx[cur_idx+norm_offset]*3+2]);  			} - +			  			cur_idx += idx_stride;  			BOOL found = FALSE; @@ -524,6 +470,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  			{  				face_list.push_back(face);  				face_list.rbegin()->fillFromLegacyData(verts, indices); +				LLVolumeFace& new_face = *face_list.rbegin(); +				if (!norm_source) +				{ +					ll_aligned_free_16(new_face.mNormals); +					new_face.mNormals = NULL; +				} + +				if (!tc_source) +				{ +					ll_aligned_free_16(new_face.mTexCoords); +					new_face.mTexCoords = NULL; +				} +  				face = LLVolumeFace();  				verts.clear();  				indices.clear(); @@ -540,10 +499,23 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  		{  			material = std::string(poly->getMaterial());  		} -		 +	  		materials.push_back(material);  		face_list.push_back(face);  		face_list.rbegin()->fillFromLegacyData(verts, indices); + +		LLVolumeFace& new_face = *face_list.rbegin(); +		if (!norm_source) +		{ +			ll_aligned_free_16(new_face.mNormals); +			new_face.mNormals = NULL; +		} + +		if (!tc_source) +		{ +			ll_aligned_free_16(new_face.mTexCoords); +			new_face.mTexCoords = NULL; +		}  	}  	return LLModel::NO_ERRORS ; @@ -557,7 +529,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  	const domInputLocalOffset_Array& inputs = poly->getInput_array(); -  	S32 v_offset = -1;  	S32 n_offset = -1;  	S32 t_offset = -1; @@ -662,15 +633,14 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  								n->get(n_idx+1),  								n->get(n_idx+2));  			} - +			  			if (t)  			{  				U32 t_idx = idx[j*stride+t_offset]*2;  				vert.mTexCoord.setVec(t->get(t_idx),  								t->get(t_idx+1));								  			} -		 -			 +						  			verts.push_back(vert);  		}  	} @@ -733,6 +703,19 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  		materials.push_back(material);  		face_list.push_back(face);  		face_list.rbegin()->fillFromLegacyData(new_verts, indices); + +		LLVolumeFace& new_face = *face_list.rbegin(); +		if (!n) +		{ +			ll_aligned_free_16(new_face.mNormals); +			new_face.mNormals = NULL; +		} + +		if (!t) +		{ +			ll_aligned_free_16(new_face.mTexCoords); +			new_face.mTexCoords = NULL; +		}  	}  	return LLModel::NO_ERRORS ; @@ -817,9 +800,9 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)  		if (getNumVolumeFaces() > 0)  		{ -			optimizeVolumeFaces();  			normalizeVolumeFaces(); - +			optimizeVolumeFaces(); +			  			if (getNumVolumeFaces() > 0)  			{  				return TRUE; @@ -853,81 +836,10 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )  void LLModel::optimizeVolumeFaces()  { -#if 0 //VECTORIZE ? -	for (std::vector<LLVolumeFace>::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ) -	{ -		std::vector<LLVolumeFace>::iterator cur_iter = iter++; -		LLVolumeFace& face = *cur_iter; - -		for (S32 i = 0; i < (S32) face.mNumIndices; i += 3) -		{ //remove zero area triangles -			U16 i0 = face.mIndices[i+0]; -			U16 i1 = face.mIndices[i+1]; -			U16 i2 = face.mIndices[i+2]; - -			if (i0 == i1 ||  -				i1 == i2 ||  -				i0 == i2) -			{ //duplicate index in triangle, remove triangle -				face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3); -				i -= 3; -			} -			else -			{  -				LLVolumeFace::VertexData& v0 = face.mVertices[i0]; -				LLVolumeFace::VertexData& v1 = face.mVertices[i1]; -				LLVolumeFace::VertexData& v2 = face.mVertices[i2]; - -				if (v0.mPosition == v1.mPosition || -					v1.mPosition == v2.mPosition || -					v2.mPosition == v0.mPosition) -				{ //zero area triangle, delete -					face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3); -					i-=3; -				} -			} -		} - -		//remove unreference vertices -		std::vector<bool> ref; -		ref.resize(face.mNumVertices); - -		for (U32 i = 0; i < ref.size(); ++i) -		{ -			ref[i] = false; -		} - -		for (U32 i = 0; i < face.mNumIndices; ++i) -		{  -			ref[face.mIndices[i]] = true; -		} - -		U32 unref_count = 0; -		for (U32 i = 0; i < ref.size(); ++i) -		{ -			if (!ref[i]) -			{ -				//vertex is unreferenced -				face.mVertices.erase(face.mVertices.begin()+(i-unref_count)); -				U16 idx = (U16) (i-unref_count); - -				for (U32 j = 0; j < face.mNumIndices; ++j) -				{ //decrement every index array value greater than idx -					if (face.mIndices[j] > idx) -					{ -						--face.mIndices[j]; -					} -				} -				++unref_count; -			} -		} - -		if (face.mVertices.empty() || face.mIndices.empty()) -		{ //face is empty, remove it -			iter = mVolumeFaces.erase(cur_iter); -		} +	for (U32 i = 0; i < getNumVolumeFaces(); ++i) +	{ +		mVolumeFaces[i].optimize();  	} -#endif  }  // Shrink the model to fit @@ -962,6 +874,25 @@ void LLModel::normalizeVolumeFaces()  			update_min_max(min, max, face.mExtents[0]);  			update_min_max(min, max, face.mExtents[1]); + +			if (face.mTexCoords) +			{ +				LLVector2& min_tc = face.mTexCoordExtents[0]; +				LLVector2& max_tc = face.mTexCoordExtents[1]; + +				min_tc = face.mTexCoords[0]; +				max_tc = face.mTexCoords[0]; + +				for (U32 j = 1; j < face.mNumVertices; ++j) +				{ +					update_min_max(min_tc, max_tc, face.mTexCoords[j]); +				} +			} +			else +			{ +				face.mTexCoordExtents[0].set(0,0); +				face.mTexCoordExtents[1].set(1,1); +			}  		}  		// Now that we have the extents of the model @@ -1029,8 +960,11 @@ void LLModel::normalizeVolumeFaces()  			{  			 	pos[j].add(trans);  				pos[j].mul(scale); -				norm[j].mul(inv_scale); -				norm[j].normalize3(); +				if (norm && !norm[j].equals3(LLVector4a::getZero())) +				{ +					norm[j].mul(inv_scale); +					norm[j].normalize3(); +				}  			}  		} @@ -1073,8 +1007,26 @@ void LLModel::setVolumeFaceData(  	face.resizeIndices(num_indices);  	LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32)); -	LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32)); -	LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); +	if (norm.get()) +	{ +		LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32)); +	} +	else +	{ +		ll_aligned_free_16(face.mNormals); +		face.mNormals = NULL; +	} + +	if (tc.get()) +	{ +		LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); +	} +	else +	{ +		ll_aligned_free_16(face.mTexCoords); +		face.mTexCoords = NULL; +	} +  	U32 size = (num_indices*2+0xF)&~0xF;  	LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);  } @@ -1257,10 +1209,23 @@ void LLModel::generateNormals(F32 angle_cutoff)  			LLVolumeFace::VertexData v;  			new_face.mPositions[i] = vol_face.mPositions[idx];  			new_face.mNormals[i].clear(); -			new_face.mTexCoords[i] = vol_face.mTexCoords[idx];  			new_face.mIndices[i] = i;  		} +		if (vol_face.mTexCoords) +		{ +			for (U32 i = 0; i < vol_face.mNumIndices; i++) +			{ +				U32 idx = vol_face.mIndices[i]; +				new_face.mTexCoords[i] = vol_face.mTexCoords[idx]; +			} +		} +		else +		{ +			ll_aligned_free_16(new_face.mTexCoords); +			new_face.mTexCoords = NULL; +		} +  		//generate normals for new face  		for (U32 i = 0; i < new_face.mNumIndices; i += 3)  		{ //for each triangle @@ -1395,7 +1360,8 @@ LLSD LLModel::writeModel(  	const LLModel::Decomposition& decomp,  	BOOL upload_skin,  	BOOL upload_joints, -	BOOL nowrite) +	BOOL nowrite, +	BOOL as_slm)  {  	LLSD mdl; @@ -1419,12 +1385,20 @@ LLSD LLModel::writeModel(  		!decomp.mHull.empty())		  	{  		mdl["physics_convex"] = decomp.asLLSD(); -		if (!decomp.mHull.empty()) -		{ //convex decomposition exists, physics mesh will not be used +		if (!decomp.mHull.empty() && !as_slm) +		{ //convex decomposition exists, physics mesh will not be used (unless this is an slm file)  			model[LLModel::LOD_PHYSICS] = NULL;  		}  	} +	if (as_slm) +	{ //save material list names +		for (U32 i = 0; i < high->mMaterialList.size(); ++i) +		{ +			mdl["material_list"][i] = high->mMaterialList[i]; +		} +	} +  	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)  	{  		if (model[idx] && model[idx]->getNumVolumeFaces() > 0) @@ -1462,13 +1436,19 @@ LLSD LLModel::writeModel(  				U32 tc_idx = 0;  				LLVector2* ftc = (LLVector2*) face.mTexCoords; -				LLVector2 min_tc = ftc[0]; -				LLVector2 max_tc = min_tc; -	 -				//get texture coordinate domain -				for (U32 j = 0; j < face.mNumVertices; ++j) +				LLVector2 min_tc; +				LLVector2 max_tc; + +				if (ftc)  				{ -					update_min_max(min_tc, max_tc, ftc[j]); +					min_tc = ftc[0]; +					max_tc = min_tc; +					 +					//get texture coordinate domain +					for (U32 j = 0; j < face.mNumVertices; ++j) +					{ +						update_min_max(min_tc, max_tc, ftc[j]); +					}  				}  				LLVector2 tc_range = max_tc - min_tc; @@ -1477,9 +1457,8 @@ LLSD LLModel::writeModel(  				{ //for each vert  					F32* pos = face.mPositions[j].getF32ptr(); -					F32* norm = face.mNormals[j].getF32ptr(); - -					//position + normal +										 +					//position  					for (U32 k = 0; k < 3; ++k)  					{ //for each component  						//convert to 16-bit normalized across domain @@ -1489,29 +1468,40 @@ LLSD LLModel::writeModel(  						//write to binary buffer  						verts[vert_idx++] = buff[0];  						verts[vert_idx++] = buff[1]; -						 -						//convert to 16-bit normalized -						val = (U16) ((norm[k]+1.f)*0.5f*65535); - -						//write to binary buffer -						normals[norm_idx++] = buff[0]; -						normals[norm_idx++] = buff[1];  					} -					F32* src_tc = (F32*) face.mTexCoords[j].mV; +					if (face.mNormals) +					{ //normals +						F32* norm = face.mNormals[j].getF32ptr(); -					//texcoord -					for (U32 k = 0; k < 2; ++k) -					{ //for each component -						//convert to 16-bit normalized -						U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535); +						for (U32 k = 0; k < 3; ++k) +						{ //for each component +							//convert to 16-bit normalized +							U16 val = (U16) ((norm[k]+1.f)*0.5f*65535); +							U8* buff = (U8*) &val; -						U8* buff = (U8*) &val; -						//write to binary buffer -						tc[tc_idx++] = buff[0]; -						tc[tc_idx++] = buff[1]; +							//write to binary buffer +							normals[norm_idx++] = buff[0]; +							normals[norm_idx++] = buff[1]; +						}  					} +					F32* src_tc = (F32*) face.mTexCoords[j].mV; + +					//texcoord +					if (face.mTexCoords) +					{ +						for (U32 k = 0; k < 2; ++k) +						{ //for each component +							//convert to 16-bit normalized +							U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535); + +							U8* buff = (U8*) &val; +							//write to binary buffer +							tc[tc_idx++] = buff[0]; +							tc[tc_idx++] = buff[1]; +						} +					}  				}  				U32 idx_idx = 0; @@ -1525,12 +1515,20 @@ LLSD LLModel::writeModel(  				//write out face data  				mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();  				mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue(); -				mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue(); -				mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue(); -  				mdl[model_names[idx]][i]["Position"] = verts; -				mdl[model_names[idx]][i]["Normal"] = normals; -				mdl[model_names[idx]][i]["TexCoord0"] = tc; +				 +				if (face.mNormals) +				{ +					mdl[model_names[idx]][i]["Normal"] = normals; +				} + +				if (face.mTexCoords) +				{ +					mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue(); +					mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue(); +					mdl[model_names[idx]][i]["TexCoord0"] = tc; +				} +  				mdl[model_names[idx]][i]["TriangleList"] = indices;  				if (skinning) @@ -1588,10 +1586,10 @@ LLSD LLModel::writeModel(  		}  	} -	return writeModelToStream(ostr, mdl, nowrite); +	return writeModelToStream(ostr, mdl, nowrite, as_slm);  } -LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite) +LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)  {  	U32 bytes = 0; @@ -1599,6 +1597,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)  	LLSD header; +	if (as_slm && mdl.has("material_list")) +	{ //save material binding names to header +		header["material_list"] = mdl["material_list"]; +	} +  	std::string skin;  	if (mdl.has("skin")) @@ -1792,6 +1795,15 @@ bool LLModel::loadModel(std::istream& is)  		}  	} +	if (header.has("material_list")) +	{ //load material list names +		mMaterialList.clear(); +		for (U32 i = 0; i < header["material_list"].size(); ++i) +		{ +			mMaterialList.push_back(header["material_list"][i].asString()); +		} +	} +  	std::string nm[] =   	{  		"lowest_lod", @@ -1808,6 +1820,7 @@ bool LLModel::loadModel(std::istream& is)  	if (header[nm[lod]]["offset"].asInteger() == -1 ||   		header[nm[lod]]["size"].asInteger() == 0 )  	{ //cannot load requested LOD +		llwarns << "LoD data is invalid!" << llendl;  		return false;  	} @@ -1821,7 +1834,7 @@ bool LLModel::loadModel(std::istream& is)  		is.seekg(cur_pos);  	} -	if (lod == LLModel::LOD_PHYSICS) +	if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)  	{  		std::ios::pos_type cur_pos = is.tellg();  		loadDecomposition(header, is); @@ -1868,11 +1881,66 @@ bool LLModel::loadModel(std::istream& is)  		}  		return true;  	} +	else +	{ +		llwarns << "unpackVolumeFaces failed!" << llendl; +	}  	return false;  } +void LLModel::matchMaterialOrder(LLModel* ref) +{ +	llassert(ref->mMaterialList.size() == mMaterialList.size()); + +	std::map<std::string, U32> index_map; +	 +	//build a map of material slot names to face indexes +	bool reorder = false; +	std::set<std::string> base_mat; +	std::set<std::string> cur_mat; + +	for (U32 i = 0; i < mMaterialList.size(); i++) +	{ +		index_map[ref->mMaterialList[i]] = i; +		if (!reorder) +		{ //if any material name does not match reference, we need to reorder +			reorder = ref->mMaterialList[i] != mMaterialList[i]; +		} +		base_mat.insert(ref->mMaterialList[i]); +		cur_mat.insert(mMaterialList[i]); +	} + + +	if (reorder &&  +		base_mat == cur_mat) //don't reorder if material name sets don't match +	{ +		std::vector<LLVolumeFace> new_face_list; +		new_face_list.resize(mVolumeFaces.size()); + +		std::vector<std::string> new_material_list; +		new_material_list.resize(mVolumeFaces.size()); + +		//rebuild face list so materials have the same order  +		//as the reference model +		for (U32 i = 0; i < mMaterialList.size(); ++i) +		{  +			U32 ref_idx = index_map[mMaterialList[i]]; +			new_face_list[ref_idx] = mVolumeFaces[i]; + +			new_material_list[ref_idx] = mMaterialList[i]; +		} + +		llassert(new_material_list == ref->mMaterialList); +		 +		mVolumeFaces = new_face_list; +	} + +	//override material list with reference model ordering +	mMaterialList = ref->mMaterialList; +} +  bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)  { @@ -2034,7 +2102,7 @@ LLModel::Decomposition::Decomposition(LLSD& data)  void LLModel::Decomposition::fromLLSD(LLSD& decomp)  { -	if (decomp.has("HullList")) +	if (decomp.has("HullList") && decomp.has("Positions"))  	{  		// updated for const-correctness. gcc is picky about this type of thing - Nyx  		const LLSD::Binary& hulls = decomp["HullList"].asBinary(); @@ -2190,6 +2258,8 @@ LLSD LLModel::Decomposition::asLLSD() const  	ret["Min"] = min.getValue();  	ret["Max"] = max.getValue(); +	LLVector3 range = max-min; +  	if (!hulls.empty())  	{  		ret["HullList"] = hulls; @@ -2199,10 +2269,6 @@ LLSD LLModel::Decomposition::asLLSD() const  	{  		LLSD::Binary p(total*3*2); -		LLVector3 min(-0.5f, -0.5f, -0.5f); -		LLVector3 max(0.5f, 0.5f, 0.5f); -		LLVector3 range = max-min; -  		U32 vert_idx = 0;  		for (U32 i = 0; i < mHull.size(); ++i) @@ -2214,12 +2280,10 @@ LLSD LLModel::Decomposition::asLLSD() const  			for (U32 j = 0; j < mHull[i].size(); ++j)  			{  				U64 test = 0; +				const F32* src = mHull[i][j].mV; +  				for (U32 k = 0; k < 3; k++)  				{ -					F32* src = (F32*) (mHull[i][j].mV); - -					llassert(src[k] <= 0.501f && src[k] >= -0.501f); -  					//convert to 16-bit normalized across domain  					U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535); @@ -2258,19 +2322,17 @@ LLSD LLModel::Decomposition::asLLSD() const  	{  		LLSD::Binary p(mBaseHull.size()*3*2); -		LLVector3 min(-0.5f, -0.5f, -0.5f); -		LLVector3 max(0.5f, 0.5f, 0.5f); -		LLVector3 range = max-min; -  		U32 vert_idx = 0;  		for (U32 j = 0; j < mBaseHull.size(); ++j)  		{ +			const F32* v = mBaseHull[j].mV; +  			for (U32 k = 0; k < 3; k++)  			{ -				llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f); +				llassert(v[k] <= 0.51f && v[k] >= -0.51f);  				//convert to 16-bit normalized across domain -				U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535); +				U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535);  				U8* buff = (U8*) &val;  				//write to binary buffer diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index cd9f76fcb7..3f58eba07d 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -137,12 +137,13 @@ public:  		const LLModel::Decomposition& decomp,  		BOOL upload_skin,  		BOOL upload_joints, -		BOOL nowrite = FALSE); +		BOOL nowrite = FALSE, +		BOOL as_slm = FALSE);  	static LLSD writeModelToStream(  		std::ostream& ostr,  		LLSD& mdl, -		BOOL nowrite = FALSE); +		BOOL nowrite = FALSE, BOOL as_slm = FALSE);  	static LLModel* loadModelFromDomMesh(domMesh* mesh);  	static std::string getElementLabel(daeElement* element); @@ -171,6 +172,11 @@ public:  	void optimizeVolumeFaces();  	void offsetMesh( const LLVector3& pivotPoint );  	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); +	 +	//reorder face list based on mMaterialList in this and reference so  +	//order matches that of reference (material ordering touchup) +	void matchMaterialOrder(LLModel* reference); +  	std::vector<std::string> mMaterialList;  	//data used for skin weights diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 76faa1b8c5..998016f8f6 100644..100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -103,6 +103,8 @@ public:  		PARAMS_LIGHT    = 0x20,  		PARAMS_SCULPT   = 0x30,  		PARAMS_LIGHT_IMAGE = 0x40, +		PARAMS_RESERVED = 0x50, // Used on server-side +		PARAMS_MESH     = 0x60,  	};  public: diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1180afa631..b6a252e8fa 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -296,7 +296,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm)  {  	U32 count = pos.size(); -	llassert(norm.size() >= pos.size()); +	llassert_always(norm.size() >= pos.size()); +	llassert_always(count > 0) ;  	unbind(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 935dd2e887..6292ee97c8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -209,6 +209,7 @@ set(viewer_SOURCE_FILES      llfloatermediasettings.cpp      llfloatermemleak.cpp      llfloatermodelpreview.cpp +    llfloatermodeluploadbase.cpp      llfloatermodelwizard.cpp      llfloaternamedesc.cpp      llfloaternotificationsconsole.cpp @@ -503,6 +504,7 @@ set(viewer_SOURCE_FILES      lltranslate.cpp      lluilistener.cpp      lluploaddialog.cpp +    lluploadfloaterobservers.cpp      llurl.cpp      llurldispatcher.cpp      llurldispatcherlistener.cpp @@ -769,6 +771,7 @@ set(viewer_HEADER_FILES      llfloatermediasettings.h      llfloatermemleak.h      llfloatermodelpreview.h +    llfloatermodeluploadbase.h      llfloatermodelwizard.h      llfloaternamedesc.h      llfloaternotificationsconsole.h @@ -1060,6 +1063,7 @@ set(viewer_HEADER_FILES      lluiconstants.h      lluilistener.h      lluploaddialog.h +    lluploadfloaterobservers.h      llurl.h      llurldispatcher.h      llurldispatcherlistener.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 648ef9ebbc..2cc7eb6d01 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1803,6 +1803,17 @@        <key>Value</key>        <integer>0</integer>      </map> +  <key>CurlUseMultipleThreads</key> +  <map> +    <key>Comment</key> +    <string>Use background threads for executing curl_multi_perform (requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map>      <key>Cursor3D</key>      <map>        <key>Comment</key> @@ -1935,17 +1946,6 @@        <key>Value</key>        <integer>0</integer>      </map> -  <key>DebugShowUploadCost</key> -  <map> -    <key>Comment</key> -    <string>Show what it would cost to upload assets in current scene</string> -    <key>Persist</key> -    <integer>1</integer> -    <key>Type</key> -    <string>Boolean</string> -    <key>Value</key> -    <integer>0</integer> -  </map>    <key>DebugShowRenderMatrices</key>    <map>      <key>Comment</key> @@ -1979,6 +1979,17 @@        <key>Value</key>        <integer>0</integer>      </map> +  <key>DebugShowUploadCost</key> +  <map> +    <key>Comment</key> +    <string>Show mesh upload cost</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map>    <key>DebugShowXUINames</key>      <map>        <key>Comment</key> @@ -5609,7 +5620,7 @@      <key>Type</key>      <string>Boolean</string>      <key>Value</key> -    <real>0</real> +    <real>1</real>    </map>    <key>MeshImportUseSLM</key>    <map> @@ -5620,7 +5631,7 @@      <key>Type</key>      <string>Boolean</string>      <key>Value</key> -    <real>0</real> +    <real>1</real>    </map>    <key>MeshUploadLogXML</key>    <map> @@ -5644,6 +5655,17 @@      <key>Value</key>      <real>0</real>    </map> +  <key>MeshUploadTimeOut</key> +  <map> +    <key>Comment</key> +    <string>Maximum time in seconds for llcurl to execute a mesh uoloading request</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>S32</string> +    <key>Value</key> +    <real>600</real> +  </map>    <key>MigrateCacheDirectory</key>      <map>        <key>Comment</key> @@ -9188,28 +9210,51 @@        <key>Value</key>        <real>1.0</real>      </map> -  <key>MeshStreamingCostScaler</key> +  <key>MeshTriangleBudget</key>    <map>      <key>Comment</key> -    <string>DEBUG</string> +    <string>Target visible triangle budget to use when estimating streaming cost.</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> -    <string>F32</string> +    <string>U32</string>      <key>Value</key> -    <real>2.0</real> +    <real>250000</real>    </map> -  <key>MeshThreadCount</key> +  <key>MeshMetaDataDiscount</key>    <map>      <key>Comment</key> -    <string>Number of threads to use for loading meshes.</string> +    <string>Number of bytes to deduct for metadata when determining streaming cost.</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <real>384</real> +  </map> +  <key>MeshMinimumByteSize</key> +  <map> +    <key>Comment</key> +    <string>Minimum number of bytes per LoD block when determining streaming cost.</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key>      <string>U32</string>      <key>Value</key> -    <integer>8</integer> +    <real>16</real>    </map> +  <key>MeshBytesPerTriangle</key> +  <map> +    <key>Comment</key> +    <string>Approximation of bytes per triangle to use for determining mesh streaming cost.</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <real>16</real> +  </map> +    <key>MeshMaxConcurrentRequests</key>    <map>      <key>Comment</key> @@ -9441,6 +9486,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>ShowAdvancedBuilderOptions</key> +    <map> +      <key>Comment</key> +      <string>Shows physics and display weight</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>ShowAdvancedGraphicsSettings</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index c30d3b9aa3..f195c985c0 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -393,8 +393,6 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi  	LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation  	LLVector3 object_extents = object->getScale();	 -	const LLVector4a* oe4 = object->mDrawable->getSpatialExtents(); -	object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] );  	// make sure they object extents are non-zero  	object_extents.clamp(0.001f, F32_MAX); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b65933f8a1..d12b971bde 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -708,7 +708,7 @@ bool LLAppViewer::init()      // *NOTE:Mani - LLCurl::initClass is not thread safe.       // Called before threads are created. -    LLCurl::initClass(); +    LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads"));  	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;      LLMachineID::init(); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 5b9a449be1..966f5b941e 100644..100755 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -127,6 +127,15 @@ void on_new_single_inventory_upload_complete(  			group_perms,  			next_owner_perms); +		U32 inventory_item_flags = 0; +		if (server_response.has("inventory_flags")) +		{ +			inventory_item_flags = (U32) server_response["inventory_flags"].asInteger(); +			if (inventory_item_flags != 0) +			{ +				llinfos << "inventory_item_flags " << inventory_item_flags << llendl; +			} +		}  		S32 creation_date_now = time_corrected();  		LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(  			server_response["new_inventory_item"].asUUID(), @@ -138,7 +147,7 @@ void on_new_single_inventory_upload_complete(  			item_name,  			item_description,  			LLSaleInfo::DEFAULT, -			LLInventoryItemFlags::II_FLAGS_NONE, +			inventory_item_flags,  			creation_date_now);  		gInventory.updateItem(item); diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp index 4b6fe4a115..86c1bf0534 100644 --- a/indra/newview/llfloaterbuildoptions.cpp +++ b/indra/newview/llfloaterbuildoptions.cpp @@ -34,15 +34,81 @@  #include "llfloaterbuildoptions.h"  #include "lluictrlfactory.h" +#include "llcombobox.h" +#include "llselectmgr.h" +  //  // Methods  // + +void commit_grid_mode(LLUICtrl *); +  LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key) -  : LLFloater(key) +  : LLFloater(key), +    mComboGridMode(NULL)  { +	mCommitCallbackRegistrar.add("GridOptions.gridMode", boost::bind(&commit_grid_mode,_1));  }  LLFloaterBuildOptions::~LLFloaterBuildOptions() +{} + +BOOL LLFloaterBuildOptions::postBuild() +{ +	mComboGridMode = getChild<LLComboBox>("combobox grid mode"); + +	return TRUE; +} + +void LLFloaterBuildOptions::setGridMode(EGridMode mode) +{ +	mComboGridMode->setCurrentByIndex((S32)mode); +} + +void LLFloaterBuildOptions::updateGridMode()  { +	if (mComboGridMode) +	{ +		S32 index = mComboGridMode->getCurrentIndex(); +		mComboGridMode->removeall(); + +		switch (mObjectSelection->getSelectType()) +		{ +		case SELECT_TYPE_HUD: +		  mComboGridMode->add(getString("grid_screen_text")); +		  mComboGridMode->add(getString("grid_local_text")); +		  break; +		case SELECT_TYPE_WORLD: +		  mComboGridMode->add(getString("grid_world_text")); +		  mComboGridMode->add(getString("grid_local_text")); +		  mComboGridMode->add(getString("grid_reference_text")); +		  break; +		case SELECT_TYPE_ATTACHMENT: +		  mComboGridMode->add(getString("grid_attachment_text")); +		  mComboGridMode->add(getString("grid_local_text")); +		  mComboGridMode->add(getString("grid_reference_text")); +		  break; +		} + +		mComboGridMode->setCurrentByIndex(index); +	} +} + +// virtual +void LLFloaterBuildOptions::onOpen(const LLSD& key) +{ +	mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();  } +// virtual +void LLFloaterBuildOptions::onClose(bool app_quitting) +{ +	mObjectSelection = NULL; +} + +void commit_grid_mode(LLUICtrl *ctrl) +{ +	LLComboBox* combo = (LLComboBox*)ctrl; + +	LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); +} diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h index 164944d7bc..7f3811bf1c 100644 --- a/indra/newview/llfloaterbuildoptions.h +++ b/indra/newview/llfloaterbuildoptions.h @@ -33,15 +33,34 @@  #define LL_LLFLOATERBUILDOPTIONS_H  #include "llfloater.h" +#include "llselectmgr.h" +class LLComboBox; +class LLObjectSelection; + +typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle;  class LLFloaterBuildOptions  	:	public LLFloater  { -	friend class LLFloaterReg; +public: + +	virtual BOOL postBuild(); + +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/	void onClose(bool app_quitting); + +	void setGridMode(EGridMode mode); +	void updateGridMode(); +  private: + +	friend class LLFloaterReg; +  	LLFloaterBuildOptions(const LLSD& key);  	~LLFloaterBuildOptions(); -}; +	LLComboBox*	mComboGridMode; +	LLObjectSelectionHandle	mObjectSelection; +};  #endif diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ab6753b4be..ef846ec42e 100644..100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -71,6 +71,7 @@  #include "llmatrix4a.h"  #include "llmenubutton.h"  #include "llmeshrepository.h" +#include "llnotificationsutil.h"  #include "llsdutil_math.h"  #include "lltextbox.h"  #include "lltoolmgr.h" @@ -100,7 +101,12 @@  #include "llcallbacklist.h"  #include "llviewerobjectlist.h"  #include "llanimationstates.h" +#include "llviewernetwork.h"  #include "glod/glod.h" +#include <boost/algorithm/string.hpp> + + +const S32 SLM_SUPPORTED_VERSION = 2;  //static  S32 LLFloaterModelPreview::sUploadAmount = 10; @@ -353,13 +359,16 @@ void LLMeshFilePicker::notify(const std::string& filename)  // LLFloaterModelPreview()  //-----------------------------------------------------------------------------  LLFloaterModelPreview::LLFloaterModelPreview(const LLSD& key) : -LLFloater(key) +LLFloaterModelUploadBase(key), +mUploadBtn(NULL), +mCalculateBtn(NULL)  {  	sInstance = this;  	mLastMouseX = 0;  	mLastMouseY = 0;  	mGLName = 0;  	mStatusLock = new LLMutex(NULL); +	mModelPreview = NULL;  	mLODMode[LLModel::LOD_HIGH] = 0;  	for (U32 i = 0; i < LLModel::LOD_HIGH; i++) @@ -394,16 +403,17 @@ BOOL LLFloaterModelPreview::postBuild()  	childSetCommitCallback("border_mode", onLODParamCommit, this);  	childSetCommitCallback("share_tolerance", onLODParamCommit, this); +	childSetCommitCallback("upload_skin", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL); +	childSetCommitCallback("upload_joints", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL); +	childSetCommitCallback("upload_textures", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL); +  	childSetTextArg("status", "[STATUS]", getString("status_idle")); -	//childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));  	childSetAction("ok_btn", onUpload, this);  	childDisable("ok_btn");  	childSetAction("reset_btn", onReset, this); -	childSetAction("clear_materials", onClearMaterials, this); -  	childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);  	childSetCommitCallback("upload_skin", onUploadSkinCommit, this); @@ -422,8 +432,6 @@ BOOL LLFloaterModelPreview::postBuild()  	childDisable("ok_btn"); -	childSetCommitCallback("confirm_checkbox", refresh, this); -  	mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn");  	mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2)); @@ -441,9 +449,7 @@ BOOL LLFloaterModelPreview::postBuild()  	mPreviewRect = preview_panel->getRect(); -	mModelPreview = new LLModelPreview(512, 512, this ); -	mModelPreview->setPreviewTarget(16.f); -	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5)); +	initModelPreview();  	//set callbacks for left click on line editor rows  	for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) @@ -472,6 +478,25 @@ BOOL LLFloaterModelPreview::postBuild()  			text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i));  		}  	} +	std::string current_grid = LLGridManager::getInstance()->getGridLabel(); +	std::transform(current_grid.begin(),current_grid.end(),current_grid.begin(),::tolower); +	std::string validate_url; +	if (current_grid == "agni") +	{ +		validate_url = "http://secondlife.com/my/account/mesh.php"; +	} +	else +	{ +		validate_url = llformat("http://secondlife.%s.lindenlab.com/my/account/mesh.php",current_grid.c_str()); +	} +	getChild<LLTextBox>("warning_message")->setTextArg("[VURL]", validate_url); + +	mUploadBtn = getChild<LLButton>("ok_btn"); +	mCalculateBtn = getChild<LLButton>("calculate_btn"); + +	mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); + +	toggleCalculateButton(true);  	return TRUE;  } @@ -497,6 +522,19 @@ LLFloaterModelPreview::~LLFloaterModelPreview()  	mStatusLock = NULL;  } +void LLFloaterModelPreview::initModelPreview() +{ +	if (mModelPreview) +	{ +		delete mModelPreview; +	} + +	mModelPreview = new LLModelPreview(512, 512, this ); +	mModelPreview->setPreviewTarget(16.f); +	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5)); +	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, _1)); +} +  void LLFloaterModelPreview::onViewOptionChecked(const LLSD& userdata)  {  	if (mModelPreview) @@ -544,6 +582,30 @@ void LLFloaterModelPreview::loadModel(S32 lod)  	(new LLMeshFilePicker(mModelPreview, lod))->getFile();  } +void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name, bool force_disable_slm) +{ +	mModelPreview->mLoading = true; + +	mModelPreview->loadModel(file_name, lod, force_disable_slm); +} + +void LLFloaterModelPreview::onClickCalculateBtn() +{ +	mModelPreview->rebuildUploadData(); + +	bool upload_skinweights = childGetValue("upload_skin").asBoolean(); +	bool upload_joint_positions = childGetValue("upload_joints").asBoolean(); + +	mUploadModelUrl.clear(); + +	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, +			childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mUploadModelUrl, false, +						  getWholeModelFeeObserverHandle()); + +	toggleCalculateButton(false); +	mUploadBtn->setEnabled(false); +} +  //static  void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)  { @@ -554,7 +616,10 @@ void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)  		return;  	} -	fp->mModelPreview->calcResourceCost(); +	fp->mModelPreview->mDirty = true; + +	fp->toggleCalculateButton(true); +  	fp->mModelPreview->refresh();  }  //static @@ -566,7 +631,11 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )  	{  		return;  	} -	fp->mModelPreview->calcResourceCost(); + +	fp->mModelPreview->mDirty = true; + +	fp->toggleCalculateButton(true); +  	fp->mModelPreview->refresh();  } @@ -615,8 +684,6 @@ void LLFloaterModelPreview::onUploadSkinCommit(LLUICtrl*,void* userdata)  	{  		return;  	} -	 -	fp->mModelPreview->calcResourceCost();  	fp->mModelPreview->refresh();  	fp->mModelPreview->resetPreviewTarget();  	fp->mModelPreview->clearBuffers(); @@ -669,6 +736,7 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)  void LLFloaterModelPreview::onLODParamCommit(LLUICtrl* ctrl, void* userdata)  {  	LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; +  	fp->mModelPreview->onLODParamCommit(false);  } @@ -707,31 +775,11 @@ void LLFloaterModelPreview::draw()  		}  	} +	childSetEnabled("ok_btn", mHasUploadPerm && !mUploadModelUrl.empty()); +  	childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));  	childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); -	if (!mCurRequest.empty()) -	{ -		LLMutexLock lock(mStatusLock); -		childSetTextArg("status", "[STATUS]", mStatusMessage); -	} -	else -	{ -		childSetVisible("Simplify", true); -		childSetVisible("simplify_cancel", false); -		childSetVisible("Decompose", true); -		childSetVisible("decompose_cancel", false); -	} -	 -	U32 resource_cost = mModelPreview->mResourceCost*10; - -	if (childGetValue("upload_textures").asBoolean()) -	{ -		resource_cost += mModelPreview->mTextureSet.size()*10; -	} - -	childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", resource_cost)); -  	if (mModelPreview)  	{  		gGL.color3f(1.f, 1.f, 1.f); @@ -864,6 +912,12 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)  	return TRUE;  } +/*virtual*/ +void LLFloaterModelPreview::onOpen(const LLSD& key) +{ +	requestAgentUploadPermissions(); +} +  //static  void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)  { @@ -925,12 +979,14 @@ void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data)  			sInstance->setStatusMessage(sInstance->getString("decomposing"));  			sInstance->childSetVisible("Decompose", false);  			sInstance->childSetVisible("decompose_cancel", true); +			sInstance->childDisable("Simplify");  		}  		else if (stage == "Simplify")  		{  			sInstance->setStatusMessage(sInstance->getString("simplifying"));  			sInstance->childSetVisible("Simplify", false);  			sInstance->childSetVisible("simplify_cancel", true); +			sInstance->childDisable("Decompose");  		}  	}  } @@ -1883,8 +1939,11 @@ bool LLModelLoader::doLoadModel()  								mesh_scale *= transformation;  								transformation = mesh_scale; -								std::vector<LLImportMaterial> materials; -								materials.resize(model->getNumVolumeFaces()); +								std::map<std::string, LLImportMaterial> materials; +								for (U32 i = 0; i < model->mMaterialList.size(); ++i) +								{ +									materials[model->mMaterialList[i]] = LLImportMaterial(); +								}  								mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));  								stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);  							} @@ -1946,6 +2005,11 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)  	//build model list for each LoD  	model_list model[LLModel::NUM_LODS]; +	if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) +	{  //unsupported version +		return false; +	} +  	LLSD& mesh = data["mesh"];  	LLVolumeParams volume_params; @@ -1968,10 +2032,6 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)  					mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );					  				}  			} -			else -			{ -				llassert(model[lod].empty()); -			}  		}  	}	 @@ -2267,14 +2327,17 @@ void LLModelLoader::loadTextures()  	{  		for(U32 i = 0 ; i < iter->second.size(); i++)  		{ -			for(U32 j = 0 ; j < iter->second[i].mMaterial.size() ; j++) +			for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin(); +				j != iter->second[i].mMaterial.end(); ++j)  			{ -				if(!iter->second[i].mMaterial[j].mDiffuseMapFilename.empty()) +				LLImportMaterial& material = j->second; + +				if(!material.mDiffuseMapFilename.empty())  				{ -					iter->second[i].mMaterial[j].mDiffuseMap =  -						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW); -					iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); -					iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage(0, F32_MAX); +					material.mDiffuseMap =  +						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW); +					material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); +					material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX);  					mNumOfFetchingTextures++ ;  				}  			} @@ -2574,7 +2637,7 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )  				{  					LLMatrix4 transformation = mTransform; -					std::vector<LLImportMaterial> materials = getMaterials(model, instance_geo); +					std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo);  					// adjust the transformation to compensate for mesh normalization  					LLVector3 mesh_scale_vector; @@ -2630,9 +2693,9 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )  	}  } -std::vector<LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) +std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo)  { -	std::vector<LLImportMaterial> materials; +	std::map<std::string, LLImportMaterial> materials;  	for (int i = 0; i < model->mMaterialList.size(); i++)  	{  		LLImportMaterial import_material; @@ -2679,7 +2742,8 @@ std::vector<LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domIns  			}  		} -		materials.push_back(import_material); +		import_material.mBinding = model->mMaterialList[i]; +		materials[model->mMaterialList[i]] = import_material;  	}  	return materials; @@ -2919,8 +2983,7 @@ U32 LLModelPreview::calcResourceCost()  	if (mFMP && mModelLoader)  	{ -		const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); -		if ( getLoadState() < LLModelLoader::ERROR_PARSING && confirmed_checkbox ) +		if ( getLoadState() < LLModelLoader::ERROR_PARSING)  		{  			mFMP->childEnable("ok_btn");  		} @@ -2942,7 +3005,6 @@ U32 LLModelPreview::calcResourceCost()  		//ok_btn should not have been changed unless something was wrong with joint list  	} -	U32 cost = 0;  	std::set<LLModel*> accounted;  	U32 num_points = 0;  	U32 num_hulls = 0; @@ -2990,8 +3052,7 @@ U32 LLModelPreview::calcResourceCost()  					   mFMP->childGetValue("upload_skin").asBoolean(),  					   mFMP->childGetValue("upload_joints").asBoolean(),  					   TRUE); -			cost += gMeshRepo.calcResourceCost(ret); - +			  			num_hulls += decomp.mHull.size();  			for (U32 i = 0; i < decomp.mHull.size(); ++i)  			{ @@ -3011,7 +3072,7 @@ U32 LLModelPreview::calcResourceCost()  			F32 z_length = z_transformed.normalize();  			LLVector3 scale = LLVector3(x_length, y_length, z_length); -			F32 radius = scale.length()*debug_scale; +			F32 radius = scale.length()*0.5f*debug_scale;  			streaming_cost += LLMeshRepository::getStreamingCost(ret, radius);  		} @@ -3023,7 +3084,7 @@ U32 LLModelPreview::calcResourceCost()  	updateStatusMessages(); -	return cost; +	return (U32) streaming_cost;  }  void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) @@ -3031,8 +3092,6 @@ void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost,  	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));  	childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));  	childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z)); -	childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost)); -	childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));	  } @@ -3062,12 +3121,24 @@ void LLModelPreview::rebuildUploadData()  	F32 max_scale = 0.f; -	const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); -	if ( mBaseScene.size() > 0 && confirmed_checkbox ) +	if ( mBaseScene.size() > 0)  	{  		mFMP->childEnable("ok_btn");  	} +	//reorder materials to match mBaseModel +	for (U32 i = 0; i < LLModel::NUM_LODS; i++) +	{ +		if (mBaseModel.size() == mModel[i].size()) +		{ +			for (U32 j = 0; j < mBaseModel.size(); ++j) +			{ +				mModel[i][j]->matchMaterialOrder(mBaseModel[j]); +				llassert(mModel[i][j]->mMaterialList == mBaseModel[j]->mMaterialList); +			} +		} +	} +  	for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)  	{ //for each transform in scene  		LLMatrix4 mat = iter->first; @@ -3107,18 +3178,20 @@ void LLModelPreview::rebuildUploadData()  				}  			} -			for (U32 i = 0; i < LLModel::NUM_LODS; i++) -			{ //fill LOD slots based on reference model index -				if (!mModel[i].empty()) -				{ -					instance.mLOD[i] = mModel[i][idx]; -				} -				else -				{ -					instance.mLOD[i] = NULL; +			if(idx < mBaseModel.size()) +			{ +				for (U32 i = 0; i < LLModel::NUM_LODS; i++) +				{ //fill LOD slots based on reference model index +					if (mModel[i].size() > idx) +					{ +						instance.mLOD[i] = mModel[i][idx]; +					} +					else +					{ +						instance.mLOD[i] = NULL; +					}  				}  			} -  			instance.mTransform = mat;  			mUploadData.push_back(instance);  		} @@ -3164,6 +3237,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw  	LLSD data; +	data["version"] = SLM_SUPPORTED_VERSION; +  	S32 mesh_id = 0;  	//build list of unique models and initialize local id @@ -3190,7 +3265,7 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw  				instance.mLOD[LLModel::LOD_LOW],   				instance.mLOD[LLModel::LOD_IMPOSTOR],   				decomp,  -				save_skinweights, save_joint_positions); +				save_skinweights, save_joint_positions, FALSE, TRUE);  			data["mesh"][instance.mModel->mLocalID] = str.str(); @@ -3217,7 +3292,7 @@ void LLModelPreview::clearModel(S32 lod)  	mScene[lod].clear();  } -void LLModelPreview::loadModel(std::string filename, S32 lod) +void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm)  {  	assert_main_thread(); @@ -3254,6 +3329,11 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)  	mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode ); +	if (force_disable_slm) +	{ +		mModelLoader->mTrySLM = false; +	} +  	mModelLoader->start();  	mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); @@ -3468,7 +3548,17 @@ void LLModelPreview::loadModelCallback(S32 lod)  	mLoading = false;  	if (mFMP) +	{  		mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE); +		if (!mBaseModel.empty()) +		{ +			if (mFMP->getChild<LLUICtrl>("description_form")->getValue().asString().empty()) +			{ +				const std::string& model_name = mBaseModel[0]->getName(); +				mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name); +			} +		} +	}  	refresh();  	mModelLoadedSignal(); @@ -3524,43 +3614,6 @@ void LLModelPreview::generateNormals()  	updateStatusMessages();  } -void LLModelPreview::clearMaterials() -{ -	for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) -	{ //for each transform in current scene -		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) -		{ //for each instance with that transform -			LLModelInstance& source_instance = *model_iter; -			LLModel* source = source_instance.mModel; - -			for (S32 i = 0; i < source->getNumVolumeFaces(); ++i) -			{ //for each face in instance -				LLImportMaterial& source_material = source_instance.mMaterial[i]; - -				//clear material info -				source_material.mDiffuseColor = LLColor4(1,1,1,1); -				source_material.mDiffuseMap = NULL; -				source_material.mDiffuseMapFilename.clear(); -				source_material.mDiffuseMapLabel.clear(); -				source_material.mFullbright = false; -			} -		} -	} - -	mVertexBuffer[mPreviewLOD].clear(); - -	if (mPreviewLOD == LLModel::LOD_HIGH) -	{ -		mBaseScene = mScene[mPreviewLOD]; -		mBaseModel = mModel[mPreviewLOD]; -		clearGLODGroup(); -		mVertexBuffer[5].clear(); -	} - -	mResourceCost = calcResourceCost(); -	refresh(); -} -  void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)  {  	if (mBaseModel.empty()) @@ -3734,7 +3787,9 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  			U32 tri_count = 0;  			for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)  			{ -				mVertexBuffer[5][mdl][i]->setBuffer(type_mask); +				LLVertexBuffer* buff = mVertexBuffer[5][mdl][i]; +				buff->setBuffer(type_mask & buff->getTypeMask()); +				  				U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();  				if (num_indices > 2)  				{ @@ -3856,6 +3911,8 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  			for (GLint i = 0; i < patch_count; ++i)  			{ +				type_mask = mVertexBuffer[5][base][i]->getTypeMask(); +  				LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);  				if (sizes[i*2+1] > 0 && sizes[i*2] > 0) @@ -3880,8 +3937,15 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  				LLStrider<U16> index;  				buff->getVertexStrider(pos); -				buff->getNormalStrider(norm); -				buff->getTexCoord0Strider(tc); +				if (type_mask & LLVertexBuffer::MAP_NORMAL) +				{ +					buff->getNormalStrider(norm); +				} +				if (type_mask & LLVertexBuffer::MAP_TEXCOORD0) +				{ +					buff->getTexCoord0Strider(tc); +				} +  				buff->getIndexStrider(index);  				target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices()); @@ -4087,18 +4151,20 @@ void LLModelPreview::updateStatusMessages()  			}  			else if (!verts[lod].empty())  			{ +				S32 sum_verts_higher_lod = 0; +				S32 sum_verts_this_lod = 0;  				for (U32 i = 0; i < verts[lod].size(); ++i)  				{ -					S32 max_verts = i < verts[lod+1].size() ? verts[lod+1][i] : 0; +					sum_verts_higher_lod += ((i < verts[lod+1].size()) ? verts[lod+1][i] : 0); +					sum_verts_this_lod += verts[lod][i]; +				} -					if (max_verts > 0) -					{ -						if (verts[lod][i] > max_verts) -						{ //too many vertices in this lod -							message = "mesh_status_too_many_vertices"; -							upload_status[lod] = 2; -						} -					} +				if ((sum_verts_higher_lod > 0) && +					(sum_verts_this_lod > sum_verts_higher_lod)) +				{ +					//too many vertices in this lod +					message = "mesh_status_too_many_vertices"; +					upload_status[lod] = 2;  				}  			}  		} @@ -4163,8 +4229,7 @@ void LLModelPreview::updateStatusMessages()  		}  	} -	const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); -	if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox) +	if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate)  	{  		mFMP->childEnable("ok_btn");  	} @@ -4269,6 +4334,24 @@ void LLModelPreview::updateStatusMessages()  			child->setEnabled(enable);  			child = panel->findNextSibling(child);  		} + +		if (fmp->mCurRequest.empty()) +		{ +			fmp->childSetVisible("Simplify", true); +			fmp->childSetVisible("simplify_cancel", false); +			fmp->childSetVisible("Decompose", true); +			fmp->childSetVisible("decompose_cancel", false); + +			if (phys_hulls > 0) +			{ +				fmp->childEnable("Simplify"); +			} +		 +			if (phys_tris || phys_hulls > 0) +			{ +				fmp->childEnable("Decompose"); +			} +		}  	}  	const char* lod_controls[] = @@ -4412,6 +4495,8 @@ void LLModelPreview::updateStatusMessages()  		crease->forceSetValue(mRequestedCreaseAngle[mPreviewLOD]);  	} +	mModelUpdatedSignal(true); +  }  void LLModelPreview::setPreviewTarget(F32 distance) @@ -4485,7 +4570,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)  			bool skinned = include_skin_weights && !mdl->mSkinWeights.empty(); -			U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; +			U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0 ;  			if (skinned)  			{ @@ -4503,8 +4588,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)  			LLStrider<LLVector4> weights_strider;  			vb->getVertexStrider(vertex_strider); -			vb->getNormalStrider(normal_strider); -			vb->getTexCoord0Strider(tc_strider);  			vb->getIndexStrider(index_strider);  			if (skinned) @@ -4513,8 +4596,18 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)  			}  			LLVector4a::memcpyNonAliased16((F32*) vertex_strider.get(), (F32*) vf.mPositions, num_vertices*4*sizeof(F32)); -			LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); -			LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32)); +			 +			if (vf.mTexCoords) +			{ +				vb->getTexCoord0Strider(tc_strider); +				LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); +			} +			 +			if (vf.mNormals) +			{ +				vb->getNormalStrider(normal_strider); +				LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32)); +			}  			if (skinned)  			{ @@ -4728,7 +4821,18 @@ BOOL LLModelPreview::render()  	glClear(GL_DEPTH_BUFFER_BIT); -	LLRect preview_rect = mFMP->getChildView("preview_panel")->getRect(); +	LLRect preview_rect; + +	LLFloaterModelWizard* floater_wizard = dynamic_cast<LLFloaterModelWizard*>(mFMP); +	if (floater_wizard) +	{ +		preview_rect = floater_wizard->getPreviewRect(); +	} +	else +	{ +		preview_rect = mFMP->getChildView("preview_panel")->getRect(); +	} +  	F32 aspect = (F32) preview_rect.getWidth()/preview_rect.getHeight();  	LLViewerCamera::getInstance()->setAspect(aspect); @@ -4773,6 +4877,8 @@ BOOL LLModelPreview::render()  	const F32 BRIGHTNESS = 0.9f;  	gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); +	const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; +  	LLGLEnable normalize(GL_NORMALIZE);  	if (!mBaseModel.empty() && mVertexBuffer[5].empty()) @@ -4795,6 +4901,19 @@ BOOL LLModelPreview::render()  			}  		} +		//make sure material lists all match +		for (U32 i = 0; i < LLModel::NUM_LODS; i++) +		{ +			if (mBaseModel.size() == mModel[i].size()) +			{ +				for (U32 j = 0; j < mBaseModel.size(); ++j) +				{ +					mModel[i][j]->matchMaterialOrder(mBaseModel[j]); +					llassert(mModel[i][j]->mMaterialList == mBaseModel[j]->mMaterialList); +				} +			} +		} +  		if (regen)  		{  			genBuffers(mPreviewLOD, skin_weight); @@ -4821,18 +4940,23 @@ BOOL LLModelPreview::render()  				for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i)  				{  					LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - -					buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); +				 +					buffer->setBuffer(type_mask & buffer->getTypeMask());  					if (textures)  					{ -						glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); -						if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull()) +						const std::string& binding = instance.mModel->mMaterialList[i]; +						const LLImportMaterial& material = instance.mMaterial[binding]; + +						llassert(binding == model->mMaterialList[i]); +						 +						glColor4fv(material.mDiffuseColor.mV); +						if (material.mDiffuseMap.notNull())  						{ -							if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) +							if (material.mDiffuseMap->getDiscardLevel() > -1)  							{ -								gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); -								mTextureSet.insert(instance.mMaterial[i].mDiffuseMap.get()); +								gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); +								mTextureSet.insert(material.mDiffuseMap.get());  							}  						}  					} @@ -4941,7 +5065,7 @@ BOOL LLModelPreview::render()  						{  							LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; -							buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); +							buffer->setBuffer(type_mask & buffer->getTypeMask());  							buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);  							gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -5007,7 +5131,7 @@ BOOL LLModelPreview::render()  							{  								LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; -								buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); +								buffer->setBuffer(type_mask & buffer->getTypeMask());  								LLStrider<LLVector3> pos_strider;   								buffer->getVertexStrider(pos_strider, 0); @@ -5132,8 +5256,10 @@ BOOL LLModelPreview::render()  								position[j] = v;  							} -							buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); -							glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); +							const std::string& binding = instance.mModel->mMaterialList[i]; +							const LLImportMaterial& material = instance.mMaterial[binding]; +							buffer->setBuffer(type_mask & buffer->getTypeMask()); +							glColor4fv(material.mDiffuseColor.mV);  							gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  							buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);  							glColor3f(0.4f, 0.4f, 0.4f); @@ -5253,7 +5379,12 @@ void LLFloaterModelPreview::onReset(void* user_data)  	LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data;  	LLModelPreview* mp = fmp->mModelPreview;  	std::string filename = mp->mLODFile[3];  -	mp->loadModel(filename,3); + +	//reset model preview +	fmp->initModelPreview(); + +	mp = fmp->mModelPreview; +	mp->loadModel(filename,3,true);  }  //static @@ -5271,31 +5402,18 @@ void LLFloaterModelPreview::onUpload(void* user_data)  	mp->mModelPreview->saveUploadData(upload_skinweights, upload_joint_positions);  	gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale, -						  mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions); - -	mp->closeFloater(false); +						  mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mp->mUploadModelUrl, +						  true, LLHandle<LLWholeModelFeeObserver>(), mp->getWholeModelUploadObserverHandle());  }  //static -void LLFloaterModelPreview::onClearMaterials(void* user_data) -{ -	LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; -	mp->mModelPreview->clearMaterials(); -} - -//static  void LLFloaterModelPreview::refresh(LLUICtrl* ctrl, void* user_data)  { +	sInstance->toggleCalculateButton(true);  	sInstance->mModelPreview->mDirty = true;  } -void LLFloaterModelPreview::updateResourceCost() -{ -	U32 cost = mModelPreview->mResourceCost; -	childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",cost)); -} -  //static  void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata )  { @@ -5339,6 +5457,97 @@ void LLFloaterModelPreview::setStatusMessage(const std::string& msg)  	mStatusMessage = msg;  } +void LLFloaterModelPreview::toggleCalculateButton() +{ +	toggleCalculateButton(true); +} + +void LLFloaterModelPreview::toggleCalculateButton(bool visible) +{ +	mCalculateBtn->setVisible(visible); + +	bool uploadingSkin		     = childGetValue("upload_skin").asBoolean(); +	bool uploadingJointPositions = childGetValue("upload_joints").asBoolean(); +	if ( uploadingSkin ) +	{ +		//Disable the calculate button *if* the rig is invalid - which is determined during the critiquing process +		if ( uploadingJointPositions && !mModelPreview->isRigValidForJointPositionUpload() ) +		{ +			mCalculateBtn->setVisible( false ); +		} +		else +		if ( !mModelPreview->isLegacyRigValid() ) +		{			 +			mCalculateBtn->setVisible( false ); +		} +	} +	 +	mUploadBtn->setVisible(!visible); +	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + +	if (visible) +	{ +		std::string tbd = getString("tbd"); +		childSetTextArg("weights", "[EQ]", tbd); +		childSetTextArg("weights", "[ST]", tbd); +		childSetTextArg("weights", "[SIM]", tbd); +		childSetTextArg("weights", "[PH]", tbd); +		childSetTextArg("upload_fee", "[FEE]", tbd); +		childSetTextArg("price_breakdown", "[STREAMING]", tbd); +		childSetTextArg("price_breakdown", "[PHYSICS]", tbd); +		childSetTextArg("price_breakdown", "[INSTANCES]", tbd); +		childSetTextArg("price_breakdown", "[TEXTURES]", tbd); +		childSetTextArg("price_breakdown", "[MODEL]", tbd); +	} +} + +void LLFloaterModelPreview::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) +{ +	mModelPhysicsFee = result; +	mModelPhysicsFee["url"] = upload_url; + +	doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::handleModelPhysicsFeeReceived,this)); +} + +void LLFloaterModelPreview::handleModelPhysicsFeeReceived() +{ +	const LLSD& result = mModelPhysicsFee; +	mUploadModelUrl = result["url"].asString(); + +	childSetTextArg("weights", "[EQ]", llformat("%0.3f", result["resource_cost"].asReal())); +	childSetTextArg("weights", "[ST]", llformat("%0.3f", result["model_streaming_cost"].asReal())); +	childSetTextArg("weights", "[SIM]", llformat("%0.3f", result["simulation_cost"].asReal())); +	childSetTextArg("weights", "[PH]", llformat("%0.3f", result["physics_cost"].asReal())); +	childSetTextArg("upload_fee", "[FEE]", llformat("%d", result["upload_price"].asInteger())); +	childSetTextArg("price_breakdown", "[STREAMING]", llformat("%d", result["upload_price_breakdown"]["mesh_streaming"].asInteger())); +	childSetTextArg("price_breakdown", "[PHYSICS]", llformat("%d", result["upload_price_breakdown"]["mesh_physics"].asInteger())); +	childSetTextArg("price_breakdown", "[INSTANCES]", llformat("%d", result["upload_price_breakdown"]["mesh_instance"].asInteger())); +	childSetTextArg("price_breakdown", "[TEXTURES]", llformat("%d", result["upload_price_breakdown"]["texture"].asInteger())); +	childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger())); +	childSetVisible("weights", true); +	childSetVisible("upload_fee", true); +	childSetVisible("price_breakdown", true); +	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); +} + +void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) +{ +	toggleCalculateButton(true); +	llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; +} + +/*virtual*/  +void LLFloaterModelPreview::onModelUploadSuccess() +{ +	closeFloater(false); +} + +/*virtual*/  +void LLFloaterModelPreview::onModelUploadFailure() +{ +	toggleCalculateButton(true); +} +  S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)  {  	if (mContinue) @@ -5378,3 +5587,25 @@ void LLFloaterModelPreview::DecompRequest::completed()  		llassert(sInstance->mCurRequest.find(this) == sInstance->mCurRequest.end());  	}  } + +void dump_llsd_to_file(const LLSD& content, std::string filename); + +void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) +{ +	dump_llsd_to_file(result,"perm_received.xml"); +	std::string upload_status = result["mesh_upload_status"].asString(); +	// BAP HACK: handle "" for case that  MeshUploadFlag cap is broken. +	mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); + +	//mUploadBtn->setEnabled(mHasUploadPerm); +	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); +	getChild<LLTextBox>("warning_title")->setVisible(!mHasUploadPerm); +	getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm); +} + +void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason) +{ +	llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; + +	LLNotificationsUtil::add("MeshUploadPermError"); +} diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index d4f6b4d293..3a5f7602fe 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -109,7 +109,7 @@ public:  	void loadTextures() ; //called in the main thread.  	void processElement(daeElement* element, bool& badElement); -	std::vector<LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo); +	std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);  	LLImportMaterial profileToMaterial(domProfile_COMMON* material);  	std::string getElementLabel(daeElement *element);  	LLColor4 getDaeColor(daeElement* element); @@ -140,7 +140,7 @@ private:  	static bool isAlive(LLModelLoader* loader) ;  }; -class LLFloaterModelPreview : public LLFloater +class LLFloaterModelPreview : public LLFloaterModelUploadBase  {  public: @@ -162,11 +162,15 @@ public:  	virtual BOOL postBuild(); +	void initModelPreview(); +  	BOOL handleMouseDown(S32 x, S32 y, MASK mask);  	BOOL handleMouseUp(S32 x, S32 y, MASK mask);  	BOOL handleHover(S32 x, S32 y, MASK mask);  	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);  +	/*virtual*/ void onOpen(const LLSD& key); +  	static void onMouseCaptureLostModelPreview(LLMouseHandler*);  	static void setUploadAmount(S32 amount) { sUploadAmount = amount; } @@ -178,13 +182,10 @@ public:  	static void onUpload(void* data); -	static void onClearMaterials(void* data); -	  	static void refresh(LLUICtrl* ctrl, void* data); -	void updateResourceCost(); -	  	void			loadModel(S32 lod); +	void 			loadModel(S32 lod, const std::string& file_name, bool force_disable_slm = false);  	void onViewOptionChecked(const LLSD& userdata);  	bool isViewOptionChecked(const LLSD& userdata); @@ -193,6 +194,20 @@ public:  	void enableViewOption(const std::string& option);  	void disableViewOption(const std::string& option); +	// shows warning message if agent has no permissions to upload model +	/*virtual*/ void onPermissionsReceived(const LLSD& result); + +	// called when error occurs during permissions request +	/*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); + +	/*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); +				void handleModelPhysicsFeeReceived(); +	/*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); + +	/*virtual*/ void onModelUploadSuccess(); + +	/*virtual*/ void onModelUploadFailure(); +  protected:  	friend class LLModelPreview;  	friend class LLMeshFilePicker; @@ -258,6 +273,17 @@ protected:  	LLToggleableMenu* mViewOptionMenu;  	LLMutex* mStatusLock; +	LLSD mModelPhysicsFee; + +private: +	void onClickCalculateBtn(); +	void toggleCalculateButton(); + +	// Toggles between "Calculate weights & fee" and "Upload" buttons. +	void toggleCalculateButton(bool visible); + +	LLButton* mUploadBtn; +	LLButton* mCalculateBtn;  };  class LLMeshFilePicker : public LLFilePickerThread @@ -276,6 +302,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  {	  	typedef boost::signals2::signal<void (F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t;  	typedef boost::signals2::signal<void (void)> model_loaded_signal_t; +	typedef boost::signals2::signal<void (bool)> model_updated_signal_t;  public:  	LLModelPreview(S32 width, S32 height, LLFloater* fmp); @@ -297,11 +324,10 @@ public:  	virtual BOOL needsRender() { return mNeedsUpdate; }  	void setPreviewLOD(S32 lod);  	void clearModel(S32 lod); -	void loadModel(std::string filename, S32 lod); +	void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);  	void loadModelCallback(S32 lod);  	void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);  	void generateNormals(); -	void clearMaterials();  	U32 calcResourceCost();  	void rebuildUploadData();  	void saveUploadData(bool save_skinweights, bool save_joint_poisitions); @@ -335,6 +361,7 @@ public:  	boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){  return mDetailsSignal.connect(cb);  }  	boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){  return mModelLoadedSignal.connect(cb);  } +	boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){  return mModelUpdatedSignal.connect(cb);  }  	void setLoadState( U32 state ) { mLoadState = state; }  	U32 getLoadState() { return mLoadState; } @@ -420,6 +447,7 @@ private:  	details_signal_t mDetailsSignal;  	model_loaded_signal_t mModelLoadedSignal; +	model_updated_signal_t mModelUpdatedSignal;  	LLVector3	mModelPivot;  	bool		mHasPivot; diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp new file mode 100644 index 0000000000..6d3800bfa4 --- /dev/null +++ b/indra/newview/llfloatermodeluploadbase.cpp @@ -0,0 +1,58 @@ +/** + * @file llfloatermodeluploadbase.cpp + * @brief LLFloaterUploadModelBase class definition + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatermodeluploadbase.h" +#include "llagent.h" +#include "llviewerregion.h" +#include "llnotificationsutil.h" + +LLFloaterModelUploadBase::LLFloaterModelUploadBase(const LLSD& key) +:LLFloater(key), + mHasUploadPerm(false) +{ +} + +void LLFloaterModelUploadBase::requestAgentUploadPermissions() +{ +	std::string capability = "MeshUploadFlag"; +	std::string url = gAgent.getRegion()->getCapability(capability); + +	if (!url.empty()) +	{ +		llinfos<< typeid(*this).name() <<"::requestAgentUploadPermissions() requesting for upload model permissions from: "<< url <<llendl; +		LLHTTPClient::get(url, new LLUploadModelPremissionsResponder(getPermObserverHandle())); +	} +	else +	{ +		LLSD args; +		args["CAPABILITY"] = capability; +		LLNotificationsUtil::add("RegionCapabilityRequestError", args); +		// BAP HACK avoid being blocked by broken server side stuff +		mHasUploadPerm = true; +	} +} diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h new file mode 100644 index 0000000000..a52bc28687 --- /dev/null +++ b/indra/newview/llfloatermodeluploadbase.h @@ -0,0 +1,61 @@ +/** + * @file llfloatermodeluploadbase.h + * @brief LLFloaterUploadModelBase class declaration + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERMODELUPLOADBASE_H +#define LL_LLFLOATERMODELUPLOADBASE_H + +#include "lluploadfloaterobservers.h" + +class LLFloaterModelUploadBase : public LLFloater, public LLUploadPermissionsObserver, public LLWholeModelFeeObserver, public LLWholeModelUploadObserver +{ +public: + +	LLFloaterModelUploadBase(const LLSD& key); + +	virtual ~LLFloaterModelUploadBase(){}; + +	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0; + +	virtual void onPermissionsReceived(const LLSD& result) = 0; + +	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0; + +	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0; + +	virtual void onModelUploadSuccess() {}; + +	virtual void onModelUploadFailure() {}; + +protected: + +	// requests agent's permissions to upload model +	void requestAgentUploadPermissions(); + +	std::string mUploadModelUrl; +	bool mHasUploadPerm; +}; + +#endif /* LL_LLFLOATERMODELUPLOADBASE_H */ diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp index 707c8288df..b517b78e5a 100644 --- a/indra/newview/llfloatermodelwizard.cpp +++ b/indra/newview/llfloatermodelwizard.cpp @@ -46,12 +46,21 @@ static	const std::string stateNames[]={  	"choose_file",  	"optimize",  	"physics", -	"physics2",  	"review",  	"upload"}; +static void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible); +  LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key) -	: LLFloater(key) +	: LLFloaterModelUploadBase(key) +	 ,mRecalculateGeometryBtn(NULL) +	 ,mRecalculatePhysicsBtn(NULL) +	 ,mRecalculatingPhysicsBtn(NULL) +	 ,mCalculateWeightsBtn(NULL) +	 ,mCalculatingWeightsBtn(NULL) +	 ,mChooseFilePreviewPanel(NULL) +	 ,mOptimizePreviewPanel(NULL) +	 ,mPhysicsPreviewPanel(NULL)  {  	mLastEnabledState = CHOOSE_FILE;  	sInstance = this; @@ -59,7 +68,6 @@ LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key)  	mCommitCallbackRegistrar.add("Wizard.Choose", boost::bind(&LLFloaterModelWizard::setState, this, CHOOSE_FILE));  	mCommitCallbackRegistrar.add("Wizard.Optimize", boost::bind(&LLFloaterModelWizard::setState, this, OPTIMIZE));  	mCommitCallbackRegistrar.add("Wizard.Physics", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS)); -	mCommitCallbackRegistrar.add("Wizard.Physics2", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS2));  	mCommitCallbackRegistrar.add("Wizard.Review", boost::bind(&LLFloaterModelWizard::setState, this, REVIEW));  	mCommitCallbackRegistrar.add("Wizard.Upload", boost::bind(&LLFloaterModelWizard::setState, this, UPLOAD));  } @@ -81,16 +89,22 @@ void LLFloaterModelWizard::setState(int state)  		}  	} +	LLView* current_preview_panel = NULL; +  	if (state == CHOOSE_FILE)  	{  		mModelPreview->mViewOption["show_physics"] = false; +		current_preview_panel = mChooseFilePreviewPanel; +  		getChildView("close")->setVisible(false);  		getChildView("back")->setVisible(true);  		getChildView("back")->setEnabled(false);  		getChildView("next")->setVisible(true);  		getChildView("upload")->setVisible(false);  		getChildView("cancel")->setVisible(true); +		mCalculateWeightsBtn->setVisible(false); +		mCalculatingWeightsBtn->setVisible(false);  	}  	if (state == OPTIMIZE) @@ -102,12 +116,16 @@ void LLFloaterModelWizard::setState(int state)  		mModelPreview->mViewOption["show_physics"] = false; +		current_preview_panel = mOptimizePreviewPanel; +  		getChildView("back")->setVisible(true);  		getChildView("back")->setEnabled(true);  		getChildView("close")->setVisible(false);  		getChildView("next")->setVisible(true);  		getChildView("upload")->setVisible(false);  		getChildView("cancel")->setVisible(true); +		mCalculateWeightsBtn->setVisible(false); +		mCalculatingWeightsBtn->setVisible(false);  	}  	if (state == PHYSICS) @@ -115,34 +133,24 @@ void LLFloaterModelWizard::setState(int state)  		if (mLastEnabledState < state)  		{  			mModelPreview->setPhysicsFromLOD(1); -		} -		mModelPreview->mViewOption["show_physics"] = true; - -		getChildView("next")->setVisible(true); -		getChildView("upload")->setVisible(false); -		getChildView("close")->setVisible(false); -		getChildView("back")->setVisible(true); -		getChildView("back")->setEnabled(true); -		getChildView("cancel")->setVisible(true); -	} - -	if (state == PHYSICS2) -	{ -		if (mLastEnabledState < state) -		{ -			executePhysicsStage("Decompose"); +			// Trigger the recalculate physics when first entering +			// the Physics step. +			onClickRecalculatePhysics();  		}  		mModelPreview->mViewOption["show_physics"] = true; -		getChildView("next")->setVisible(true); -		getChildView("next")->setEnabled(true); +		current_preview_panel = mPhysicsPreviewPanel; + +		getChildView("next")->setVisible(false);  		getChildView("upload")->setVisible(false);  		getChildView("close")->setVisible(false);  		getChildView("back")->setVisible(true);  		getChildView("back")->setEnabled(true);  		getChildView("cancel")->setVisible(true); +		mCalculateWeightsBtn->setVisible(true); +		mCalculatingWeightsBtn->setVisible(false);  	}  	if (state == REVIEW) @@ -156,6 +164,8 @@ void LLFloaterModelWizard::setState(int state)  		getChildView("back")->setEnabled(true);  		getChildView("upload")->setVisible(true);  		getChildView("cancel")->setVisible(true); +		mCalculateWeightsBtn->setVisible(false); +		mCalculatingWeightsBtn->setVisible(false);  	}  	if (state == UPLOAD) @@ -165,8 +175,24 @@ void LLFloaterModelWizard::setState(int state)  		getChildView("back")->setVisible(false);  		getChildView("upload")->setVisible(false);  		getChildView("cancel")->setVisible(false); +		mCalculateWeightsBtn->setVisible(false); +		mCalculatingWeightsBtn->setVisible(false);  	} +	if (current_preview_panel) +	{ +		LLRect rect; +		current_preview_panel->localRectToOtherView(current_preview_panel->getLocalRect(), &rect, this); + +		// Reduce the preview rect by 1 px to fit the borders +		rect.stretch(-1); + +		if (rect != mPreviewRect) +		{ +			mPreviewRect = rect; +			mModelPreview->refresh(); +		} +	}  	updateButtons();  } @@ -198,18 +224,60 @@ void LLFloaterModelWizard::updateButtons()  			button->setEnabled(FALSE);  		}  	} +} -	LLButton *physics_button = getChild<LLButton>(stateNames[PHYSICS]+"_btn"); -	 -	if (mState == PHYSICS2) +void LLFloaterModelWizard::onClickSwitchToAdvanced() +{ +	LLFloaterModelPreview* floater_preview = LLFloaterReg::getTypedInstance<LLFloaterModelPreview>("upload_model"); +	if (!floater_preview)  	{ -		physics_button->setVisible(false); +		llwarns << "FLoater model preview not found." << llendl; +		return;  	} -	else + +	// Open floater model preview +	floater_preview->openFloater(); + +	// Close the wizard +	closeFloater(); + +	std::string filename = getChild<LLUICtrl>("lod_file")->getValue().asString(); +	if (!filename.empty())  	{ -		physics_button->setVisible(true); +		// Re-load the model to the floater model preview if it has been loaded +		// into the wizard. +		floater_preview->loadModel(3, filename);  	} +} + +void LLFloaterModelWizard::onClickRecalculateGeometry() +{ +	S32 val = getChild<LLUICtrl>("accuracy_slider")->getValue().asInteger(); + +	mModelPreview->genLODs(-1, NUM_LOD - val); + +	mModelPreview->refresh(); +} + +void LLFloaterModelWizard::onClickRecalculatePhysics() +{ +	// Hide the "Recalculate physics" button and show the "Recalculating..." +	// button instead. +	swap_controls(mRecalculatePhysicsBtn, mRecalculatingPhysicsBtn, false); + +	executePhysicsStage("Decompose"); +} +void LLFloaterModelWizard::onClickCalculateUploadFee() +{ +	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, false); + +	mModelPreview->rebuildUploadData(); + +	mUploadModelUrl.clear(); + +	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, +			true, false, false, mUploadModelUrl, false, getWholeModelFeeObserverHandle());  }  void LLFloaterModelWizard::loadModel() @@ -344,6 +412,7 @@ BOOL LLFloaterModelWizard::handleScrollWheel(S32 x, S32 y, S32 clicks)  	return TRUE;  } +  void LLFloaterModelWizard::initDecompControls()  {  	LLSD key; @@ -401,12 +470,83 @@ void LLFloaterModelWizard::initDecompControls()  	mDecompParams["Simplify Method"] = 0; // set it to retain %  } +/*virtual*/ +void LLFloaterModelWizard::onPermissionsReceived(const LLSD& result) +{ +	std::string upload_status = result["mesh_upload_status"].asString(); +	// BAP HACK: handle "" for case that  MeshUploadFlag cap is broken. +	mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); + +	getChildView("warning_label")->setVisible(!mHasUploadPerm); +	getChildView("warning_text")->setVisible(!mHasUploadPerm); +} + +/*virtual*/ +void LLFloaterModelWizard::setPermissonsErrorStatus(U32 status, const std::string& reason) +{ +	llwarns << "LLFloaterModelWizard::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; +} + +/*virtual*/ +void LLFloaterModelWizard::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) +{ +	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); + +	// Enable the "Upload" buton if we have calculated the upload fee +	// and have the permission to upload. +	getChildView("upload")->setEnabled(mHasUploadPerm); + +	mUploadModelUrl = upload_url; + +	S32 fee = result["upload_price"].asInteger(); +	childSetTextArg("review_fee", "[FEE]", llformat("%d", fee)); +	childSetTextArg("charged_fee", "[FEE]", llformat("%d", fee)); + +	setState(REVIEW); +} + +/*virtual*/ +void LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) +{ +	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true); + +	// Disable the "Review" step if it has been previously enabled. +	modelChangedCallback(); + +	llwarns << "LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; + +	setState(PHYSICS); +} + +/*virtual*/  +void LLFloaterModelWizard::onModelUploadSuccess()  +{ +	// success! +	setState(UPLOAD); +} + +/*virtual*/ +void LLFloaterModelWizard::onModelUploadFailure() +{ +	// Failure. Make the user recalculate fees +	setState(PHYSICS); +	// Disable the "Review" step if it has been previously enabled. +	if (mLastEnabledState > PHYSICS) +	{ +		 mLastEnabledState = PHYSICS; +	} + +	updateButtons(); +} +  //static  void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)  {  	if (sInstance)  	{ -		F64 physics_accuracy = sInstance->getChild<LLSliderCtrl>("physics_slider")->getValue().asReal(); +		// Invert the slider value so that "performance" end is giving the least detailed physics, +		// and the "accuracy" end is giving the most detailed physics +		F64 physics_accuracy = 1 - sInstance->getChild<LLSliderCtrl>("physics_slider")->getValue().asReal();  		sInstance->mDecompParams["Retain%"] = physics_accuracy; @@ -471,13 +611,16 @@ void LLFloaterModelWizard::DecompRequest::completed()  	{  		executePhysicsStage("Simplify");  	} +	else +	{ +		// Decomp request is complete so we can enable the "Recalculate physics" button again. +		swap_controls(sInstance->mRecalculatePhysicsBtn, sInstance->mRecalculatingPhysicsBtn, true); +	}  }  BOOL LLFloaterModelWizard::postBuild()  { -	LLView* preview_panel = getChildView("preview_panel"); -  	childSetValue("import_scale", (F32) 0.67335826);  	getChild<LLUICtrl>("browse")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); @@ -488,23 +631,36 @@ BOOL LLFloaterModelWizard::postBuild()  	getChild<LLUICtrl>("next")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickNext, this));  	getChild<LLUICtrl>("preview_lod_combo")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1));  	getChild<LLUICtrl>("preview_lod_combo2")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); -	getChild<LLUICtrl>("preview_lod_combo3")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1)); -	getChild<LLUICtrl>("accuracy_slider")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onAccuracyPerformance, this, _2));  	getChild<LLUICtrl>("upload")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onUpload, this)); -	getChild<LLUICtrl>("physics_slider")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPhysicsChanged, this)); +	getChild<LLUICtrl>("switch_to_advanced")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickSwitchToAdvanced, this)); + +	mRecalculateGeometryBtn = getChild<LLButton>("recalculate_geometry_btn"); +	mRecalculateGeometryBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculateGeometry, this)); + +	mRecalculatePhysicsBtn = getChild<LLButton>("recalculate_physics_btn"); +	mRecalculatePhysicsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculatePhysics, this)); + +	mRecalculatingPhysicsBtn = getChild<LLButton>("recalculating_physics_btn"); + +	mCalculateWeightsBtn = getChild<LLButton>("calculate"); +	mCalculateWeightsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCalculateUploadFee, this)); + +	mCalculatingWeightsBtn = getChild<LLButton>("calculating"); + +	mChooseFilePreviewPanel = getChild<LLView>("choose_file_preview_panel"); +	mOptimizePreviewPanel = getChild<LLView>("optimize_preview_panel"); +	mPhysicsPreviewPanel = getChild<LLView>("physics_preview_panel");  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;  	enable_registrar.add("Next.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableNext, this));  	enable_registrar.add("Back.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableBack, this)); - - -	mPreviewRect = preview_panel->getRect();  	mModelPreview = new LLModelPreview(512, 512, this);  	mModelPreview->setPreviewTarget(16.f);  	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelWizard::setDetails, this, _1, _2, _3, _4, _5));  	mModelPreview->setModelLoadedCallback(boost::bind(&LLFloaterModelWizard::modelLoadedCallback, this)); +	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelWizard::modelChangedCallback, this));  	mModelPreview->mViewOption["show_textures"] = true;  	center(); @@ -517,6 +673,8 @@ BOOL LLFloaterModelWizard::postBuild()  	initDecompControls(); +	requestAgentUploadPermissions(); +  	return TRUE;  } @@ -532,22 +690,29 @@ void LLFloaterModelWizard::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F  			panel->childSetText("dimension_x", llformat("%.1f", x));  			panel->childSetText("dimension_y", llformat("%.1f", y));  			panel->childSetText("dimension_z", llformat("%.1f", z)); -			panel->childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost)); -			panel->childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));	  		}  	} + +	childSetTextArg("review_prim_equiv", "[EQUIV]", llformat("%d", mModelPreview->mResourceCost));  }  void LLFloaterModelWizard::modelLoadedCallback()  {  	mLastEnabledState = CHOOSE_FILE; -	getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE);  	updateButtons();  } -void LLFloaterModelWizard::onPhysicsChanged() +void LLFloaterModelWizard::modelChangedCallback()  { -	mLastEnabledState = PHYSICS; +	// Don't allow to proceed to the "Review" step if the model has changed +	// but the new upload fee hasn't been calculated yet. +	if (mLastEnabledState > PHYSICS) +	{ +		 mLastEnabledState = PHYSICS; +	} + +	getChildView("upload")->setEnabled(false); +  	updateButtons();  } @@ -556,22 +721,10 @@ void LLFloaterModelWizard::onUpload()  	mModelPreview->rebuildUploadData();  	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,  -						  true, false, false); -	 -	setState(UPLOAD); -	 -} - -void LLFloaterModelWizard::onAccuracyPerformance(const LLSD& data) -{ -	int val = (int) data.asInteger(); - -	mModelPreview->genLODs(-1, NUM_LOD-val); - -	mModelPreview->refresh(); +						  true, false, false, mUploadModelUrl, true, +						  LLHandle<LLWholeModelFeeObserver>(), getWholeModelUploadObserverHandle());  } -  void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl)  {  	if (!mModelPreview) @@ -601,11 +754,6 @@ void LLFloaterModelWizard::refresh()  		getChildView("next")->setEnabled(model_loaded);  	} -	if (mState == REVIEW) -	{ -		getChildView("upload")->setEnabled(getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean()); -	} -  }  void LLFloaterModelWizard::draw() @@ -613,42 +761,35 @@ void LLFloaterModelWizard::draw()  	refresh();  	LLFloater::draw(); -	LLRect r = getRect(); -	 -	mModelPreview->update(); -	if (mModelPreview) +	if (mModelPreview && mState < REVIEW)  	{ +		mModelPreview->update(); +  		gGL.color3f(1.f, 1.f, 1.f);  		gGL.getTexUnit(0)->bind(mModelPreview); -		LLView *view = getChildView(stateNames[mState]+"_panel"); -		LLView* preview_panel = view->getChildView("preview_panel"); - -		LLRect rect = preview_panel->getRect(); -		if (rect != mPreviewRect) -		{ -			mModelPreview->refresh(); -			mPreviewRect = preview_panel->getRect(); -		} -		 -		LLRect item_rect; -		preview_panel->localRectToOtherView(preview_panel->getLocalRect(), &item_rect, this); -	  		gGL.begin( LLRender::QUADS );  		{  			gGL.texCoord2f(0.f, 1.f); -			gGL.vertex2i(item_rect.mLeft, item_rect.mTop-1); +			gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop);  			gGL.texCoord2f(0.f, 0.f); -			gGL.vertex2i(item_rect.mLeft, item_rect.mBottom); +			gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom);  			gGL.texCoord2f(1.f, 0.f); -			gGL.vertex2i(item_rect.mRight-1, item_rect.mBottom); +			gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom);  			gGL.texCoord2f(1.f, 1.f); -			gGL.vertex2i(item_rect.mRight-1, item_rect.mTop-1); +			gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop);  		}  		gGL.end();  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  	}  } + +// static +void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible) +{ +	first_ctrl->setVisible(first_ctr_visible); +	second_ctrl->setVisible(!first_ctr_visible); +} diff --git a/indra/newview/llfloatermodelwizard.h b/indra/newview/llfloatermodelwizard.h index b166d26295..db9b605777 100644 --- a/indra/newview/llfloatermodelwizard.h +++ b/indra/newview/llfloatermodelwizard.h @@ -30,12 +30,13 @@  #include "llmeshrepository.h"  #include "llmodel.h"  #include "llthread.h" +#include "llfloatermodeluploadbase.h"  class LLModelPreview; -class LLFloaterModelWizard : public LLFloater +class LLFloaterModelWizard : public LLFloaterModelUploadBase  {  public: @@ -62,13 +63,29 @@ public:  	BOOL handleMouseDown(S32 x, S32 y, MASK mask);  	BOOL handleMouseUp(S32 x, S32 y, MASK mask);  	BOOL handleHover(S32 x, S32 y, MASK mask); -	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);  +	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);  	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);  	void modelLoadedCallback(); -	void onPhysicsChanged(); +	void modelChangedCallback();  	void initDecompControls(); +	// shows warning message if agent has no permissions to upload model +	/*virtual*/ void onPermissionsReceived(const LLSD& result); + +	// called when error occurs during permissions request +	/*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); + +	/*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); + +	/*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); + +	/*virtual*/ void onModelUploadSuccess(); + +	/*virtual*/ void onModelUploadFailure(); + +	const LLRect& getPreviewRect() const { return mPreviewRect; } +  	LLPhysicsDecomp::decomp_params mDecompParams;  	std::set<LLPointer<DecompRequest> > mCurRequest;  	std::string mStatusMessage; @@ -80,13 +97,16 @@ private:  		CHOOSE_FILE = 0,  		OPTIMIZE,  		PHYSICS, -		PHYSICS2,  		REVIEW,  		UPLOAD  	};  	void setState(int state);  	void updateButtons(); +	void onClickSwitchToAdvanced(); +	void onClickRecalculateGeometry(); +	void onClickRecalculatePhysics(); +	void onClickCalculateUploadFee();  	void onClickCancel();  	void onClickBack();  	void onClickNext(); @@ -94,7 +114,6 @@ private:  	bool onEnableBack();  	void loadModel();  	void onPreviewLODCommit(LLUICtrl*); -	void onAccuracyPerformance(const LLSD& data);  	void onUpload();  	LLModelPreview*	mModelPreview; @@ -106,7 +125,15 @@ private:  	U32			    mLastEnabledState; +	LLButton*		mRecalculateGeometryBtn; +	LLButton*		mRecalculatePhysicsBtn; +	LLButton*		mRecalculatingPhysicsBtn; +	LLButton*		mCalculateWeightsBtn; +	LLButton*		mCalculatingWeightsBtn; +	LLView*		mChooseFilePreviewPanel; +	LLView*		mOptimizePreviewPanel; +	LLView*		mPhysicsPreviewPanel;  }; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 33b7777d2e..84fb8bd9e7 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -36,7 +36,6 @@  #include "llagentcamera.h"  #include "llbutton.h"  #include "llcheckboxctrl.h" -#include "llcombobox.h"  #include "lldraghandle.h"  #include "llerror.h"  #include "llfloaterbuildoptions.h" @@ -101,6 +100,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =  	std::string("Content"),	// PANEL_CONTENTS,  }; +  // Local prototypes  void commit_select_component(void *data);  void click_show_more(void*); @@ -116,7 +116,6 @@ void commit_radio_group_focus(LLUICtrl* ctrl);  void commit_radio_group_move(LLUICtrl* ctrl);  void commit_radio_group_edit(LLUICtrl* ctrl);  void commit_radio_group_land(LLUICtrl* ctrl); -void commit_grid_mode(LLUICtrl *);  void commit_slider_zoom(LLUICtrl *ctrl); @@ -234,7 +233,6 @@ BOOL	LLFloaterTools::postBuild()  	getChild<LLUICtrl>("checkbox uniform")->setValue((BOOL)gSavedSettings.getBOOL("ScaleUniform"));  	mCheckStretchTexture	= getChild<LLCheckBoxCtrl>("checkbox stretch textures");  	getChild<LLUICtrl>("checkbox stretch textures")->setValue((BOOL)gSavedSettings.getBOOL("ScaleStretchTextures")); -	mComboGridMode			= getChild<LLComboBox>("combobox grid mode");  	mCheckStretchUniformLabel = getChild<LLTextBox>("checkbox uniform label");  	// @@ -269,6 +267,8 @@ BOOL	LLFloaterTools::postBuild()  	// the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here  	getChild<LLUICtrl>("slider force")->setValue(log10(gSavedSettings.getF32("LandBrushForce"))); +	mCostTextBorder = getChild<LLViewBorder>("cost_text_border"); +  	mTab = getChild<LLTabContainer>("Object Info Tabs");  	if(mTab)  	{ @@ -311,7 +311,6 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)  	mCheckSnapToGrid(NULL),  	mBtnGridOptions(NULL),  	mTitleMedia(NULL), -	mComboGridMode(NULL),  	mCheckStretchUniform(NULL),  	mCheckStretchTexture(NULL),  	mCheckStretchUniformLabel(NULL), @@ -344,6 +343,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)  	mPanelFace(NULL),  	mPanelLandInfo(NULL), +	mCostTextBorder(NULL),  	mTabLand(NULL),  	mDirty(TRUE),  	mNeedMediaTitle(TRUE) @@ -367,7 +367,6 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)  	mCommitCallbackRegistrar.add("BuildTool.selectComponent",	boost::bind(&commit_select_component, this));  	mCommitCallbackRegistrar.add("BuildTool.gridOptions",		boost::bind(&LLFloaterTools::onClickGridOptions,this));  	mCommitCallbackRegistrar.add("BuildTool.applyToSelection",	boost::bind(&click_apply_to_selection, this)); -	mCommitCallbackRegistrar.add("BuildTool.gridMode",			boost::bind(&commit_grid_mode,_1));  	mCommitCallbackRegistrar.add("BuildTool.commitRadioLand",	boost::bind(&commit_radio_group_land,_1));  	mCommitCallbackRegistrar.add("BuildTool.LandBrushForce",	boost::bind(&commit_slider_dozer_force,_1));  	mCommitCallbackRegistrar.add("BuildTool.AddMedia",			boost::bind(&LLFloaterTools::onClickBtnAddMedia,this)); @@ -423,15 +422,15 @@ void LLFloaterTools::refresh()  	// Refresh object and prim count labels  	LLLocale locale(LLLocale::USER_LOCALE); - +#if 0  	if (!gMeshRepo.meshRezEnabled())  	{		  		std::string obj_count_string;  		LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount()); -		getChild<LLUICtrl>("obj_count")->setTextArg("[COUNT]", obj_count_string);	 +		getChild<LLUICtrl>("selection_count")->setTextArg("[OBJ_COUNT]", obj_count_string);  		std::string prim_count_string;  		LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount()); -		getChild<LLUICtrl>("prim_count")->setTextArg("[COUNT]", prim_count_string); +		getChild<LLUICtrl>("selection_count")->setTextArg("[PRIM_COUNT]", prim_count_string);  		// calculate selection rendering cost  		if (sShowObjectCost) @@ -448,56 +447,52 @@ void LLFloaterTools::refresh()  		getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost);  	}  	else +#endif  	{ -		// Get the number of objects selected -		std::string root_object_count_string; -		std::string object_count_string; - -		LLResMgr::getInstance()->getIntegerString( -			root_object_count_string, -			LLSelectMgr::getInstance()->getSelection()->getRootObjectCount()); -		LLResMgr::getInstance()->getIntegerString( -			object_count_string, -			LLSelectMgr::getInstance()->getSelection()->getObjectCount()); - -		F32 obj_cost = -			LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); -		F32 link_cost = -			LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); -		F32 obj_physics_cost = -			LLSelectMgr::getInstance()->getSelection()->getSelectedPhysicsCost(); -		F32 link_physics_cost = -			LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetPhysicsCost(); - -		// Update the text for the counts -		childSetTextArg( -			"linked_set_count", -			"[COUNT]", -			root_object_count_string); -		childSetTextArg("object_count", "[COUNT]", object_count_string); - -		// Update the text for the resource costs -		childSetTextArg("linked_set_cost","[COST]",llformat("%.1f", link_cost)); -		childSetTextArg("object_cost", "[COST]", llformat("%.1f", obj_cost)); -		childSetTextArg("linked_set_cost","[PHYSICS]",llformat("%.1f", link_physics_cost)); -		childSetTextArg("object_cost", "[PHYSICS]", llformat("%.1f", obj_physics_cost)); - -		// Display rendering cost if needed -		if (sShowObjectCost) +		F32 link_phys_cost  = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetPhysicsCost(); +		F32 link_cost  = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); +		S32 prim_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +		S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); + +		LLStringUtil::format_map_t selection_args; +		selection_args["OBJ_COUNT"] = llformat("%.1d", link_count); +		selection_args["PRIM_COUNT"] = llformat("%.1d", prim_count); + +		std::ostringstream selection_info; + +		bool show_adv_weight = gSavedSettings.getBOOL("ShowAdvancedBuilderOptions"); +		bool show_mesh_cost = gMeshRepo.meshRezEnabled(); + +		if (show_mesh_cost)  		{ -			std::string prim_cost_string; -			LLResMgr::getInstance()->getIntegerString(prim_cost_string, calcRenderCost()); -			getChild<LLUICtrl>("RenderingCost")->setTextArg("[COUNT]", prim_cost_string); +			LLStringUtil::format_map_t prim_equiv_args; +			prim_equiv_args["SEL_WEIGHT"] = llformat("%.1d", (S32)link_cost); +			selection_args["PE_STRING"] = getString("status_selectprimequiv", prim_equiv_args); +		} +		else +		{ +			selection_args["PE_STRING"] = "";  		} +		selection_info << getString("status_selectcount", selection_args); -		// disable the object and prim counts if nothing selected -		bool have_selection = ! LLSelectMgr::getInstance()->getSelection()->isEmpty(); -		childSetEnabled("linked_set_count", have_selection); -		childSetEnabled("object_count", have_selection); -		childSetEnabled("linked_set_cost", have_selection); -		childSetEnabled("object_cost", have_selection); -		getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost); +		if (show_adv_weight) +		{ +			selection_info << ","; + +			childSetTextArg("selection_weight", "[PHYS_WEIGHT]", llformat("%.1f", link_phys_cost)); +			childSetTextArg("selection_weight", "[DISP_WEIGHT]", llformat("%.1d", calcRenderCost())); +		} +		else +		{ +			selection_info<<"."; +		} +		getChild<LLTextBox>("selection_count")->setText(selection_info.str()); + +		bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); +		childSetVisible("selection_count",  have_selection); +		childSetVisible("selection_weight", have_selection && show_adv_weight); +		childSetVisible("selection_empty", !have_selection);  	} @@ -662,33 +657,6 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  		mRadioGroupEdit->setValue("radio select face");  	} -	if (mComboGridMode)  -	{ -		mComboGridMode->setVisible( edit_visible ); -		S32 index = mComboGridMode->getCurrentIndex(); -		mComboGridMode->removeall(); - -		switch (mObjectSelection->getSelectType()) -		{ -		case SELECT_TYPE_HUD: -		  mComboGridMode->add(getString("grid_screen_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  //mComboGridMode->add(getString("grid_reference_text")); -		  break; -		case SELECT_TYPE_WORLD: -		  mComboGridMode->add(getString("grid_world_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  mComboGridMode->add(getString("grid_reference_text")); -		  break; -		case SELECT_TYPE_ATTACHMENT: -		  mComboGridMode->add(getString("grid_attachment_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  mComboGridMode->add(getString("grid_reference_text")); -		  break; -		} - -		mComboGridMode->setCurrentByIndex(index); -	}  	// Snap to grid disabled for grab tool - very confusing  	if (mCheckSnapToGrid) mCheckSnapToGrid->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ );  	if (mBtnGridOptions) mBtnGridOptions->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ ); @@ -737,6 +705,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  	// Land buttons  	BOOL land_visible = (tool == LLToolBrushLand::getInstance() || tool == LLToolSelectLand::getInstance() ); +	mCostTextBorder->setVisible(!land_visible); +  	if (mBtnLand)	mBtnLand	->setToggleState( land_visible );  	mRadioGroupLand->setVisible( land_visible ); @@ -789,15 +759,11 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  		getChildView("Strength:")->setVisible( land_visible);  	} -	bool show_mesh_cost = gMeshRepo.meshRezEnabled(); +	bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); -	getChildView("obj_count")->setVisible( !land_visible && !show_mesh_cost); -	getChildView("prim_count")->setVisible( !land_visible && !show_mesh_cost); -	getChildView("linked_set_count")->setVisible( !land_visible && show_mesh_cost); -	getChildView("linked_set_cost")->setVisible( !land_visible && show_mesh_cost); -	getChildView("object_count")->setVisible( !land_visible && show_mesh_cost); -	getChildView("object_cost")->setVisible( !land_visible && show_mesh_cost); -	getChildView("RenderingCost")->setVisible( !land_visible && sShowObjectCost); +	getChildView("selection_count")->setVisible(!land_visible && have_selection); +	getChildView("selection_weight")->setVisible(!land_visible && have_selection && gSavedSettings.getBOOL("ShowAdvancedBuilderOptions")); +	getChildView("selection_empty")->setVisible(!land_visible && !have_selection);  	mTab->setVisible(!land_visible);  	mPanelLandInfo->setVisible(land_visible); @@ -1030,13 +996,6 @@ void commit_select_component(void *data)  	}  } -void commit_grid_mode(LLUICtrl *ctrl)    -{    -	LLComboBox* combo = (LLComboBox*)ctrl;    -     -	LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); -}  -  // static   void LLFloaterTools::setObjectType( LLPCode pcode )  { diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index fd81a75397..69636190fc 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -32,7 +32,6 @@  #include "llparcelselection.h"  class LLButton; -class LLComboBox;  class LLCheckBoxCtrl;  class LLPanelPermissions;  class LLPanelObject; @@ -140,7 +139,6 @@ public:  	LLCheckBoxCtrl*	mCheckSnapToGrid;  	LLButton*		mBtnGridOptions; -	LLComboBox*		mComboGridMode;  	LLCheckBoxCtrl*	mCheckStretchUniform;  	LLCheckBoxCtrl*	mCheckStretchTexture; @@ -179,6 +177,8 @@ public:  	LLPanelFace				*mPanelFace;  	LLPanelLandInfo			*mPanelLandInfo; +	LLViewBorder*			mCostTextBorder; +  	LLTabContainer*			mTabLand;  	LLParcelSelectionHandle	mParcelSelection; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 6e0722bcf9..afed306a28 100644..100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -34,9 +34,9 @@  #include "llagent.h"  #include "llappviewer.h"  #include "llbufferstream.h" +#include "llcallbacklist.h"  #include "llcurl.h"  #include "lldatapacker.h" -#include "llfasttimer.h"  #include "llfloatermodelpreview.h"  #include "llfloaterperms.h"  #include "lleconomy.h" @@ -49,6 +49,7 @@  #include "llthread.h"  #include "llvfile.h"  #include "llviewercontrol.h" +#include "llviewerinventory.h"  #include "llviewermenufile.h"  #include "llviewerobjectlist.h"  #include "llviewerregion.h" @@ -62,6 +63,7 @@  #include "llinventorymodel.h"  #include "llfoldertype.h"  #include "llviewerparcelmgr.h" +#include "lluploadfloaterobservers.h"  #include "boost/lexical_cast.hpp" @@ -71,13 +73,18 @@  #include <queue> -LLFastTimer::DeclareTimer FTM_MESH_UPDATE("Mesh Update"); -LLFastTimer::DeclareTimer FTM_LOAD_MESH("Load Mesh"); -  LLMeshRepository gMeshRepo;  const U32 MAX_MESH_REQUESTS_PER_SECOND = 100; +// Maximum mesh version to support.  Three least significant digits are reserved for the minor version,  +// with major version changes indicating a format change that is not backwards compatible and should not +// be parsed by viewers that don't specifically support that version. For example, if the integer "1" is  +// present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999,  +// but not 1.0 (integer 1000). +// See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format +const S32 MAX_MESH_VERSION = 999; +  U32 LLMeshRepository::sBytesReceived = 0;  U32 LLMeshRepository::sHTTPRequestCount = 0;  U32 LLMeshRepository::sHTTPRetryCount = 0; @@ -190,196 +197,6 @@ S32 LLMeshRepoThread::sActiveHeaderRequests = 0;  S32 LLMeshRepoThread::sActiveLODRequests = 0;  U32	LLMeshRepoThread::sMaxConcurrentRequests = 1; - -class LLTextureCostResponder : public LLCurl::Responder -{ -public: -	LLTextureUploadData mData; -	LLMeshUploadThread* mThread; - -	LLTextureCostResponder(LLTextureUploadData data, LLMeshUploadThread* thread)  -		: mData(data), mThread(thread) -	{ - -	} - -	virtual void completed(U32 status, const std::string& reason, const LLSD& content) -	{ -		mThread->mPendingConfirmations--; -		if (isGoodStatus(status)) -		{ -			mThread->priceResult(mData, content);	 -		} -		else -		{ -			llwarns << status << ": " << reason << llendl; - -			if (mData.mRetries < MAX_TEXTURE_UPLOAD_RETRIES) -			{ -				llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; -			 -				if (status == 499 || status == 500) -				{ -					mThread->uploadTexture(mData); -				} -				else -				{ -					llerrs << "Unhandled status " << status << llendl; -				} -			} -			else -			{  -				llwarns << "Giving up after " << mData.mRetries << " retries." << llendl; -			} -		} -	} -}; - -class LLTextureUploadResponder : public LLCurl::Responder -{ -public: -	LLTextureUploadData mData; -	LLMeshUploadThread* mThread; - -	LLTextureUploadResponder(LLTextureUploadData data, LLMeshUploadThread* thread) -		: mData(data), mThread(thread) -	{ -	} - -	virtual void completed(U32 status, const std::string& reason, const LLSD& content) -	{ -		mThread->mPendingUploads--; -		if (isGoodStatus(status)) -		{ -			mData.mUUID = content["new_asset"].asUUID(); -			gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content)); -			mThread->onTextureUploaded(mData); -		} -		else -		{ -			llwarns << status << ": " << reason << llendl; -			llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; - -			if (status == 404) -			{ -				mThread->uploadTexture(mData); -			} -			else if (status == 499) -			{ -				mThread->mConfirmedTextureQ.push(mData); -			} -			else -			{ -				llerrs << "Unhandled status " << status << llendl; -			} -		} -	} -}; - -class LLMeshCostResponder : public LLCurl::Responder -{ -public: -	LLMeshUploadData mData; -	LLMeshUploadThread* mThread; - -	LLMeshCostResponder(LLMeshUploadData data, LLMeshUploadThread* thread)  -		: mData(data), mThread(thread) -	{ - -	} - -	virtual void completed(U32 status, const std::string& reason, const LLSD& content) -	{ -		mThread->mPendingConfirmations--; - -		if (isGoodStatus(status)) -		{ -			mThread->priceResult(mData, content);	 -		} -		else -		{ -			llwarns << status << ": " << reason << llendl;			 -			 -			if (status == HTTP_INTERNAL_ERROR) -			{ -				llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; -				mThread->uploadModel(mData); -			} -			else if (status == HTTP_BAD_REQUEST) -			{ -				llwarns << "Status 400 received from server, giving up." << llendl; -			} -			else if (status == HTTP_NOT_FOUND) -			{ -				llwarns <<"Status 404 received, server is disconnected, giving up." << llendl ; -			} -			else -			{ -				llerrs << "Unhandled status " << status << llendl; -			} -		} -	} -}; - -class LLMeshUploadResponder : public LLCurl::Responder -{ -public: -	LLMeshUploadData mData; -	LLMeshUploadThread* mThread; - -	LLMeshUploadResponder(LLMeshUploadData data, LLMeshUploadThread* thread) -		: mData(data), mThread(thread) -	{ -	} - -	virtual void completed(U32 status, const std::string& reason, const LLSD& content) -	{ -		mThread->mPendingUploads--; -		if (isGoodStatus(status)) -		{ -			mData.mUUID = content["new_asset"].asUUID(); -			if (mData.mUUID.isNull()) -			{ -				LLSD args; -				std::string message = content["error"]["message"]; -				std::string identifier = content["error"]["identifier"]; -				std::string invalidity_identifier = content["error"]["invalidity_identifier"]; - -				args["MESSAGE"] = message; -				args["IDENTIFIER"] = identifier; -				args["INVALIDITY_IDENTIFIER"] = invalidity_identifier; -				args["LABEL"] = mData.mBaseModel->mLabel; - -				gMeshRepo.uploadError(args); -			} -			else -			{ -				gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content)); -				mThread->onModelUploaded(mData); -			} -		} -		else -		{ -			llwarns << status << ": " << reason << llendl; -			llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; - -			if (status == 404) -			{ -				mThread->uploadModel(mData); -			} -			else if (status == 499) -			{ -				mThread->mConfirmedQ.push(mData); -			} -			else if (status != 500) -			{ //drop internal server errors on the floor, otherwise grab -				llerrs << "Unhandled status " << status << llendl; -			} -		} -	} -}; - -  class LLMeshHeaderResponder : public LLCurl::Responder  {  public: @@ -518,38 +335,16 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s  	}  } -class LLModelObjectUploadResponder: public LLCurl::Responder -{ -	LLSD mObjectAsset; -	LLMeshUploadThread* mThread; - -public: -	LLModelObjectUploadResponder(LLMeshUploadThread* thread, const LLSD& object_asset): -		mThread(thread), -		mObjectAsset(object_asset) -	{ -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -	{ -		assert_main_thread(); -		 -		llinfos << "completed" << llendl; -		mThread->mPendingUploads--; -		mThread->mFinished = true; -	} -}; -  class LLWholeModelFeeResponder: public LLCurl::Responder  {  	LLMeshUploadThread* mThread;  	LLSD mModelData; +	LLHandle<LLWholeModelFeeObserver> mObserverHandle;  public: -	LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data): +	LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):  		mThread(thread), -		mModelData(model_data) +		mModelData(model_data), +		mObserverHandle(observer_handle)  	{  	}  	virtual void completed(U32 status, @@ -562,20 +357,32 @@ public:  			cc = llsd_from_file("fake_upload_error.xml");  		} -		llinfos << "completed" << llendl;  		mThread->mPendingUploads--;  		dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num)); + +		LLWholeModelFeeObserver* observer = mObserverHandle.get(); +  		if (isGoodStatus(status) &&  			cc["state"].asString() == "upload")  		{ -			llinfos << "fee request succeeded" << llendl; -			mThread->mWholeModelUploadURL = cc["uploader"].asString();  +			mThread->mWholeModelUploadURL = cc["uploader"].asString(); + +			if (observer) +			{ +				cc["data"]["upload_price"] = cc["upload_price"]; +				observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL); +			}  		}  		else  		{  			llwarns << "fee request failed" << llendl;  			log_upload_error(status,cc,"fee",mModelData["name"]);  			mThread->mWholeModelUploadURL = ""; + +			if (observer) +			{ +				observer->setModelPhysicsFeeErrorStatus(status, reason); +			}  		}  	} @@ -585,11 +392,13 @@ class LLWholeModelUploadResponder: public LLCurl::Responder  {  	LLMeshUploadThread* mThread;  	LLSD mModelData; +	LLHandle<LLWholeModelUploadObserver> mObserverHandle;  public: -	LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data): +	LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):  		mThread(thread), -		mModelData(model_data) +		mModelData(model_data), +		mObserverHandle(observer_handle)  	{  	}  	virtual void completed(U32 status, @@ -605,21 +414,32 @@ public:  		//assert_main_thread();  		mThread->mPendingUploads--;  		dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num)); -		llinfos << "LLWholeModelUploadResponder content: " << cc << llendl; +		 +		LLWholeModelUploadObserver* observer = mObserverHandle.get(); +  		// requested "mesh" asset type isn't actually the type  		// of the resultant object, fix it up here.  		if (isGoodStatus(status) &&  			cc["state"].asString() == "complete")  		{ -			llinfos << "upload succeeded" << llendl;  			mModelData["asset_type"] = "object";  			gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc)); + +			if (observer) +			{ +				doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer)); +			}  		}  		else  		{  			llwarns << "upload failed" << llendl;  			std::string model_name = mModelData["name"].asString();  			log_upload_error(status,cc,"upload",model_name); + +			if (observer) +			{ +				doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer)); +			}  		}  	}  }; @@ -840,15 +660,16 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  	}  	U32 header_size = mMeshHeaderSize[mesh_id]; - +	  	if (header_size > 0)  	{ +		S32 version = mMeshHeader[mesh_id]["version"].asInteger();  		S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger();  		S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger();  		mHeaderMutex->unlock(); -		if (offset >= 0 && size > 0) +		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)  		{  			//check VFS for mesh skin info  			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); @@ -859,7 +680,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  				U8* buffer = new U8[size];  				file.read(buffer, size); -				//make sure buffer isn't all 0's (reserved block but not written) +				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)  				bool zero = true;  				for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)  				{ @@ -915,12 +736,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	if (header_size > 0)  	{ +		S32 version = mMeshHeader[mesh_id]["version"].asInteger();  		S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();  		S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();  		mHeaderMutex->unlock(); -		if (offset >= 0 && size > 0) +		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)  		{  			//check VFS for mesh skin info  			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); @@ -931,7 +753,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  				U8* buffer = new U8[size];  				file.read(buffer, size); -				//make sure buffer isn't all 0's (reserved block but not written) +				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)  				bool zero = true;  				for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)  				{ @@ -987,12 +809,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	if (header_size > 0)  	{ +		S32 version = mMeshHeader[mesh_id]["version"].asInteger();  		S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();  		S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();  		mHeaderMutex->unlock(); -		if (offset >= 0 && size > 0) +		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)  		{  			//check VFS for mesh physics shape info  			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); @@ -1003,7 +826,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  				U8* buffer = new U8[size];  				file.read(buffer, size); -				//make sure buffer isn't all 0's (reserved block but not written) +				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)  				bool zero = true;  				for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)  				{ @@ -1060,9 +883,9 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)  		S32 size = file.getSize();  		if (size > 0) -		{ -			U8 buffer[1024]; -			S32 bytes = llmin(size, 1024); +		{ //NOTE -- if the header size is ever more than 4KB, this will break +			U8 buffer[4096]; +			S32 bytes = llmin(size, 4096);  			LLMeshRepository::sCacheBytesRead += bytes;	  			file.read(buffer, bytes);  			if (headerReceived(mesh_params, buffer, bytes)) @@ -1084,6 +907,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)  		retval = true;  		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits  		//within the first 4KB +		//NOTE -- this will break of headers ever exceed 4KB  		LLMeshRepository::sHTTPRequestCount++;  		mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));  	} @@ -1103,10 +927,12 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  	if (header_size > 0)  	{ +		S32 version = mMeshHeader[mesh_id]["version"].asInteger();  		S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger();  		S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger();  		mHeaderMutex->unlock(); -		if (offset >= 0 && size > 0) +				 +		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)  		{  			//check VFS for mesh asset @@ -1118,7 +944,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  				U8* buffer = new U8[size];  				file.read(buffer, size); -				//make sure buffer isn't all 0's (reserved block but not written) +				//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)  				bool zero = true;  				for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)  				{ @@ -1204,14 +1030,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  	}  	{ -		U32 cost = gMeshRepo.calcResourceCost(header); -  		LLUUID mesh_id = mesh_params.getSculptID();  		mHeaderMutex->lock();  		mMeshHeaderSize[mesh_id] = header_size;  		mMeshHeader[mesh_id] = header; -		mMeshResourceCost[mesh_id] = cost;  		mHeaderMutex->unlock();  		//check for pending requests @@ -1363,9 +1186,14 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32  }  LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, -										bool upload_skin, bool upload_joints) +										bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, +					   LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)  : LLThread("mesh upload"), -	mDiscarded(FALSE) +	mDiscarded(FALSE), +	mDoUpload(do_upload), +	mWholeModelUploadURL(upload_url), +	mFeeObserverHandle(fee_observer), +	mUploadObserverHandle(upload_observer)  {  	mInstanceList = data;  	mUploadTextures = upload_textures; @@ -1373,9 +1201,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,  	mUploadJoints = upload_joints;  	mMutex = new LLMutex(NULL);  	mCurlRequest = NULL; -	mPendingConfirmations = 0;  	mPendingUploads = 0; -	mPendingCost = 0;  	mFinished = false;  	mOrigin = gAgent.getPositionAgent();  	mHost = gAgent.getRegionHost(); @@ -1383,6 +1209,8 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,  	mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");  	mOrigin += gAgent.getAtAxis() * scale.magVec(); + +	mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;  }  LLMeshUploadThread::~LLMeshUploadThread() @@ -1441,7 +1269,14 @@ BOOL LLMeshUploadThread::isDiscarded()  void LLMeshUploadThread::run()  { -	doWholeModelUpload(); +	if (mDoUpload) +	{ +		doWholeModelUpload(); +	} +	else +	{ +		requestWholeModelFee(); +	}  }  void dump_llsd_to_file(const LLSD& content, std::string filename) @@ -1467,10 +1302,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  	LLSD res;  	result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); +	result["texture_folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);  	result["asset_type"] = "mesh";  	result["inventory_type"] = "object"; -	result["name"] = "mesh model"; -	result["description"] = "your description here"; +	result["description"] = "(No Description)"; +	result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms()); +	result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms()); +	result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms());  	res["mesh_list"] = LLSD::emptyArray();  	res["texture_list"] = LLSD::emptyArray(); @@ -1482,6 +1320,7 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  	std::map<LLViewerTexture*,S32> texture_index;  	std::map<LLModel*,S32> mesh_index; +	std::string model_name;  	S32 instance_num = 0; @@ -1498,10 +1337,9 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  		if (mesh_index.find(data.mBaseModel) == mesh_index.end())  		{  			// Have not seen this model before - create a new mesh_list entry for it. -			std::string model_name = data.mBaseModel->getName(); -			if (!model_name.empty()) +			if (model_name.empty())  			{ -				result["name"] = model_name; +				model_name = data.mBaseModel->getName();  			}  			std::stringstream ostr; @@ -1556,24 +1394,15 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  			instance_entry["scale"] = ll_sd_from_vector3(scale);  			instance_entry["material"] = LL_MCODE_WOOD; -			LLPermissions perm; -			perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false); -			perm.setCreator(gAgent.getID()); -		 -			perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base -						   PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner -						   LLFloaterPerms::getEveryonePerms(), -						   LLFloaterPerms::getGroupPerms(), -						   LLFloaterPerms::getNextOwnerPerms()); -			instance_entry["permissions"] = ll_create_sd_from_permissions(perm);  			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);  			instance_entry["mesh"] = mesh_index[data.mBaseModel];  			instance_entry["face_list"] = LLSD::emptyArray(); -			for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++) +			S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; +			for (S32 face_num = 0; face_num < end; face_num++)  			{ -				LLImportMaterial& material = instance.mMaterial[face_num]; +				LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];  				LLSD face_entry = LLSD::emptyMap();  				LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); @@ -1624,75 +1453,66 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  		}  	} +	if (model_name.empty()) model_name = "mesh model"; +	result["name"] = model_name;  	result["asset_resources"] = res;  	dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));  	dest = result;  } -void LLMeshUploadThread::doWholeModelUpload() +void LLMeshUploadThread::generateHulls()  { -	dump_num++; -	 -	mCurlRequest = new LLCurlRequest();	 - -	// Queue up models for hull generation (viewer-side)  	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) -	{ -		LLMeshUploadData data; -		data.mBaseModel = iter->first; - -		LLModelInstance& instance = *(iter->second.begin()); - -		for (S32 i = 0; i < 5; i++)  		{ -			data.mModel[i] = instance.mLOD[i]; -		} +			LLMeshUploadData data; +			data.mBaseModel = iter->first; -		//queue up models for hull generation -		LLModel* physics = NULL; +			LLModelInstance& instance = *(iter->second.begin()); -		if (data.mModel[LLModel::LOD_PHYSICS].notNull()) -		{ -			physics = data.mModel[LLModel::LOD_PHYSICS]; -		} -		else if (data.mModel[LLModel::LOD_MEDIUM].notNull()) -		{ -			physics = data.mModel[LLModel::LOD_MEDIUM]; -		} -		else -		{ -			physics = data.mModel[LLModel::LOD_HIGH]; -		} +			for (S32 i = 0; i < 5; i++) +			{ +				data.mModel[i] = instance.mLOD[i]; +			} -		llassert(physics != NULL); -		 -		DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this); -		if(request->isValid()) -		{ -			gMeshRepo.mDecompThread->submitRequest(request); -		}		 -	} +			//queue up models for hull generation +			LLModel* physics = NULL; -	while (!mPhysicsComplete) -	{ -		apr_sleep(100); -	} +			if (data.mModel[LLModel::LOD_PHYSICS].notNull()) +			{ +				physics = data.mModel[LLModel::LOD_PHYSICS]; +			} +			else if (data.mModel[LLModel::LOD_LOW].notNull()) +			{ +				physics = data.mModel[LLModel::LOD_LOW]; +			} +			else if (data.mModel[LLModel::LOD_MEDIUM].notNull()) +			{ +				physics = data.mModel[LLModel::LOD_MEDIUM]; +			} +			else +			{ +				physics = data.mModel[LLModel::LOD_HIGH]; +			} -	LLSD model_data; -	wholeModelToLLSD(model_data,false); -	dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num)); +			llassert(physics != NULL); -	mPendingUploads++; -	LLCurlRequest::headers_t headers; -	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, -					   new LLWholeModelFeeResponder(this,model_data)); +			DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this); +			if(request->isValid()) +			{ +				gMeshRepo.mDecompThread->submitRequest(request); +			} +		} -	do -	{ -		mCurlRequest->process(); -	} while (mCurlRequest->getQueued() > 0); +		while (!mPhysicsComplete) +		{ +			apr_sleep(100); +		} +} +void LLMeshUploadThread::doWholeModelUpload() +{ +	mCurlRequest = new LLCurlRequest();  	if (mWholeModelUploadURL.empty())  	{ @@ -1700,15 +1520,20 @@ void LLMeshUploadThread::doWholeModelUpload()  	}  	else  	{ +		generateHulls(); +  		LLSD full_model_data;  		wholeModelToLLSD(full_model_data, true);  		LLSD body = full_model_data["asset_resources"];  		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num)); +		LLCurlRequest::headers_t headers;  		mCurlRequest->post(mWholeModelUploadURL, headers, body, -						   new LLWholeModelUploadResponder(this, model_data)); +						   new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut);  		do  		{  			mCurlRequest->process(); +			//sleep for 10ms to prevent eating a whole core +			apr_sleep(10000);  		} while (mCurlRequest->getQueued() > 0);  	} @@ -1719,22 +1544,36 @@ void LLMeshUploadThread::doWholeModelUpload()  	mFinished = true;  } -void LLMeshUploadThread::uploadModel(LLMeshUploadData& data) -{ //called from arbitrary thread -	{ -		LLMutexLock lock(mMutex); -		mUploadQ.push(data); -	} -} +void LLMeshUploadThread::requestWholeModelFee() +{ +	dump_num++; -void LLMeshUploadThread::uploadTexture(LLTextureUploadData& data) -{ //called from mesh upload thread -	mTextureQ.push(data);	 -} +	mCurlRequest = new LLCurlRequest(); + +	generateHulls(); + +	LLSD model_data; +	wholeModelToLLSD(model_data,false); +	dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num)); +	mPendingUploads++; +	LLCurlRequest::headers_t headers; +	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, +					   new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); -static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_LOADED("Notify Loaded"); -static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_UNAVAILABLE("Notify Unavailable"); +	do +	{ +		mCurlRequest->process(); +		//sleep for 10ms to prevent eating a whole core +		apr_sleep(10000); +	} while (mCurlRequest->getQueued() > 0); + +	delete mCurlRequest; +	mCurlRequest = NULL; + +	// Currently a no-op. +	mFinished = true; +}  void LLMeshRepoThread::notifyLoadedMeshes()  { @@ -1799,7 +1638,9 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)  {  	lod = llclamp(lod, 0, 3); -	if (header.has("404")) +	S32 version = header["version"]; + +	if (header.has("404") || version > MAX_MESH_VERSION)  	{  		return -1;  	} @@ -1832,19 +1673,6 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)  	return -1;  } -U32 LLMeshRepoThread::getResourceCost(const LLUUID& mesh_id) -{ -	LLMutexLock lock(mHeaderMutex); -	 -	std::map<LLUUID, U32>::iterator iter = mMeshResourceCost.find(mesh_id); -	if (iter != mMeshResourceCost.end()) -	{ -		return iter->second; -	} - -	return 0; -} -  void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)  {  	mThread->mMeshHeader[data.mUUID] = header; @@ -2135,54 +1963,54 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  		LLUUID mesh_id = mMeshParams.getSculptID();  		LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; -		std::stringstream str; +		S32 version = header["version"].asInteger(); + +		if (version <= MAX_MESH_VERSION) +		{ +			std::stringstream str; -		S32 lod_bytes = 0; +			S32 lod_bytes = 0; -		for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) -		{ //figure out how many bytes we'll need to reserve in the file -			std::string lod_name = header_lod[i]; -			lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); -		} +			for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) +			{ //figure out how many bytes we'll need to reserve in the file +				std::string lod_name = header_lod[i]; +				lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); +			} -		//just in case skin info or decomposition is at the end of the file (which it shouldn't be) -		lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); -		lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); +			//just in case skin info or decomposition is at the end of the file (which it shouldn't be) +			lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); +			lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); -		S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; -		S32 bytes = lod_bytes + header_bytes;  +			S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; +			S32 bytes = lod_bytes + header_bytes;  -		//it's possible for the remote asset to have more data than is needed for the local cache -		//only allocate as much space in the VFS as is needed for the local cache -		data_size = llmin(data_size, bytes); +			//it's possible for the remote asset to have more data than is needed for the local cache +			//only allocate as much space in the VFS as is needed for the local cache +			data_size = llmin(data_size, bytes); -		LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); -		if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) -		{ -			LLMeshRepository::sCacheBytesWritten += data_size; +			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); +			if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) +			{ +				LLMeshRepository::sCacheBytesWritten += data_size; -			file.write((const U8*) data, data_size); +				file.write((const U8*) data, data_size); -			//zero out the rest of the file  -			U8 block[4096]; -			memset(block, 0, 4096); - -			while (bytes-file.tell() > 4096) -			{ -				file.write(block, 4096); -			} +				//zero out the rest of the file  +				U8 block[4096]; +				memset(block, 0, 4096); -			S32 remaining = bytes-file.tell(); +				while (bytes-file.tell() > 4096) +				{ +					file.write(block, 4096); +				} -			if (remaining < 0 || remaining > 4096) -			{ -				llerrs << "Bad padding of mesh asset cache entry." << llendl; -			} +				S32 remaining = bytes-file.tell(); -			if (remaining > 0) -			{ -				file.write(block, remaining); +				if (remaining > 0) +				{ +					file.write(block, remaining); +				}  			}  		}  	} @@ -2292,8 +2120,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para  		return detail;  	} -	LLFastTimer t(FTM_LOAD_MESH);  -  	{  		LLMutexLock lock(mMeshMutex);  		//add volume to list of loading meshes @@ -2369,11 +2195,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para  	return detail;  } -static LLFastTimer::DeclareTimer FTM_START_MESH_THREAD("Start Thread"); -static LLFastTimer::DeclareTimer FTM_LOAD_MESH_LOD("Load LOD"); -static LLFastTimer::DeclareTimer FTM_MESH_LOCK1("Lock 1"); -static LLFastTimer::DeclareTimer FTM_MESH_LOCK2("Lock 2"); -  void LLMeshRepository::notifyLoadedMeshes()  { //called from main thread @@ -2406,6 +2227,38 @@ void LLMeshRepository::notifyLoadedMeshes()  			LLAssetType::EType asset_type = LLAssetType::lookup(data.mPostData["asset_type"].asString());  			LLInventoryType::EType inventory_type = LLInventoryType::lookup(data.mPostData["inventory_type"].asString()); +			// Handle addition of texture, if any. +			if ( data.mResponse.has("new_texture_folder_id") ) +			{ +				const LLUUID& folder_id = data.mResponse["new_texture_folder_id"].asUUID(); + +				if ( folder_id.notNull() ) +				{ +					LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); + +					std::string name; +					// Check if the server built a different name for the texture folder +					if ( data.mResponse.has("new_texture_folder_name") ) +					{ +						name = data.mResponse["new_texture_folder_name"].asString(); +					} +					else +					{ +						name = data.mPostData["name"].asString(); +					} + +					// Add the category to the internal representation +					LLPointer<LLViewerInventoryCategory> cat =  +						new LLViewerInventoryCategory(folder_id, parent_id,  +							LLFolderType::FT_NONE, name, gAgent.getID()); +					cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); + +					LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); +					gInventory.accountForUpdate(update); +					gInventory.updateCategory(cat); +				} +			} +  			on_new_single_inventory_upload_complete(  				asset_type,  				inventory_type, @@ -2414,7 +2267,8 @@ void LLMeshRepository::notifyLoadedMeshes()  				data.mPostData["name"],  				data.mPostData["description"],  				data.mResponse, -				0); +				data.mResponse["upload_price"]); +			//}  			mInventoryQ.pop();  		} @@ -2439,18 +2293,9 @@ void LLMeshRepository::notifyLoadedMeshes()  		}  	} -	LLFastTimer t(FTM_MESH_UPDATE); - -	{ -		LLFastTimer t(FTM_MESH_LOCK1); -		mMeshMutex->lock();	 -	} - -	{ -		LLFastTimer t(FTM_MESH_LOCK2); -		mThread->mMutex->lock(); -	} -	 +	mMeshMutex->lock();	 +	mThread->mMutex->lock(); +		  	//popup queued error messages from background threads  	while (!mUploadErrorQ.empty())  	{ @@ -2502,7 +2347,6 @@ void LLMeshRepository::notifyLoadedMeshes()  		while (!mPendingRequests.empty() && push_count > 0)  		{ -			LLFastTimer t(FTM_LOAD_MESH_LOD);  			LLMeshRepoThread::LODRequest& request = mPendingRequests.front();  			mThread->loadMeshLOD(request.mMeshParams, request.mLOD);  			mPendingRequests.erase(mPendingRequests.begin()); @@ -2652,25 +2496,6 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo  	return mThread->getActualMeshLOD(mesh_params, lod);  } -U32 LLMeshRepository::calcResourceCost(LLSD& header) -{ -	U32 bytes = 0; - -	for (U32 i = 0; i < 4; i++) -	{ -		bytes += header[header_lod[i]]["size"].asInteger(); -	} - -	bytes += header["skin"]["size"].asInteger(); - -	return bytes/4096 + 1; -} - -U32 LLMeshRepository::getResourceCost(const LLUUID& mesh_id) -{ -	return mThread->getResourceCost(mesh_id); -} -  const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)  {  	if (mesh_id.notNull()) @@ -2809,9 +2634,11 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)  void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, -									bool upload_skin, bool upload_joints) +									bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, +								   LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)  { -	LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints); +	LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url,  +														do_upload, fee_observer, upload_observer);  	mUploadWaitList.push_back(thread);  } @@ -2839,101 +2666,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)  } - -void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data) -{ -	if(isDiscarded()) -	{ -		return ; -	} - -	if (!data.mRSVP.empty()) -	{ -		std::stringstream ostr; - -		LLModel::Decomposition& decomp = -			data.mModel[LLModel::LOD_PHYSICS].notNull() ?  -			data.mModel[LLModel::LOD_PHYSICS]->mPhysics :  -			data.mBaseModel->mPhysics; - -		decomp.mBaseHull = mHullMap[data.mBaseModel]; - -		LLModel::writeModel( -			ostr,   -			data.mModel[LLModel::LOD_PHYSICS], -			data.mModel[LLModel::LOD_HIGH], -			data.mModel[LLModel::LOD_MEDIUM], -			data.mModel[LLModel::LOD_LOW], -			data.mModel[LLModel::LOD_IMPOSTOR],  -			decomp, -			mUploadSkin, -			mUploadJoints); - -		data.mAssetData = ostr.str(); - -		LLCurlRequest::headers_t headers; -		mPendingUploads++; - -		mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLMeshUploadResponder(data, this)); -	} -} - -void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data) -{ -	if(isDiscarded()) -	{ -		return ; -	} - -	if (!data.mRSVP.empty()) -	{ -		std::stringstream ostr; -		 -		if (!data.mTexture->isRawImageValid()) -		{ -			data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel()); -		} - -		if(data.mTexture->hasSavedRawImage()) -		{ -			LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getSavedRawImage()); -		 -			ostr.write((const char*) upload_file->getData(), upload_file->getDataSize()); -		} - -		data.mAssetData = ostr.str(); - -		LLCurlRequest::headers_t headers; -		mPendingUploads++; - -		mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLTextureUploadResponder(data, this)); -	} -} - - -void LLMeshUploadThread::onModelUploaded(LLMeshUploadData& data) -{ -	createObjects(data); -} - -void LLMeshUploadThread::onTextureUploaded(LLTextureUploadData& data) -{ -	mTextureMap[data.mTexture] = data; -} - - -void LLMeshUploadThread::createObjects(LLMeshUploadData& data) -{ -	instance_list& instances = mInstance[data.mBaseModel]; - -	for (instance_list::iterator iter = instances.begin(); iter != instances.end(); ++iter) -	{ //create prims that reference given mesh -		LLModelInstance& instance = *iter; -		instance.mMeshID = data.mUUID; -		mInstanceQ.push(instance); -	} -} -  void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,  											 LLVector3& result_pos,  											 LLQuaternion& result_rot, @@ -2974,147 +2706,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,  	result_rot = quat_rotation;   } -										  -LLSD LLMeshUploadThread::createObject(LLModelInstance& instance) -{ -	LLMatrix4 transformation = instance.mTransform; - -	llassert(instance.mMeshID.notNull()); -	 -	// check for reflection -	BOOL reflected = (transformation.determinant() < 0); - -	// compute position -	LLVector3 position = LLVector3(0, 0, 0) * transformation; - -	// compute scale -	LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position; -	LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position; -	LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position; -	F32 x_length = x_transformed.normalize(); -	F32 y_length = y_transformed.normalize(); -	F32 z_length = z_transformed.normalize(); -	LLVector3 scale = LLVector3(x_length, y_length, z_length); - -    // adjust for "reflected" geometry -	LLVector3 x_transformed_reflected = x_transformed; -	if (reflected) -	{ -		x_transformed_reflected *= -1.0; -	} -	 -	// compute rotation -	LLMatrix3 rotation_matrix; -	rotation_matrix.setRows(x_transformed_reflected, y_transformed, z_transformed); -	LLQuaternion quat_rotation = rotation_matrix.quaternion(); -	quat_rotation.normalize(); // the rotation_matrix might not have been orthoginal.  make it so here. -	LLVector3 euler_rotation; -	quat_rotation.getEulerAngles(&euler_rotation.mV[VX], &euler_rotation.mV[VY], &euler_rotation.mV[VZ]); - -	// -	// build parameter block to construct this prim -	// -	 -	LLSD object_params; - -	// create prim - -	// set volume params -	U8 sculpt_type = LL_SCULPT_TYPE_MESH; -	if (reflected) -	{ -		sculpt_type |= LL_SCULPT_FLAG_MIRROR; -	} -	LLVolumeParams  volume_params; -	volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); -	volume_params.setBeginAndEndS( 0.f, 1.f ); -	volume_params.setBeginAndEndT( 0.f, 1.f ); -	volume_params.setRatio  ( 1, 1 ); -	volume_params.setShear  ( 0, 0 ); -	volume_params.setSculptID(instance.mMeshID, sculpt_type); -	object_params["shape"] = volume_params.asLLSD(); - -	object_params["material"] = LL_MCODE_WOOD; - -	object_params["group-id"] = gAgent.getGroupID(); -	object_params["pos"] = ll_sd_from_vector3(position + mOrigin); -	object_params["rotation"] = ll_sd_from_quaternion(quat_rotation); -	object_params["scale"] = ll_sd_from_vector3(scale); -	object_params["name"] = instance.mLabel; - -	// load material from dae file -	object_params["facelist"] = LLSD::emptyArray(); -	for (S32 i = 0; i < instance.mMaterial.size(); i++) -	{ -		LLTextureEntry te; -		LLImportMaterial& mat = instance.mMaterial[i]; - -		te.setColor(mat.mDiffuseColor); - -		LLUUID diffuse_id = mTextureMap[mat.mDiffuseMap].mUUID; - -		if (diffuse_id.notNull()) -		{ -			te.setID(diffuse_id); -		} -		else -		{ -			te.setID(LLUUID("5748decc-f629-461c-9a36-a35a221fe21f")); // blank texture -		} - -		te.setFullbright(mat.mFullbright); - -		object_params["facelist"][i] = te.asLLSD(); -	} - -	// set extra parameters -	LLSculptParams sculpt_params; -	sculpt_params.setSculptTexture(instance.mMeshID); -	sculpt_params.setSculptType(sculpt_type); -	U8 buffer[MAX_OBJECT_PARAMS_SIZE+1]; -	LLDataPackerBinaryBuffer dp(buffer, MAX_OBJECT_PARAMS_SIZE); -	sculpt_params.pack(dp); -	std::vector<U8> v(dp.getCurrentSize()); -	memcpy(&v[0], buffer, dp.getCurrentSize()); -	LLSD extra_parameter; -	extra_parameter["extra_parameter"] = sculpt_params.mType; -	extra_parameter["param_data"] = v; -	object_params["extra_parameters"].append(extra_parameter); - -	LLPermissions perm; -	perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false); -	perm.setCreator(gAgent.getID()); - -	perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base -				   PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner -				   LLFloaterPerms::getEveryonePerms(), -				   LLFloaterPerms::getGroupPerms(), -				   LLFloaterPerms::getNextOwnerPerms()); -		 -	object_params["permissions"] = ll_create_sd_from_permissions(perm); - -	object_params["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); - -	return object_params; -} - -void LLMeshUploadThread::priceResult(LLMeshUploadData& data, const LLSD& content) -{ -	mPendingCost += content["upload_price"].asInteger(); -	data.mRSVP = content["rsvp"].asString(); - -	mConfirmedQ.push(data); -} - -void LLMeshUploadThread::priceResult(LLTextureUploadData& data, const LLSD& content) -{ -	mPendingCost += content["upload_price"].asInteger(); -	data.mRSVP = content["rsvp"].asString(); - -	mConfirmedTextureQ.push(data); -} - -  bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const  {  	if (mDiffuseMap != rhs.mDiffuseMap) @@ -3137,6 +2728,11 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const  		return mDiffuseColor < rhs.mDiffuseColor;  	} +	if (mBinding != rhs.mBinding) +	{ +		return mBinding < rhs.mBinding; +	} +  	return mFullbright < rhs.mFullbright;  } @@ -3158,55 +2754,66 @@ void LLMeshRepository::uploadError(LLSD& args)  //static  F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod)  { -	F32 dlowest = llmin(radius/0.03f, 256.f); -	F32 dlow = llmin(radius/0.06f, 256.f); -	F32 dmid = llmin(radius/0.24f, 256.f); -	 -	F32 bytes_lowest = header["lowest_lod"]["size"].asReal()/1024.f; -	F32 bytes_low = header["low_lod"]["size"].asReal()/1024.f; -	F32 bytes_mid = header["medium_lod"]["size"].asReal()/1024.f; -	F32 bytes_high = header["high_lod"]["size"].asReal()/1024.f; +	F32 max_distance = 512.f; -	if (bytes) -	{ -		*bytes = 0; -		*bytes += header["lowest_lod"]["size"].asInteger(); -		*bytes += header["low_lod"]["size"].asInteger(); -		*bytes += header["medium_lod"]["size"].asInteger(); -		*bytes += header["high_lod"]["size"].asInteger(); -	} +	F32 dlowest = llmin(radius/0.03f, max_distance); +	F32 dlow = llmin(radius/0.06f, max_distance); +	F32 dmid = llmin(radius/0.24f, max_distance); +	 +	F32 METADATA_DISCOUNT = (F32) gSavedSettings.getU32("MeshMetaDataDiscount");  //discount 128 bytes to cover the cost of LLSD tags and compression domain overhead +	F32 MINIMUM_SIZE = (F32) gSavedSettings.getU32("MeshMinimumByteSize"); //make sure nothing is "free" +	F32 bytes_per_triangle = (F32) gSavedSettings.getU32("MeshBytesPerTriangle"); -	if (bytes_visible) -	{ -		lod = LLMeshRepository::getActualMeshLOD(header, lod); -		if (lod >= 0 && lod <= 3) -		{ -			*bytes_visible = header[header_lod[lod]]["size"].asInteger(); -		} -	} +	S32 bytes_lowest = header["lowest_lod"]["size"].asInteger(); +	S32 bytes_low = header["low_lod"]["size"].asInteger(); +	S32 bytes_mid = header["medium_lod"]["size"].asInteger(); +	S32 bytes_high = header["high_lod"]["size"].asInteger(); -	if (bytes_high == 0.f) +	if (bytes_high == 0)  	{  		return 0.f;  	} -	if (bytes_mid == 0.f) +	if (bytes_mid == 0)  	{  		bytes_mid = bytes_high;  	} -	if (bytes_low == 0.f) +	if (bytes_low == 0)  	{  		bytes_low = bytes_mid;  	} -	if (bytes_lowest == 0.f) +	if (bytes_lowest == 0)  	{  		bytes_lowest = bytes_low;  	} -	F32 max_area = 65536.f; +	F32 triangles_lowest = llmax((F32) bytes_lowest-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; +	F32 triangles_low = llmax((F32) bytes_low-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; +	F32 triangles_mid = llmax((F32) bytes_mid-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; +	F32 triangles_high = llmax((F32) bytes_high-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + +	if (bytes) +	{ +		*bytes = 0; +		*bytes += header["lowest_lod"]["size"].asInteger(); +		*bytes += header["low_lod"]["size"].asInteger(); +		*bytes += header["medium_lod"]["size"].asInteger(); +		*bytes += header["high_lod"]["size"].asInteger(); +	} + +	if (bytes_visible) +	{ +		lod = LLMeshRepository::getActualMeshLOD(header, lod); +		if (lod >= 0 && lod <= 3) +		{ +			*bytes_visible = header[header_lod[lod]]["size"].asInteger(); +		} +	} + +	F32 max_area = 102932.f; //area of circle that encompasses region  	F32 min_area = 1.f;  	F32 high_area = llmin(F_PI*dmid*dmid, max_area); @@ -3229,12 +2836,12 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32  	low_area /= total_area;  	lowest_area /= total_area; -	F32 weighted_avg = bytes_high*high_area + -					   bytes_mid*mid_area + -					   bytes_low*low_area + -					  bytes_lowest*lowest_area; +	F32 weighted_avg = triangles_high*high_area + +					   triangles_mid*mid_area + +					   triangles_low*low_area + +					  triangles_lowest*lowest_area; -	return weighted_avg * gSavedSettings.getF32("MeshStreamingCostScaler"); +	return weighted_avg/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;  } @@ -3291,24 +2898,27 @@ S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2)  	return 1;  } -void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh) +void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based)  {  	mesh.mVertexBase = mCurRequest->mPositions[0].mV;  	mesh.mVertexStrideBytes = 12;  	mesh.mNumVertices = mCurRequest->mPositions.size(); -	mesh.mIndexType = LLCDMeshData::INT_16; -	mesh.mIndexBase = &(mCurRequest->mIndices[0]); -	mesh.mIndexStrideBytes = 6; +	if(!vertex_based) +	{ +		mesh.mIndexType = LLCDMeshData::INT_16; +		mesh.mIndexBase = &(mCurRequest->mIndices[0]); +		mesh.mIndexStrideBytes = 6; -	mesh.mNumTriangles = mCurRequest->mIndices.size()/3; +		mesh.mNumTriangles = mCurRequest->mIndices.size()/3; +	} -	if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2) +	if ((vertex_based || mesh.mNumTriangles > 0) && mesh.mNumVertices > 2)  	{  		LLCDResult ret = LLCD_OK;  		if (LLConvexDecomposition::getInstance() != NULL)  		{ -			ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh); +			ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh, vertex_based);  		}  		if (ret) @@ -3332,7 +2942,7 @@ void LLPhysicsDecomp::doDecomposition()  	//load data intoLLCD  	if (stage == 0)  	{ -		setMeshData(mesh); +		setMeshData(mesh, false);  	}  	//build parameter map @@ -3506,11 +3116,54 @@ void make_box(LLPhysicsDecomp::Request * request)  void LLPhysicsDecomp::doDecompositionSingleHull()  { -	LLCDMeshData mesh; +	LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance(); + +	if (decomp == NULL) +	{ +		//stub. do nothing. +		return; +	} -	setMeshData(mesh); +	LLCDMeshData mesh;	 + +#if 1 +	setMeshData(mesh, true); + +	LLCDResult ret = decomp->buildSingleHull() ; +	if(ret) +	{ +		llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl; +		make_box(mCurRequest); +	} + +	mMutex->lock(); +	mCurRequest->mHull.clear(); +	mCurRequest->mHull.resize(1); +	mCurRequest->mHullMesh.clear(); +	mMutex->unlock(); + +	std::vector<LLVector3> p; +	LLCDHull hull; +		 +	// if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code +	decomp->getSingleHull(&hull); + +	const F32* v = hull.mVertexBase; + +	for (S32 j = 0; j < hull.mNumVertices; ++j) +	{ +		LLVector3 vert(v[0], v[1], v[2]);  +		p.push_back(vert); +		v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); +	} +						 +	mMutex->lock(); +	mCurRequest->mHull[0] = p; +	mMutex->unlock();	 -	 +#else +	setMeshData(mesh, false); +  	//set all parameters to default  	std::map<std::string, const LLCDParam*> param_map; @@ -3519,23 +3172,15 @@ void LLPhysicsDecomp::doDecompositionSingleHull()  	if (!params)  	{ -		param_count = LLConvexDecomposition::getInstance()->getParameters(¶ms); +		param_count = decomp->getParameters(¶ms);  	} -	LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance(); - -	if (decomp == NULL) -	{ -		//stub. do nothing. -		return; -	} -  	for (S32 i = 0; i < param_count; ++i)  	{  		decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);  	} -	const S32 STAGE_DECOMPOSE = mStageID["Decompose"]; +	const S32 STAGE_DECOMPOSE = mStageID["Decompose"];	  	const S32 STAGE_SIMPLIFY = mStageID["Simplify"];  	const S32 DECOMP_PREVIEW = 0;  	const S32 SIMPLIFY_RETAIN = 0; @@ -3597,7 +3242,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull()  			}  		}  	} - +#endif  	{  		completeCurrent(); @@ -3760,7 +3405,8 @@ LLModelInstance::LLModelInstance(LLSD& data)  	for (U32 i = 0; i < data["material"].size(); ++i)  	{ -		mMaterial.push_back(LLImportMaterial(data["material"][i])); +		LLImportMaterial mat(data["material"][i]); +		mMaterial[mat.mBinding] = mat;  	}  } @@ -3773,9 +3419,10 @@ LLSD LLModelInstance::asLLSD()  	ret["label"] = mLabel;  	ret["transform"] = mTransform.getValue(); -	for (U32 i = 0; i < mMaterial.size(); ++i) +	U32 i = 0; +	for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)  	{ -		ret["material"][i] = mMaterial[i].asLLSD(); +		ret["material"][i++] = iter->second.asLLSD();  	}  	return ret; @@ -3787,6 +3434,7 @@ LLImportMaterial::LLImportMaterial(LLSD& data)  	mDiffuseMapLabel = data["diffuse"]["label"].asString();  	mDiffuseColor.setValue(data["diffuse"]["color"]);  	mFullbright = data["fullbright"].asBoolean(); +	mBinding = data["binding"].asString();  } @@ -3798,7 +3446,8 @@ LLSD LLImportMaterial::asLLSD()  	ret["diffuse"]["label"] = mDiffuseMapLabel;  	ret["diffuse"]["color"] = mDiffuseColor.getValue();  	ret["fullbright"] = mFullbright; -	 +	ret["binding"] = mBinding; +  	return ret;  } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index f237c3a60e..35a7314cd5 100644..100755 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -36,6 +36,7 @@  #define LLCONVEXDECOMPINTER_STATIC 1  #include "llconvexdecomposition.h" +#include "lluploadfloaterobservers.h"  class LLVOVolume;  class LLMeshResponder; @@ -91,6 +92,7 @@ public:  	LLPointer<LLViewerFetchedTexture> mDiffuseMap;  	std::string mDiffuseMapFilename;  	std::string mDiffuseMapLabel; +	std::string mBinding;  	LLColor4 mDiffuseColor;  	bool mFullbright; @@ -119,9 +121,9 @@ public:  	S32 mLocalMeshID;  	LLMatrix4 mTransform; -	std::vector<LLImportMaterial> mMaterial; +	std::map<std::string, LLImportMaterial> mMaterial; -	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::vector<LLImportMaterial>& materials) +	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)  		: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)  	{  		mLocalMeshID = -1; @@ -189,7 +191,7 @@ public:  	static S32 llcdCallback(const char*, S32, S32);  	void cancel(); -	void setMeshData(LLCDMeshData& mesh); +	void setMeshData(LLCDMeshData& mesh, bool vertex_based);  	void doDecomposition();  	void doDecompositionSingleHull(); @@ -229,8 +231,7 @@ public:  	mesh_header_map mMeshHeader;  	std::map<LLUUID, U32> mMeshHeaderSize; -	std::map<LLUUID, U32> mMeshResourceCost; - +	  	class HeaderRequest  	{   	public: @@ -333,8 +334,7 @@ public:  	void notifyLoadedMeshes();  	S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); -	U32 getResourceCost(const LLUUID& mesh_params); - +	  	void loadMeshSkinInfo(const LLUUID& mesh_id);  	void loadMeshDecomposition(const LLUUID& mesh_id);  	void loadMeshPhysicsShape(const LLUUID& mesh_id); @@ -356,6 +356,9 @@ public:  class LLMeshUploadThread : public LLThread   { +private: +	S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request. +  public:  	class DecompRequest : public LLPhysicsDecomp::Request  	{ @@ -385,9 +388,7 @@ public:  	LLMutex*					mMutex;  	LLCurlRequest* mCurlRequest; -	S32				mPendingConfirmations;  	S32				mPendingUploads; -	S32				mPendingCost;  	LLVector3		mOrigin;  	bool			mFinished;	  	bool			mUploadTextures; @@ -399,38 +400,21 @@ public:  	std::string		mWholeModelFeeCapability;  	std::string		mWholeModelUploadURL; -	std::queue<LLMeshUploadData> mUploadQ; -	std::queue<LLMeshUploadData> mConfirmedQ; -	std::queue<LLModelInstance> mInstanceQ; - -	std::queue<LLTextureUploadData> mTextureQ; -	std::queue<LLTextureUploadData> mConfirmedTextureQ; - -	std::map<LLViewerFetchedTexture*, LLTextureUploadData> mTextureMap; -  	LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures, -			bool upload_skin, bool upload_joints); +			bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true, +					   LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));  	~LLMeshUploadThread(); -	void uploadTexture(LLTextureUploadData& data); -	void doUploadTexture(LLTextureUploadData& data); -	void priceResult(LLTextureUploadData& data, const LLSD& content); -	void onTextureUploaded(LLTextureUploadData& data); - -	void uploadModel(LLMeshUploadData& data); -	void doUploadModel(LLMeshUploadData& data); -	void onModelUploaded(LLMeshUploadData& data); -	void createObjects(LLMeshUploadData& data); -	LLSD createObject(LLModelInstance& instance); -	void priceResult(LLMeshUploadData& data, const LLSD& content); -  	bool finished() { return mFinished; }  	virtual void run();  	void preStart();  	void discard() ;  	BOOL isDiscarded(); +	void generateHulls(); +  	void doWholeModelUpload(); +	void requestWholeModelFee();  	void wholeModelToLLSD(LLSD& dest, bool include_textures); @@ -438,6 +422,15 @@ public:  							 LLVector3& result_pos,  							 LLQuaternion& result_rot,  							 LLVector3& result_scale); + +	void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; } +	void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; } + +private: +	LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle; +	LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle; + +	bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded  };  class LLMeshRepository @@ -471,8 +464,6 @@ public:  	S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);  	static S32 getActualMeshLOD(LLSD& header, S32 lod); -	U32 calcResourceCost(LLSD& header); -	U32 getResourceCost(const LLUUID& mesh_params);  	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);  	LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);  	void fetchPhysicsShape(const LLUUID& mesh_id); @@ -488,7 +479,8 @@ public:  	LLSD& getMeshHeader(const LLUUID& mesh_id);  	void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, -			bool upload_skin, bool upload_joints); +			bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true, +					 LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));  	S32 getMeshSize(const LLUUID& mesh_id, S32 lod); diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp index 8e8fc9dd25..09e799e4f7 100644 --- a/indra/newview/llsceneview.cpp +++ b/indra/newview/llsceneview.cpp @@ -83,6 +83,9 @@ void LLSceneView::draw()  	S32 total_visible_triangles[] = {0, 0};  	S32 total_triangles[] = {0, 0}; +	S32 total_visible_bytes[] = {0, 0}; +	S32 total_bytes[] = {0, 0}; +  	//streaming cost  	std::vector<F32> streaming_cost[2];  	F32 total_streaming[] = { 0.f, 0.f }; @@ -122,13 +125,19 @@ void LLSceneView::draw()  				visible_triangles[idx].push_back(visible);  				triangles[idx].push_back(high_triangles); -				F32 streaming = object->getStreamingCost(); +				S32 bytes = 0; +				S32 visible_bytes = 0; + +				F32 streaming = object->getStreamingCost(&bytes, &visible_bytes);  				total_streaming[idx] += streaming;  				streaming_cost[idx].push_back(streaming);  				F32 physics = object->getPhysicsCost();  				total_physics[idx] += physics;  				physics_cost[idx].push_back(physics); + +				total_bytes[idx] += bytes; +				total_visible_bytes[idx] += visible_bytes;  			}  		}  	} @@ -279,8 +288,8 @@ void LLSceneView::draw()  				total_visible += tri_count;	  			} -			std::string label = llformat("%s Object Triangle Counts (Ktris) -- [%.2f, %.2f] Mean: %.2f  Median: %.2f  Visible: %.2f/%.2f", -											category[idx], tri_domain[0]/1024.f, tri_domain[1]/1024.f, (total/count)/1024.f, triangles[idx][count/2]/1024.f, total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f); +			std::string label = llformat("%s Object Triangle Counts (Ktris) -- Visible: %.2f/%.2f (%.2f KB Visible)", +				category[idx], total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f, total_visible_bytes[idx]/1024.f);  			LLFontGL::getFontMonospace()->renderUTF8(label,  											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4dfcb85295..46ff3d808a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1242,6 +1242,25 @@ bool idle_startup()  	//---------------------------------------------------------------------  	if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())  	{ +		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); +		if (regionp->capabilitiesReceived()) +		{ +			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); +		} +		else +		{ +			U32 num_retries = regionp->getNumSeedCapRetries(); +			if (num_retries > 0) +			{ +				LLStringUtil::format_map_t args; +				args["[NUMBER]"] = llformat("%d", num_retries + 1); +				set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD); +			} +			else +			{ +				set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD); +			} +		}  		return FALSE;  	} diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index bccabe21a8..66df7dae3e 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -334,6 +334,17 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global)  	}  } +void LLSurface::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ) +{ +	S32 i; +	for (i = 0; i < 8; i++) +	{ +		if ( mNeighbors[i] != NULL ) +		{ +			uniqueRegions.push_back( mNeighbors[i]->getRegion() ); +		} +	}	 +}  void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)  { diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index 673ee83fe3..a4ef4fe2de 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -140,6 +140,9 @@ public:  	friend class LLSurfacePatch;  	friend std::ostream& operator<<(std::ostream &s, const LLSurface &S); +	 +	void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ); +	  public:  	// Number of grid points on one side of a region, including +1 buffer for  	// north and east edge. diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp new file mode 100644 index 0000000000..5a6a17fbca --- /dev/null +++ b/indra/newview/lluploadfloaterobservers.cpp @@ -0,0 +1,56 @@ +/** + * @file lluploadfloaterobservers.cpp + * @brief LLUploadModelPremissionsResponder definition + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lluploadfloaterobservers.h" + +LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer) +:mObserverHandle(observer) +{ +} + +void LLUploadModelPremissionsResponder::error(U32 status, const std::string& reason) +{ +	llwarns << "LLUploadModelPremissionsResponder::error("<< status << ": " << reason << ")" << llendl; + +	LLUploadPermissionsObserver* observer = mObserverHandle.get(); + +	if (observer) +	{ +		observer->setPermissonsErrorStatus(status, reason); +	} +} + +void LLUploadModelPremissionsResponder::result(const LLSD& content) +{ +	LLUploadPermissionsObserver* observer = mObserverHandle.get(); + +	if (observer) +	{ +		observer->onPermissionsReceived(content); +	} +} diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h new file mode 100644 index 0000000000..79aad282d7 --- /dev/null +++ b/indra/newview/lluploadfloaterobservers.h @@ -0,0 +1,97 @@ +/** + * @file lluploadfloaterobservers.h + * @brief LLUploadModelPremissionsResponder declaration + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLUPLOADFLOATEROBSERVERS_H +#define LL_LLUPLOADFLOATEROBSERVERS_H + +#include "llfloater.h" +#include "llhttpclient.h" +#include "llhandle.h" + +class LLUploadPermissionsObserver +{ +public: + +	LLUploadPermissionsObserver(){mUploadPermObserverHandle.bind(this);} +	virtual ~LLUploadPermissionsObserver() {} + +	virtual void onPermissionsReceived(const LLSD& result) = 0; +	virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0; + +	LLHandle<LLUploadPermissionsObserver> getPermObserverHandle() const {return mUploadPermObserverHandle;} + +protected: +	LLRootHandle<LLUploadPermissionsObserver> mUploadPermObserverHandle; +}; + +class LLWholeModelFeeObserver +{ +public: +	LLWholeModelFeeObserver() { mWholeModelFeeObserverHandle.bind(this); } +	virtual ~LLWholeModelFeeObserver() {} + +	virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0; +	virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0; + +	LLHandle<LLWholeModelFeeObserver> getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; } + +protected: +	LLRootHandle<LLWholeModelFeeObserver> mWholeModelFeeObserverHandle; +}; + + +class LLWholeModelUploadObserver +{ +public: +	LLWholeModelUploadObserver() { mWholeModelUploadObserverHandle.bind(this); } +	virtual ~LLWholeModelUploadObserver() {} + +	virtual void onModelUploadSuccess() = 0; + +	virtual void onModelUploadFailure() = 0; + +	LLHandle<LLWholeModelUploadObserver> getWholeModelUploadObserverHandle() const { return mWholeModelUploadObserverHandle; } + +protected: +	LLRootHandle<LLWholeModelUploadObserver> mWholeModelUploadObserverHandle; +}; + + +class LLUploadModelPremissionsResponder : public LLHTTPClient::Responder +{ +public: + +	LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer); + +	void error(U32 status, const std::string& reason); + +	void result(const LLSD& content); + +private: +	LLHandle<LLUploadPermissionsObserver> mObserverHandle; +}; + +#endif /* LL_LLUPLOADFLOATEROBSERVERS_H */ diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 6ae8e79be4..26f05337a4 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -130,12 +130,12 @@  // *NOTE: Please add files in alphabetical order to keep merges easy. -// handle secondlife:///app/floater/{NAME} URLs +// handle secondlife:///app/openfloater/{NAME} URLs  class LLFloaterOpenHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLFloaterOpenHandler() : LLCommandHandler("floater", UNTRUSTED_THROTTLE) { } +	LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }  	bool handle(const LLSD& params, const LLSD& query_map,  				LLMediaCtrl* web) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f74bcafc5c..f6499e12de 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -62,6 +62,7 @@  #include "llfloatersnapshot.h"  #include "llfloatertools.h"  #include "llfloaterworldmap.h" +#include "llfloaterbuildoptions.h"  #include "llavataractions.h"  #include "lllandmarkactions.h"  #include "llgroupmgr.h" @@ -7163,9 +7164,11 @@ class LLToolsUseSelectionForGrid : public view_listener_t  		} func;  		LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);  		LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); -		if (gFloaterTools) + +		LLFloaterBuildOptions* build_options_floater = LLFloaterReg::getTypedInstance<LLFloaterBuildOptions>("build_options"); +		if (build_options_floater && build_options_floater->getVisible())  		{ -			gFloaterTools->mComboGridMode->setCurrentByIndex((S32)GRID_MODE_REF_OBJECT); +			build_options_floater->setGridMode(GRID_MODE_REF_OBJECT);  		}  		return true;  	} diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 972993202a..b5fdca632b 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -516,7 +516,6 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)  	}  } -  // This method returns true if the object is over land owned by the  // agent.  bool LLViewerObject::isReturnable() @@ -525,17 +524,108 @@ bool LLViewerObject::isReturnable()  	{  		return false;  	} +		  	std::vector<LLBBox> boxes;  	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());  	for (child_list_t::iterator iter = mChildList.begin();  		 iter != mChildList.end(); iter++)  	{  		LLViewerObject* child = *iter; -		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); +		boxes.push_back( LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); +	} + +	bool result = (mRegionp && mRegionp->objectIsReturnable(getPositionRegion(), boxes)) ? 1 : 0; +	 +	if ( !result ) +	{		 +		//Get list of neighboring regions relative to this vo's region +		std::vector<LLViewerRegion*> uniqueRegions; +		mRegionp->getNeighboringRegions( uniqueRegions ); +	 +		//Build aabb's - for root and all children +		std::vector<PotentialReturnableObject> returnables; +		typedef std::vector<LLViewerRegion*>::iterator RegionIt; +		RegionIt regionStart = uniqueRegions.begin(); +		RegionIt regionEnd   = uniqueRegions.end(); +		 +		for (; regionStart != regionEnd; ++regionStart ) +		{ +			LLViewerRegion* pTargetRegion = *regionStart; +			//Add the root vo as there may be no children and we still want +			//to test for any edge overlap +			buildReturnablesForChildrenVO( returnables, this, pTargetRegion ); +			//Add it's children +			for (child_list_t::iterator iter = mChildList.begin();  iter != mChildList.end(); iter++) +			{ +				LLViewerObject* pChild = *iter;		 +				buildReturnablesForChildrenVO( returnables, pChild, pTargetRegion ); +			} +		}	 +	 +		//TBD#Eventually create a region -> box list map  +		typedef std::vector<PotentialReturnableObject>::iterator ReturnablesIt; +		ReturnablesIt retCurrentIt = returnables.begin(); +		ReturnablesIt retEndIt = returnables.end(); +	 +		for ( ; retCurrentIt !=retEndIt; ++retCurrentIt ) +		{ +			boxes.clear(); +			LLViewerRegion* pRegion = (*retCurrentIt).pRegion; +			boxes.push_back( (*retCurrentIt).box );	 +			bool retResult = 	pRegion +							 && pRegion->childrenObjectReturnable( boxes ) +							 && pRegion->canManageEstate(); +			if ( retResult ) +			{  +				result = true; +				break; +			} +		} +	} +	return result; +} + +void LLViewerObject::buildReturnablesForChildrenVO( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ) +{ +	if ( !pChild ) +	{ +		llerrs<<"child viewerobject is NULL "<<llendl;  	} +	 +	constructAndAddReturnable( returnables, pChild, pTargetRegion ); +	 +	//We want to handle any children VO's as well +	for (child_list_t::iterator iter = pChild->mChildList.begin();  iter != pChild->mChildList.end(); iter++) +	{ +		LLViewerObject* pChildofChild = *iter; +		buildReturnablesForChildrenVO( returnables, pChildofChild, pTargetRegion ); +	} +} -	return mRegionp -		&& mRegionp->objectIsReturnable(getPositionRegion(), boxes); +void LLViewerObject::constructAndAddReturnable( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ) +{ +	 +	LLVector3 targetRegionPos; +	targetRegionPos.setVec( pChild->getPositionGlobal() );	 +	 +	LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f,  +							    pChild->getScale() * 0.5f).getAxisAligned(); +	 +	LLVector3 edgeA = targetRegionPos + childBBox.getMinLocal(); +	LLVector3 edgeB = targetRegionPos + childBBox.getMaxLocal(); +	 +	LLVector3d edgeAd, edgeBd; +	edgeAd.setVec(edgeA); +	edgeBd.setVec(edgeB); +	 +	//Only add the box when either of the extents are in a neighboring region +	if ( pTargetRegion->pointInRegionGlobal( edgeAd ) || pTargetRegion->pointInRegionGlobal( edgeBd ) ) +	{ +		PotentialReturnableObject returnableObj; +		returnableObj.box		= childBBox; +		returnableObj.pRegion	= pTargetRegion; +		returnables.push_back( returnableObj ); +	}  }  BOOL LLViewerObject::setParent(LLViewerObject* parent) @@ -4787,6 +4877,10 @@ void LLViewerObject::adjustAudioGain(const F32 gain)  bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)  { +	if (LLNetworkData::PARAMS_MESH == param_type) +	{ +		param_type = LLNetworkData::PARAMS_SCULPT; +	}  	ExtraParameter* param = getExtraParameterEntryCreate(param_type);  	if (param)  	{ diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 7ebcee7b74..1828a64917 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -44,11 +44,11 @@  #include "v3math.h"  #include "llvertexbuffer.h"  #include "llaccountingquota.h" +#include "llbbox.h"  class LLAgent;			// TODO: Get rid of this.  class LLAudioSource;  class LLAudioSourceVO; -class LLBBox;  class LLDataPacker;  class LLColor4;  class LLFrameTimer; @@ -112,6 +112,12 @@ public:  	LLColor4	mColor;  }; +struct PotentialReturnableObject +{ +	LLBBox			box; +	LLViewerRegion* pRegion; +}; +  //============================================================================  class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate @@ -234,6 +240,9 @@ public:  	// anti-encroachment is enabled  	bool isReturnable(); +	void buildReturnablesForChildrenVO( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); +	void constructAndAddReturnable( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); +  	/*  	// This method will scan through this object, and then query the  	// selection manager to see if the local agent probably has the diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 48ccc7d035..db5684665b 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1071,10 +1071,12 @@ void LLViewerObjectList::fetchObjectCosts()  				LLSD id_list;  				U32 object_index = 0; +				U32 count = 0; +  				for (  					std::set<LLUUID>::iterator iter = mStaleObjectCost.begin();  					iter != mStaleObjectCost.end(); -					++iter) +					)  				{  					// Check to see if a request for this object  					// has already been made. @@ -1084,13 +1086,15 @@ void LLViewerObjectList::fetchObjectCosts()  						mPendingObjectCost.insert(*iter);  						id_list[object_index++] = *iter;  					} -				} -				// id_list should now contain all -				// requests in mStaleObjectCost before, so clear -				// it now -				mStaleObjectCost.clear(); +					mStaleObjectCost.erase(iter++); +					if (count++ >= 450) +					{ +						break; +					} +				} +									  				if ( id_list.size() > 0 )  				{  					LLSD post_data = LLSD::emptyMap(); @@ -1410,6 +1414,10 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp)  void LLViewerObjectList::updateObjectCost(LLViewerObject* object)  { +	if (!object->isRoot()) +	{ //always fetch cost for the parent when fetching cost for children +		mStaleObjectCost.insert(((LLViewerObject*)object->getParent())->getID()); +	}  	mStaleObjectCost.insert(object->getID());  } diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 26765bdd01..eff16b6a6e 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -173,6 +173,33 @@ bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) co  	}  	return false;  } +bool LLViewerParcelOverlay::encroachesOnUnowned(const std::vector<LLBBox>& boxes) const +{ +	// boxes are expected to already be axis aligned +	for (U32 i = 0; i < boxes.size(); ++i) +	{ +		LLVector3 min = boxes[i].getMinAgent(); +		LLVector3 max = boxes[i].getMaxAgent(); +		 +		S32 left   = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 right  = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 top    = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		 +		for (S32 row = top; row <= bottom; row++) +		{ +			for (S32 column = left; column <= right; column++) +			{ +				U8 type = ownership(row, column); +				if ((PARCEL_SELF != type)) +				{ +					return true; +				} +			} +		} +	} +	return false; +}  BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const  { diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index c80baedda6..3c6794e7d0 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -60,6 +60,7 @@ public:  	// might be in another parcel. for now, we simply test axis aligned   	// bounding boxes which isn't perfect, but is close  	bool encroachesOwned(const std::vector<LLBBox>& boxes) const; +	bool encroachesOnUnowned(const std::vector<LLBBox>& boxes) const;  	BOOL			isSoundLocal(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index d4e0831c33..db2dc531db 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -77,6 +77,13 @@  const F32 WATER_TEXTURE_SCALE = 8.f;			//  Number of times to repeat the water texture across a region  const S16 MAX_MAP_DIST = 10; +// The server only keeps our pending agent info for 60 seconds. +// We want to allow for seed cap retry, but its not useful after that 60 seconds. +// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. +const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; +const F32 CAP_REQUEST_TIMEOUT = 18; +// Even though we gave up on login, keep trying for caps after we are logged in: +const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;  typedef std::map<std::string, std::string> CapabilityMap; @@ -86,6 +93,10 @@ public:  		:	mHost(host),  			mCompositionp(NULL),  			mEventPoll(NULL), +			mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), +			mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), +			mSeedCapAttempts(0), +			mHttpResponderID(0),  		    // I'd prefer to set the LLCapabilityListener name to match the region  		    // name -- it's disappointing that's not available at construction time.  		    // We could instead store an LLCapabilityListener*, making @@ -100,6 +111,8 @@ public:  	{  	} +	void buildCapabilityNames(LLSD& capabilityNames); +  	// The surfaces and other layers  	LLSurface*	mLandp; @@ -132,6 +145,12 @@ public:  	LLEventPoll* mEventPoll; +	S32 mSeedCapMaxAttempts; +	S32 mSeedCapMaxAttemptsBeforeLogin; +	S32 mSeedCapAttempts; + +	S32 mHttpResponderID; +  	/// Post an event to this LLCapabilityListener to invoke a capability message on  	/// this LLViewerRegion's server  	/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) @@ -139,8 +158,6 @@ public:  	//spatial partitions for objects in this region  	std::vector<LLSpatialPartition*> mObjectPartition; - -	LLHTTPClient::ResponderPtr  mHttpResponderPtr ;  };  // support for secondlife:///app/region/{REGION} SLapps @@ -186,54 +203,51 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder  {  	LOG_CLASS(BaseCapabilitiesComplete);  public: -    BaseCapabilitiesComplete(LLViewerRegion* region) -		: mRegion(region) +    BaseCapabilitiesComplete(U64 region_handle, S32 id) +		: mRegionHandle(region_handle), mID(id)      { }  	virtual ~BaseCapabilitiesComplete() -	{ -		if(mRegion) -		{ -			mRegion->setHttpResponderPtrNULL() ; -		} -	} - -	void setRegion(LLViewerRegion* region) -	{ -		mRegion = region ; -	} +	{ }      void error(U32 statusNum, const std::string& reason)      {  		LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; -		 -		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) +		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp)  		{ -			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); +			regionp->failedSeedCapability();  		}      }      void result(const LLSD& content)      { -		if(!mRegion || LLHTTPClient::ResponderPtr(this) != mRegion->getHttpResponderPtr()) //region is removed or responder is not created. +		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if(!regionp) //region was removed +		{ +			LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; +			return ; +		} +		if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder  		{ +			LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL;  			return ;  		}  		LLSD::map_const_iterator iter;  		for(iter = content.beginMap(); iter != content.endMap(); ++iter)  		{ -			mRegion->setCapability(iter->first, iter->second); +			regionp->setCapability(iter->first, iter->second);  			LL_DEBUGS2("AppInit", "Capabilities") << "got capability for "   				<< iter->first << LL_ENDL;  			/* HACK we're waiting for the ServerReleaseNotes */ -			if (iter->first == "ServerReleaseNotes" && mRegion->getReleaseNotesRequested()) +			if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())  			{ -				mRegion->showReleaseNotes(); +				regionp->showReleaseNotes();  			}  		} -		mRegion->setCapabilitiesReceived(true); +		regionp->setCapabilitiesReceived(true);  		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())  		{ @@ -241,15 +255,15 @@ public:  		}  	} -    static boost::intrusive_ptr<BaseCapabilitiesComplete> build( -								LLViewerRegion* region) +    static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )      { -		return boost::intrusive_ptr<BaseCapabilitiesComplete>( -							 new BaseCapabilitiesComplete(region)); +		return boost::intrusive_ptr<BaseCapabilitiesComplete>(  +				new BaseCapabilitiesComplete(region_handle, id) );      }  private: -	LLViewerRegion* mRegion; +	U64 mRegionHandle; +	S32 mID;  }; @@ -340,11 +354,6 @@ void LLViewerRegion::initStats()  LLViewerRegion::~LLViewerRegion()   { -	if(mImpl->mHttpResponderPtr) -	{ -		(static_cast<BaseCapabilitiesComplete*>(mImpl->mHttpResponderPtr.get()))->setRegion(NULL) ; -	} -  	gVLManager.cleanupData(this);  	// Can't do this on destruction, because the neighbor pointers might be invalid.  	// This should be reference counted... @@ -896,14 +905,9 @@ U32 LLViewerRegion::getPacketsLost() const  	}  } -void LLViewerRegion::setHttpResponderPtrNULL() -{ -	mImpl->mHttpResponderPtr = NULL; -} - -const LLHTTPClient::ResponderPtr LLViewerRegion::getHttpResponderPtr() const +S32 LLViewerRegion::getHttpResponderID() const  { -	return mImpl->mHttpResponderPtr; +	return mImpl->mHttpResponderID;  }  BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const @@ -1482,22 +1486,9 @@ void LLViewerRegion::unpackRegionHandshake()  	msg->sendReliable(host);  } -void LLViewerRegion::setSeedCapability(const std::string& url) -{ -	if (getCapability("Seed") == url) -    { -		// llwarns << "Ignoring duplicate seed capability" << llendl; -		return; -    } -	 -	delete mImpl->mEventPoll; -	mImpl->mEventPoll = NULL; -	 -	mImpl->mCapabilities.clear(); -	setCapability("Seed", url); - -	LLSD capabilityNames = LLSD::emptyArray(); +void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) +{  	capabilityNames.append("AccountingParcel");  	capabilityNames.append("AccountingSelection");  	capabilityNames.append("AttachmentResources"); @@ -1529,6 +1520,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("LandResources");  	capabilityNames.append("MapLayer");  	capabilityNames.append("MapLayerGod"); +	capabilityNames.append("MeshUploadFlag");  	capabilityNames.append("NewFileAgentInventory");  	capabilityNames.append("ParcelPropertiesUpdate");  	capabilityNames.append("ParcelMediaURLFilterList"); @@ -1570,46 +1562,118 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	// Please add new capabilities alphabetically to reduce  	// merge conflicts. +} + +void LLViewerRegion::setSeedCapability(const std::string& url) +{ +	if (getCapability("Seed") == url) +    { +		// llwarns << "Ignoring duplicate seed capability" << llendl; +		return; +    } +	 +	delete mImpl->mEventPoll; +	mImpl->mEventPoll = NULL; +	 +	mImpl->mCapabilities.clear(); +	setCapability("Seed", url); + +	LLSD capabilityNames = LLSD::emptyArray(); +	mImpl->buildCapabilityNames(capabilityNames);  	llinfos << "posting to seed " << url << llendl; -	mImpl->mHttpResponderPtr = BaseCapabilitiesComplete::build(this) ; -	LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr); +	S32 id = ++mImpl->mHttpResponderID; +	LLHTTPClient::post(url, capabilityNames,  +						BaseCapabilitiesComplete::build(getHandle(), id), +						LLSD(), CAP_REQUEST_TIMEOUT); +} + +S32 LLViewerRegion::getNumSeedCapRetries() +{ +	return mImpl->mSeedCapAttempts; +} + +void LLViewerRegion::failedSeedCapability() +{ +	// Should we retry asking for caps? +	mImpl->mSeedCapAttempts++; +	std::string url = getCapability("Seed"); +	if ( url.empty() ) +	{ +		LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; +		return; +	} +	// After a few attempts, continue login.  We will keep trying once in-world: +	if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && +		 STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) +	{ +		LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); +	} + +	if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) +	{ +		LLSD capabilityNames = LLSD::emptyArray(); +		mImpl->buildCapabilityNames(capabilityNames); + +		llinfos << "posting to seed " << url << " (retry "  +				<< mImpl->mSeedCapAttempts << ")" << llendl; + +		S32 id = ++mImpl->mHttpResponderID; +		LLHTTPClient::post(url, capabilityNames,  +						BaseCapabilitiesComplete::build(getHandle(), id), +						LLSD(), CAP_REQUEST_TIMEOUT); +	} +	else +	{ +		// *TODO: Give a user pop-up about this error? +		LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL; +	}  }  class SimulatorFeaturesReceived : public LLHTTPClient::Responder  {  	LOG_CLASS(SimulatorFeaturesReceived);  public: -    SimulatorFeaturesReceived(LLViewerRegion* region) -	: mRegion(region) +    SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle,  +			S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) +	: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)      { }      void error(U32 statusNum, const std::string& reason)      {  		LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; +		retry();      } -	 +      void result(const LLSD& content)      { -		if(!mRegion) //region is removed or responder is not created. +		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if(!regionp) //region is removed or responder is not created.  		{ +			LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;  			return ;  		} -		mRegion->setSimulatorFeatures(content); +		regionp->setSimulatorFeatures(content);  	} -	 -    static boost::intrusive_ptr<SimulatorFeaturesReceived> build( -																 LLViewerRegion* region) -    { -		return boost::intrusive_ptr<SimulatorFeaturesReceived>( -															   new SimulatorFeaturesReceived(region)); -    } -	 +  private: -	LLViewerRegion* mRegion; +	void retry() +	{ +		if (mAttempt < mMaxAttempts) +		{ +			mAttempt++; +			LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'.  Retry #" << mAttempt << LL_ENDL; +			LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); +		} +	} +	 +	std::string mRetryURL; +	U64 mRegionHandle; +	S32 mAttempt; +	S32 mMaxAttempts;  }; @@ -1628,7 +1692,7 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u  	else if (name == "SimulatorFeatures")  	{  		// kick off a request for simulator features -		LLHTTPClient::get(url, new SimulatorFeaturesReceived(this)); +		LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT);  	}  	else  	{ @@ -1718,6 +1782,18 @@ bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<  				&& mParcelOverlay->encroachesOwned(boxes)) );  } +bool LLViewerRegion::childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const +{ +	bool result = false; +	result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; +	return result; +} + +void LLViewerRegion::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ) +{ +	mImpl->mLandp->getNeighboringRegions( uniqueRegions ); +} +  void LLViewerRegion::showReleaseNotes()  {  	std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index a105ff625d..ef1a6d285c 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -226,11 +226,12 @@ public:  	U32	getPacketsLost() const; -	void setHttpResponderPtrNULL(); -	const LLHTTPClient::ResponderPtr getHttpResponderPtr() const; +	S32 getHttpResponderID() const;  	// Get/set named capability URLs for this region.  	void setSeedCapability(const std::string& url); +	void failedSeedCapability(); +	S32 getNumSeedCapRetries();  	void setCapability(const std::string& name, const std::string& url);  	// implements LLCapabilityProvider      virtual std::string getCapability(const std::string& name) const; @@ -320,6 +321,10 @@ public:  	LLSpatialPartition* getSpatialPartition(U32 type);  	bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const; +	bool childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const; + +	void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ); +	  public:  	struct CompareDistance  	{ diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 988c4ed1a2..d7509b4e41 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -528,8 +528,8 @@ public:  				addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost));  				ypos += y_inc; -				addText(xpos, ypos, llformat("    %.1f KTris, %.1f/%.1f KB, %d objects", -										count/1024.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); +				addText(xpos, ypos, llformat("    %.3f KTris, %.1f/%.1f KB, %d objects", +										count/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count));  				ypos += y_inc;  			} @@ -726,19 +726,6 @@ public:  			}  		}				 -		if (gSavedSettings.getBOOL("DebugShowUploadCost")) -		{ -			addText(xpos, ypos, llformat("       Meshes: L$%d", gPipeline.mDebugMeshUploadCost)); -			ypos += y_inc/2; -			addText(xpos, ypos, llformat("    Sculpties: L$%d", gPipeline.mDebugSculptUploadCost)); -			ypos += y_inc/2; -			addText(xpos, ypos, llformat("     Textures: L$%d", gPipeline.mDebugTextureUploadCost)); -			ypos += y_inc/2; -			addText(xpos, ypos, "Upload Cost: "); -						 -			ypos += y_inc; -		} -  		//temporary hack to give feedback on mesh upload progress  		if (!gMeshRepo.mUploads.empty())  		{ @@ -747,10 +734,8 @@ public:  			{  				LLMeshUploadThread* thread = *iter; -				addText(xpos, ypos, llformat("Mesh Upload -- price quote: %d:%d | upload: %d:%d | create: %d",  -								thread->mPendingConfirmations, thread->mUploadQ.size()+thread->mTextureQ.size(), -								thread->mPendingUploads, thread->mConfirmedQ.size()+thread->mConfirmedTextureQ.size(), -								thread->mInstanceQ.size())); +				addText(xpos, ypos, llformat("Mesh Uploads: %d",  +								thread->mPendingUploads));  				ypos += y_inc;  			}  		} @@ -3161,6 +3146,12 @@ void LLViewerWindow::updateLayout()  		//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());  	} +	LLFloaterBuildOptions* build_options_floater = LLFloaterReg::getTypedInstance<LLFloaterBuildOptions>("build_options"); +	if (build_options_floater && build_options_floater->getVisible()) +	{ +		build_options_floater->updateGridMode(); +	} +  	// Always update console  	if(gConsole)  	{ diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3f98df9eb9..b5be3cd552 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1123,14 +1123,20 @@ void LLVOAvatar::initClass()  	// Process XML data  	// avatar_skeleton.xml -	llassert(!sAvatarSkeletonInfo); +	if (sAvatarSkeletonInfo) +	{ //this can happen if a login attempt failed +		delete sAvatarSkeletonInfo; +	}  	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo;  	if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))  	{  		llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;  	}  	// parse avatar_lad.xml -	llassert(!sAvatarXmlInfo); +	if (sAvatarXmlInfo) +	{ //this can happen if a login attempt failed +		deleteAndClear(sAvatarXmlInfo); +	}  	sAvatarXmlInfo = new LLVOAvatarXmlInfo;  	if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))  	{ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4c137d3394..30216f02db 100644..100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1017,6 +1017,9 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  	if (is404)  	{  		setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); +		//render prim proxy when mesh loading attempts give up +		volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); +  	}  	if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) @@ -3096,7 +3099,7 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const  F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)  { -	F32 radius = getScale().length(); +	F32 radius = getScale().length()*0.5f;  	if (isMesh())  	{	 diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0abeed988c..4899df13e5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4223,63 +4223,6 @@ void LLPipeline::renderDebug()  		}  	} -	if (gSavedSettings.getBOOL("DebugShowUploadCost")) -	{ -		std::set<LLUUID> textures; -		std::set<LLUUID> sculpts; -		std::set<LLUUID> meshes; -		 -		BOOL selected = TRUE; -		if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) -		{ -			selected = FALSE; -		} -			 -		for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) -		{ -			LLSpatialGroup* group = *iter; -			LLSpatialGroup::OctreeNode* node = group->mOctreeNode; -			for (LLSpatialGroup::OctreeNode::element_iter elem = node->getData().begin(); elem != node->getData().end(); ++elem) -			{ -				LLDrawable* drawable = *elem; -				LLVOVolume* volume = drawable->getVOVolume(); -				if (volume && volume->isSelected() == selected) -				{ -					for (U32 i = 0; i < volume->getNumTEs(); ++i) -					{ -						LLTextureEntry* te = volume->getTE(i); -						textures.insert(te->getID()); -					} - -					if (volume->isSculpted()) -					{ -						LLUUID sculpt_id = volume->getVolume()->getParams().getSculptID(); -						if (volume->isMesh()) -						{ -							meshes.insert(sculpt_id); -						} -						else -						{ -							sculpts.insert(sculpt_id); -						} -					} -				} -			} -		} - -		gPipeline.mDebugTextureUploadCost = textures.size() * 10; -		gPipeline.mDebugSculptUploadCost = sculpts.size()*10; -		 -		U32 mesh_cost = 0; - -		for (std::set<LLUUID>::iterator iter = meshes.begin(); iter != meshes.end(); ++iter) -		{ -			mesh_cost += gMeshRepo.getResourceCost(*iter)*10; -		} - -		gPipeline.mDebugMeshUploadCost = mesh_cost; -	} -  	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))  	{  		LLVertexBuffer::unbind(); diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml index 56230e912c..c247a12e7a 100644 --- a/indra/newview/skins/default/xui/en/floater_build_options.xml +++ b/indra/newview/skins/default/xui/en/floater_build_options.xml @@ -2,27 +2,84 @@  <floater   legacy_header_height="18"   follows="right" - height="170" + height="198"   layout="topleft"   name="build options floater"   help_topic="build_options_floater"   save_rect="true"   title="GRID OPTIONS"   width="264"> + 	<floater.string +     name="grid_screen_text"> +        Screen +    </floater.string> +    <floater.string +     name="grid_local_text"> +        Local +    </floater.string> +    <floater.string +     name="grid_world_text"> +        World +    </floater.string> +    <floater.string +     name="grid_reference_text"> +        Reference +    </floater.string> +    <floater.string +     name="grid_attachment_text"> +        Attachment +    </floater.string> +    <text +     type="string" +     length="1" +     follows="left|top" +     height="16" +     layout="topleft" +     left="10" +     tool_tip="Grid opacity" +     name="grid_opacity_label" +     top_pad="30" +     width="123"> +        Mode +    </text> +    <combo_box +     height="23" +     layout="topleft" +     left_pad="9" +     follows="left|top" +     name="combobox grid mode" +     tool_tip="Choose the type of grid ruler for positioning the object" +     top_delta="-3" +     width="108"> +      <combo_box.item +       label="World grid" +       name="World" +       value="World" /> +      <combo_box.item +       label="Local grid" +       name="Local" +       value="Local" /> +      <combo_box.item +       label="Reference grid" +       name="Reference" +       value="Reference" /> +       <combo_box.commit_callback +      function="GridOptions.gridMode"/> +    </combo_box>      <spinner       control_name="GridResolution"       follows="left|top"       height="23"       initial_value="1" -     label="Grid Units (meters)" -     label_width="160" +     label="Units (meters)" +     label_width="130"       layout="topleft"       left="10"       max_val="5"       min_val="0.01"       name="GridResolution" -     top="25" -     width="230" /> +     top_pad="4" +     width="200" />      <spinner       control_name="GridDrawSize"       decimal_digits="1" @@ -30,15 +87,15 @@       height="23"       increment="0.5"       initial_value="5" -     label="Grid Extents (meters)" -     label_width="160" +     label="Extents (meters)" +     label_width="130"       layout="topleft"       left_delta="0"       max_val="50"       min_val="1"       name="GridDrawSize"       top_pad="0" -     width="230" /> +     width="200" />      <check_box       control_name="GridSubUnit"       height="16" 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 f58595b3c5..1d4a1d4827 100644..100755 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,7 +1,8 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater can_close="true" can_drag_on_left="false" can_minimize="false"       can_resize="true" height="550" min_height="550" min_width="620" -     name="Model Preview" title="Upload Model" width="620"> +     name="Model Preview" title="Upload Model" width="620" +      help_topic="upload_model" >    <string name="status_idle">Idle</string>    <string name="status_parse_error">Dae parsing issue - see log for details.</string> @@ -23,6 +24,7 @@    <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->    <string name="decomposing">Analyzing...</string>    <string name="simplifying">Simplifying...</string> +  <string name="tbd">TBD</string>    <text left="15" bottom="25" follows="top|left" height="15" name="name_label"> @@ -70,43 +72,89 @@      width="290"      height="290"      follows="all"/> - -  <text bottom_delta="25" left="25" width="100" follows="bottom|left">Upload Details</text> -  <panel top_pad="5" border="true" left="15" width="290" height="70" follows="bottom|left" -          bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> -    <text left="25" follows="bottom|left" width="140" height="15" name="streaming cost"> -      Resource Cost: [COST] -    </text> -    <text left="25" top_pad="5" width="140" follows="bottom|left" height="15" name="physics cost"> -      Physics Cost: [COST] +     +    <text +     font="SansSerif" +	 bottom_delta="15" +     left_delta="0" +     name="warning_title" +     text_color="Yellow" +     visible="false"> +     WARNING:      </text> -    <text left="25" top_pad="5" follows="bottom|left" height="15" name="upload fee"> -      Upload Fee: N/A -    </text> -  </panel> +    <text +     text_color="White" +     height="40" +	 width="290" +	 top_delta="15" +     left_delta="0" +     name="warning_message" +     parse_urls="true" +     wrap="true" +     visible="false"> +     You will not be able to complete the final upload of this model to the Second Life servers. [[VURL] Find out how] to get enabled for mesh model uploads.</text> -  <check_box -	height="16" +  <text +	height="65" +	top_delta="45"  	left_delta="0" -	name="confirm_checkbox" -	top_pad="15" -	follows="bottom|left" -	width="16" /> +	name="weights_text" +	width="80" +	word_wrap="true"  +	> +Download: +Physics: +Server: + +Prim equivs: +  </text>    <text -	height="30" -	width="570" +	height="65" +	top_delta="0" +	left_delta="80" +	name="weights" +	width="70"  	word_wrap="true"  -	left_delta="25" -	top_delta="0">I confirm that I have the appropriate rights to the material contained in this model. [secondlife:///app/floater/learn_more Learn more]</text> -  <text left="10" bottom="540" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text> +	> +[ST] +[PH] +[SIM] -   -  <button bottom="540" left="300"  follows="bottom|right" height="20" label="Defaults" -	     width="80" name="reset_btn" tool_tip="Reset to defaults"/> -  <button bottom="540" left="430"  follows="bottom|right" height="20" label="Upload" -	     width="80" name="ok_btn" tool_tip="Upload to simulator"/> -  <button left_pad="10" follows="right|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/> +[EQ] +  </text> + +<!-- +  <text +	height="65" +	top_delta="0" +	left_delta="70" +	name="price_breakdown_text" +	width="80" +	word_wrap="true"  +	> +Streaming: +Physics: +Instances: +Textures: +Model: +  </text> + +  <text +	height="65" +	top_delta="0" +	left_delta="80" +	name="price_breakdown" +	width="65" +	word_wrap="true"  +	> +L$ [STREAMING] +L$ [PHYSICS] +L$ [INSTANCES] +L$ [TEXTURES] +L$ [MODEL] +  </text> +    -->    <tab_container      follows="right|top|bottom" @@ -122,7 +170,8 @@      <panel        border="true"        label="Level of Detail" -      name="lod_panel"> +      name="lod_panel" +      help_topic="upload_model_lod">        <text left="10" width="240" bottom="20" height="15" follows="left|top" name="lod_table_header">          Select Level of Detail: @@ -245,7 +294,8 @@      <panel        border="true"        label="Physics" -      name="physics_panel"> +      name="physics_panel" +      help_topic="upload_model_physics">        <!-- PHYSICS GEOMETRY-->        <panel @@ -386,7 +436,9 @@      <panel        border="true"        label="Modifiers" -      name="modifiers_panel"> +      name="modifiers_panel" +      help_topic="upload_model_modifiers"> +        <text left="10" width="90" bottom="30" follows="top|left" height="15">          Scale:        </text> @@ -416,6 +468,26 @@      </panel>    </tab_container> + +  <text +	height="16" +	left_delta="5" +	bottom_delta="30" +	name="upload_fee" +	width="300" +	follows="bottom|right" +	word_wrap="true"  +	> +	    Upload fee: L$ [FEE] +  </text> +   +  <button bottom="540" left="10"  follows="bottom|left" height="20" label="Set to defaults" +	     width="100" name="reset_btn" tool_tip="Set to defaults"/> +  <button left="310"  follows="bottom|right" height="20" label="Calculate weights & fee" +	     width="150" name="calculate_btn" tool_tip="Calculate weights & fee" top_delta="0"/> +  <button bottom="540" left="310"  follows="bottom|right" height="20" label="Upload" +	     width="80" name="ok_btn" tool_tip="Upload to simulator" visible="false"/> +  <button right="-10" follows="right|bottom" height="20" width="80" label="Cancel" name="cancel_btn" top_delta="0"/>    <!--    <button bottom_delta="0" left="10" width="120" name="auto fill" label="Generate LOD" tool_tip="Automatically generate levels of detail"/> diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml index 8603682e3a..b5a5ff5342 100644 --- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml +++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml @@ -49,24 +49,6 @@  	 top="32"  	 left="210"  	 height="32" -	 name="physics2_btn" -	 label="3. Physics" -	 tab_stop="false" -	 enabled="false" -	 border="false" -	 image_unselected="BreadCrumbBtn_Middle_Off" -	 image_selected="BreadCrumbBtn_Middle_Press" -	 image_hover_unselected="BreadCrumbBtn_Middle_Over" -	 image_disabled="BreadCrumbBtn_Middle_Disabled" -	 image_disabled_selected="BreadCrumbBtn_Middle_Disabled" -	 width="110"> -		<button.commit_callback -		function="Wizard.Physics2"/> -	</button> -	<button -	 top="32" -	 left="210" -	 height="32"  	 name="physics_btn"  	 label="3. Physics"  	 tab_stop="false" @@ -140,41 +122,50 @@  			 height="10"  			 font="SansSerifBig"  			 layout="topleft"> -				Upload Model +				Choose model file  			</text>  		</panel> -		<text -		 top_pad="14" -		 width="460" -		 height="20" -		 name="description" -		 font="SansSerifSmall" -		 layout="topleft" -		 word_wrap="true" -		 left_delta="5"> -			This wizard will help you import mesh models to Second Life.  First specify a file containing the model you wish to import.  Second Life supports COLLADA (.dae) files. -		</text>  		<panel -		 top_delta="40" +		 top_pad="14"  		 left="15" -		 height="270" +		 height="310"  		 width="505"  		 name="content"  		 bg_opaque_color="DkGray2"  		 background_visible="true"  		 background_opaque="true"> +            <text +			 height="32" +			 left="10" +			 name="advanced_users_text" +			 text_color="White" +			 top="15" +			 width="320" +			 word_wrap="true"> +				Advanced users: If you are familiar with 3D content creation tools you may wish to use the Advanced Uploader. +			</text> +			<button +			 follows="left|top" +			 height="20" +			 label="Switch to Advanced" +			 layout="topleft" +			 left_delta="0" +			 name="switch_to_advanced" +			 top_pad="5" +			 width="130"> +			</button>  			<text  			 type="string"  			 length="1"  			 text_color="White"   			 follows="left|top" -			 top="10" +			 top_pad="30"  			 height="10"  			 layout="topleft" -			 left_delta="10" +			 left_delta="0"  			 name="Cache location" -			 width="300"> -				Filename: +			 width="320"> +				Choose model file to upload  			</text>  			<line_editor  			 border_style="line" @@ -187,7 +178,7 @@  			 max_length="4096"  			 name="lod_file"  			 top_pad="5" -			 width="220" /> +			 width="230" />  			<button  			 follows="left|top"  			 height="23" @@ -200,23 +191,27 @@  			 width="85">  			</button>  			<text -			 top_delta="-15" -			 width="200" -			 height="15" -			 font="SansSerifSmall" +			 type="string" +			 length="1" +			 text_color="White"  +			 follows="left|top" +			 top_pad="5" +			 height="10"  			 layout="topleft" -			 text_color="White" -			 left_pad="19"> -				Model Preview: +			 left="10" +			 name="Cache location" +			 width="320"> +				Second Life supports COLLADA (.dae) files  			</text>  			<!-- Placeholder panel for 3D preview render -->  			<panel -			 left_delta="0" -			 top_pad="0" -			 name="preview_panel" +			 top="30" +			 right="-10" +			 name="choose_file_preview_panel"  			 bevel_style="none"  			 highlight_light_color="0.09 0.09 0.09 1"  			 border="true" +			 border_style="line"  			 height="150"  			 follows="all"  			 width="150"> @@ -225,7 +220,7 @@  			 top_pad="10"  			 width="130"  			 height="14" -			 left="340" +			 left_delta="0"  			 text_color="White"  			 word_wrap="true">  				Dimensions (meters): @@ -238,15 +233,7 @@  			 text_color="White"  			 name="dimensions"  			 left_delta="0"> -				X:         Y:         Z:  -			</text> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_dividers" -			 left_delta="41"> -				 |               |    +				X         Y         Z   			</text>  			<text  			 top_delta="0" @@ -266,23 +253,26 @@  			 height="15"  			 name="dimension_z"  			 left="450"/> -			<text -			 top="100" -			 width="320" -			 height="15" -			 left="10" -			 text_color="White"  -			 word_wrap="true"> -				Note: -			</text> -			<text -			 top_pad="0" -			 width="320" -			 height="40" -			 left="10" -			 word_wrap="true"> -Advanced users familiar with 3d content creation tools may prefer to use the [secondlife:///app/floater/upload_model Advanced Mesh Import Window] . -			</text> +            <text +             height="16" +             left="10" +             name="warning_label" +             text_color="Yellow" +             top="200" +             visible="false" +             width="320"> +                WARNING: +            </text> +            <text +             height="50" +             left="10" +             name="warning_text" +             top_pad="0" +             visible="false" +             width="320" +             word_wrap="true"> +                You will not be able to complete the final step of uploading this model to the Second Life servers. [secondlife:///app/floater/learn_more Find out how] to set up your account for mesh model uploads.  +            </text>  		</panel>  	</panel> @@ -291,7 +281,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 height="388"  		 top_delta="0"  		 name="optimize_panel" -		 visible="false" +		 visible="true"  		 width="535"  		 left="0">  		<panel @@ -312,7 +302,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  			 height="10"  			 font="SansSerifBig"  			 layout="topleft"> -				Optimize +				Optimize model  			</text>  		</panel>  		<text @@ -324,7 +314,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 name="description"  		 word_wrap="true"  		 left_delta="5"> -			This wizard has optimized your model to improve performance. You may adjust the results of the optimization process bellow or click Next to continue. +			We have optimized the model for performance. Adjust it further if you wish.  		</text>  		<panel  		 top_delta="40" @@ -411,116 +401,89 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  				 bg_opaque_color="DkGray2"  				 background_visible="true"  				 background_opaque="true"> -			<text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> -				Model Preview: -			</text> -			<combo_box left_pad="5" top_delta="-5"  follows="left|top" list_position="below" height="22" -	     name="preview_lod_combo2" width="90" tool_tip="LOD to view in preview render"> -				<combo_item name="high"> -					High -				</combo_item> -				<combo_item name="medium"> -					Medium -				</combo_item> -				<combo_item name="low"> -					Low -				</combo_item> -				<combo_item name="lowest"> -					Lowest -				</combo_item> -			</combo_box> -			<panel -				 left="10" -				 top_pad="5" -				 name="preview_panel" -				 bevel_style="none" -				 highlight_light_color="0.09 0.09 0.09 1" -				 border_style="line" -				 border="true" -				 height="185" -				 follows="all" -				 width="185"> -			</panel> -			<text top="45" left="214" text_color="White" font="SansSerifSmallBold" halign="center" width="110" height="30" wrap="true">Higher Performance</text> -			<text top="75" left="204" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text> -			<text top="45" left="378" text_color="White" font="SansSerifSmallBold" halign="center" width="90" height="30" wrap="true">Higher Accuracy</text> -			<text top="75" left="364" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text> +			<text top="69" left="10" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Performance</text> +			<text top="85" left="10" width="120" word_wrap="true" font="SansSerifSmall" height="40">Faster rendering +Less detail +Lower prim weight</text> +			<text top="69" left="184" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Accuracy</text> +			<text top="85" left="184" width="120" word_wrap="true" font="SansSerifSmall" height="40">Slower rendering +More detail +Higher prim weight</text> -			<slider +          <slider  		   follows="left|top"  		   height="20"  		   increment="1"  		   layout="topleft" -		   left="204" -		   max_val="3" -		   initial_value="2" +		   left="10" +		   max_val="2" +		   initial_value="1"  		   min_val="0"  		   name="accuracy_slider"  		   show_text="false"  		   top="130"  		   width="290" /> -			<text  +          <text   			font="SansSerifSmall"   			top_pad="0"   -			width="300"  +			width="5"   			left_delta="6"   			height="4">'   -      </text> - - -			<icon -				 top_pad="14" -				 left_delta="0" -				 width="280" -				 height="2" -				 image_name="model_wizard\divider_line.png"/> -	 -			<text top_delta="20" width="200" text_color="White" left_delta="50" name="streaming cost"  height="20">Resource Cost:    [COST]</text> -			<text -						 top_pad="15" -						 width="130" -						 height="14" -						 left="10" -						 text_color="White" -						 word_wrap="true"> -				Dimensions (meters): -			</text> -			<text -			 top_pad="0" -			 width="160" -			 height="15" -			 font="SansSerifSmallBold" -			 text_color="White" -			 name="dimensions" -			 left_delta="0"> -				X:         Y:         Z: -			</text> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_dividers" -			 left_delta="41"> -				|               | +          </text> +          <text  +			font="SansSerifSmall"  +			top_delta="0"   +			width="5"  +			left_delta="137"  +			height="4">'   +          </text> +          <text  +			font="SansSerifSmall"  +			top_delta="0"   +			width="5"  +			left_delta="137"  +			height="4">'   +          </text> +          <button +			follows="left|top" +			height="20" +			label="Recalculate Geometry" +			layout="topleft" +			left="80" +			name="recalculate_geometry_btn" +			top_pad="15" +            width="150"> +          </button> +			<text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> +				Geometry preview  			</text> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_x" -			 left_delta="-25"/> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_y" -			 left_delta="46"/> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_z" -			 left_delta="46"/> +			<panel +				 right="-10" +				 top="32" +				 name="optimize_preview_panel" +				 bevel_style="none" +				 highlight_light_color="0.09 0.09 0.09 1" +				 border_style="line" +				 border="true" +				 height="185" +				 follows="all" +				 width="185"> +			</panel> +			<combo_box left_delta="75" top_pad="10"  follows="left|top" list_position="below" height="22" +	     name="preview_lod_combo" width="110" tool_tip="LOD to view in preview render"> +				<combo_item name="high"> +					High detail +				</combo_item> +				<combo_item name="medium"> +					Medium detail +				</combo_item> +				<combo_item name="low"> +					Low detail +				</combo_item> +				<combo_item name="lowest"> +					Lowest detail +				</combo_item> +			</combo_box>  		</panel>  	</panel> @@ -549,7 +512,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  			 font="SansSerifBig"  			 text_color="White"   			 layout="topleft"> -				Physics +				Adjust physics  			</text>  		</panel>  		<text @@ -561,7 +524,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 name="description"  		 word_wrap="true"  		 left_delta="5"> -			The wizard will create a physical shape, which determines how the object interacts with other objects and avatars. Set the slider to the detail level most appropriate for how your object will be used: +			We will create a shape for the outer hull of the model. Adjust the shape's detail level as needed for the intended purpose of your model.  		</text>      <panel  		 top_delta="44" @@ -572,172 +535,94 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 bg_opaque_color="DkGray2"  		 background_visible="true"  		 background_opaque="true"> -      <text top="15" left="20" text_color="White" font="SansSerifSmallBold" width="110" height="30" wrap="true" halign="center">Higher Performance</text> -      <text top="45" left="10" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text> -      <text top="15" left="372" text_color="White" font="SansSerifSmallBold" width="90" height="30" wrap="true" halign="center">Higher Accuracy</text> -      <text top="45" left="360" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text> +      <text top="10" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Performance</text> +      <text top="26" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Faster rendering +Less detail +Lower prim weight</text> +      <text top="174" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Accuracy</text> +      <text top="190" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Slower rendering +More detail +Higher prim weight</text>        <slider  		   follows="left|top" -		   height="22" +		   height="190"  		   increment=".1"  		   layout="topleft" -		   left="20" +		   left="140"  		   max_val="1"  		   initial_value="0.5"  		   min_val="0"  		   name="physics_slider" +		   orientation="vertical"  		   show_text="false" -		   top="90" -		   width="440" /> -      <text -			font="SansSerifSmall" -			top_pad="0" -			width="500" -			left_delta="6" -			height="4">'             '             '             '             '              '             '             '             '              '             '</text> -      <text top_pad="10" width="110" halign="center" word_wrap="true" left="25"  height="40">Recommended for solid objects</text> -      <text top_delta="0" width="110" halign="center" word_wrap="true" left="190"  height="40">Recommended for buildings</text> -      <text top_delta="0" width="110" halign="center" word_wrap="true" left="350"  height="40">Recommended for vehicles</text> - - -		<icon -			 top_pad="5" -			 left="15" -			 width="470" -			 height="2" -			 image_name="model_wizard\divider_line.png"/> -		 -	<text top_delta="30" width="180" text_color="White" left="160" name="streaming cost"  height="20">Resource Cost:       [COST]</text> -  -    </panel> -	</panel> - -	<panel -		 height="388" -		 top_delta="0" -		 name="physics2_panel" -		 visible="true" -		 width="535" -		 left="0"> -		<panel -		 height="22" -		 top_pad="15" -		 name="header_panel" -		 width="505" -		 bg_opaque_color="DkGray2" -		 background_visible="true" -		 background_opaque="true" -		 left="15"> -			<text -			 width="200" -			 left="10" -			 name="header_text" -			 text_color="White" -			 top="3" -			 height="10" -			 font="SansSerifBig" -			 layout="topleft"> -				Physics -			</text> -		</panel> -		<text -		 top_pad="14" -		 width="475" -		 height="50" -		 font="SansSerifSmall" -		 layout="topleft" -		 name="description" -		 word_wrap="true" -		 left_delta="5"> -			Preview the physics shape below then click Next to continue.  To modify the physics shape, click the Back button. -		</text> -		<panel -			 top_delta="40" -			 left="15" -			 height="270" -			 width="505" -			 name="content" -			 bg_opaque_color="DkGray2" -			 background_visible="true" -			 background_opaque="true"> -			<text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> -				Model Preview: +		   top="25" +		   width="22" /> +      <text top="10" width="120" word_wrap="true" left_pad="10" height="50">Examples: +Moving objects +Flying objects +Vehicles</text> +      <text top="95" width="120" word_wrap="true" left_delta="0" height="50">Examples: +Small static objects +Less detailed objects +Simple furniture</text> +      <text top="180" width="120" word_wrap="true" left_delta="0" height="50">Examples: +Static objects +Detailed objects +Buildings</text> +          <button +			follows="left|top" +			height="20" +			label="Recalculate physics" +			layout="topleft" +			left="80" +			name="recalculate_physics_btn" +			top_pad="10" +            width="150"> +          </button> +          <button +            enabled="false" +			follows="left|top" +			height="20" +			label="Recalculating..." +			layout="topleft" +			left_delta="0" +			name="recalculating_physics_btn" +			top_delta="0" +			visible="false" +            width="150"> +          </button> +			<text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label"> +				Physics preview  			</text> -			<combo_box left_pad="5" top_delta="-5"  follows="left|top" list_position="below" height="22" -			   name="preview_lod_combo3" width="90" tool_tip="LOD to view in preview render"> +			<panel +				 right="-10" +				 top="32" +				 name="physics_preview_panel" +				 bevel_style="none" +				 highlight_light_color="0.09 0.09 0.09 1" +				 border_style="line" +				 border="true" +				 height="185" +				 follows="all" +				 width="185"> +			</panel> +			<combo_box left_delta="75" top_pad="10"  follows="left|top" list_position="below" height="22" +	     name="preview_lod_combo2" width="110" tool_tip="LOD to view in preview render">  				<combo_item name="high"> -					High +					High detail  				</combo_item>  				<combo_item name="medium"> -					Medium +					Medium detail  				</combo_item>  				<combo_item name="low"> -					Low +					Low detail  				</combo_item>  				<combo_item name="lowest"> -					Lowest +					Lowest detail  				</combo_item>  			</combo_box> -			<panel -					   left="10" -					   top_pad="10" -					   name="preview_panel" -					   bevel_style="none" -					   highlight_light_color="0.09 0.09 0.09 1" -					   border_style="line" -					   border="true" -					   height="190" -					   follows="all" -					   width="190"> -			</panel> -			<text -						 top_pad="8" -						 width="130" -						 height="14" -						 left="10" -						 text_color="White" -						 word_wrap="true"> -				Dimensions (meters): -			</text> -			<text -			 top_pad="0" -			 width="160" -			 height="15" -			 font="SansSerifSmallBold" -			 text_color="White" -			 name="dimensions" -			 left_delta="0"> -				X:         Y:         Z: -			</text> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_dividers" -			 left_delta="41"> -				|               | -			</text> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_x" -			 left_delta="-25"/> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_y" -			 left_delta="46"/> -			<text -			 top_delta="0" -			 width="160" -			 height="15" -			 name="dimension_z" -			 left_delta="46"/> -			<text top="60" width="180" text_color="White" left="225" name="streaming cost"  height="20">Resource Cost:       [COST]</text> -		</panel> +    </panel>  	</panel>  	<panel @@ -768,162 +653,44 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  				Review  			</text>  		</panel> -		<text +		<panel  		 top_pad="14" -		 width="470" -		 height="24" -		 font="SansSerifSmall" -		 layout="topleft" -		 name="description" -		 word_wrap="true" -		 left_delta="5"> -			Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload. -		</text> -		<icon -			 top_pad="10" -			 left="20" -			 width="495" -			 height="2" -			 image_name="model_wizard\divider_line.png"/> -    <panel -		 top_pad="5"  		 left="15" -		 height="270" +		 height="310"  		 width="505" -		 name="content"> -      <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> -        Model Preview: -      </text> -      <combo_box left_pad="5" top_delta="-5"  follows="left|top" list_position="below" height="22" -	     name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render"> -        <combo_item name="high"> -          High -        </combo_item> -        <combo_item name="medium"> -          Medium -        </combo_item> -        <combo_item name="low"> -          Low -        </combo_item> -        <combo_item name="lowest"> -          Lowest -        </combo_item> -      </combo_box> -      <panel -				 left="10" -				 top_pad="10" -				 name="preview_panel" -				 bevel_style="none" -				 highlight_light_color="0.09 0.09 0.09 1" -				 border_style="line" -				 border="true" -				 height="190" -				 follows="all" -				 width="190"> -			</panel> -		<text -					 top_pad="8" -					 width="130" -					 height="14" -					 left="10" -					 text_color="White" -					 word_wrap="true"> -			Dimensions (meters): -		</text> -		<text -		 top_pad="0" -		 width="160" -		 height="15" -		 font="SansSerifSmallBold" -		 text_color="White" -		 name="dimensions" -		 left_delta="0"> -			X:         Y:         Z: -		</text> -		<text -		 top_delta="0" -		 width="160" -		 height="15" -		 name="dimension_dividers" -		 left_delta="41"> -			|               | -		</text> -		<text -		 top_delta="0" -		 width="160" -		 height="15" -		 name="dimension_x" -		 left_delta="-25"/> -		<text -		 top_delta="0" -		 width="160" -		 height="15" -		 name="dimension_y" -		 left_delta="46"/> -		<text -		 top_delta="0" -		 width="160" -		 height="15" -		 name="dimension_z" -		 left_delta="46"/> +		 name="content" +		 bg_opaque_color="DkGray2" +		 background_visible="true" +		 background_opaque="true"> +			<text +			 top="20" +			 width="485" +			 font="SansSerifMedium" +			 text_color="White" +			 left="10" +			 name="review_prim_equiv" +			 height="16">Impact to parcel/region: [EQUIV] prim equivalents +			</text> +			<text +			 top_pad="20" +			 width="485" +			 font="SansSerifMedium" +			 text_color="White" +			 left="10" +			 name="review_fee" +			 height="16">Your account will be charged an upload fee of L$ [FEE]. +			</text> +			<text  +			 top_pad="20" +			 width="485" +			 font="SansSerifMedium" +			 text_color="White" +			 left="10" +			 name="review_confirmation" +			 height="32" +			 word_wrap="true">By clicking the upload button, you confirm that you have the appropriate rights to the material contained in the model. +			</text>        </panel> -    <text -      width="300" -      height="12" -      top="125"  -	  name="streaming cost"  -      left="230"  -      font="SansSerifSmallBold"  -      text_color="White">Resource Cost:         [COST]</text> -    <text -      width="285" -      height="30" -      top_pad="0" -      left_delta="0" -      word_wrap="true" -      font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text> -	<text -	 width="300" -	 height="12" -	 name="physics cost"  -	 top_pad="10" -		 left_delta="0" -	 font="SansSerifSmallBold" -	 text_color="White">Physics Cost:        [COST]</text> -	<text -	  width="285" -	  height="30" -	  top_pad="0" -		  left_delta="0" -	  word_wrap="true" -	  font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text> -		<text -		 width="200" -		 height="12" -		 top_pad="10" -		left_delta="0" -		 font="SansSerifSmallBold" -		 text_color="White">Upload Fee:</text> -		<text -		  width="285" -		  height="26" -		  top_pad="0" -		  left_delta="0" -		  word_wrap="true" -		  font="SansSerifItalic">This is the amount the upload will cost.</text> -		<check_box -			height="16" -			layout="topleft" -			left_delta="0" -			name="confirm_checkbox" -			top_pad="15" -			width="16" /> -		<text -		  height="100" -		  width="240" -		  word_wrap="true"  -		  left_delta="25" -		  top_delta="0">I confirm that I have the appropriate rights to the material contained in this model. [secondlife:///app/floater/learn_more Learn more]</text>  	</panel> @@ -954,46 +721,79 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  			 height="10"  			 font="SansSerifBig"  			 layout="topleft"> -				Upload Complete! +				Upload complete  			</text>  		</panel>  		<text  		 top_pad="14" -		 width="474" -		 height="20" -		 font="SansSerifSmall" +		 width="495" +		 height="16" +		 font="SansSerifMedium"  		 layout="topleft" -		 name="description" +		 name="model_uploaded_text" +		 text_color="White"  		 word_wrap="true" -		 left_delta="5"> -			Congratulations! Your model has been sucessfully uploaded.  You will find the model in the Objects folder in your inventory. +		 left="25"> +			Your model has been uploaded. +		</text> +		<text +		 top_pad="5" +		 width="495" +		 height="16" +		 font="SansSerifMedium" +		 layout="topleft" +		 name="inventory_text" +		 text_color="White" +		 word_wrap="true" +		 left="25"> +			You will find it in the Objects folder in your inventory. +		</text> +		<text +		 top_pad="20" +		 width="495" +		 font="SansSerifMedium" +		 text_color="White" +		 left="25" +		 name="charged_fee" +		 height="16">Your account has been charged L$ [FEE].  		</text> -		<icon -			 top_pad="15" -			 left_delta="0" -			 width="495" -			 height="2" -			 image_name="model_wizard\divider_line.png"/>  	</panel>  	<button  	 top="440" -	 right="-245" +	 right="-285"  	 width="90"  	 height="22"  	 name="back"  	 label="<< Back" />  	<button  	 top_delta="0" -	 right="-150" +	 right="-190"  	 width="90"  	 height="22"  	 name="next"  	 label="Next >> " />  	<button  	 top_delta="0" +	 left_delta="0" +	 width="160" +	 height="22" +	 name="calculate" +	 label="Calculate weights & fee >> " /> +	<button +	 enabled="false" +	 visible="false" +	 top_delta="0" +	 left_delta="0" +	 width="160" +	 height="22" +	 name="calculating" +	 label="Calculating... " /> +	<button +	 enabled="false" +	 top_delta="0"  	 right="-150"  	 width="90"  	 height="22" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 8b8f70b940..8901583799 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -47,24 +47,12 @@          Click and drag to select land      </floater.string>      <floater.string -     name="grid_screen_text"> -        Screen +     name="status_selectcount"> +        [OBJ_COUNT] objects ( [PRIM_COUNT] prims[PE_STRING] ) selected      </floater.string>      <floater.string -     name="grid_local_text"> -        Local -    </floater.string> -    <floater.string -     name="grid_world_text"> -        World -    </floater.string> -    <floater.string -     name="grid_reference_text"> -        Reference -    </floater.string> -    <floater.string -     name="grid_attachment_text"> -        Attachment +     name="status_selectprimequiv"> +        , [SEL_WEIGHT] prim equivs      </floater.string>      <button       follows="left|top" @@ -221,7 +209,7 @@  	<radio_group       follows="left|top"  	 left="5" -	 top="59" +	 top="55"  	 height="70"       layout="topleft"  	 name="edit_radio_group"> @@ -255,18 +243,18 @@       label="Edit linked"       layout="topleft"       name="checkbox edit linked parts" -     top_pad="-10"> +     top_pad="-18">  		  <check_box.commit_callback  			function="BuildTool.selectComponent"/>  	</check_box>     <button       follows="left|top" -     height="23" +     height="20"       label="Link" -     top_pad="2" +     top="108"       layout="topleft" -     left="5" +     left="143"       name="link_btn"       width="50">  	  <button.commit_callback @@ -274,27 +262,15 @@      </button>      <button       follows="left|top" -     height="23" +     height="20"       label="Unlink"       layout="topleft"       left_pad="2"       name="unlink_btn" -     width="105"> +     width="90">  	  <button.commit_callback  	     function="BuildTool.UnlinkObjects"/>      </button> -    <text -	   text_color="LtGray_50" -	   follows="top|left" -	   halign="left" -	   left_pad="3" -	   name="RenderingCost" -	   tool_tip="Shows the rendering cost calculated for this object" -	   top_delta="11" -	   type="string" -	   width="100"> -	   รพ: [COUNT] -	   </text>      <check_box       control_name="ScaleUniform"       height="19" @@ -302,7 +278,7 @@       layout="topleft"       left="143"       name="checkbox uniform" -     top="50" +     top="48"       width="20" />      <text       height="19" @@ -324,53 +300,29 @@       layout="topleft"       left="143"       name="checkbox stretch textures" -     top_pad="-6" +     top_pad="-4"       follows="left|top"       width="134" />     <check_box       control_name="SnapEnabled"       height="18"       initial_value="true" -     label="Snap to grid" +     label="Snap"       layout="topleft"       top_pad="0"       name="checkbox snap to grid"       width="134" /> -    <combo_box -     height="23" -     layout="topleft" -     follows="left|top" -     name="combobox grid mode" -     tool_tip="Choose the type of grid ruler for positioning the object" -     top_pad="0" -     width="108"> -        <combo_box.item -         label="World grid" -         name="World" -         value="World" /> -        <combo_box.item -         label="Local grid" -         name="Local" -         value="Local" /> -        <combo_box.item -         label="Reference grid" -         name="Reference" -         value="Reference" /> -		 <combo_box.commit_callback -	     function="BuildTool.gridMode"/> -    </combo_box>      <button       left_pad="0" -     image_selected="ForwardArrow_Press" -     image_unselected="ForwardArrow_Off" +     label="Options..."       layout="topleft"       follows="top|left"       name="Options..."       tool_tip="See more grid options" -     top_pad="-22" -     right="-10" -     width="18" -     height="23" > +     top="83" +     right="-35" +     width="65" +     height="21" >  	 <button.commit_callback  	     function="BuildTool.gridOptions"/>  	</button> @@ -385,7 +337,7 @@       left="10"       name="ToolCube"       tool_tip="Cube" -     top="51" +     top="58"       width="20" />      <button       follows="left|top" @@ -447,10 +399,10 @@       image_selected="Object_Hemi_Cylinder_Selected"       image_unselected="Object_Hemi_Cylinder"       layout="topleft" -     left_delta="29" +     left="10"       name="ToolHemiCylinder"       tool_tip="Hemicylinder" -     top_delta="0" +     top="84"       width="20" />      <button       follows="left|top" @@ -515,7 +467,7 @@       left="10"       name="ToolTorus"       tool_tip="Torus" -     top="77" +     top="109"       width="20" />      <button       follows="left|top" @@ -575,9 +527,9 @@       height="19"       label="Keep Tool selected"       layout="topleft" -     left="4" +     left="155"       name="checkbox sticky" -     top="101" +     top="55"       width="128" />      <check_box       control_name="CreateToolCopySelection" @@ -596,7 +548,7 @@       layout="topleft"       left_delta="18"       name="checkbox copy centers" -     top="132" +     top="85"       width="134" />      <check_box       control_name="CreateToolCopyRotates" @@ -749,89 +701,49 @@  	  <button.commit_callback  	     function="BuildTool.applyToSelection"/>      </button> +    <text +	 text_color="LtGray_50" +	  type="string" +	  length="1" +	  height="16" +	  follows="left|top" +	  font="SansSerifSmall" +	  layout="topleft" +	  left="10" +	  name="selection_empty" +	  top_pad="0" +	  width="100"> +		Nothing selected. +	</text>  	<text  	 text_color="LtGray_50"  	  type="string"  	  length="1" -	  height="10" +	  height="16"  	  follows="left|top" -	  halign="right" +	  font="SansSerifSmall"  	  layout="topleft" -	  right="-10" -	  name="obj_count" -	  top_pad="5" -	  width="143"> -		Objects: [COUNT] +	  left="10" +	  name="selection_count" +	  top_delta="0" +	  visible="false" +	  width="280">  	</text>  	<text -    text_color="LtGray_50" -     type="string" -     length="1" -	height="10"  -     follows="left|top" -     halign="right" -     layout="topleft" -     right="-10" -     name="prim_count" -     width="143"> -		Prims: [COUNT] +	 text_color="LtGray_50" +	  type="string" +	  length="1" +	  height="16" +	  follows="left|top" +	  font="SansSerifSmall" +	  layout="topleft" +	  left="10" +	  name="selection_weight" +	  top_pad="0" +	  visible="false" +	  width="280"> +	  Physics weight [PHYS_WEIGHT], Render Cost [DISP_WEIGHT].  	</text> -    <text -    text_color="LtGray_50" -     type="string" -     length="1" -     height="10" -     follows="left|top" -     halign="right" -     layout="topleft" -     right="-120" -     name="linked_set_count" -     top="144" -     width="80"> -        Linked Sets: [COUNT] -    </text> -    <text -    text_color="LtGray_50" -     type="string" -     length="1" -     height="10" -     follows="left|top" -     halign="right" -     layout="topleft" -     top_delta="0" -     right="-8" -     name="linked_set_cost" -     tool_tip="Cost of currently selected linked sets as [prims],[physics complexity]"  -     width="80"> -        Cost: [COST] / [PHYSICS] -    </text> -    <text -    text_color="LtGray_50" -     type="string" -     length="1" -     follows="left|top" -     halign="right" -     layout="topleft" -     top_pad="5" -     right="-120" -     name="object_count" -     width="80"> -        Objects: [COUNT] -    </text> -    <text -    text_color="LtGray_50" -     type="string" -     length="1" -     follows="left|top" -     halign="right" -     layout="topleft" -	 top_delta="0" -     right="-8" -     name="object_cost" -     tool_tip="Cost of currently selected objects as [prims] / [physics complexity]" -     width="80"> -        Cost: [COST] / [PHYSICS] -    </text>      <!-- <text -->      <!-- text_color="LtGray_50" -->      <!--  type="string" --> @@ -858,6 +770,15 @@      <!--  width="143"> -->      <!--     Prims: [COUNT] -->      <!-- </text> --> +    <view_border +    bevel_style="none" +    follows="top|left" +    height="0" +    layout="topleft" +    left="6" +    name="cost_text_border" +    top="135" +    width="282"/>      <tab_container       follows="left|top"       height="410" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index e0ccb18c08..0f42000ae7 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -54,18 +54,6 @@                  <menu_item_call.on_visible                  function="File.VisibleUploadModel"/>                  </menu_item_call> -              <menu_item_call -                label="Model Wizard..." -                layout="topleft" -                name="Upload Model Wizard"> -                <menu_item_call.on_click -                 function="Floater.Show" -                 parameter="upload_model_wizard" /> -                <menu_item_call.on_enable -                 function="File.EnableUploadModel" /> -                <menu_item_call.on_visible -                function="File.VisibleUploadModel"/> -	      </menu_item_call>                  <menu_item_call                   label="Bulk (L$[COST] per file)..."                   layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index ab5c543376..01699955a6 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1083,19 +1083,7 @@              <menu_item_call.on_visible              function="File.VisibleUploadModel"/>              </menu_item_call> -			<menu_item_call -           label="Model Wizard..." -           layout="topleft" -           name="Upload Model Wizard"> -				<menu_item_call.on_click -				 function="Floater.Show" -				 parameter="upload_model_wizard" /> -				<menu_item_call.on_enable -				 function="File.EnableUploadModel" /> -				<menu_item_call.on_visible -				function="File.VisibleUploadModel"/> -			</menu_item_call> -            <menu_item_call +	   <menu_item_call               label="Bulk (L$[COST] per file)..."               layout="topleft"               name="Bulk Upload"> @@ -2097,15 +2085,14 @@              </menu_item_check>            <menu_item_check               label="Show Upload Cost" -             layout="topleft"               name="Show Upload Cost"> -            <menu_item_check.on_check +              <menu_item_check.on_check               function="CheckControl"               parameter="DebugShowUploadCost" />              <menu_item_check.on_click -             function="ToggleControl" -             parameter="DebugShowUploadCost" /> -          </menu_item_check> +                 function="ToggleControl" +                 parameter="DebugShowUploadCost" /> +            </menu_item_check>              <menu_item_check               label="Show Render Info"               name="Show Render Info"> @@ -2116,7 +2103,7 @@                   function="ToggleControl"                   parameter="DebugShowRenderInfo" />              </menu_item_check> -			<menu_item_check +			  <menu_item_check               label="Show Texture Info"               name="Show Texture Info">                  <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 661165069e..6e2596a49e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6810,6 +6810,20 @@ Select residents to share with.  See the log file for details.    </notification> +   <notification +    name="MeshUploadPermError" +    icon="alert.tga" +    type="alert"> +    Error while requesting mesh upload permissons. +  </notification> +   +  <notification +    name="RegionCapabilityRequestError" +    icon="alert.tga" +    type="alert"> +    Could not get region capability '[CAPABILITY]'. +  </notification> +       <notification     icon="notifytip.tga"     name="ShareItemsConfirmation" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ee6317f367..47e02378fe 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -44,6 +44,8 @@  	<string name="LoginInitializingQuicktime">Initializing QuickTime...</string>  	<string name="LoginQuicktimeNotFound">QuickTime not found - unable to initialize.</string>  	<string name="LoginQuicktimeOK">QuickTime initialized successfully.</string> +	<string name="LoginRequestSeedCapGrant">Requesting region capabilities...</string> +	<string name="LoginRetrySeedCapGrant">Requesting region capabilities, attempt [NUMBER]...</string>  	<string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string>  	<string name="LoginConnectingToRegion">Connecting to region...</string>  	<string name="LoginDownloadingClothing">Downloading clothing...</string> diff --git a/scripts/gpu_table_tester b/scripts/gpu_table_tester index 52b1c8f31d..52b1c8f31d 100755..100644 --- a/scripts/gpu_table_tester +++ b/scripts/gpu_table_tester | 
