summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llfasttimer_class.cpp12
-rwxr-xr-x[-rw-r--r--]indra/llcommon/llversionviewer.h0
-rw-r--r--indra/llcrashlogger/llcrashlogger.cpp2
-rwxr-xr-x[-rw-r--r--]indra/llmath/llvolume.cpp158
-rw-r--r--indra/llmessage/llcurl.cpp125
-rw-r--r--indra/llmessage/llcurl.h9
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp2848
-rw-r--r--indra/llplugin/llpluginclassmedia.h850
-rw-r--r--indra/llprimitive/llmodel.cpp504
-rw-r--r--indra/llprimitive/llmodel.h10
-rwxr-xr-x[-rw-r--r--]indra/llprimitive/llprimitive.h2
-rw-r--r--indra/llrender/llvertexbuffer.cpp3
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/settings.xml98
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl93
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl28
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl59
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl60
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl113
-rw-r--r--indra/newview/llagentcamera.cpp2
-rw-r--r--indra/newview/llappviewer.cpp2
-rwxr-xr-x[-rw-r--r--]indra/newview/llassetuploadresponders.cpp11
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp28
-rw-r--r--indra/newview/llenvmanager.cpp36
-rw-r--r--indra/newview/llenvmanager.h36
-rw-r--r--indra/newview/llfloaterbuildoptions.cpp68
-rw-r--r--indra/newview/llfloaterbuildoptions.h23
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloatermodelpreview.cpp549
-rw-r--r--indra/newview/llfloatermodelpreview.h44
-rw-r--r--indra/newview/llfloatermodeluploadbase.cpp58
-rw-r--r--indra/newview/llfloatermodeluploadbase.h61
-rw-r--r--indra/newview/llfloatermodelwizard.cpp303
-rw-r--r--indra/newview/llfloatermodelwizard.h37
-rw-r--r--indra/newview/llfloatertools.cpp149
-rw-r--r--indra/newview/llfloatertools.h4
-rwxr-xr-x[-rw-r--r--]indra/newview/llmeshrepository.cpp1085
-rwxr-xr-x[-rw-r--r--]indra/newview/llmeshrepository.h60
-rw-r--r--indra/newview/llpanelmarketplaceinbox.cpp496
-rw-r--r--indra/newview/llsceneview.cpp15
-rw-r--r--indra/newview/llstartup.cpp19
-rw-r--r--indra/newview/llsurface.cpp11
-rw-r--r--indra/newview/llsurface.h3
-rw-r--r--indra/newview/lluploadfloaterobservers.cpp56
-rw-r--r--indra/newview/lluploadfloaterobservers.h97
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp7
-rw-r--r--indra/newview/llviewerobject.cpp102
-rw-r--r--indra/newview/llviewerobject.h11
-rw-r--r--indra/newview/llviewerobjectlist.cpp20
-rw-r--r--indra/newview/llviewerparceloverlay.cpp27
-rw-r--r--indra/newview/llviewerparceloverlay.h1
-rw-r--r--indra/newview/llviewerprecompiledheaders.h4
-rw-r--r--indra/newview/llviewerregion.cpp220
-rw-r--r--indra/newview/llviewerregion.h9
-rw-r--r--indra/newview/llviewerwindow.cpp29
-rw-r--r--indra/newview/llvoavatar.cpp10
-rw-r--r--indra/newview/llvosky.cpp5
-rwxr-xr-x[-rw-r--r--]indra/newview/llvovolume.cpp5
-rw-r--r--indra/newview/llwlhandlers.cpp36
-rw-r--r--indra/newview/llwlhandlers.h36
-rw-r--r--indra/newview/pipeline.cpp120
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml73
-rwxr-xr-x[-rw-r--r--]indra/newview/skins/default/xui/en/floater_model_preview.xml140
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_wizard.xml774
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml217
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml12
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml25
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml14
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/tests/lldir_stub.cpp21
-rw-r--r--indra/newview/tests/llglslshader_stub.cpp21
-rw-r--r--indra/newview/tests/llpipeline_stub.cpp21
-rw-r--r--indra/newview/tests/llsky_stub.cpp21
-rw-r--r--indra/newview/tests/llviewershadermgr_stub.cpp21
-rw-r--r--indra/newview/tests/llwlanimator_stub.cpp21
-rw-r--r--indra/newview/tests/llwldaycycle_stub.cpp21
-rw-r--r--indra/newview/tests/llwlparammanager_test.cpp21
-rw-r--r--indra/newview/tests/llwlparamset_stub.cpp21
83 files changed, 5580 insertions, 4753 deletions
diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index 675eda2fc5..0737f954e8 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -229,12 +229,12 @@ void LLFastTimer::DeclareTimer::updateCachedPointers()
it->mFrameState = &it->mTimer.getFrameState();
}
- // also update frame states of timers on stack
- LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
- while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)
- {
- cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
- cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
+ // also update frame states of timers on stack
+ LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
+ while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)
+ {
+ cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
+ cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
}
}
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 99c5412ae5..99c5412ae5 100644..100755
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
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/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index d3d0403bbb..d081109acc 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1,1424 +1,1424 @@
-/**
- * @file llpluginclassmedia.cpp
- * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llpluginclassmedia.h"
-#include "llpluginmessageclasses.h"
-
-#include "llqtwebkit.h"
-
-static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
-
-static int nextPowerOf2( int value )
-{
- int next_power_of_2 = 1;
- while ( next_power_of_2 < value )
- {
- next_power_of_2 <<= 1;
- }
-
- return next_power_of_2;
-}
-
-LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
-{
- mOwner = owner;
- mPlugin = NULL;
- reset();
-
- //debug use
- mDeleteOK = true ;
-}
-
-
-LLPluginClassMedia::~LLPluginClassMedia()
-{
- llassert_always(mDeleteOK) ;
- reset();
-}
-
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{
- LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
- LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
- LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-
- mPlugin = new LLPluginProcessParent(this);
- mPlugin->setSleepTime(mSleepTime);
-
- // Queue up the media init message -- it will be sent after all the currently queued messages.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
- message.setValue("target", mTarget);
- sendMessage(message);
-
- mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
-
- return true;
-}
-
-
-void LLPluginClassMedia::reset()
-{
- if(mPlugin != NULL)
- {
- delete mPlugin;
- mPlugin = NULL;
- }
-
- mTextureParamsReceived = false;
- mRequestedTextureDepth = 0;
- mRequestedTextureInternalFormat = 0;
- mRequestedTextureFormat = 0;
- mRequestedTextureType = 0;
- mRequestedTextureSwapBytes = false;
- mRequestedTextureCoordsOpenGL = false;
- mTextureSharedMemorySize = 0;
- mTextureSharedMemoryName.clear();
- mDefaultMediaWidth = 0;
- mDefaultMediaHeight = 0;
- mNaturalMediaWidth = 0;
- mNaturalMediaHeight = 0;
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- mRequestedMediaWidth = 0;
- mRequestedMediaHeight = 0;
- mRequestedTextureWidth = 0;
- mRequestedTextureHeight = 0;
- mFullMediaWidth = 0;
- mFullMediaHeight = 0;
- mTextureWidth = 0;
- mTextureHeight = 0;
- mMediaWidth = 0;
- mMediaHeight = 0;
- mDirtyRect = LLRect::null;
- mAutoScaleMedia = false;
- mRequestedVolume = 1.0f;
- mPriority = PRIORITY_NORMAL;
- mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
- mAllowDownsample = false;
- mPadding = 0;
- mLastMouseX = 0;
- mLastMouseY = 0;
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- mSleepTime = 1.0f / 100.0f;
- mCanCut = false;
- mCanCopy = false;
- mCanPaste = false;
- mMediaName.clear();
- mMediaDescription.clear();
- mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-
- // media_browser class
- mNavigateURI.clear();
- mNavigateResultCode = -1;
- mNavigateResultString.clear();
- mHistoryBackAvailable = false;
- mHistoryForwardAvailable = false;
- mStatusText.clear();
- mProgressPercent = 0;
- mClickURL.clear();
- mClickNavType.clear();
- mClickTarget.clear();
- mClickUUID.clear();
- mStatusCode = 0;
-
- // media_time class
- mCurrentTime = 0.0f;
- mDuration = 0.0f;
- mCurrentRate = 0.0f;
- mLoadedDuration = 0.0f;
-}
-
-void LLPluginClassMedia::idle(void)
-{
- if(mPlugin)
- {
- mPlugin->idle();
- }
-
- if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
- {
- // Can't process a size change at this time
- }
- else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
- {
- // Calculate the correct size for the media texture
- mRequestedTextureHeight = mRequestedMediaHeight;
- if(mPadding < 0)
- {
- // negative values indicate the plugin wants a power of 2
- mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
- }
- else
- {
- mRequestedTextureWidth = mRequestedMediaWidth;
-
- if(mPadding > 1)
- {
- // Pad up to a multiple of the specified number of bytes per row
- int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
- int pad = rowbytes % mPadding;
- if(pad != 0)
- {
- rowbytes += mPadding - pad;
- }
-
- if(rowbytes % mRequestedTextureDepth == 0)
- {
- mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
- }
- else
- {
- LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
- }
- }
- }
-
-
- // Size change has been requested but not initiated yet.
- size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
- // Add an extra line for padding, just in case.
- newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
- if(newsize != mTextureSharedMemorySize)
- {
- if(!mTextureSharedMemoryName.empty())
- {
- // Tell the plugin to remove the old memory segment
- mPlugin->removeSharedMemory(mTextureSharedMemoryName);
- mTextureSharedMemoryName.clear();
- }
-
- mTextureSharedMemorySize = newsize;
- mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
- if(!mTextureSharedMemoryName.empty())
- {
- void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-
- // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
- memset( addr, 0x00, newsize );
-
- // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
- // so it may not be worthwhile.
- // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
- }
- }
-
- // This is our local indicator that a change is in progress.
- mTextureWidth = -1;
- mTextureHeight = -1;
- mMediaWidth = -1;
- mMediaHeight = -1;
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // Send a size change message to the plugin
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
- message.setValue("name", mTextureSharedMemoryName);
- message.setValueS32("width", mRequestedMediaWidth);
- message.setValueS32("height", mRequestedMediaHeight);
- message.setValueS32("texture_width", mRequestedTextureWidth);
- message.setValueS32("texture_height", mRequestedTextureHeight);
- message.setValueReal("background_r", mBackgroundColor.mV[VX]);
- message.setValueReal("background_g", mBackgroundColor.mV[VY]);
- message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
- message.setValueReal("background_a", mBackgroundColor.mV[VW]);
- mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-
- LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
- }
- }
-
- if(mPlugin && mPlugin->isRunning())
- {
- // Send queued messages
- while(!mSendQueue.empty())
- {
- LLPluginMessage message = mSendQueue.front();
- mSendQueue.pop();
- mPlugin->sendMessage(message);
- }
- }
-}
-
-int LLPluginClassMedia::getTextureWidth() const
-{
- return nextPowerOf2(mTextureWidth);
-}
-
-int LLPluginClassMedia::getTextureHeight() const
-{
- return nextPowerOf2(mTextureHeight);
-}
-
-unsigned char* LLPluginClassMedia::getBitsData()
-{
- unsigned char *result = NULL;
- if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
- {
- result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
- }
- return result;
-}
-
-void LLPluginClassMedia::setSize(int width, int height)
-{
- if((width > 0) && (height > 0))
- {
- mSetMediaWidth = width;
- mSetMediaHeight = height;
- }
- else
- {
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- }
-
- setSizeInternal();
-}
-
-void LLPluginClassMedia::setSizeInternal(void)
-{
- if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
- {
- mRequestedMediaWidth = mSetMediaWidth;
- mRequestedMediaHeight = mSetMediaHeight;
- }
- else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
- {
- mRequestedMediaWidth = mNaturalMediaWidth;
- mRequestedMediaHeight = mNaturalMediaHeight;
- }
- else
- {
- mRequestedMediaWidth = mDefaultMediaWidth;
- mRequestedMediaHeight = mDefaultMediaHeight;
- }
-
- // Save these for size/interest calculations
- mFullMediaWidth = mRequestedMediaWidth;
- mFullMediaHeight = mRequestedMediaHeight;
-
- if(mAllowDownsample)
- {
- switch(mPriority)
- {
- case PRIORITY_SLIDESHOW:
- case PRIORITY_LOW:
- // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
- while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
- {
- mRequestedMediaWidth /= 2;
- mRequestedMediaHeight /= 2;
- }
- break;
-
- default:
- // Don't adjust texture size
- break;
- }
- }
-
- if(mAutoScaleMedia)
- {
- mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
- mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
- }
-
- if(mRequestedMediaWidth > 2048)
- mRequestedMediaWidth = 2048;
-
- if(mRequestedMediaHeight > 2048)
- mRequestedMediaHeight = 2048;
-}
-
-void LLPluginClassMedia::setAutoScale(bool auto_scale)
-{
- if(auto_scale != mAutoScaleMedia)
- {
- mAutoScaleMedia = auto_scale;
- setSizeInternal();
- }
-}
-
-bool LLPluginClassMedia::textureValid(void)
-{
- if(
- !mTextureParamsReceived ||
- mTextureWidth <= 0 ||
- mTextureHeight <= 0 ||
- mMediaWidth <= 0 ||
- mMediaHeight <= 0 ||
- mRequestedMediaWidth != mMediaWidth ||
- mRequestedMediaHeight != mMediaHeight ||
- getBitsData() == NULL
- )
- return false;
-
- return true;
-}
-
-bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
-{
- bool result = !mDirtyRect.isEmpty();
-
- if(dirty_rect != NULL)
- {
- *dirty_rect = mDirtyRect;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::resetDirty(void)
-{
- mDirtyRect = LLRect::null;
-}
-
-std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
-{
- std::string result;
-
-
- if(modifiers & MASK_CONTROL)
- {
- result += "control|";
- }
-
- if(modifiers & MASK_ALT)
- {
- result += "alt|";
- }
-
- if(modifiers & MASK_SHIFT)
- {
- result += "shift|";
- }
-
- // TODO: should I deal with platform differences here or in callers?
- // TODO: how do we deal with the Mac "command" key?
-/*
- if(modifiers & MASK_SOMETHING)
- {
- result += "meta|";
- }
-*/
- return result;
-}
-
-void LLPluginClassMedia::jsEnableObject( bool enable )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
- message.setValueBoolean( "enable", enable );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
- message.setValueReal( "angle", angle );
-
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
- message.setValue( "language", language );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
- message.setValue( "region", region );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
- message.setValue( "maturity", maturity );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
-{
- if(type == MOUSE_EVENT_MOVE)
- {
- if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
- {
- // Don't queue up mouse move events that can't be delivered.
- return;
- }
-
- if((x == mLastMouseX) && (y == mLastMouseY))
- {
- // Don't spam unnecessary mouse move events.
- return;
- }
-
- mLastMouseX = x;
- mLastMouseY = y;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
- std::string temp;
- switch(type)
- {
- case MOUSE_EVENT_DOWN: temp = "down"; break;
- case MOUSE_EVENT_UP: temp = "up"; break;
- case MOUSE_EVENT_MOVE: temp = "move"; break;
- case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("button", button);
-
- message.setValueS32("x", x);
-
- // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
- if(!mRequestedTextureCoordsOpenGL)
- {
- // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
- y = mMediaHeight - y;
- }
- message.setValueS32("y", y);
-
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
-{
- bool result = true;
-
- // FIXME:
- // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
- // For now, return false for the ones the webkit plugin won't handle properly.
-
- switch(key_code)
- {
- case KEY_BACKSPACE:
- case KEY_TAB:
- case KEY_RETURN:
- case KEY_PAD_RETURN:
- case KEY_SHIFT:
- case KEY_CONTROL:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_ESCAPE:
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_END:
- case KEY_HOME:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_INSERT:
- case KEY_DELETE:
- // These will be handled
- break;
-
- default:
- // regular ASCII characters will also be handled
- if(key_code >= KEY_SPECIAL)
- {
- // Other "special" codes will not work properly.
- result = false;
- }
- break;
- }
-
-#if LL_DARWIN
- if(modifiers & MASK_ALT)
- {
- // Option-key modified characters should be handled by the unicode input path instead of this one.
- result = false;
- }
-#endif
-
- if(result)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
- std::string temp;
- switch(type)
- {
- case KEY_EVENT_DOWN: temp = "down"; break;
- case KEY_EVENT_UP: temp = "up"; break;
- case KEY_EVENT_REPEAT: temp = "repeat"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("key", key_code);
-
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
- }
-
- return result;
-}
-
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
-
- message.setValueS32("x", x);
- message.setValueS32("y", y);
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
-
- message.setValue("text", text);
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
-
- return true;
-}
-
-void LLPluginClassMedia::loadURI(const std::string &uri)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
-
- message.setValue("uri", uri);
-
- sendMessage(message);
-}
-
-const char* LLPluginClassMedia::priorityToString(EPriority priority)
-{
- const char* result = "UNKNOWN";
- switch(priority)
- {
- case PRIORITY_UNLOADED: result = "unloaded"; break;
- case PRIORITY_STOPPED: result = "stopped"; break;
- case PRIORITY_HIDDEN: result = "hidden"; break;
- case PRIORITY_SLIDESHOW: result = "slideshow"; break;
- case PRIORITY_LOW: result = "low"; break;
- case PRIORITY_NORMAL: result = "normal"; break;
- case PRIORITY_HIGH: result = "high"; break;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::setPriority(EPriority priority)
-{
- if(mPriority != priority)
- {
- mPriority = priority;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-
- std::string priority_string = priorityToString(priority);
- switch(priority)
- {
- case PRIORITY_UNLOADED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_STOPPED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_HIDDEN:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_SLIDESHOW:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_LOW:
- mSleepTime = 1.0f / 25.0f;
- break;
- case PRIORITY_NORMAL:
- mSleepTime = 1.0f / 50.0f;
- break;
- case PRIORITY_HIGH:
- mSleepTime = 1.0f / 100.0f;
- break;
- }
-
- message.setValue("priority", priority_string);
-
- sendMessage(message);
-
- if(mPlugin)
- {
- mPlugin->setSleepTime(mSleepTime);
- }
-
- LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
-{
- int power = nextPowerOf2(size);
- if(mLowPrioritySizeLimit != power)
- {
- mLowPrioritySizeLimit = power;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-F64 LLPluginClassMedia::getCPUUsage()
-{
- F64 result = 0.0f;
-
- if(mPlugin)
- {
- result = mPlugin->getCPUUsage();
- }
-
- return result;
-}
-
-void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
- message.setValue("file", file);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
- message.setValueBoolean("ok", ok);
- message.setValue("username", username);
- message.setValue("password", password);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::cut()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::copy()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::paste()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
- message.setValue("path", user_data_path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
- message.setValue("language", language_code);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setTarget(const std::string &target)
-{
- mTarget = target;
-}
-
-/* virtual */
-void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
-{
- std::string message_class = message.getClass();
-
- if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- std::string message_name = message.getName();
- if(message_name == "texture_params")
- {
- mRequestedTextureDepth = message.getValueS32("depth");
- mRequestedTextureInternalFormat = message.getValueU32("internalformat");
- mRequestedTextureFormat = message.getValueU32("format");
- mRequestedTextureType = message.getValueU32("type");
- mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
- mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
-
- // These two are optional, and will default to 0 if they're not specified.
- mDefaultMediaWidth = message.getValueS32("default_width");
- mDefaultMediaHeight = message.getValueS32("default_height");
-
- mAllowDownsample = message.getValueBoolean("allow_downsample");
- mPadding = message.getValueS32("padding");
-
- setSizeInternal();
-
- mTextureParamsReceived = true;
- }
- else if(message_name == "updated")
- {
- if(message.hasValue("left"))
- {
- LLRect newDirtyRect;
- newDirtyRect.mLeft = message.getValueS32("left");
- newDirtyRect.mTop = message.getValueS32("top");
- newDirtyRect.mRight = message.getValueS32("right");
- newDirtyRect.mBottom = message.getValueS32("bottom");
-
- // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
- // If they're backwards, swap them.
- if(newDirtyRect.mTop < newDirtyRect.mBottom)
- {
- S32 temp = newDirtyRect.mTop;
- newDirtyRect.mTop = newDirtyRect.mBottom;
- newDirtyRect.mBottom = temp;
- }
-
- if(mDirtyRect.isEmpty())
- {
- mDirtyRect = newDirtyRect;
- }
- else
- {
- mDirtyRect.unionWith(newDirtyRect);
- }
-
- LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
- << newDirtyRect.mLeft << ", "
- << newDirtyRect.mTop << ", "
- << newDirtyRect.mRight << ", "
- << newDirtyRect.mBottom << "), new dirty rect is: ("
- << mDirtyRect.mLeft << ", "
- << mDirtyRect.mTop << ", "
- << mDirtyRect.mRight << ", "
- << mDirtyRect.mBottom << ")"
- << LL_ENDL;
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
- }
-
-
- bool time_duration_updated = false;
- int previous_percent = mProgressPercent;
-
- if(message.hasValue("current_time"))
- {
- mCurrentTime = message.getValueReal("current_time");
- time_duration_updated = true;
- }
- if(message.hasValue("duration"))
- {
- mDuration = message.getValueReal("duration");
- time_duration_updated = true;
- }
-
- if(message.hasValue("current_rate"))
- {
- mCurrentRate = message.getValueReal("current_rate");
- }
-
- if(message.hasValue("loaded_duration"))
- {
- mLoadedDuration = message.getValueReal("loaded_duration");
- time_duration_updated = true;
- }
- else
- {
- // If the message doesn't contain a loaded_duration param, assume it's equal to duration
- mLoadedDuration = mDuration;
- }
-
- // Calculate a percentage based on the loaded duration and total duration.
- if(mDuration != 0.0f) // Don't divide by zero.
- {
- mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
- }
-
- if(time_duration_updated)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
- }
-
- if(previous_percent != mProgressPercent)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- }
- else if(message_name == "media_status")
- {
- std::string status = message.getValue("status");
-
- LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-
- if(status == "loading")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
- }
- else if(status == "loaded")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
- }
- else if(status == "error")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
- }
- else if(status == "playing")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
- }
- else if(status == "paused")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
- }
- else if(status == "done")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
- }
- else
- {
- // empty string or any unknown string
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- }
- }
- else if(message_name == "size_change_request")
- {
- S32 width = message.getValueS32("width");
- S32 height = message.getValueS32("height");
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
- mNaturalMediaWidth = width;
- mNaturalMediaHeight = height;
-
- setSizeInternal();
- }
- else if(message_name == "size_change_response")
- {
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
-
- mTextureWidth = message.getValueS32("texture_width");
- mTextureHeight = message.getValueS32("texture_height");
- mMediaWidth = message.getValueS32("width");
- mMediaHeight = message.getValueS32("height");
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // TODO: should we verify that the plugin sent back the right values?
- // Two size changes in a row may cause them to not match, due to queueing, etc.
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
- }
- else if(message_name == "cursor_changed")
- {
- mCursorName = message.getValue("name");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
- }
- else if(message_name == "edit_state")
- {
- if(message.hasValue("cut"))
- {
- mCanCut = message.getValueBoolean("cut");
- }
- if(message.hasValue("copy"))
- {
- mCanCopy = message.getValueBoolean("copy");
- }
- if(message.hasValue("paste"))
- {
- mCanPaste = message.getValueBoolean("paste");
- }
- }
- else if(message_name == "name_text")
- {
- mMediaName = message.getValue("name");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
- }
- else if(message_name == "pick_file")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
- }
- else if(message_name == "auth_request")
- {
- mAuthURL = message.getValue("url");
- mAuthRealm = message.getValue("realm");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
- {
- std::string message_name = message.getName();
- if(message_name == "navigate_begin")
- {
- mNavigateURI = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
- }
- else if(message_name == "navigate_complete")
- {
- mNavigateURI = message.getValue("uri");
- mNavigateResultCode = message.getValueS32("result_code");
- mNavigateResultString = message.getValue("result_string");
- mHistoryBackAvailable = message.getValueBoolean("history_back_available");
- mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
- }
- else if(message_name == "progress")
- {
- mProgressPercent = message.getValueS32("percent");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- else if(message_name == "status_text")
- {
- mStatusText = message.getValue("status");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
- }
- else if(message_name == "location_changed")
- {
- mLocation = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
- }
- else if(message_name == "click_href")
- {
- mClickURL = message.getValue("uri");
- mClickTarget = message.getValue("target");
- mClickUUID = message.getValue("uuid");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
- }
- else if(message_name == "click_nofollow")
- {
- mClickURL = message.getValue("uri");
- mClickNavType = message.getValue("nav_type");
- mClickTarget.clear();
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
- }
- else if(message_name == "navigate_error_page")
- {
- mStatusCode = message.getValueS32("status_code");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
- }
- else if(message_name == "cookie_set")
- {
- if(mOwner)
- {
- mOwner->handleCookieSet(this, message.getValue("cookie"));
- }
- }
- else if(message_name == "close_request")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
- }
- else if(message_name == "geometry_change")
- {
- mClickUUID = message.getValue("uuid");
- mGeometryX = message.getValueS32("x");
- mGeometryY = message.getValueS32("y");
- mGeometryWidth = message.getValueS32("width");
- mGeometryHeight = message.getValueS32("height");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
- }
- else if(message_name == "link_hovered")
- {
- // text is not currently used -- the tooltip hover text is taken from the "title".
- mHoverLink = message.getValue("link");
- mHoverText = message.getValue("title");
- // message.getValue("text");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- std::string message_name = message.getName();
-
- // This class hasn't defined any incoming messages yet.
-// if(message_name == "message_name")
-// {
-// }
-// else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
-
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginLaunchFailed()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginDied()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
-}
-
-void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
-{
- if(mOwner)
- {
- mOwner->handleMediaEvent(this, event);
- }
-}
-
-void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
-{
- if(mPlugin && mPlugin->isRunning())
- {
- mPlugin->sendMessage(message);
- }
- else
- {
- // The plugin isn't set up yet -- queue this message to be sent after initialization.
- mSendQueue.push(message);
- }
-}
-
-////////////////////////////////////////////////////////////
-// MARK: media_browser class functions
-bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
- return !version.empty();
-}
-
-void LLPluginClassMedia::focus(bool focused)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
-
- message.setValueBoolean("focused", focused);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cache()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cookies()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::set_cookies(const std::string &cookies)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
- message.setValue("cookies", cookies);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::enable_cookies(bool enable)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
- message.setValueBoolean("enable", enable);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
-
- message.setValueBoolean("enable", enable);
- message.setValue("host", host);
- message.setValueS32("port", port);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_reload(bool ignore_cache)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
-
- message.setValueBoolean("ignore_cache", ignore_cache);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_forward()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_back()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
-
- message.setValue("user_agent", user_agent);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
-
- message.setValue("target", target);
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
-
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
- message.setValueBoolean("ignore", ignore);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
- message.setValue("path", path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::crashPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::hangPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
-
- sendMessage(message);
-}
-
-
-////////////////////////////////////////////////////////////
-// MARK: media_time class functions
-bool LLPluginClassMedia::pluginSupportsMediaTime(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
- return !version.empty();
-}
-
-void LLPluginClassMedia::stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::start(float rate)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
-
- message.setValueReal("rate", rate);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::pause()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::seek(float time)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
-
- message.setValueReal("time", time);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLoop(bool loop)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
-
- message.setValueBoolean("loop", loop);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setVolume(float volume)
-{
- if(volume != mRequestedVolume)
- {
- mRequestedVolume = volume;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
-
- message.setValueReal("volume", volume);
-
- sendMessage(message);
- }
-}
-
-float LLPluginClassMedia::getVolume()
-{
- return mRequestedVolume;
-}
-
-void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
-{
- // Send URL history to plugin
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
- message.setValueLLSD("history", url_history);
- sendMessage(message);
-
- LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
-}
-
+/**
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
+
+ return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+ mOwner = owner;
+ mPlugin = NULL;
+ reset();
+
+ //debug use
+ mDeleteOK = true ;
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+ llassert_always(mDeleteOK) ;
+ reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
+{
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+
+ mPlugin = new LLPluginProcessParent(this);
+ mPlugin->setSleepTime(mSleepTime);
+
+ // Queue up the media init message -- it will be sent after all the currently queued messages.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+ message.setValue("target", mTarget);
+ sendMessage(message);
+
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+
+ return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+ if(mPlugin != NULL)
+ {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mRequestedTextureWidth = 0;
+ mRequestedTextureHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 1.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickNavType.clear();
+ mClickTarget.clear();
+ mClickUUID.clear();
+ mStatusCode = 0;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ memset( addr, 0x00, newsize );
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+ return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+ return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
+
+ setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
+
+ if(mRequestedMediaWidth > 2048)
+ mRequestedMediaWidth = 2048;
+
+ if(mRequestedMediaHeight > 2048)
+ mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
+
+ return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+ bool result = !mDirtyRect.isEmpty();
+
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+ mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+ std::string result;
+
+
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
+
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
+
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
+
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
+/*
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
+*/
+ return result;
+}
+
+void LLPluginClassMedia::jsEnableObject( bool enable )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+ message.setValueReal( "angle", angle );
+
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+ message.setValue( "language", language );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+ message.setValue( "region", region );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+ message.setValue( "maturity", maturity );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+ {
+ // Don't queue up mouse move events that can't be delivered.
+ return;
+ }
+
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("button", button);
+
+ message.setValueS32("x", x);
+
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
+{
+ bool result = true;
+
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
+
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
+
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
+
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+
+ return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+ message.setValue("uri", uri);
+
+ sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+ F64 result = 0.0f;
+
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+ message.setValue("file", file);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::cut()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+ message.setValue("path", user_data_path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+ message.setValue("language", language_code);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setTarget(const std::string &target)
+{
+ mTarget = target;
+}
+
+/* virtual */
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else if(message_name == "pick_file")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+ }
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+ mClickUUID = message.getValue("uuid");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickNavType = message.getValue("nav_type");
+ mClickTarget.clear();
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else if(message_name == "navigate_error_page")
+ {
+ mStatusCode = message.getValueS32("status_code");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+ }
+ else if(message_name == "cookie_set")
+ {
+ if(mOwner)
+ {
+ mOwner->handleCookieSet(this, message.getValue("cookie"));
+ }
+ }
+ else if(message_name == "close_request")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+ }
+ else if(message_name == "geometry_change")
+ {
+ mClickUUID = message.getValue("uuid");
+ mGeometryX = message.getValueS32("x");
+ mGeometryY = message.getValueS32("y");
+ mGeometryWidth = message.getValueS32("width");
+ mGeometryHeight = message.getValueS32("height");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+ }
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginDied()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+ message.setValueBoolean("focused", focused);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::set_cookies(const std::string &cookies)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
+ message.setValue("cookies", cookies);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+ message.setValueBoolean("enable", enable);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+ message.setValueBoolean("ignore_cache", ignore_cache);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+ message.setValue("user_agent", user_agent);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+
+ message.setValue("target", target);
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+ sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+ message.setValueReal("rate", rate);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+ message.setValueReal("time", time);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+ message.setValueBoolean("loop", loop);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+ message.setValueReal("volume", volume);
+
+ sendMessage(message);
+ }
+}
+
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
+
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index f8ed89f644..e7f303275e 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -1,425 +1,425 @@
-/**
- * @file llpluginclassmedia.h
- * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#ifndef LL_LLPLUGINCLASSMEDIA_H
-#define LL_LLPLUGINCLASSMEDIA_H
-
-#include "llgltypes.h"
-#include "llpluginprocessparent.h"
-#include "llrect.h"
-#include "llpluginclassmediaowner.h"
-#include <queue>
-#include "v4color.h"
-
-class LLPluginClassMedia : public LLPluginProcessParentOwner
-{
- LOG_CLASS(LLPluginClassMedia);
-public:
- LLPluginClassMedia(LLPluginClassMediaOwner *owner);
- virtual ~LLPluginClassMedia();
-
- // local initialization, called by the media manager when creating a source
- virtual bool init(const std::string &launcher_filename,
- const std::string &plugin_dir,
- const std::string &plugin_filename,
- bool debug);
-
- // undoes everything init() didm called by the media manager when destroying a source
- virtual void reset();
-
- void idle(void);
-
- // All of these may return 0 or an actual valid value.
- // Callers need to check the return for 0, and not use the values in that case.
- int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
- int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
- int getNaturalWidth() const { return mNaturalMediaWidth; };
- int getNaturalHeight() const { return mNaturalMediaHeight; };
- int getSetWidth() const { return mSetMediaWidth; };
- int getSetHeight() const { return mSetMediaHeight; };
- int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
- int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
- int getTextureWidth() const;
- int getTextureHeight() const;
- int getFullWidth() const { return mFullMediaWidth; };
- int getFullHeight() const { return mFullMediaHeight; };
-
- // This may return NULL. Callers need to check for and handle this case.
- unsigned char* getBitsData();
-
- // gets the format details of the texture data
- // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
- int getTextureDepth() const { return mRequestedTextureDepth; };
- int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
- int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
- int getTextureFormatType() const { return mRequestedTextureType; };
- bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
- bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
-
- void setSize(int width, int height);
- void setAutoScale(bool auto_scale);
-
- void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
-
- void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
-
- // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
- // This will initially be false, and will also be false for some time after setSize while the resize is processed.
- // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
- // until you call idle() again.
- bool textureValid(void);
-
- bool getDirty(LLRect *dirty_rect = NULL);
- void resetDirty(void);
-
- typedef enum
- {
- MOUSE_EVENT_DOWN,
- MOUSE_EVENT_UP,
- MOUSE_EVENT_MOVE,
- MOUSE_EVENT_DOUBLE_CLICK
- }EMouseEventType;
-
- void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
-
- typedef enum
- {
- KEY_EVENT_DOWN,
- KEY_EVENT_UP,
- KEY_EVENT_REPEAT
- }EKeyEventType;
-
- bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
-
- void scrollEvent(int x, int y, MASK modifiers);
-
- // Javascript <-> viewer events
- void jsEnableObject( bool enable );
- void jsAgentLocationEvent( double x, double y, double z );
- void jsAgentGlobalLocationEvent( double x, double y, double z );
- void jsAgentOrientationEvent( double angle );
- void jsAgentLanguageEvent( const std::string& language );
- void jsAgentRegionEvent( const std::string& region_name );
- void jsAgentMaturityEvent( const std::string& maturity );
-
- // Text may be unicode (utf8 encoded)
- bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-
- void loadURI(const std::string &uri);
-
- // "Loading" means uninitialized or any state prior to fully running (processing commands)
- bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
-
- // "Running" means the steady state -- i.e. processing messages
- bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
-
- // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
- bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
-
- std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
-
- bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
- void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
-
- // Inherited from LLPluginProcessParentOwner
- /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
- /* virtual */ void pluginLaunchFailed();
- /* virtual */ void pluginDied();
-
-
- typedef enum
- {
- PRIORITY_UNLOADED, // media plugin isn't even loaded.
- PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
- PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
- PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
- PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
- PRIORITY_NORMAL, // normal (default) priority
- PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
- }EPriority;
-
- static const char* priorityToString(EPriority priority);
- void setPriority(EPriority priority);
- void setLowPrioritySizeLimit(int size);
-
- F64 getCPUUsage();
-
- void sendPickFileResponse(const std::string &file);
-
- void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
-
- // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
- std::string getCursorName() const { return mCursorName; };
-
- LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
-
- void cut();
- bool canCut() const { return mCanCut; };
-
- void copy();
- bool canCopy() const { return mCanCopy; };
-
- void paste();
- bool canPaste() const { return mCanPaste; };
-
- // These can be called before init(), and they will be queued and sent before the media init message.
- void setUserDataPath(const std::string &user_data_path);
- void setLanguageCode(const std::string &language_code);
- void setPluginsEnabled(const bool enabled);
- void setJavascriptEnabled(const bool enabled);
- void setTarget(const std::string &target);
-
- ///////////////////////////////////
- // media browser class functions
- bool pluginSupportsMediaBrowser(void);
-
- void focus(bool focused);
- void clear_cache();
- void clear_cookies();
- void set_cookies(const std::string &cookies);
- void enable_cookies(bool enable);
- void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
- void browse_stop();
- void browse_reload(bool ignore_cache = false);
- void browse_forward();
- void browse_back();
- void setBrowserUserAgent(const std::string& user_agent);
- void proxyWindowOpened(const std::string &target, const std::string &uuid);
- void proxyWindowClosed(const std::string &uuid);
- void ignore_ssl_cert_errors(bool ignore);
- void addCertificateFilePath(const std::string& path);
-
- // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
- std::string getNavigateURI() const { return mNavigateURI; };
-
- // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
- S32 getNavigateResultCode() const { return mNavigateResultCode; };
- std::string getNavigateResultString() const { return mNavigateResultString; };
- bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
- bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
-
- // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
- int getProgressPercent() const { return mProgressPercent; };
-
- // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
- std::string getStatusText() const { return mStatusText; };
-
- // This is valid after MEDIA_EVENT_LOCATION_CHANGED
- std::string getLocation() const { return mLocation; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickURL() const { return mClickURL; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickNavType() const { return mClickNavType; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
- std::string getClickTarget() const { return mClickTarget; };
-
- // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
- std::string getClickUUID() const { return mClickUUID; };
-
- // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
- S32 getStatusCode() const { return mStatusCode; };
-
- // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
- S32 getGeometryX() const { return mGeometryX; };
- S32 getGeometryY() const { return mGeometryY; };
- S32 getGeometryWidth() const { return mGeometryWidth; };
- S32 getGeometryHeight() const { return mGeometryHeight; };
-
- // These are valid during MEDIA_EVENT_AUTH_REQUEST
- std::string getAuthURL() const { return mAuthURL; };
- std::string getAuthRealm() const { return mAuthRealm; };
-
- // These are valid during MEDIA_EVENT_LINK_HOVERED
- std::string getHoverText() const { return mHoverText; };
- std::string getHoverLink() const { return mHoverLink; };
-
- std::string getMediaName() const { return mMediaName; };
- std::string getMediaDescription() const { return mMediaDescription; };
-
- // Crash the plugin. If you use this outside of a testbed, you will be punished.
- void crashPlugin();
-
- // Hang the plugin. If you use this outside of a testbed, you will be punished.
- void hangPlugin();
-
- ///////////////////////////////////
- // media time class functions
- bool pluginSupportsMediaTime(void);
- void stop();
- void start(float rate = 0.0f);
- void pause();
- void seek(float time);
- void setLoop(bool loop);
- void setVolume(float volume);
- float getVolume();
-
- F64 getCurrentTime(void) const { return mCurrentTime; };
- F64 getDuration(void) const { return mDuration; };
- F64 getCurrentPlayRate(void) { return mCurrentRate; };
- F64 getLoadedDuration(void) const { return mLoadedDuration; };
-
- // Initialize the URL history of the plugin by sending
- // "init_history" message
- void initializeUrlHistory(const LLSD& url_history);
-
-protected:
-
- LLPluginClassMediaOwner *mOwner;
-
- // Notify this object's owner that an event has occurred.
- void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
-
- void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
- std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
-
- void setSizeInternal(void);
-
- bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
- S32 mRequestedTextureDepth;
- LLGLenum mRequestedTextureInternalFormat;
- LLGLenum mRequestedTextureFormat;
- LLGLenum mRequestedTextureType;
- bool mRequestedTextureSwapBytes;
- bool mRequestedTextureCoordsOpenGL;
-
- std::string mTextureSharedMemoryName;
- size_t mTextureSharedMemorySize;
-
- // True to scale requested media up to the full size of the texture (i.e. next power of two)
- bool mAutoScaleMedia;
-
- // default media size for the plugin, from the texture_params message.
- int mDefaultMediaWidth;
- int mDefaultMediaHeight;
-
- // Size that has been requested by the plugin itself
- int mNaturalMediaWidth;
- int mNaturalMediaHeight;
-
- // Size that has been requested with setSize()
- int mSetMediaWidth;
- int mSetMediaHeight;
-
- // Full calculated media size (before auto-scale and downsample calculations)
- int mFullMediaWidth;
- int mFullMediaHeight;
-
- // Actual media size being set (after auto-scale)
- int mRequestedMediaWidth;
- int mRequestedMediaHeight;
-
- // Texture size calculated from actual media size
- int mRequestedTextureWidth;
- int mRequestedTextureHeight;
-
- // Size that the plugin has acknowledged
- int mTextureWidth;
- int mTextureHeight;
- int mMediaWidth;
- int mMediaHeight;
-
- float mRequestedVolume;
-
- // Priority of this media stream
- EPriority mPriority;
- int mLowPrioritySizeLimit;
-
- bool mAllowDownsample;
- int mPadding;
-
-
- LLPluginProcessParent *mPlugin;
-
- LLRect mDirtyRect;
-
- std::string translateModifiers(MASK modifiers);
-
- std::string mCursorName;
- int mLastMouseX;
- int mLastMouseY;
-
- LLPluginClassMediaOwner::EMediaStatus mStatus;
-
- F64 mSleepTime;
-
- bool mCanCut;
- bool mCanCopy;
- bool mCanPaste;
-
- std::string mMediaName;
- std::string mMediaDescription;
-
- LLColor4 mBackgroundColor;
-
- std::string mTarget;
-
- /////////////////////////////////////////
- // media_browser class
- std::string mNavigateURI;
- S32 mNavigateResultCode;
- std::string mNavigateResultString;
- bool mHistoryBackAvailable;
- bool mHistoryForwardAvailable;
- std::string mStatusText;
- int mProgressPercent;
- std::string mLocation;
- std::string mClickURL;
- std::string mClickNavType;
- std::string mClickTarget;
- std::string mClickUUID;
- S32 mGeometryX;
- S32 mGeometryY;
- S32 mGeometryWidth;
- S32 mGeometryHeight;
- S32 mStatusCode;
- std::string mAuthURL;
- std::string mAuthRealm;
- std::string mHoverText;
- std::string mHoverLink;
-
- /////////////////////////////////////////
- // media_time class
- F64 mCurrentTime;
- F64 mDuration;
- F64 mCurrentRate;
- F64 mLoadedDuration;
-
-//--------------------------------------
- //debug use only
- //
-private:
- bool mDeleteOK ;
-public:
- void setDeleteOK(bool flag) { mDeleteOK = flag ;}
-//--------------------------------------
-};
-
-#endif // LL_LLPLUGINCLASSMEDIA_H
+/**
+ * @file llpluginclassmedia.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIA_H
+#define LL_LLPLUGINCLASSMEDIA_H
+
+#include "llgltypes.h"
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include "llpluginclassmediaowner.h"
+#include <queue>
+#include "v4color.h"
+
+class LLPluginClassMedia : public LLPluginProcessParentOwner
+{
+ LOG_CLASS(LLPluginClassMedia);
+public:
+ LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+ virtual ~LLPluginClassMedia();
+
+ // local initialization, called by the media manager when creating a source
+ virtual bool init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
+ const std::string &plugin_filename,
+ bool debug);
+
+ // undoes everything init() didm called by the media manager when destroying a source
+ virtual void reset();
+
+ void idle(void);
+
+ // All of these may return 0 or an actual valid value.
+ // Callers need to check the return for 0, and not use the values in that case.
+ int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+ int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+ int getNaturalWidth() const { return mNaturalMediaWidth; };
+ int getNaturalHeight() const { return mNaturalMediaHeight; };
+ int getSetWidth() const { return mSetMediaWidth; };
+ int getSetHeight() const { return mSetMediaHeight; };
+ int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+ int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+ int getTextureWidth() const;
+ int getTextureHeight() const;
+ int getFullWidth() const { return mFullMediaWidth; };
+ int getFullHeight() const { return mFullMediaHeight; };
+
+ // This may return NULL. Callers need to check for and handle this case.
+ unsigned char* getBitsData();
+
+ // gets the format details of the texture data
+ // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
+ int getTextureDepth() const { return mRequestedTextureDepth; };
+ int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+ int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+ int getTextureFormatType() const { return mRequestedTextureType; };
+ bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+ bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+ void setSize(int width, int height);
+ void setAutoScale(bool auto_scale);
+
+ void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+
+ void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+
+ // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+ // This will initially be false, and will also be false for some time after setSize while the resize is processed.
+ // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+ // until you call idle() again.
+ bool textureValid(void);
+
+ bool getDirty(LLRect *dirty_rect = NULL);
+ void resetDirty(void);
+
+ typedef enum
+ {
+ MOUSE_EVENT_DOWN,
+ MOUSE_EVENT_UP,
+ MOUSE_EVENT_MOVE,
+ MOUSE_EVENT_DOUBLE_CLICK
+ }EMouseEventType;
+
+ void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
+
+ typedef enum
+ {
+ KEY_EVENT_DOWN,
+ KEY_EVENT_UP,
+ KEY_EVENT_REPEAT
+ }EKeyEventType;
+
+ bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
+
+ void scrollEvent(int x, int y, MASK modifiers);
+
+ // Javascript <-> viewer events
+ void jsEnableObject( bool enable );
+ void jsAgentLocationEvent( double x, double y, double z );
+ void jsAgentGlobalLocationEvent( double x, double y, double z );
+ void jsAgentOrientationEvent( double angle );
+ void jsAgentLanguageEvent( const std::string& language );
+ void jsAgentRegionEvent( const std::string& region_name );
+ void jsAgentMaturityEvent( const std::string& maturity );
+
+ // Text may be unicode (utf8 encoded)
+ bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+
+ void loadURI(const std::string &uri);
+
+ // "Loading" means uninitialized or any state prior to fully running (processing commands)
+ bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
+
+ // "Running" means the steady state -- i.e. processing messages
+ bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
+
+ // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
+ bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
+
+ std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
+
+ bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
+ void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
+
+ // Inherited from LLPluginProcessParentOwner
+ /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
+ /* virtual */ void pluginDied();
+
+
+ typedef enum
+ {
+ PRIORITY_UNLOADED, // media plugin isn't even loaded.
+ PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
+ PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
+ PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
+ PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
+ PRIORITY_NORMAL, // normal (default) priority
+ PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
+ }EPriority;
+
+ static const char* priorityToString(EPriority priority);
+ void setPriority(EPriority priority);
+ void setLowPrioritySizeLimit(int size);
+
+ F64 getCPUUsage();
+
+ void sendPickFileResponse(const std::string &file);
+
+ void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
+ // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+ std::string getCursorName() const { return mCursorName; };
+
+ LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+ void cut();
+ bool canCut() const { return mCanCut; };
+
+ void copy();
+ bool canCopy() const { return mCanCopy; };
+
+ void paste();
+ bool canPaste() const { return mCanPaste; };
+
+ // These can be called before init(), and they will be queued and sent before the media init message.
+ void setUserDataPath(const std::string &user_data_path);
+ void setLanguageCode(const std::string &language_code);
+ void setPluginsEnabled(const bool enabled);
+ void setJavascriptEnabled(const bool enabled);
+ void setTarget(const std::string &target);
+
+ ///////////////////////////////////
+ // media browser class functions
+ bool pluginSupportsMediaBrowser(void);
+
+ void focus(bool focused);
+ void clear_cache();
+ void clear_cookies();
+ void set_cookies(const std::string &cookies);
+ void enable_cookies(bool enable);
+ void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+ void browse_stop();
+ void browse_reload(bool ignore_cache = false);
+ void browse_forward();
+ void browse_back();
+ void setBrowserUserAgent(const std::string& user_agent);
+ void proxyWindowOpened(const std::string &target, const std::string &uuid);
+ void proxyWindowClosed(const std::string &uuid);
+ void ignore_ssl_cert_errors(bool ignore);
+ void addCertificateFilePath(const std::string& path);
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+ std::string getNavigateURI() const { return mNavigateURI; };
+
+ // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+ S32 getNavigateResultCode() const { return mNavigateResultCode; };
+ std::string getNavigateResultString() const { return mNavigateResultString; };
+ bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+ bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+ // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+ int getProgressPercent() const { return mProgressPercent; };
+
+ // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+ std::string getStatusText() const { return mStatusText; };
+
+ // This is valid after MEDIA_EVENT_LOCATION_CHANGED
+ std::string getLocation() const { return mLocation; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickURL() const { return mClickURL; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickNavType() const { return mClickNavType; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ std::string getClickTarget() const { return mClickTarget; };
+
+ // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
+ std::string getClickUUID() const { return mClickUUID; };
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
+ S32 getStatusCode() const { return mStatusCode; };
+
+ // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
+ S32 getGeometryX() const { return mGeometryX; };
+ S32 getGeometryY() const { return mGeometryY; };
+ S32 getGeometryWidth() const { return mGeometryWidth; };
+ S32 getGeometryHeight() const { return mGeometryHeight; };
+
+ // These are valid during MEDIA_EVENT_AUTH_REQUEST
+ std::string getAuthURL() const { return mAuthURL; };
+ std::string getAuthRealm() const { return mAuthRealm; };
+
+ // These are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getHoverText() const { return mHoverText; };
+ std::string getHoverLink() const { return mHoverLink; };
+
+ std::string getMediaName() const { return mMediaName; };
+ std::string getMediaDescription() const { return mMediaDescription; };
+
+ // Crash the plugin. If you use this outside of a testbed, you will be punished.
+ void crashPlugin();
+
+ // Hang the plugin. If you use this outside of a testbed, you will be punished.
+ void hangPlugin();
+
+ ///////////////////////////////////
+ // media time class functions
+ bool pluginSupportsMediaTime(void);
+ void stop();
+ void start(float rate = 0.0f);
+ void pause();
+ void seek(float time);
+ void setLoop(bool loop);
+ void setVolume(float volume);
+ float getVolume();
+
+ F64 getCurrentTime(void) const { return mCurrentTime; };
+ F64 getDuration(void) const { return mDuration; };
+ F64 getCurrentPlayRate(void) { return mCurrentRate; };
+ F64 getLoadedDuration(void) const { return mLoadedDuration; };
+
+ // Initialize the URL history of the plugin by sending
+ // "init_history" message
+ void initializeUrlHistory(const LLSD& url_history);
+
+protected:
+
+ LLPluginClassMediaOwner *mOwner;
+
+ // Notify this object's owner that an event has occurred.
+ void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
+
+ void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
+ std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
+
+ void setSizeInternal(void);
+
+ bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
+ S32 mRequestedTextureDepth;
+ LLGLenum mRequestedTextureInternalFormat;
+ LLGLenum mRequestedTextureFormat;
+ LLGLenum mRequestedTextureType;
+ bool mRequestedTextureSwapBytes;
+ bool mRequestedTextureCoordsOpenGL;
+
+ std::string mTextureSharedMemoryName;
+ size_t mTextureSharedMemorySize;
+
+ // True to scale requested media up to the full size of the texture (i.e. next power of two)
+ bool mAutoScaleMedia;
+
+ // default media size for the plugin, from the texture_params message.
+ int mDefaultMediaWidth;
+ int mDefaultMediaHeight;
+
+ // Size that has been requested by the plugin itself
+ int mNaturalMediaWidth;
+ int mNaturalMediaHeight;
+
+ // Size that has been requested with setSize()
+ int mSetMediaWidth;
+ int mSetMediaHeight;
+
+ // Full calculated media size (before auto-scale and downsample calculations)
+ int mFullMediaWidth;
+ int mFullMediaHeight;
+
+ // Actual media size being set (after auto-scale)
+ int mRequestedMediaWidth;
+ int mRequestedMediaHeight;
+
+ // Texture size calculated from actual media size
+ int mRequestedTextureWidth;
+ int mRequestedTextureHeight;
+
+ // Size that the plugin has acknowledged
+ int mTextureWidth;
+ int mTextureHeight;
+ int mMediaWidth;
+ int mMediaHeight;
+
+ float mRequestedVolume;
+
+ // Priority of this media stream
+ EPriority mPriority;
+ int mLowPrioritySizeLimit;
+
+ bool mAllowDownsample;
+ int mPadding;
+
+
+ LLPluginProcessParent *mPlugin;
+
+ LLRect mDirtyRect;
+
+ std::string translateModifiers(MASK modifiers);
+
+ std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
+
+ LLPluginClassMediaOwner::EMediaStatus mStatus;
+
+ F64 mSleepTime;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+
+ std::string mMediaName;
+ std::string mMediaDescription;
+
+ LLColor4 mBackgroundColor;
+
+ std::string mTarget;
+
+ /////////////////////////////////////////
+ // media_browser class
+ std::string mNavigateURI;
+ S32 mNavigateResultCode;
+ std::string mNavigateResultString;
+ bool mHistoryBackAvailable;
+ bool mHistoryForwardAvailable;
+ std::string mStatusText;
+ int mProgressPercent;
+ std::string mLocation;
+ std::string mClickURL;
+ std::string mClickNavType;
+ std::string mClickTarget;
+ std::string mClickUUID;
+ S32 mGeometryX;
+ S32 mGeometryY;
+ S32 mGeometryWidth;
+ S32 mGeometryHeight;
+ S32 mStatusCode;
+ std::string mAuthURL;
+ std::string mAuthRealm;
+ std::string mHoverText;
+ std::string mHoverLink;
+
+ /////////////////////////////////////////
+ // media_time class
+ F64 mCurrentTime;
+ F64 mDuration;
+ F64 mCurrentRate;
+ F64 mLoadedDuration;
+
+//--------------------------------------
+ //debug use only
+ //
+private:
+ bool mDeleteOK ;
+public:
+ void setDeleteOK(bool flag) { mDeleteOK = flag ;}
+//--------------------------------------
+};
+
+#endif // LL_LLPLUGINCLASSMEDIA_H
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..34b4fc66e5 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>
+ <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>
- <integer>8</integer>
+ <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>
@@ -12584,7 +12640,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>WaterGLFogDensityScale</key>
<map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 60082f40d6..d327216a0c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -270,72 +270,41 @@ void main()
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
- calcAtmospherics(pos.xyz, 1.0);
+ vec3 col;
+ float bloom = 0.0;
+ if (diffuse.a < 0.9)
+ {
+ calcAtmospherics(pos.xyz, 1.0);
+
+ col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
- vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
+ col *= diffuse.rgb;
- col *= diffuse.rgb;
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib);
+ col += spec_contrib;
+ }
- if (spec.a > 0.0) // specular reflection
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ col = mix(col.rgb, diffuse.rgb, diffuse.a);
+ }
+ else
{
- // the old infinite-sky shiny reflection
- //
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
- float sa = dot(refnormpersp, vary_light.xyz);
- vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
-
- /*
- // screen-space cheap fakey reflection map
- //
- vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
- depth -= 0.5; // unbias depth
- // first figure out where we'll make our 2D guess from
- vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
- // Offset the guess source a little according to a trivial
- // checkerboard dither function and spec.a.
- // This is meant to be similar to sampling a blurred version
- // of the diffuse map. LOD would be better in that regard.
- // The goal of the blur is to soften reflections in surfaces
- // with low shinyness, and also to disguise our lameness.
- float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
- float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
- ref2d += vec2(checkoffset, checkoffset);
- ref2d += tc.xy; // use as offset from destination
- // Get attributes from the 2D guess point.
- // We average two samples of diffuse (not of anything else) per
- // pixel to try to reduce aliasing some more.
- vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
- texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
- float refdepth = texture2DRect(depthMap, ref2d).a;
- vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
- vec3 refn = texture2DRect(normalMap, ref2d).rgb;
- refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm
- // figure out how appropriate our guess actually was
- float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
- // darken reflections from points which face away from the reflected ray - our guess was a back-face
- //refapprop *= step(dot(refnorm, refn), 0.0);
- refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
- // get appropriate light strength for guess-point.
- // reflect light direction to increase the illusion that
- // these are reflections.
- vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
- float reflit = max(dot(refn, reflight.xyz), 0.0);
- // apply sun color to guess-point, dampen according to inappropriateness of guess
- float refmod = min(refapprop, reflit);
- vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
- vec3 ssshiny = (refprod * spec.a);
- ssshiny *= 0.3; // dampen it even more
- */
- vec3 ssshiny = vec3(0,0,0);
-
- // add the two types of shiny together
- col += (ssshiny + dumbshiny) * spec.rgb;
+ col = diffuse.rgb;
}
-
- col = atmosLighting(col);
- col = scaleSoftClip(col);
-
+
gl_FragColor.rgb = col;
- gl_FragColor.a = 0.0;
+ gl_FragColor.a = bloom;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
index 9dfacfb520..2cce43e2bf 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
@@ -266,7 +266,7 @@ void main()
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
- vec3 fcol = vec3(0,0,0);
+ vec4 fcol = vec4(0,0,0,0);
for (int i = 0; i < samples; ++i)
{
@@ -280,17 +280,16 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texelFetch(diffuseRect, itc, i);
- if (diffuse.a >= 1.0)
- {
- fcol += diffuse.rgb;
- }
- else
+ vec3 col;
+ float bloom = 0.0;
+
+ if (diffuse.a < 0.9)
{
vec4 spec = texelFetch(specularRect, itc, i);
calcAtmospherics(pos.xyz, 1.0);
- vec3 col = atmosAmbient(vec3(0));
+ col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
@@ -304,15 +303,22 @@ void main()
vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
- col += dumbshiny * spec.rgb;
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib);
+ col += spec_contrib;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
- fcol += col;
+ col = mix(col, diffuse.rgb, diffuse.a);
}
+ else
+ {
+ col = diffuse.rgb;
+ }
+
+ fcol += vec4(col, bloom);
}
- gl_FragColor.rgb = fcol.rgb/samples;
- gl_FragColor.a = 0.0;
+ gl_FragColor = fcol/samples;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl
index ae943cc438..5b7cc57574 100644
--- a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl
@@ -9,7 +9,7 @@ uniform sampler2D tex0;
void main()
{
- float alpha = texture2D(tex0, gl_TexCoord[0].xy).a;
+ float alpha = texture2D(tex0, gl_TexCoord[0].xy).a * gl_Color.a;
gl_FragColor = vec4(gl_Color.rgb, alpha);
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
index f44a5ce32e..5283e80407 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
@@ -10,8 +10,6 @@
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
-attribute vec4 object_weight;
-
void main()
{
mat4 mat = getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
index e5dafa8c78..1db79791de 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
@@ -10,8 +10,6 @@
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
-attribute vec4 object_weight;
-
void main()
{
//transform vertex
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
index cd655f3bb5..eea41bb4f0 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
@@ -11,8 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
-attribute vec4 object_weight;
-
void main()
{
mat4 mat = getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
index 900448035c..af92e5e002 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
@@ -11,8 +11,6 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
-attribute vec4 object_weight;
-
void main()
{
//transform vertex
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 66a1a8515f..f0c9b01671 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -267,34 +267,49 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texture2DRect(diffuseRect, tc);
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- float scol = max(scol_ambocc.r, diffuse.a);
- float ambocc = scol_ambocc.g;
+
+ vec3 col;
+ float bloom = 0.0;
+
+ if (diffuse.a < 0.9)
+ {
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, ambocc);
- vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+ col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
- col *= diffuse.rgb;
+ col *= diffuse.rgb;
- if (spec.a > 0.0) // specular reflection
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib);
+ col += spec_contrib;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ col = mix(col, diffuse.rgb, diffuse.a);
+ }
+ else
{
- // the old infinite-sky shiny reflection
- //
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
- float sa = dot(refnormpersp, vary_light.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
-
- // add the two types of shiny together
- col += dumbshiny * spec.rgb;
+ col = diffuse.rgb;
}
-
- col = atmosLighting(col);
- col = scaleSoftClip(col);
gl_FragColor.rgb = col;
- gl_FragColor.a = 0.0;
+ gl_FragColor.a = bloom;
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
index 0bae10ca7d..3b572320c3 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
@@ -255,7 +255,7 @@ void main()
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
- vec3 fcol = vec3(0,0,0);
+ vec4 fcol = vec4(0,0,0,0);
vec2 scol_ambocc = texture2DRect(lightMap, tc).rg;
float ambocc = scol_ambocc.g;
@@ -270,38 +270,50 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texelFetch(diffuseRect, itc, i);
- vec4 spec = texelFetch(specularRect, itc, i);
+ vec3 col;
+ float bloom = 0.0;
+ if (diffuse.a < 0.9)
+ {
+ vec4 spec = texelFetch(specularRect, itc, i);
- float amb = 0;
+ float amb = 0;
- float scol = max(scol_ambocc.r, diffuse.a);
- amb += ambocc;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ amb += ambocc;
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, ambocc);
+
+ col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
- vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+ col *= diffuse.rgb;
- col *= diffuse.rgb;
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib);
+ col += spec_contrib;
+ }
- if (spec.a > 0.0) // specular reflection
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ col = mix(col, diffuse.rgb, diffuse.a);
+ }
+ else
{
- // the old infinite-sky shiny reflection
- //
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
- float sa = dot(refnormpersp, vary_light.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
-
- // add the two types of shiny together
- col += dumbshiny * spec.rgb;
+ col = diffuse.rgb;
}
-
- col = atmosLighting(col);
- col = scaleSoftClip(col);
- fcol += col;
+ fcol += vec4(col, bloom);
}
- gl_FragColor.rgb = fcol/samples;
- gl_FragColor.a = 0.0;
+ gl_FragColor = fcol/samples;
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index d38d33cc21..1ae10a5faa 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -268,91 +268,50 @@ void main()
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texture2DRect(diffuseRect, tc);
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec3 col;
+ float bloom = 0.0;
+
+ if (diffuse.a < 0.9)
+ {
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
- da = texture2D(lightFunc, vec2(da, 0.0)).a;
+ da = texture2D(lightFunc, vec2(da, 0.0)).a;
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- float scol = max(scol_ambocc.r, diffuse.a);
- float ambocc = scol_ambocc.g;
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, ambocc);
- vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+ col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
- col *= diffuse.rgb;
+ col *= diffuse.rgb;
- if (spec.a > 0.0) // specular reflection
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib);
+ col += spec_contrib;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ col = mix(col, diffuse.rgb, diffuse.a);
+ }
+ else
{
- // the old infinite-sky shiny reflection
- //
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
- float sa = dot(refnormpersp, vary_light.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a;
-
- /*
- // screen-space cheap fakey reflection map
- //
- vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
- depth -= 0.5; // unbias depth
- // first figure out where we'll make our 2D guess from
- vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
- // Offset the guess source a little according to a trivial
- // checkerboard dither function and spec.a.
- // This is meant to be similar to sampling a blurred version
- // of the diffuse map. LOD would be better in that regard.
- // The goal of the blur is to soften reflections in surfaces
- // with low shinyness, and also to disguise our lameness.
- float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
- float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
-
- ref2d += vec2(checkoffset, checkoffset);
- ref2d += tc.xy; // use as offset from destination
- // Get attributes from the 2D guess point.
- // We average two samples of diffuse (not of anything else) per
- // pixel to try to reduce aliasing some more.
- vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
- texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
- float refdepth = texture2DRect(depthMap, ref2d).a;
- vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
- float refshad = texture2DRect(lightMap, ref2d).r;
- vec3 refn = texture2DRect(normalMap, ref2d).rgb;
- refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
- refn = normalize(refn);
- // figure out how appropriate our guess actually was
- float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
- // darken reflections from points which face away from the reflected ray - our guess was a back-face
- //refapprop *= step(dot(refnorm, refn), 0.0);
- refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
- // get appropriate light strength for guess-point.
- // reflect light direction to increase the illusion that
- // these are reflections.
- vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
- float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
- // apply sun color to guess-point, dampen according to inappropriateness of guess
- float refmod = min(refapprop, reflit);
- vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
- vec3 ssshiny = (refprod * spec.a);
- ssshiny *= 0.3; // dampen it even more
- */
- vec3 ssshiny = vec3(0,0,0);
-
- // add the two types of shiny together
- col += (ssshiny + dumbshiny) * spec.rgb;
+ col = diffuse.rgb;
}
-
- col = atmosLighting(col);
- col = scaleSoftClip(col);
gl_FragColor.rgb = col;
-
- //gl_FragColor.rgb = gi_col.rgb;
- gl_FragColor.a = 0.0;
-
- //gl_FragColor.rg = scol_ambocc.rg;
- //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
- //gl_FragColor.rgb = norm.rgb*0.5+0.5;
- //gl_FragColor.rgb = vec3(ambocc);
- //gl_FragColor.rgb = vec3(scol);
+ gl_FragColor.a = bloom;
}
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/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index f9fd501072..a219386b53 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -62,13 +62,24 @@ LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
llerrs << "Error: Failed to load cloud noise image " << cloudNoiseFilename << llendl;
}
- cloudNoiseFile->load(cloudNoiseFilename);
-
- sCloudNoiseRawImage = new LLImageRaw();
+ if(cloudNoiseFile->load(cloudNoiseFilename))
+ {
+ sCloudNoiseRawImage = new LLImageRaw();
- cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f);
+ if(cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f))
+ {
+ //debug use
+ lldebugs << "cloud noise raw image width: " << sCloudNoiseRawImage->getWidth() << " : height: " << sCloudNoiseRawImage->getHeight() << " : components: " <<
+ (S32)sCloudNoiseRawImage->getComponents() << " : data size: " << sCloudNoiseRawImage->getDataSize() << llendl ;
+ llassert_always(sCloudNoiseRawImage->getData()) ;
- sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
+ sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
+ }
+ else
+ {
+ sCloudNoiseRawImage = NULL ;
+ }
+ }
LLWLParamManager::getInstance()->propagateParameters();
}
@@ -218,7 +229,7 @@ void LLDrawPoolWLSky::renderStars(void) const
void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
{
- if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS))
+ if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && sCloudNoiseTexture.notNull())
{
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -399,5 +410,8 @@ void LLDrawPoolWLSky::cleanupGL()
//static
void LLDrawPoolWLSky::restoreGL()
{
- sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
+ if(sCloudNoiseRawImage.notNull())
+ {
+ sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
+ }
}
diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp
index c2720eaf28..86fe6754dc 100644
--- a/indra/newview/llenvmanager.cpp
+++ b/indra/newview/llenvmanager.cpp
@@ -2,31 +2,25 @@
* @file llenvmanager.cpp
* @brief Implementation of classes managing WindLight and water settings.
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h
index 96af102c1a..ad56761bc7 100644
--- a/indra/newview/llenvmanager.h
+++ b/indra/newview/llenvmanager.h
@@ -2,31 +2,25 @@
* @file llenvmanager.h
* @brief Declaration of classes managing WindLight and water settings.
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
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(&params);
+ param_count = decomp->getParameters(&params);
}
- 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/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
index af74f8f261..9f05a61812 100644
--- a/indra/newview/llpanelmarketplaceinbox.cpp
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -1,248 +1,248 @@
-/**
- * @file llpanelmarketplaceinbox.cpp
- * @brief Panel for marketplace inbox
- *
-* $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llpanelmarketplaceinbox.h"
-
-#include "llappviewer.h"
-#include "llbutton.h"
-#include "llinventorypanel.h"
-#include "llfolderview.h"
-#include "llsidepanelinventory.h"
-
-
-#define SUPPORTING_FRESH_ITEM_COUNT 0
-
-
-static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
-
-const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams()
-{
- return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>();
-}
-
-// protected
-LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
- : LLPanel(p)
- , mInventoryPanel(NULL)
-{
-}
-
-LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
-{
-}
-
-// virtual
-BOOL LLPanelMarketplaceInbox::postBuild()
-{
- LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
-
- LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
-
- return TRUE;
-}
-
-void LLPanelMarketplaceInbox::onSelectionChange()
-{
- LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
-
- sidepanel_inventory->updateVerbs();
-}
-
-
-void LLPanelMarketplaceInbox::handleLoginComplete()
-{
- // Set us up as the class to drive the badge value for the sidebar_inventory button
- LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
-}
-
-void LLPanelMarketplaceInbox::setupInventoryPanel()
-{
- LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
- LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
-
- mInventoryPanel =
- LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
- inbox_inventory_parent,
- LLInventoryPanel::child_registry_t::instance());
-
- // Reshape the inventory to the proper size
- LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
- mInventoryPanel->setShape(inventory_placeholder_rect);
-
- // Set the sort order newest to oldest, and a selection change callback
- mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
- mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
-
- // Set up the note to display when the inbox is empty
- mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
-
- // Hide the placeholder text
- inbox_inventory_placeholder->setVisible(FALSE);
-}
-
-void LLPanelMarketplaceInbox::onFocusReceived()
-{
- LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
-
- if (sidepanel_inventory)
- {
- LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
-
- if (inv_panel)
- {
- inv_panel->clearSelection();
- }
-
- LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
-
- if (outbox_panel)
- {
- outbox_panel->clearSelection();
- }
-
- sidepanel_inventory->updateVerbs();
- }
-}
-
-BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
-{
- *accept = ACCEPT_NO;
- return TRUE;
-}
-
-U32 LLPanelMarketplaceInbox::getFreshItemCount() const
-{
-#if SUPPORTING_FRESH_ITEM_COUNT
-
- //
- // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
- // will return "2" for the Inventory and LIBRARY top-levels when that happens.
- //
-
- U32 fresh_item_count = 0;
-
- if (mInventoryPanel)
- {
- const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
-
- if (inbox_folder)
- {
- LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin();
- LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd();
-
- for (; folders_it != folders_end; ++folders_it)
- {
- const LLFolderViewFolder * folder = *folders_it;
-
- // TODO: Replace this check with new "fresh" flag
- if (folder->getCreationDate() > 1500)
- {
- fresh_item_count++;
- }
- }
- }
- }
-
- return fresh_item_count;
-#else
- return getTotalItemCount();
-#endif
-}
-
-U32 LLPanelMarketplaceInbox::getTotalItemCount() const
-{
- U32 item_count = 0;
-
- if (mInventoryPanel)
- {
- const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
-
- if (inbox_folder)
- {
- item_count += inbox_folder->getFoldersCount();
- }
- }
-
- return item_count;
-}
-
-std::string LLPanelMarketplaceInbox::getBadgeString() const
-{
- std::string item_count_str("");
-
- // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
- if (getParent()->getVisible() &&
- (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
- {
- U32 item_count = getFreshItemCount();
-
- if (item_count)
- {
- item_count_str = llformat("%d", item_count);
- }
- }
-
- return item_count_str;
-}
-
-void LLPanelMarketplaceInbox::draw()
-{
- U32 item_count = getTotalItemCount();
-
- LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
-
- if (item_count > 0)
- {
- std::string item_count_str = llformat("%d", item_count);
-
- LLStringUtil::format_map_t args;
- args["[NUM]"] = item_count_str;
- getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
-
-#if SUPPORTING_FRESH_ITEM_COUNT
- // set green text to fresh item count
- U32 fresh_item_count = getFreshItemCount();
- fresh_new_count_view->setVisible((fresh_item_count > 0));
-
- if (fresh_item_count > 0)
- {
- getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
- }
-#else
- fresh_new_count_view->setVisible(FALSE);
-#endif
- }
- else
- {
- getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
-
- fresh_new_count_view->setVisible(FALSE);
- }
-
- LLPanel::draw();
-}
+/**
+ * @file llpanelmarketplaceinbox.cpp
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+#include "llsidepanelinventory.h"
+
+
+#define SUPPORTING_FRESH_ITEM_COUNT 0
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
+
+const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>();
+}
+
+// protected
+LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+{
+}
+
+LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceInbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceInbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+
+void LLPanelMarketplaceInbox::handleLoginComplete()
+{
+ // Set us up as the class to drive the badge value for the sidebar_inventory button
+ LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
+}
+
+void LLPanelMarketplaceInbox::setupInventoryPanel()
+{
+ LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
+ LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
+ inbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
+
+ // Set up the note to display when the inbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
+
+ // Hide the placeholder text
+ inbox_inventory_placeholder->setVisible(FALSE);
+}
+
+void LLPanelMarketplaceInbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ if (sidepanel_inventory)
+ {
+ LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+ if (inv_panel)
+ {
+ inv_panel->clearSelection();
+ }
+
+ LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+ if (outbox_panel)
+ {
+ outbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+ }
+}
+
+BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+ *accept = ACCEPT_NO;
+ return TRUE;
+}
+
+U32 LLPanelMarketplaceInbox::getFreshItemCount() const
+{
+#if SUPPORTING_FRESH_ITEM_COUNT
+
+ //
+ // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
+ // will return "2" for the Inventory and LIBRARY top-levels when that happens.
+ //
+
+ U32 fresh_item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin();
+ LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd();
+
+ for (; folders_it != folders_end; ++folders_it)
+ {
+ const LLFolderViewFolder * folder = *folders_it;
+
+ // TODO: Replace this check with new "fresh" flag
+ if (folder->getCreationDate() > 1500)
+ {
+ fresh_item_count++;
+ }
+ }
+ }
+ }
+
+ return fresh_item_count;
+#else
+ return getTotalItemCount();
+#endif
+}
+
+U32 LLPanelMarketplaceInbox::getTotalItemCount() const
+{
+ U32 item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ item_count += inbox_folder->getFoldersCount();
+ }
+ }
+
+ return item_count;
+}
+
+std::string LLPanelMarketplaceInbox::getBadgeString() const
+{
+ std::string item_count_str("");
+
+ // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
+ if (getParent()->getVisible() &&
+ (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
+ {
+ U32 item_count = getFreshItemCount();
+
+ if (item_count)
+ {
+ item_count_str = llformat("%d", item_count);
+ }
+ }
+
+ return item_count_str;
+}
+
+void LLPanelMarketplaceInbox::draw()
+{
+ U32 item_count = getTotalItemCount();
+
+ LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+
+ if (item_count > 0)
+ {
+ std::string item_count_str = llformat("%d", item_count);
+
+ LLStringUtil::format_map_t args;
+ args["[NUM]"] = item_count_str;
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+
+#if SUPPORTING_FRESH_ITEM_COUNT
+ // set green text to fresh item count
+ U32 fresh_item_count = getFreshItemCount();
+ fresh_new_count_view->setVisible((fresh_item_count > 0));
+
+ if (fresh_item_count > 0)
+ {
+ getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+ }
+#else
+ fresh_new_count_view->setVisible(FALSE);
+#endif
+ }
+ else
+ {
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+
+ fresh_new_count_view->setVisible(FALSE);
+ }
+
+ LLPanel::draw();
+}
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/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index 252183b6d7..12f6a0dd1c 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -120,8 +120,8 @@
// Library includes from llvfs
#include "lldir.h"
-
-// Library includes from llmessage project
+
+// Library includes from llmessage project
#include "llcachename.h"
#endif
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/llvosky.cpp b/indra/newview/llvosky.cpp
index 66ba6249d3..ef21e7373e 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -755,6 +755,11 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo
// project the direction ray onto the sky dome.
F32 phi = acos(Pn[1]);
F32 sinA = sin(F_PI - phi);
+ if (fabsf(sinA) < 0.01f)
+ { //avoid division by zero
+ sinA = 0.01f;
+ }
+
F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA;
Pn *= Plen;
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 &params_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/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index b5f53232cc..2425b96678 100644
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -2,31 +2,25 @@
* @file llwlhandlers.cpp
* @brief Various classes which handle Windlight-related messaging
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
index 213bc7c7ce..23558876da 100644
--- a/indra/newview/llwlhandlers.h
+++ b/indra/newview/llwlhandlers.h
@@ -2,31 +2,25 @@
* @file llwlhandlers.h
* @brief Headers for classes in llwlhandlers.cpp
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index dfcc7396ba..4899df13e5 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3741,52 +3741,55 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
LLVertexBuffer::unbind();
LLGLState::checkStates();
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
-
- if (!sReflectionRender)
+ if (!LLPipeline::sImpostorRender)
{
- renderHighlights();
- }
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
- // Contains a list of the faces of objects that are physical or
- // have touch-handlers.
- mHighlightFaces.clear();
+ if (!sReflectionRender)
+ {
+ renderHighlights();
+ }
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
+ // Contains a list of the faces of objects that are physical or
+ // have touch-handlers.
+ mHighlightFaces.clear();
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
- renderDebug();
+ renderDebug();
- LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
- if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
- {
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
{
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ gObjectList.resetObjectBeacons();
+ }
+ else
+ {
+ // Make sure particle effects disappear
+ LLHUDObject::renderAllForTimer();
+ }
}
else
{
// Make sure particle effects disappear
LLHUDObject::renderAllForTimer();
}
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::renderAllForTimer();
- }
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
- //HACK: preserve/restore matrices around HUD render
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- for (U32 i = 0; i < 16; i++)
+ //HACK: preserve/restore matrices around HUD render
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{
- gGLModelView[i] = saved_modelview[i];
- gGLProjection[i] = saved_projection[i];
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLModelView[i] = saved_modelview[i];
+ gGLProjection[i] = saved_projection[i];
+ }
}
}
@@ -4220,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 &amp; fee"
+ width="150" name="calculate_btn" tool_tip="Calculate weights &amp; 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="&lt;&lt; Back" />
<button
top_delta="0"
- right="-150"
+ right="-190"
width="90"
height="22"
name="next"
label="Next &gt;&gt; " />
<button
top_delta="0"
+ left_delta="0"
+ width="160"
+ height="22"
+ name="calculate"
+ label="Calculate weights &amp; fee &gt;&gt; " />
+ <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 &apos;[CAPABILITY]&apos;.
+ </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 9b1cfa8f51..f049f857f0 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/indra/newview/tests/lldir_stub.cpp b/indra/newview/tests/lldir_stub.cpp
index 6646860b5e..18cf4e7419 100644
--- a/indra/newview/tests/lldir_stub.cpp
+++ b/indra/newview/tests/lldir_stub.cpp
@@ -2,8 +2,25 @@
* @file lldir_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llglslshader_stub.cpp b/indra/newview/tests/llglslshader_stub.cpp
index 5333c8a361..8947a632c8 100644
--- a/indra/newview/tests/llglslshader_stub.cpp
+++ b/indra/newview/tests/llglslshader_stub.cpp
@@ -2,8 +2,25 @@
* @file llglslshader_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llpipeline_stub.cpp b/indra/newview/tests/llpipeline_stub.cpp
index 85bf0ae3fb..ad112cbf6a 100644
--- a/indra/newview/tests/llpipeline_stub.cpp
+++ b/indra/newview/tests/llpipeline_stub.cpp
@@ -2,8 +2,25 @@
* @file llpipeline_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llsky_stub.cpp b/indra/newview/tests/llsky_stub.cpp
index 35f4944a95..241d740635 100644
--- a/indra/newview/tests/llsky_stub.cpp
+++ b/indra/newview/tests/llsky_stub.cpp
@@ -2,8 +2,25 @@
* @file llsky_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llviewershadermgr_stub.cpp b/indra/newview/tests/llviewershadermgr_stub.cpp
index 0dae527035..18eff72f3c 100644
--- a/indra/newview/tests/llviewershadermgr_stub.cpp
+++ b/indra/newview/tests/llviewershadermgr_stub.cpp
@@ -2,8 +2,25 @@
* @file llglslshader_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llwlanimator_stub.cpp b/indra/newview/tests/llwlanimator_stub.cpp
index 4d1bb85544..f5e15b2e7b 100644
--- a/indra/newview/tests/llwlanimator_stub.cpp
+++ b/indra/newview/tests/llwlanimator_stub.cpp
@@ -2,8 +2,25 @@
* @file llwlanimator_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llwldaycycle_stub.cpp b/indra/newview/tests/llwldaycycle_stub.cpp
index d98c9614b4..a7bc9a7b83 100644
--- a/indra/newview/tests/llwldaycycle_stub.cpp
+++ b/indra/newview/tests/llwldaycycle_stub.cpp
@@ -2,8 +2,25 @@
* @file llwldaycycle_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llwlparammanager_test.cpp b/indra/newview/tests/llwlparammanager_test.cpp
index a6c6a2abf4..be0dc9fd0c 100644
--- a/indra/newview/tests/llwlparammanager_test.cpp
+++ b/indra/newview/tests/llwlparammanager_test.cpp
@@ -2,8 +2,25 @@
* @file llwlparammanager_test.cpp
* @brief LLWLParamManager tests
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/
diff --git a/indra/newview/tests/llwlparamset_stub.cpp b/indra/newview/tests/llwlparamset_stub.cpp
index 6ce4b5827d..ccb99db475 100644
--- a/indra/newview/tests/llwlparamset_stub.cpp
+++ b/indra/newview/tests/llwlparamset_stub.cpp
@@ -2,8 +2,25 @@
* @file llwlparamset_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2009&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$
*/