summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llaccountingcost.h (renamed from indra/llcommon/llaccountingquota.h)24
-rw-r--r--indra/llinventory/llparcel.cpp9
-rw-r--r--indra/llinventory/llparcel.h5
-rw-r--r--indra/llmath/llmath.h7
-rwxr-xr-xindra/llmath/llvolume.cpp177
-rw-r--r--indra/llmath/llvolume.h6
-rw-r--r--indra/llprimitive/llmodel.cpp85
-rw-r--r--indra/llprimitive/llmodel.h22
-rw-r--r--indra/llwindow/llwindowmacosx.cpp1
-rw-r--r--indra/llwindow/llwindowsdl.cpp3
-rw-r--r--indra/llwindow/llwindowwin32.cpp1
-rw-r--r--indra/newview/CMakeLists.txt6
-rw-r--r--indra/newview/app_settings/settings.xml95
-rwxr-xr-x[-rw-r--r--]indra/newview/featuretable.txt2
-rw-r--r--indra/newview/llaccountingcostmanager.cpp176
-rw-r--r--indra/newview/llaccountingcostmanager.h (renamed from indra/newview/llaccountingquotamanager.h)38
-rw-r--r--indra/newview/llaccountingquotamanager.cpp278
-rw-r--r--indra/newview/llchathistory.cpp2
-rw-r--r--indra/newview/lldrawpoolavatar.cpp41
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp597
-rw-r--r--indra/newview/llfloatermodelpreview.h8
-rw-r--r--indra/newview/llfloaterobjectweights.cpp328
-rw-r--r--indra/newview/llfloaterobjectweights.h89
-rw-r--r--indra/newview/llfloaterregioninfo.cpp52
-rw-r--r--indra/newview/llfloaterregioninfo.h4
-rw-r--r--indra/newview/llfloatertools.cpp58
-rw-r--r--indra/newview/llfloatertools.h1
-rwxr-xr-xindra/newview/llmeshrepository.cpp150
-rwxr-xr-xindra/newview/llmeshrepository.h4
-rw-r--r--indra/newview/llpanelobject.cpp13
-rw-r--r--indra/newview/llpanelvolume.cpp2
-rw-r--r--indra/newview/llselectmgr.cpp67
-rw-r--r--indra/newview/llspatialpartition.cpp116
-rw-r--r--indra/newview/llviewercontrol.cpp10
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp21
-rw-r--r--indra/newview/llviewerobject.h12
-rw-r--r--indra/newview/llviewerobjectlist.cpp13
-rw-r--r--indra/newview/llviewerobjectlist.h3
-rw-r--r--indra/newview/llviewerparceloverlay.cpp59
-rw-r--r--indra/newview/llviewerparceloverlay.h1
-rw-r--r--indra/newview/llviewerregion.cpp13
-rw-r--r--indra/newview/llviewerregion.h1
-rw-r--r--indra/newview/llvoavatar.cpp54
-rw-r--r--indra/newview/llvoavatar.h2
-rwxr-xr-xindra/newview/llvovolume.cpp277
-rw-r--r--indra/newview/llvovolume.h18
-rw-r--r--indra/newview/pipeline.h1
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_model_preview.xml146
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_wizard.xml89
-rw-r--r--indra/newview/skins/default/xui/en/floater_object_weights.xml342
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml14
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml12
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml8
57 files changed, 2418 insertions, 1165 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index cc6bddc4da..658eefbab2 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -117,7 +117,7 @@ set(llcommon_HEADER_FILES
indra_constants.h
linden_common.h
linked_lists.h
- llaccountingquota.h
+ llaccountingcost.h
llallocator.h
llallocator_heap_profile.h
llagentconstants.h
diff --git a/indra/llcommon/llaccountingquota.h b/indra/llcommon/llaccountingcost.h
index 140333de07..0ef3b50c6d 100644
--- a/indra/llcommon/llaccountingquota.h
+++ b/indra/llcommon/llaccountingcost.h
@@ -1,5 +1,5 @@
/**
- * @file llaccountingquota.h
+ * @file llaccountingcost.h
* @
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
@@ -58,22 +58,28 @@ struct ParcelQuota
F32 mParcelCapacity;
};
-struct SelectionQuota
+//SelectionQuota atm does not require a id
+struct SelectionCost
{
- SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
- : mLocalId( localId)
- , mRenderCost( renderCost )
- , mPhysicsCost( physicsCost )
+ SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost )
+ //: mTransactionId( transactionId)
+ : mPhysicsCost( physicsCost )
, mNetworkCost( networkCost )
, mSimulationCost( simulationCost )
{
}
- SelectionQuota() {}
+ SelectionCost()
+ : mPhysicsCost( 0.0f )
+ , mNetworkCost( 0.0f )
+ , mSimulationCost( 0.0f )
+ {}
- F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;
- LLUUID mLocalId;
+ F32 mPhysicsCost, mNetworkCost, mSimulationCost;
+ //LLTransactionID mTransactionId;
};
+typedef enum { Roots = 0 , Prims } eSelectionType;
+
#endif
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index c95f922301..433076c7a9 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -1373,12 +1373,3 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
// is a distinct option from "None" and "Other"
return LLParcel::C_ANY;
}
-
-void LLParcel::updateQuota( const LLUUID& objectId, const ParcelQuota& quota )
-{
- if ( mID == objectId )
- {
- mQuota = quota;
- }
-}
-
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index ff35caab4c..e36d0b20d2 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -34,7 +34,6 @@
#include "llpermissions.h"
#include "lltimer.h"
#include "v3math.h"
-#include "llaccountingquota.h"
// Grid out of which parcels taken is stepped every 4 meters.
const F32 PARCEL_GRID_STEP_METERS = 4.f;
@@ -603,9 +602,6 @@ public:
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
- void updateQuota( const LLUUID& objectId, const ParcelQuota& quota );
- const ParcelQuota& getQuota( void ) { return mQuota; }
-
protected:
LLUUID mID;
LLUUID mOwnerID;
@@ -681,7 +677,6 @@ protected:
BOOL mAllowGroupAVSounds;
BOOL mAllowAnyAVSounds;
- ParcelQuota mQuota;
public:
// HACK, make private
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index eea7c977fb..9297bcbac2 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -510,6 +510,13 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
VEC_TYPE Q1 = data[data.size()/4];
VEC_TYPE Q3 = data[data.size()-data.size()/4-1];
+ if ((F32)(Q3-Q1) < 1.f)
+ {
+ // not enough variation to detect outliers
+ return;
+ }
+
+
VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1));
VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1));
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 2893e746e9..1a95f9cd46 100755
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2078,7 +2078,7 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mFaceMask = 0x0;
mDetail = detail;
mSculptLevel = -2;
- mIsTetrahedron = FALSE;
+ mIsMeshAssetLoaded = FALSE;
mLODScaleBias.setVec(1,1,1);
mHullPoints = NULL;
mHullIndices = NULL;
@@ -2100,7 +2100,7 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
generate();
- if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE)
+ if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE || mParams.getSculptType() == LL_SCULPT_TYPE_MESH)
{
createVolumeFaces();
}
@@ -2408,7 +2408,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLSD mdl;
if (!unzip_llsd(mdl, is, size))
{
- llwarns << "not a valid mesh asset!" << llendl;
+ LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD, will probably fetch from sim again." << llendl;
return false;
}
@@ -2706,173 +2706,21 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
return true;
}
-void tetrahedron_set_normal(LLVolumeFace::VertexData* cv)
-{
- LLVector4a v0;
- v0.setSub(cv[1].getPosition(), cv[0].getNormal());
- LLVector4a v1;
- v1.setSub(cv[2].getNormal(), cv[0].getPosition());
-
- cv[0].getNormal().setCross3(v0,v1);
- cv[0].getNormal().normalize3fast();
- cv[1].setNormal(cv[0].getNormal());
- cv[2].setNormal(cv[1].getNormal());
-}
-BOOL LLVolume::isTetrahedron()
+BOOL LLVolume::isMeshAssetLoaded()
{
- return mIsTetrahedron;
+ return mIsMeshAssetLoaded;
}
-void LLVolume::makeTetrahedron()
+void LLVolume::setMeshAssetLoaded(BOOL loaded)
{
- mVolumeFaces.clear();
-
- LLVolumeFace face;
-
- F32 x = 0.25f;
- LLVector4a p[] =
- { //unit tetrahedron corners
- LLVector4a(x,x,x),
- LLVector4a(-x,-x,x),
- LLVector4a(-x,x,-x),
- LLVector4a(x,-x,-x)
- };
-
- face.mExtents[0].splat(-x);
- face.mExtents[1].splat(x);
-
- LLVolumeFace::VertexData cv[3];
-
- //set texture coordinates
- cv[0].mTexCoord = LLVector2(0,0);
- cv[1].mTexCoord = LLVector2(1,0);
- cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3);
-
-
- //side 1
- cv[0].setPosition(p[1]);
- cv[1].setPosition(p[0]);
- cv[2].setPosition(p[2]);
-
- tetrahedron_set_normal(cv);
-
- face.resizeVertices(12);
- face.resizeIndices(12);
-
- LLVector4a* v = (LLVector4a*) face.mPositions;
- LLVector4a* n = (LLVector4a*) face.mNormals;
- LLVector2* tc = (LLVector2*) face.mTexCoords;
-
- v[0] = cv[0].getPosition();
- v[1] = cv[1].getPosition();
- v[2] = cv[2].getPosition();
- v += 3;
-
- n[0] = cv[0].getNormal();
- n[1] = cv[1].getNormal();
- n[2] = cv[2].getNormal();
- n += 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]);
- cv[1].setPosition(p[0]);
- cv[2].setPosition(p[1]);
-
- tetrahedron_set_normal(cv);
-
- v[0] = cv[0].getPosition();
- v[1] = cv[1].getPosition();
- v[2] = cv[2].getPosition();
- v += 3;
-
- n[0] = cv[0].getNormal();
- n[1] = cv[1].getNormal();
- n[2] = cv[2].getNormal();
- n += 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]);
- cv[2].setPosition(p[2]);
-
- tetrahedron_set_normal(cv);
-
- v[0] = cv[0].getPosition();
- v[1] = cv[1].getPosition();
- v[2] = cv[2].getPosition();
- v += 3;
-
- n[0] = cv[0].getNormal();
- n[1] = cv[1].getNormal();
- n[2] = cv[2].getNormal();
- n += 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]);
- cv[1].setPosition(p[0]);
- cv[2].setPosition(p[3]);
-
- tetrahedron_set_normal(cv);
-
- v[0] = cv[0].getPosition();
- v[1] = cv[1].getPosition();
- v[2] = cv[2].getPosition();
- v += 3;
-
- n[0] = cv[0].getNormal();
- n[1] = cv[1].getNormal();
- n[2] = cv[2].getNormal();
- n += 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++)
- {
- face.mIndices[i] = i;
- }
-
- mVolumeFaces.push_back(face);
- mSculptLevel = 0;
- mIsTetrahedron = TRUE;
+ mIsMeshAssetLoaded = loaded;
}
void LLVolume::copyVolumeFaces(const LLVolume* volume)
{
mVolumeFaces = volume->mVolumeFaces;
mSculptLevel = 0;
- mIsTetrahedron = FALSE;
}
void LLVolume::cacheOptimize()
@@ -2886,14 +2734,7 @@ void LLVolume::cacheOptimize()
S32 LLVolume::getNumFaces() const
{
- U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK);
-
- if (sculpt_type == LL_SCULPT_TYPE_MESH)
- {
- return LL_SCULPT_MESH_MAX_FACES;
- }
-
- return (S32)mProfilep->mFaces.size();
+ return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size();
}
@@ -7269,7 +7110,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
resizeVertices(num_vertices);
resizeIndices(num_indices);
- if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
+ if (!volume->isMeshAssetLoaded())
{
mEdge.resize(num_indices);
}
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index f67f8f644d..f0e59a3c00 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -1058,14 +1058,14 @@ protected:
public:
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
- virtual void makeTetrahedron();
- virtual BOOL isTetrahedron();
+ virtual void setMeshAssetLoaded(BOOL loaded);
+ virtual BOOL isMeshAssetLoaded();
protected:
BOOL mUnique;
F32 mDetail;
S32 mSculptLevel;
- BOOL mIsTetrahedron;
+ BOOL mIsMeshAssetLoaded;
LLVolumeParams mParams;
LLPath *mPathp;
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 434fb7650b..6e4bb7ec97 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1679,6 +1679,19 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO
LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
+ //1. If a vertex has been weighted then we'll find it via pos and return it's weight list
+ weight_map::iterator iterPos = mSkinWeights.begin();
+ weight_map::iterator iterEnd = mSkinWeights.end();
+
+ for ( ; iterPos!=iterEnd; ++iterPos )
+ {
+ if ( jointPositionalLookup( iterPos->first, pos ) )
+ {
+ return iterPos->second;
+ }
+ }
+
+ //2. Otherwise we'll use the older implementation
weight_map::iterator iter = mSkinWeights.find(pos);
if (iter != mSkinWeights.end())
@@ -1692,13 +1705,13 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
}
else
{ //no exact match found, get closest point
- const F32 epsilon = 2.f/65536;
+ const F32 epsilon = 1e-5f;
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
weight_map::iterator iter_down = ++iter_up;
weight_map::iterator best = iter_up;
- F32 min_dist = (iter->first - pos).magVecSquared();
+ F32 min_dist = (iter->first - pos).magVec();
bool done = false;
while (!done)
@@ -1709,7 +1722,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
if (iter_up != mSkinWeights.end() && ++iter_up != mSkinWeights.end())
{
done = false;
- F32 dist = (iter_up->first - pos).magVecSquared();
+ F32 dist = (iter_up->first - pos).magVec();
if (dist < epsilon)
{
@@ -1727,7 +1740,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
done = false;
- F32 dist = (iter_down->first - pos).magVecSquared();
+ F32 dist = (iter_down->first - pos).magVec();
if (dist < epsilon)
{
@@ -1890,14 +1903,71 @@ bool LLModel::loadModel(std::istream& is)
}
-void LLModel::matchMaterialOrder(LLModel* ref)
+bool LLModel::isMaterialListSubset( LLModel* ref )
{
- llassert(ref->mMaterialList.size() == mMaterialList.size());
+ int refCnt = ref->mMaterialList.size();
+ int modelCnt = mMaterialList.size();
+
+ for (U32 src = 0; src < modelCnt; ++src)
+ {
+ bool foundRef = false;
+
+ for (U32 dst = 0; dst < refCnt; ++dst)
+ {
+ //llinfos<<mMaterialList[src]<<" "<<ref->mMaterialList[dst]<<llendl;
+ foundRef = mMaterialList[src] == ref->mMaterialList[dst];
+
+ if ( foundRef )
+ {
+ break;
+ }
+ }
+ if (!foundRef)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+bool LLModel::needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt )
+{
+ bool changed = false;
+ if ( refFaceCnt< modelFaceCnt )
+ {
+ refFaceCnt += modelFaceCnt - refFaceCnt;
+ changed = true;
+ }
+ else
+ if ( modelFaceCnt < refFaceCnt )
+ {
+ modelFaceCnt += refFaceCnt - modelFaceCnt;
+ changed = true;
+ }
+
+ return changed;
+}
+
+bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt )
+{
+ //Is this a subset?
+ //LODs cannot currently add new materials, e.g.
+ //1. ref = a,b,c lod1 = d,e => This is not permitted
+ //2. ref = a,b,c lod1 = c => This would be permitted
+
+ bool isASubset = isMaterialListSubset( ref );
+ if ( !isASubset )
+ {
+ llinfos<<"Material of model is not a subset of reference."<<llendl;
+ return false;
+ }
+
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;
@@ -1939,6 +2009,7 @@ void LLModel::matchMaterialOrder(LLModel* ref)
//override material list with reference model ordering
mMaterialList = ref->mMaterialList;
+ return true;
}
@@ -2329,8 +2400,6 @@ LLSD LLModel::Decomposition::asLLSD() const
for (U32 k = 0; k < 3; k++)
{
- llassert(v[k] <= 0.51f && v[k] >= -0.51f);
-
//convert to 16-bit normalized across domain
U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535);
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 3f58eba07d..1cf528fd9f 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -148,6 +148,7 @@ public:
static LLModel* loadModelFromDomMesh(domMesh* mesh);
static std::string getElementLabel(daeElement* element);
std::string getName() const;
+ std::string getMetric() const {return mMetric;}
EModelStatus getStatus() const {return mStatus;}
static std::string getStatusString(U32 status) ;
@@ -175,8 +176,10 @@ public:
//reorder face list based on mMaterialList in this and reference so
//order matches that of reference (material ordering touchup)
- void matchMaterialOrder(LLModel* reference);
-
+ bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
+ bool isMaterialListSubset( LLModel* ref );
+ bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
+
std::vector<std::string> mMaterialList;
//data used for skin weights
@@ -217,6 +220,19 @@ public:
}
};
+
+ //Are the doubles the same w/in epsilon specified tolerance
+ bool areEqual( double a, double b )
+ {
+ const float epsilon = 1e-5f;
+ return (fabs((a - b)) < epsilon) ? true : false ;
+ }
+ //Make sure that we return false for any values that are within the tolerance for equivalence
+ bool jointPositionalLookup( const LLVector3& a, const LLVector3& b )
+ {
+ return ( areEqual( a[0],b[0]) && areEqual( a[1],b[1] ) && areEqual( a[2],b[2]) ) ? true : false;
+ }
+
//copy of position array for this model -- mPosition[idx].mV[X,Y,Z]
std::vector<LLVector3> mPosition;
@@ -234,6 +250,8 @@ public:
std::string mRequestedLabel; // name requested in UI, if any.
std::string mLabel; // name computed from dae.
+ std::string mMetric; // user-supplied metric data for upload
+
LLVector3 mNormalizedScale;
LLVector3 mNormalizedTranslation;
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index cb2abc5bc0..4dd11541b9 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -1266,6 +1266,7 @@ BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
void LLWindowMacOSX::swapBuffers()
{
+ glFinish();
aglSwapBuffers(mContext);
}
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index b65287715c..e41aa9820f 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -984,7 +984,10 @@ BOOL LLWindowSDL::setSize(const LLCoordScreen size)
void LLWindowSDL::swapBuffers()
{
if (mWindow)
+ {
+ glFinish();
SDL_GL_SwapBuffers();
+ }
}
U32 LLWindowSDL::getFSAASamples()
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 1239e2d40b..121c7880df 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -2896,6 +2896,7 @@ BOOL LLWindowWin32::resetDisplayResolution()
void LLWindowWin32::swapBuffers()
{
+ glFinish();
SwapBuffers(mhDC);
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a117d9a593..c8f975d3f5 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -77,7 +77,7 @@ include_directories(
set(viewer_SOURCE_FILES
groupchatlistener.cpp
- llaccountingquotamanager.cpp
+ llaccountingcostmanager.cpp
llagent.cpp
llagentaccess.cpp
llagentcamera.cpp
@@ -213,6 +213,7 @@ set(viewer_SOURCE_FILES
llfloatermodelwizard.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
+ llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloaterpay.cpp
llfloaterperms.cpp
@@ -638,7 +639,7 @@ set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
groupchatlistener.h
- llaccountingquotamanager.h
+ llaccountingcostmanager.h
llagent.h
llagentaccess.h
llagentcamera.h
@@ -775,6 +776,7 @@ set(viewer_HEADER_FILES
llfloatermodelwizard.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
+ llfloaterobjectweights.h
llfloateropenobject.h
llfloaterpay.h
llfloaterperms.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0996f75fbb..baa083d96c 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7405,7 +7405,89 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>RenderAvatarLODFactor</key>
+ <key>RenderAvatarComplexityLimit</key>
+ <map>
+ <key>Comment</key>
+ <string>Max visual complexity of avatars in a scene</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>-1</integer>
+ </map>
+ <key>RenderComplexityColorMin</key>
+ <map>
+ <key>Comment</key>
+ <string>Max visual complexity of avatars in a scene</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Color4</string>
+ <key>Value</key>
+ <array>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.5</real>
+ </array>
+ </map>
+ <key>RenderComplexityColorMid</key>
+ <map>
+ <key>Comment</key>
+ <string>Max visual complexity of avatars in a scene</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Color4</string>
+ <key>Value</key>
+ <array>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ </array>
+ </map>
+ <key>RenderComplexityColorMax</key>
+ <map>
+ <key>Comment</key>
+ <string>Max visual complexity of avatars in a scene</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Color4</string>
+ <key>Value</key>
+ <array>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ </array>
+ </map>
+ <key>RenderComplexityThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>Only color objects higher than render threshold</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>-1</integer>
+ </map>
+ <key>RenderComplexityStaticMax</key>
+ <map>
+ <key>Comment</key>
+ <string>Sets a static max value for scaling of RenderComplexity
+ display (-1 for dynamic scaling)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>-1</integer>
+ </map>
+ <key>RenderAvatarLODFactor</key>
<map>
<key>Comment</key>
<string>Controls level of detail of avatars (multiplier for current screen area when calculated level of detail)</string>
@@ -9569,17 +9651,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowAdvancedBuilderOptions</key>
- <map>
- <key>Comment</key>
- <string>Shows physics and display weight</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>ShowAdvancedGraphicsSettings</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 1f9dc6e4e5..e12c2f7853 100644..100755
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -88,7 +88,7 @@ RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
-RenderVolumeLODFactor 1 0.5
+RenderVolumeLODFactor 1 1.125
VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
new file mode 100644
index 0000000000..0669bdfffa
--- /dev/null
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -0,0 +1,176 @@
+/**
+ * @file LLAccountingQuotaManager.cpp
+ * @ Handles the setting and accessing for costs associated with mesh
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llaccountingcostmanager.h"
+#include "llagent.h"
+#include "llcurl.h"
+#include "llhttpclient.h"
+//===============================================================================
+LLAccountingCostManager::LLAccountingCostManager()
+{
+}
+//===============================================================================
+class LLAccountingCostResponder : public LLCurl::Responder
+{
+public:
+ LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
+ : mObjectIDs( objectIDs ),
+ mObserverHandle( observer_handle )
+ {
+ }
+
+ void clearPendingRequests ( void )
+ {
+ for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
+ {
+ LLAccountingCostManager::getInstance()->removePendingObject( iter->asUUID() );
+ }
+ }
+
+ void error( U32 statusNum, const std::string& reason )
+ {
+ llwarns << "Transport error "<<reason<<llendl;
+ clearPendingRequests();
+
+ LLAccountingCostObserver* observer = mObserverHandle.get();
+ if (observer)
+ {
+ observer->setErrorStatus(statusNum, reason);
+ }
+ }
+
+ void result( const LLSD& content )
+ {
+ //Check for error
+ if ( !content.isMap() || content.has("error") )
+ {
+ llwarns << "Error on fetched data"<< llendl;
+ }
+ else if (content.has("selected"))
+ {
+ F32 physicsCost = 0.0f;
+ F32 networkCost = 0.0f;
+ F32 simulationCost = 0.0f;
+
+ //LLTransactionID transactionID;
+
+ //transactionID = content["selected"][i]["local_id"].asUUID();
+ physicsCost = content["selected"]["physics"].asReal();
+ networkCost = content["selected"]["streaming"].asReal();
+ simulationCost = content["selected"]["simulation"].asReal();
+
+ SelectionCost selectionCost( /*transactionID,*/ physicsCost, networkCost, simulationCost );
+
+ LLAccountingCostObserver* observer = mObserverHandle.get();
+ if (observer)
+ {
+ observer->onWeightsUpdate(selectionCost);
+ }
+ }
+
+ clearPendingRequests();
+ }
+
+private:
+ //List of posted objects
+ LLSD mObjectIDs;
+
+ // Cost update observer handle
+ LLHandle<LLAccountingCostObserver> mObserverHandle;
+};
+//===============================================================================
+void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
+ const std::string& url,
+ const LLHandle<LLAccountingCostObserver>& observer_handle )
+{
+ // Invoking system must have already determined capability availability
+ if ( !url.empty() )
+ {
+ LLSD objectList;
+ U32 objectIndex = 0;
+
+ IDIt IDIter = mObjectList.begin();
+ IDIt IDIterEnd = mObjectList.end();
+
+ for ( ; IDIter != IDIterEnd; ++IDIter )
+ {
+ // Check to see if a request for this object has already been made.
+ if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
+ {
+ mPendingObjectQuota.insert( *IDIter );
+ objectList[objectIndex++] = *IDIter;
+ }
+ }
+
+ mObjectList.clear();
+
+ //Post results
+ if ( objectList.size() > 0 )
+ {
+ std::string keystr;
+ if ( selectionType == Roots )
+ {
+ keystr="selected_roots";
+ }
+ else
+ if ( selectionType == Prims )
+ {
+ keystr="selected_prims";
+ }
+ else
+ {
+ llinfos<<"Invalid selection type "<<llendl;
+ mObjectList.clear();
+ mPendingObjectQuota.clear();
+ return;
+ }
+
+ LLSD dataToPost = LLSD::emptyMap();
+ dataToPost[keystr.c_str()] = objectList;
+
+ LLHTTPClient::post( url, dataToPost, new LLAccountingCostResponder( objectList, observer_handle ));
+ }
+ }
+ else
+ {
+ //url was empty - warn & continue
+ llwarns<<"Supplied url is empty "<<llendl;
+ mObjectList.clear();
+ mPendingObjectQuota.clear();
+ }
+}
+//===============================================================================
+void LLAccountingCostManager::addObject( const LLUUID& objectID )
+{
+ mObjectList.insert( objectID );
+}
+//===============================================================================
+void LLAccountingCostManager::removePendingObject( const LLUUID& objectID )
+{
+ mPendingObjectQuota.erase( objectID );
+}
+//===============================================================================
diff --git a/indra/newview/llaccountingquotamanager.h b/indra/newview/llaccountingcostmanager.h
index 9251ef9351..cccdc2e2d9 100644
--- a/indra/newview/llaccountingquotamanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -27,29 +27,45 @@
#ifndef LL_ACCOUNTINGQUOTAMANAGER_H
#define LL_ACCOUNTINGQUOTAMANAGER_H
//===============================================================================
-#include "llaccountingquota.h"
+#include "llhandle.h"
+
+#include "llaccountingcost.h"
//===============================================================================
-class LLAccountingQuotaManager : public LLSingleton<LLAccountingQuotaManager>
+// An interface class for panels which display the parcel accounting information.
+class LLAccountingCostObserver
+{
+public:
+ LLAccountingCostObserver() { mObserverHandle.bind(this); }
+ virtual ~LLAccountingCostObserver() {}
+ virtual void onWeightsUpdate(const SelectionCost& selection_cost) = 0;
+ virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+ const LLHandle<LLAccountingCostObserver>& getObserverHandle() const { return mObserverHandle; }
+
+protected:
+ LLRootHandle<LLAccountingCostObserver> mObserverHandle;
+};
+//===============================================================================
+class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager>
{
public:
//Ctor
- LLAccountingQuotaManager();
+ LLAccountingCostManager();
//Store an object that will be eventually fetched
- void updateObjectCost( const LLUUID& objectID );
+ void addObject( const LLUUID& objectID );
//Request quotas for object list
- void fetchQuotas( const std::string& url );
+ void fetchCosts( eSelectionType selectionType, const std::string& url,
+ const LLHandle<LLAccountingCostObserver>& observer_handle );
//Delete a specific object from the pending list
- void removePendingObjectQuota( const LLUUID& objectID );
+ void removePendingObject( const LLUUID& objectID );
private:
- //Set of objects that need to update their cost
- std::set<LLUUID> mUpdateObjectQuota;
- //During fetchQuota we move object into a the pending set to signify that
+ //Set of objects that will be used to generate a cost
+ std::set<LLUUID> mObjectList;
+ //During fetchCosts we move object into a the pending set to signify that
//a fetch has been instigated.
std::set<LLUUID> mPendingObjectQuota;
typedef std::set<LLUUID>::iterator IDIt;
};
//===============================================================================
-#endif // LLACCOUNTINGQUOTAMANAGER
-
+#endif // LLACCOUNTINGCOSTMANAGER
diff --git a/indra/newview/llaccountingquotamanager.cpp b/indra/newview/llaccountingquotamanager.cpp
deleted file mode 100644
index a4f5de5632..0000000000
--- a/indra/newview/llaccountingquotamanager.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * @file LLAccountingQuotaManager.cpp
- * @ Handles the setting and accessing for costs associated with mesh
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llaccountingquotamanager.h"
-#include "llagent.h"
-#include "llviewerregion.h"
-#include "llviewerobject.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llparcel.h"
-
-//===============================================================================
-LLAccountingQuotaManager::LLAccountingQuotaManager()
-{
-}
-//===============================================================================
-class LLAccountingQuotaResponder : public LLCurl::Responder
-{
-public:
- LLAccountingQuotaResponder( const LLSD& objectIDs )
- : mObjectIDs( objectIDs )
- {
- }
-
- void clearPendingRequests ( void )
- {
- for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
- {
- LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( iter->asUUID() );
- }
- }
-
- void error( U32 statusNum, const std::string& reason )
- {
- llwarns << "Transport error "<<reason<<llendl;
- //prep#do we really want to remove all because of one failure - verify
- clearPendingRequests();
- }
-
- void result( const LLSD& content )
- {
- if ( !content.isMap() || content.has("error") )
- {
- llwarns << "Error on fetched data"<< llendl;
- //prep#do we really want to remove all because of one failure - verify
- clearPendingRequests();
- return;
- }
-
- //Differentiate what the incoming caps could be from the data
- bool containsParcel = content.has("parcel");
- bool containsSelection = content.has("selected");
-
- //Loop over the stored object ids checking against the incoming data
- for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
- {
- LLUUID objectID = iter->asUUID();
-
- LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
-
- if ( containsParcel )
- {
- //Typically should be one
- S32 dataCount = content["parcel"].size();
- for(S32 i = 0; i < dataCount; i++)
- {
- //prep#todo verify that this is safe, otherwise just add a bool
- LLUUID parcelId;
- //S32 parcelOwner = 0;
- if ( content["parcel"][i].has("parcel_id") )
- {
- parcelId = content["parcel"][i]["parcel_id"].asUUID();
- }
-
- //if ( content["parcel"][i].has("parcel_owner") )
- //{
- // parcelOwner = content["parcel"][i]["parcel_owner"].asInteger();
- //}
-
- F32 ownerRenderCost = 0;
- F32 ownerPhysicsCost = 0;
- F32 ownerNetworkCost = 0;
- F32 ownerSimulationCost = 0;
-
- F32 groupRenderCost = 0;
- F32 groupPhysicsCost = 0;
- F32 groupNetworkCost = 0;
- F32 groupSimulationCost = 0;
-
- F32 otherRenderCost = 0;
- F32 otherPhysicsCost = 0;
- F32 otherNetworkCost = 0;
- F32 otherSimulationCost = 0;
-
- F32 tempRenderCost = 0;
- F32 tempPhysicsCost = 0;
- F32 tempNetworkCost = 0;
- F32 tempSimulationCost = 0;
-
- F32 selectedRenderCost = 0;
- F32 selectedPhysicsCost = 0;
- F32 selectedNetworkCost = 0;
- F32 selectedSimulationCost = 0;
-
- F32 parcelCapacity = 0;
-
- if ( content["parcel"][i].has("capacity") )
- {
- parcelCapacity = content["parcel"][i].has("capacity");
- }
-
- if ( content["parcel"][i].has("owner") )
- {
- ownerRenderCost = content["parcel"][i]["owner"]["rendering"].asReal();
- ownerPhysicsCost = content["parcel"][i]["owner"]["physics"].asReal();
- ownerNetworkCost = content["parcel"][i]["owner"]["streaming"].asReal();
- ownerSimulationCost = content["parcel"][i]["owner"]["simulation"].asReal();
- }
-
- if ( content["parcel"][i].has("group") )
- {
- groupRenderCost = content["parcel"][i]["group"]["rendering"].asReal();
- groupPhysicsCost = content["parcel"][i]["group"]["physics"].asReal();
- groupNetworkCost = content["parcel"][i]["group"]["streaming"].asReal();
- groupSimulationCost = content["parcel"][i]["group"]["simulation"].asReal();
-
- }
- if ( content["parcel"][i].has("other") )
- {
- otherRenderCost = content["parcel"][i]["other"]["rendering"].asReal();
- otherPhysicsCost = content["parcel"][i]["other"]["physics"].asReal();
- otherNetworkCost = content["parcel"][i]["other"]["streaming"].asReal();
- otherSimulationCost = content["parcel"][i]["other"]["simulation"].asReal();
- }
-
- if ( content["parcel"][i].has("temp") )
- {
- tempRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
- tempPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
- tempNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
- tempSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
- }
-
- if ( content["parcel"][i].has("selected") )
- {
- selectedRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
- selectedPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
- selectedNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
- selectedSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
- }
-
- ParcelQuota parcelQuota( ownerRenderCost, ownerPhysicsCost, ownerNetworkCost, ownerSimulationCost,
- groupRenderCost, groupPhysicsCost, groupNetworkCost, groupSimulationCost,
- otherRenderCost, otherPhysicsCost, otherNetworkCost, otherSimulationCost,
- tempRenderCost, tempPhysicsCost, tempNetworkCost, tempSimulationCost,
- selectedRenderCost, selectedPhysicsCost, selectedNetworkCost, selectedSimulationCost,
- parcelCapacity );
- //Update the Parcel
- LLParcel* pParcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
- if ( pParcel )
- {
- pParcel->updateQuota( objectID, parcelQuota );
- }
- }
- }
- else
- if ( containsSelection )
- {
- S32 dataCount = content["selected"].size();
- for(S32 i = 0; i < dataCount; i++)
- {
-
- F32 renderCost = 0;
- F32 physicsCost = 0;
- F32 networkCost = 0;
- F32 simulationCost = 0;
-
- LLUUID objectId;
-
- objectId = content["selected"][i]["local_id"].asUUID();
- renderCost = content["selected"][i]["rendering"].asReal();
- physicsCost = content["selected"][i]["physics"].asReal();
- networkCost = content["selected"][i]["streaming"].asReal();
- simulationCost = content["selected"][i]["simulation"].asReal();
-
- SelectionQuota selectionQuota( objectId, renderCost, physicsCost, networkCost, simulationCost );
-
- //Update the objects
- gObjectList.updateQuota( objectId, selectionQuota );
-
- }
- }
- else
- {
- //Nothing in string
- LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
- }
- }
- }
-
-private:
- //List of posted objects
- LLSD mObjectIDs;
-};
-//===============================================================================
-void LLAccountingQuotaManager::fetchQuotas( const std::string& url )
-{
- // Invoking system must have already determined capability availability
- if ( !url.empty() )
- {
- LLSD objectList;
- U32 objectIndex = 0;
- IDIt IDIter = mUpdateObjectQuota.begin();
- IDIt IDIterEnd = mUpdateObjectQuota.end();
-
- for ( ; IDIter != IDIterEnd; ++IDIter )
- {
- // Check to see if a request for this object has already been made.
- if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
- {
- mPendingObjectQuota.insert( *IDIter );
- objectList[objectIndex++] = *IDIter;
- }
- }
-
- mUpdateObjectQuota.clear();
-
- //Post results
- if ( objectList.size() > 0 )
- {
- LLSD dataToPost = LLSD::emptyMap();
- dataToPost["object_ids"] = objectList;
- LLHTTPClient::post( url, dataToPost, new LLAccountingQuotaResponder( objectList ));
- }
- }
- else
- {
- //url was empty - warn & continue
- llwarns<<"Supplied url is empty "<<llendl;
- mUpdateObjectQuota.clear();
- mPendingObjectQuota.clear();
- }
-}
-//===============================================================================
-void LLAccountingQuotaManager::updateObjectCost( const LLUUID& objectID )
-{
- mUpdateObjectQuota.insert( objectID );
-}
-//===============================================================================
-void LLAccountingQuotaManager::removePendingObjectQuota( const LLUUID& objectID )
-{
- mPendingObjectQuota.erase( objectID );
-}
-//===============================================================================
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c0c9ea1451..913d2f34b0 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -255,7 +255,7 @@ public:
mSourceType = chat.mSourceType;
//*TODO overly defensive thing, source type should be maintained out there
- if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
+ if((chat.mFromID.isNull() && chat.mFromName.empty()) || (chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull()))
{
mSourceType = CHAT_SOURCE_SYSTEM;
}
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 28e464b60d..37ee81aeb5 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1299,30 +1299,38 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
return;
}
- LLVertexBuffer* buffer = face->getVertexBuffer();
+ LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
+ LLDrawable* drawable = face->getDrawable();
U32 data_mask = face->getRiggedVertexBufferDataMask();
- if (!buffer ||
+ if (buffer.isNull() ||
buffer->getTypeMask() != data_mask ||
- buffer->getRequestedVerts() != vol_face.mNumVertices)
+ buffer->getRequestedVerts() != vol_face.mNumVertices ||
+ buffer->getRequestedIndices() != vol_face.mNumIndices ||
+ (drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
{
face->setGeomIndex(0);
face->setIndicesIndex(0);
- face->setSize(vol_face.mNumVertices, vol_face.mNumIndices, true);
-
-
- if (sShaderLevel > 0)
- {
- buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
+
+ if (buffer.isNull() || buffer->getTypeMask() != data_mask)
+ { //make a new buffer
+ if (sShaderLevel > 0)
+ {
+ buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
+ }
+ else
+ {
+ buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+ }
+ buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true);
}
else
- {
- buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+ { //resize existing buffer
+ buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
}
- buffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true);
-
+ face->setSize(vol_face.mNumVertices, vol_face.mNumIndices);
face->setVertexBuffer(buffer);
U16 offset = 0;
@@ -1423,6 +1431,11 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
}
}
}
+
+ if (drawable && (face->getTEOffset() == drawable->getNumFaces()-1))
+ {
+ drawable->clearState(LLDrawable::REBUILD_ALL);
+ }
}
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
@@ -1453,7 +1466,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
LLVolume* volume = vobj->getVolume();
S32 te = face->getTEOffset();
- if (!volume || volume->getNumVolumeFaces() <= te)
+ if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded())
{
continue;
}
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 2510f43aa7..b424ad45fb 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -96,6 +96,7 @@
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "lltoggleablemenu.h"
+#include "lltrans.h"
#include "llvfile.h"
#include "llvfs.h"
#include "llcallbacklist.h"
@@ -106,7 +107,7 @@
#include <boost/algorithm/string.hpp>
-const S32 SLM_SUPPORTED_VERSION = 2;
+const S32 SLM_SUPPORTED_VERSION = 3;
//static
S32 LLFloaterModelPreview::sUploadAmount = 10;
@@ -184,6 +185,13 @@ std::string lod_label_name[NUM_LOD+1] =
"I went off the end of the lod_label_name array. Me so smart."
};
+std::string colladaVersion[VERSIONTYPE_COUNT+1] =
+{
+ "1.4.0",
+ "1.4.1",
+ "Unsupported"
+};
+
#define LL_DEGENERACY_TOLERANCE 1e-7f
@@ -429,8 +437,6 @@ BOOL LLFloaterModelPreview::postBuild()
childDisable("upload_skin");
childDisable("upload_joints");
-
- childDisable("ok_btn");
mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn");
@@ -768,6 +774,7 @@ void LLFloaterModelPreview::draw()
if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
{
childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
+ toggleCalculateButton(false);
}
else
{
@@ -775,8 +782,6 @@ 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()));
@@ -1032,6 +1037,11 @@ void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data)
}
sInstance->mCurRequest.clear();
+
+ if (sInstance->mModelPreview)
+ {
+ sInstance->mModelPreview->updateStatusMessages();
+ }
}
}
@@ -1145,7 +1155,11 @@ void LLFloaterModelPreview::initDecompControls()
//llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue
// << " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl;
- combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName,
+ std::string name(param[i].mDetails.mEnumValues.mEnumsArray[k].mName);
+ std::string localized_name;
+ bool is_localized = LLTrans::findString(localized_name, name);
+
+ combo_box->add(is_localized ? localized_name : name,
LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue));
}
combo_box->setValue(param[i].mDefault.mIntOrEnumValue);
@@ -1385,9 +1399,26 @@ bool LLModelLoader::doLoadModel()
if (!dom)
{
+ llinfos<<" Error with dae - traditionally indicates a corrupt file."<<llendl;
+ setLoadState( ERROR_PARSING );
return false;
}
-
+ //Dom version
+ daeString domVersion = dae.getDomVersion();
+ std::string sldom(domVersion);
+ llinfos<<"Collada Importer Version: "<<sldom<<llendl;
+ //Dae version
+ domVersionType docVersion = dom->getVersion();
+ //0=1.4
+ //1=1.4.1
+ //2=Currently unsupported, however may work
+ if (docVersion > 1 )
+ {
+ docVersion = VERSIONTYPE_COUNT;
+ }
+ llinfos<<"Dae version "<<colladaVersion[docVersion]<<llendl;
+
+
daeDatabase* db = dae.getDatabase();
daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
@@ -1536,8 +1567,7 @@ bool LLModelLoader::doLoadModel()
LLMatrix4 trans = normalized_transformation;
trans *= skin_info.mBindShapeMatrix;
- skin_info.mBindShapeMatrix = trans;
-
+ skin_info.mBindShapeMatrix = trans;
}
@@ -1610,7 +1640,7 @@ bool LLModelLoader::doLoadModel()
{
//Build a joint for the resolver to work with
char str[64]={0};
- sprintf(str,"./%s",(*jointIt).second.c_str() );
+ sprintf(str,"./%s",(*jointIt).first.c_str() );
//llwarns<<"Joint "<< str <<llendl;
//Setup the resolver
@@ -1621,15 +1651,22 @@ bool LLModelLoader::doLoadModel()
if ( pJoint )
{
//Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolver( pJoint, "./translate" );
- domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
+ daeSIDResolver jointResolverA( pJoint, "./translate" );
+ domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+ daeSIDResolver jointResolverB( pJoint, "./location" );
+ domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
LLMatrix4 workingTransform;
//Translation via SID
- if ( pTranslate )
+ if ( pTranslateA )
{
- extractTranslation( pTranslate, workingTransform );
+ extractTranslation( pTranslateA, workingTransform );
+ }
+ else
+ if ( pTranslateB )
+ {
+ extractTranslation( pTranslateB, workingTransform );
}
else
{
@@ -1740,7 +1777,7 @@ bool LLModelLoader::doLoadModel()
}
}
- model->mSkinInfo.mInvBindMatrix.push_back(mat);
+ model->mSkinInfo.mInvBindMatrix.push_back(mat);
}
}
}
@@ -1748,7 +1785,7 @@ bool LLModelLoader::doLoadModel()
}
//Now that we've parsed the joint array, let's determine if we have a full rig
- //(which means we have all the joints that are required for an avatar versus
+ //(which means we have all the joint sthat are required for an avatar versus
//a skinned asset attached to a node in a file that contains an entire skeleton,
//but does not use the skeleton).
buildJointToNodeMappingFromScene( root );
@@ -2040,6 +2077,14 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
return false;
}
+ // Set name.
+ std::string name = data["name"];
+ if (!name.empty())
+ {
+ model[LLModel::LOD_HIGH][0]->mLabel = name;
+ }
+
+
//load instance list
model_instance_list instance_list;
@@ -2152,15 +2197,37 @@ void LLModelLoader::processJointToNodeMapping( domNode* pNode )
mJointsFromNode.push_front( pNode->getName() );
}
//2. Handle the kiddo's
- daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
- S32 childOfChildCount = childOfChild.getCount();
- for (S32 i = 0; i < childOfChildCount; ++i)
+ processChildJoints( pNode );
+ }
+ else
+ {
+ //Determine if the're any children wrt to this failed node.
+ //This occurs when an armature is exported and ends up being what essentially amounts to
+ //as the root for the visual_scene
+ if ( pNode )
{
- domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
- if ( pChildNode )
- {
- processJointToNodeMapping( pChildNode );
- }
+ processChildJoints( pNode );
+ }
+ else
+ {
+ llinfos<<"Node is NULL"<<llendl;
+ }
+
+ }
+}
+//-----------------------------------------------------------------------------
+// processChildJoint()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processChildJoints( domNode* pParentNode )
+{
+ daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren();
+ S32 childOfChildCount = childOfChild.getCount();
+ for (S32 i = 0; i < childOfChildCount; ++i)
+ {
+ domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+ if ( pChildNode )
+ {
+ processJointToNodeMapping( pChildNode );
}
}
}
@@ -2185,15 +2252,11 @@ void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::s
setRigValidForJointPositionUpload( true );
}
- if ( isRigLegacyOK )
- {
+ if ( isRigLegacyOK)
+ {
setLegacyRigValid( true );
}
- if ( getRigWithSceneParity() && isJointPositionUploadOK )
- {
- setResetJointFlag( true );
- }
}
//-----------------------------------------------------------------------------
// critiqueJointToNodeMappingFromScene()
@@ -2233,12 +2296,7 @@ void LLModelPreview::critiqueJointToNodeMappingFromScene( void )
//2. Partial rig but w/o parity between the scene and joint array
if ( result )
{
- setResetJointFlag( true );
setRigWithSceneParity( true );
- }
- else
- {
- setResetJointFlag( false );
}
}
//-----------------------------------------------------------------------------
@@ -2355,8 +2413,20 @@ void LLModelLoader::loadTextures()
//-----------------------------------------------------------------------------
bool LLModelLoader::isNodeAJoint( domNode* pNode )
{
- if ( !pNode || pNode->getName() == NULL)
+ if ( !pNode )
{
+ llinfos<<"Created node is NULL"<<llendl;
+ return false;
+ }
+
+ if ( pNode->getName() == NULL )
+ {
+ llinfos<<"Parsed node has no name "<<llendl;
+ //Attempt to write the node id, if possible (aids in debugging the visual scene)
+ if ( pNode->getId() )
+ {
+ llinfos<<"Parsed node ID: "<<pNode->getId()<<llendl;
+ }
return false;
}
@@ -2489,13 +2559,20 @@ void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTr
LLMatrix4 workingTransform;
//Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolver( pNode, "./translate" );
- domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
+ daeSIDResolver jointResolverA( pNode, "./translate" );
+ domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+ daeSIDResolver jointResolverB( pNode, "./location" );
+ domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
//Translation via SID was successful
- if ( pTranslate )
+ if ( pTranslateA )
{
- extractTranslation( pTranslate, workingTransform );
+ extractTranslation( pTranslateA, workingTransform );
+ }
+ else
+ if ( pTranslateB )
+ {
+ extractTranslation( pTranslateB, workingTransform );
}
else
{
@@ -2637,6 +2714,12 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )
{
LLMatrix4 transformation = mTransform;
+ if (mTransform.determinant() < 0)
+ { //negative scales are not supported
+ llinfos << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << llendl;
+ badElement = true;
+ }
+
std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo);
// adjust the transformation to compensate for mesh normalization
@@ -2981,14 +3064,6 @@ U32 LLModelPreview::calcResourceCost()
rebuildUploadData();
- if (mFMP && mModelLoader)
- {
- if ( getLoadState() < LLModelLoader::ERROR_PARSING)
- {
- mFMP->childEnable("ok_btn");
- }
- }
-
//Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
{
@@ -2996,13 +3071,7 @@ U32 LLModelPreview::calcResourceCost()
if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
{
mFMP->childDisable("ok_btn");
- }
- else
- if ( !isLegacyRigValid() )
- {
- mFMP->childDisable("ok_btn");
- }
- //ok_btn should not have been changed unless something was wrong with joint list
+ }
}
std::set<LLModel*> accounted;
@@ -3089,6 +3158,7 @@ U32 LLModelPreview::calcResourceCost()
void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
{
+ assert_main_thread();
childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
@@ -3106,14 +3176,10 @@ void LLModelPreview::rebuildUploadData()
std::string requested_name = mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
+ std::string metric = mFMP->getChild<LLUICtrl>("model_category_combo")->getValue().asString();
LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
- if (!scale_spinner)
- {
- llerrs << "floater_model_preview.xml MUST contain import_scale spinner." << llendl;
- }
-
F32 scale = scale_spinner->getValue().asReal();
LLMatrix4 scale_mat;
@@ -3121,11 +3187,6 @@ void LLModelPreview::rebuildUploadData()
F32 max_scale = 0.f;
- if ( mBaseScene.size() > 0)
- {
- mFMP->childEnable("ok_btn");
- }
-
//reorder materials to match mBaseModel
for (U32 i = 0; i < LLModel::NUM_LODS; i++)
{
@@ -3133,8 +3194,14 @@ void LLModelPreview::rebuildUploadData()
{
for (U32 j = 0; j < mBaseModel.size(); ++j)
{
- mModel[i][j]->matchMaterialOrder(mBaseModel[j]);
- llassert(mModel[i][j]->mMaterialList == mBaseModel[j]->mMaterialList);
+
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+
+ if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
+ {
+ mFMP->childDisable( "calculate_btn" );
+ }
}
}
}
@@ -3167,6 +3234,7 @@ void LLModelPreview::rebuildUploadData()
if (base_model)
{
base_model->mRequestedLabel = requested_name;
+ base_model->mMetric = metric;
}
S32 idx = 0;
@@ -3197,7 +3265,14 @@ void LLModelPreview::rebuildUploadData()
}
}
- F32 max_import_scale = DEFAULT_MAX_PRIM_SCALE/max_scale;
+ F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale;
+
+ F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
+ max_axis = llmax(max_axis, mPreviewScale.mV[2]);
+ max_axis *= 2.f;
+
+ //clamp scale so that total imported model bounding box is smaller than 240m on a side
+ max_import_scale = llmin(max_import_scale, 240.f/max_axis);
scale_spinner->setMaxValue(max_import_scale);
@@ -3238,6 +3313,10 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
LLSD data;
data["version"] = SLM_SUPPORTED_VERSION;
+ if (!mBaseModel.empty())
+ {
+ data["name"] = mBaseModel[0]->getName();
+ }
S32 mesh_id = 0;
@@ -3343,6 +3422,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
if ( getLoadState() >= LLModelLoader::ERROR_PARSING )
{
mFMP->childDisable("ok_btn");
+ mFMP->childDisable( "calculate_btn" );
}
if (lod == mPreviewLOD)
@@ -4213,12 +4293,7 @@ void LLModelPreview::updateStatusMessages()
if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
{
skinAndRigOk = false;
- }
- else
- if ( !isLegacyRigValid() )
- {
- skinAndRigOk = false;
- }
+ }
}
if(upload_ok && mModelLoader)
@@ -4229,11 +4304,7 @@ void LLModelPreview::updateStatusMessages()
}
}
- if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate)
- {
- mFMP->childEnable("ok_btn");
- }
- else
+ if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate)
{
mFMP->childDisable("ok_btn");
}
@@ -4313,7 +4384,7 @@ void LLModelPreview::updateStatusMessages()
//fmp->childSetEnabled("physics_optimize", !use_hull);
- bool enable = phys_tris > 0 || phys_hulls > 0;
+ bool enable = (phys_tris > 0 || phys_hulls > 0) && fmp->mCurRequest.empty();
//enable = enable && !use_hull && fmp->childGetValue("physics_optimize").asBoolean();
//enable/disable "analysis" UI
@@ -4325,7 +4396,7 @@ void LLModelPreview::updateStatusMessages()
child = panel->findNextSibling(child);
}
- enable = phys_hulls > 0;
+ enable = phys_hulls > 0 && fmp->mCurRequest.empty();
//enable/disable "simplification" UI
panel = fmp->getChild<LLPanel>("physics simplification");
child = panel->getFirstChild();
@@ -4352,6 +4423,11 @@ void LLModelPreview::updateStatusMessages()
fmp->childEnable("Decompose");
}
}
+ else
+ {
+ fmp->childEnable("simplify_cancel");
+ fmp->childEnable("decompose_cancel");
+ }
}
const char* lod_controls[] =
@@ -4703,6 +4779,42 @@ void LLModelPreview::createPreviewAvatar( void )
}
}
+void LLModelPreview::addEmptyFace( LLModel* pTarget )
+{
+ U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
+
+ buff->allocateBuffer(1, 3, true);
+ memset( buff->getMappedData(), 0, buff->getSize() );
+ memset( buff->getIndicesPointer(), 0, buff->getIndicesSize() );
+
+ buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 );
+
+ LLStrider<LLVector3> pos;
+ LLStrider<LLVector3> norm;
+ LLStrider<LLVector2> tc;
+ LLStrider<U16> index;
+
+ buff->getVertexStrider(pos);
+
+ if ( type_mask & LLVertexBuffer::MAP_NORMAL )
+ {
+ buff->getNormalStrider(norm);
+ }
+ if ( type_mask & LLVertexBuffer::MAP_TEXCOORD0 )
+ {
+ buff->getTexCoord0Strider(tc);
+ }
+
+ buff->getIndexStrider(index);
+
+ //resize face array
+ int faceCnt = pTarget->getNumVolumeFaces();
+ pTarget->setNumVolumeFaces( faceCnt+1 );
+ pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() );
+
+}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
@@ -4814,8 +4926,12 @@ BOOL LLModelPreview::render()
mFMP->childSetValue("upload_joints", false);
upload_joints = false;
}
-
- mFMP->childSetEnabled("upload_joints", upload_skin);
+
+ //Only enable joint offsets if it passed the earlier critiquing
+ if ( isRigValidForJointPositionUpload() )
+ {
+ mFMP->childSetEnabled("upload_joints", upload_skin);
+ }
F32 explode = mFMP->childGetValue("physics_explode").asReal();
@@ -4869,6 +4985,8 @@ BOOL LLModelPreview::render()
target_pos); // point of interest
+ z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f);
+
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, width, height, FALSE, z_near, z_far);
stop_glerror();
@@ -4908,8 +5026,13 @@ BOOL LLModelPreview::render()
{
for (U32 j = 0; j < mBaseModel.size(); ++j)
{
- mModel[i][j]->matchMaterialOrder(mBaseModel[j]);
- llassert(mModel[i][j]->mMaterialList == mBaseModel[j]->mMaterialList);
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+
+ if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
+ {
+ mFMP->childDisable( "calculate_btn" );
+ }
}
}
}
@@ -4945,18 +5068,20 @@ BOOL LLModelPreview::render()
if (textures)
{
- 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())
+ int materialCnt = instance.mModel->mMaterialList.size();
+ if ( i < materialCnt )
{
- if (material.mDiffuseMap->getDiscardLevel() > -1)
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
+
+ glColor4fv(material.mDiffuseColor.mV);
+ if (material.mDiffuseMap.notNull())
{
- gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
- mTextureSet.insert(material.mDiffuseMap.get());
+ if (material.mDiffuseMap->getDiscardLevel() > -1)
+ {
+ gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
+ mTextureSet.insert(material.mDiffuseMap.get());
+ }
}
}
}
@@ -4984,184 +5109,197 @@ BOOL LLModelPreview::render()
if (physics)
{
glClear(GL_DEPTH_BUFFER_BIT);
- LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ZERO);
-
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+
+ for (U32 i = 0; i < 2; i++)
{
- LLModelInstance& instance = *iter;
+ if (i == 0)
+ { //depth only pass
+ gGL.setColorMask(false, false);
+ }
+ else
+ {
+ gGL.setColorMask(true, true);
+ }
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+ //enable alpha blending on second pass but not first pass
+ LLGLState blend(GL_BLEND, i);
+
+ gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
- if (!model)
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
{
- continue;
- }
+ LLModelInstance& instance = *iter;
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
- glMultMatrixf((GLfloat*) mat.mMatrix);
+ if (!model)
+ {
+ continue;
+ }
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
- bool render_mesh = true;
+ glMultMatrixf((GLfloat*) mat.mMatrix);
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
- LLModel::Decomposition& physics = model->mPhysics;
+ bool render_mesh = true;
- if (!physics.mHull.empty())
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
{
- render_mesh = false;
+ LLMutexLock(decomp->mMutex);
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (!physics.mHull.empty())
+ {
+ render_mesh = false;
+
+ if (physics.mMesh.empty())
+ { //build vertex buffer for physics mesh
+ gMeshRepo.buildPhysicsMesh(physics);
+ }
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
+ if (!physics.mMesh.empty())
+ { //render hull instead of mesh
+ for (U32 i = 0; i < physics.mMesh.size(); ++i)
{
- gGL.pushMatrix();
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
+ LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+ offset *= explode;
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
- static std::vector<LLColor4U> hull_colors;
+ static std::vector<LLColor4U> hull_colors;
- if (i+1 >= hull_colors.size())
- {
- hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
- }
+ if (i+1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
+ }
glColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
- if (explode > 0.f)
- {
- gGL.popMatrix();
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
}
}
}
}
- }
- if (render_mesh)
- {
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
- {
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ if (render_mesh)
{
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+ for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glColor4f(0.4f, 0.4f, 0.0f, 0.4f);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ glColor4f(0.4f, 0.4f, 0.0f, 0.4f);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glColor3f(1.f, 1.f, 0.f);
+ glColor3f(1.f, 1.f, 0.f);
- glLineWidth(2.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ glLineWidth(2.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
}
- }
-
- gGL.popMatrix();
- }
-
- glLineWidth(3.f);
- glPointSize(8.f);
- gPipeline.enableLightsFullbright(LLColor4::white);
- //show degenerate triangles
- LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- LLGLDisable cull(GL_CULL_FACE);
- glColor4f(1.f,0.f,0.f,1.f);
- const LLVector4a scale(0.5f);
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
+ gGL.popMatrix();
+ }
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+ glLineWidth(3.f);
+ glPointSize(8.f);
+ gPipeline.enableLightsFullbright(LLColor4::white);
+ //show degenerate triangles
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ LLGLDisable cull(GL_CULL_FACE);
+ glColor4f(1.f,0.f,0.f,1.f);
+ const LLVector4a scale(0.5f);
- if (!model)
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
{
- continue;
- }
+ LLModelInstance& instance = *iter;
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
- glMultMatrixf((GLfloat*) mat.mMatrix);
+ if (!model)
+ {
+ continue;
+ }
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
+ glMultMatrixf((GLfloat*) mat.mMatrix);
- LLModel::Decomposition& physics = model->mPhysics;
- if (physics.mHull.empty())
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
{
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ LLMutexLock(decomp->mMutex);
+
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (physics.mHull.empty())
{
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+ for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
- buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
- LLStrider<LLVector3> pos_strider;
- buffer->getVertexStrider(pos_strider, 0);
- LLVector4a* pos = (LLVector4a*) pos_strider.get();
+ LLStrider<LLVector3> pos_strider;
+ buffer->getVertexStrider(pos_strider, 0);
+ LLVector4a* pos = (LLVector4a*) pos_strider.get();
- LLStrider<U16> idx;
- buffer->getIndexStrider(idx, 0);
-
- for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
- {
- LLVector4a v1; v1.setMul(pos[*idx++], scale);
- LLVector4a v2; v2.setMul(pos[*idx++], scale);
- LLVector4a v3; v3.setMul(pos[*idx++], scale);
+ LLStrider<U16> idx;
+ buffer->getIndexStrider(idx, 0);
- if (ll_is_degenerate(v1,v2,v3))
+ for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
{
- buffer->draw(LLRender::LINE_LOOP, 3, i);
- buffer->draw(LLRender::POINTS, 3, i);
+ LLVector4a v1; v1.setMul(pos[*idx++], scale);
+ LLVector4a v2; v2.setMul(pos[*idx++], scale);
+ LLVector4a v3; v3.setMul(pos[*idx++], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ buffer->draw(LLRender::LINE_LOOP, 3, i);
+ buffer->draw(LLRender::POINTS, 3, i);
+ }
}
}
}
}
- }
- gGL.popMatrix();
+ gGL.popMatrix();
+ }
+ glLineWidth(1.f);
+ glPointSize(1.f);
+ gPipeline.enableLightsPreview();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
- glLineWidth(1.f);
- glPointSize(1.f);
- gPipeline.enableLightsPreview();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
else
@@ -5394,6 +5532,8 @@ void LLFloaterModelPreview::onUpload(void* user_data)
LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data;
+ mp->mUploadBtn->setEnabled(false);
+
mp->mModelPreview->rebuildUploadData();
bool upload_skinweights = mp->childGetValue("upload_skin").asBoolean();
@@ -5475,11 +5615,6 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
{
mCalculateBtn->setVisible( false );
}
- else
- if ( !mModelPreview->isLegacyRigValid() )
- {
- mCalculateBtn->setVisible( false );
- }
}
mUploadBtn->setVisible(!visible);
@@ -5488,10 +5623,10 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
if (visible)
{
std::string tbd = getString("tbd");
- childSetTextArg("weights", "[EQ]", tbd);
- childSetTextArg("weights", "[ST]", tbd);
- childSetTextArg("weights", "[SIM]", tbd);
- childSetTextArg("weights", "[PH]", tbd);
+ childSetTextArg("weights_right", "[EQ]", tbd);
+ childSetTextArg("weights_left", "[ST]", tbd);
+ childSetTextArg("weights_right", "[SIM]", tbd);
+ childSetTextArg("weights_left", "[PH]", tbd);
childSetTextArg("upload_fee", "[FEE]", tbd);
childSetTextArg("price_breakdown", "[STREAMING]", tbd);
childSetTextArg("price_breakdown", "[PHYSICS]", tbd);
@@ -5514,17 +5649,16 @@ 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("weights_right", "[EQ]", llformat("%0.3f", result["resource_cost"].asReal()));
+ childSetTextArg("weights_left", "[ST]", llformat("%0.3f", result["model_streaming_cost"].asReal()));
+ childSetTextArg("weights_right", "[SIM]", llformat("%0.3f", result["simulation_cost"].asReal()));
+ childSetTextArg("weights_left", "[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());
@@ -5532,20 +5666,23 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason)
{
- toggleCalculateButton(true);
llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl;
+ doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
}
/*virtual*/
void LLFloaterModelPreview::onModelUploadSuccess()
{
+ assert_main_thread();
closeFloater(false);
}
/*virtual*/
void LLFloaterModelPreview::onModelUploadFailure()
{
+ assert_main_thread();
toggleCalculateButton(true);
+ mUploadBtn->setEnabled(true);
}
S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 3a5f7602fe..723e8c48b8 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -125,7 +125,7 @@ public:
void buildJointToNodeMappingFromScene( daeElement* pRoot );
void processJointToNodeMapping( domNode* pNode );
-
+ void processChildJoints( domNode* pParentNode );
//map of avatar joints as named in COLLADA assets to internal joint names
std::map<std::string, std::string> mJointMap;
@@ -336,7 +336,8 @@ public:
void updateStatusMessages();
void clearGLODGroup();
void onLODParamCommit(bool enforce_tri_limit);
-
+ void addEmptyFace( LLModel* pTarget );
+
const bool getModelPivot( void ) const { return mHasPivot; }
void setHasPivot( bool val ) { mHasPivot = val; }
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
@@ -365,9 +366,6 @@ public:
void setLoadState( U32 state ) { mLoadState = state; }
U32 getLoadState() { return mLoadState; }
- //setRestJointFlag: If an asset comes through that changes the joints, we want the reset to persist
- void setResetJointFlag( bool state ) { if ( !mResetJoints ) mResetJoints = state; }
- const bool getResetJointFlag( void ) const { return mResetJoints; }
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
new file mode 100644
index 0000000000..7ad34431fb
--- /dev/null
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -0,0 +1,328 @@
+/**
+ * @file llfloaterobjectweights.cpp
+ * @brief Object weights advanced view floater
+ *
+ * $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 "llfloaterobjectweights.h"
+
+#include "llparcel.h"
+
+#include "llfloaterreg.h"
+#include "lltextbox.h"
+
+#include "llagent.h"
+#include "llselectmgr.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+/**
+ * struct LLCrossParcelFunctor
+ *
+ * A functor that checks whether a bounding box for all
+ * selected objects crosses a region or parcel bounds.
+ */
+struct LLCrossParcelFunctor : public LLSelectedObjectFunctor
+{
+ /*virtual*/ bool apply(LLViewerObject* obj)
+ {
+ // Add the root object box.
+ mBoundingBox.addBBoxAgent(LLBBox(obj->getPositionRegion(), obj->getRotationRegion(), obj->getScale() * -0.5f, obj->getScale() * 0.5f).getAxisAligned());
+
+ // Extend the bounding box across all the children.
+ LLViewerObject::const_child_list_t children = obj->getChildren();
+ for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin();
+ iter != children.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ mBoundingBox.addBBoxAgent(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+ }
+
+ bool result = false;
+
+ LLViewerRegion* region = obj->getRegion();
+ if (region)
+ {
+ std::vector<LLBBox> boxes;
+ boxes.push_back(mBoundingBox);
+ result = region->objectsCrossParcel(boxes);
+ }
+
+ return result;
+ }
+
+private:
+ LLBBox mBoundingBox;
+};
+
+/**
+ * Class LLLandImpactsObserver
+ *
+ * An observer class to monitor parcel selection and update
+ * the land impacts data from a parcel containing the selected object.
+ */
+class LLLandImpactsObserver : public LLParcelObserver
+{
+public:
+ virtual void changed()
+ {
+ LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights");
+ if(object_weights_floater)
+ {
+ object_weights_floater->updateLandImpacts();
+ }
+ }
+};
+
+
+LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
+: LLFloater(key),
+ mSelectedObjects(NULL),
+ mSelectedPrims(NULL),
+ mSelectedDownloadWeight(NULL),
+ mSelectedPhysicsWeight(NULL),
+ mSelectedServerWeight(NULL),
+ mSelectedDisplayWeight(NULL),
+ mSelectedOnLand(NULL),
+ mRezzedOnLand(NULL),
+ mRemainingCapacity(NULL),
+ mTotalCapacity(NULL),
+ mLandImpactsObserver(NULL)
+{
+ mLandImpactsObserver = new LLLandImpactsObserver();
+ LLViewerParcelMgr::getInstance()->addObserver(mLandImpactsObserver);
+}
+
+LLFloaterObjectWeights::~LLFloaterObjectWeights()
+{
+ mObjectSelection = NULL;
+ mParcelSelection = NULL;
+
+ mSelectMgrConnection.disconnect();
+
+ LLViewerParcelMgr::getInstance()->removeObserver(mLandImpactsObserver);
+ delete mLandImpactsObserver;
+}
+
+// virtual
+BOOL LLFloaterObjectWeights::postBuild()
+{
+ mSelectedObjects = getChild<LLTextBox>("objects");
+ mSelectedPrims = getChild<LLTextBox>("prims");
+
+ mSelectedDownloadWeight = getChild<LLTextBox>("download");
+ mSelectedPhysicsWeight = getChild<LLTextBox>("physics");
+ mSelectedServerWeight = getChild<LLTextBox>("server");
+ mSelectedDisplayWeight = getChild<LLTextBox>("display");
+
+ mSelectedOnLand = getChild<LLTextBox>("selected");
+ mRezzedOnLand = getChild<LLTextBox>("rezzed_on_land");
+ mRemainingCapacity = getChild<LLTextBox>("remaining_capacity");
+ mTotalCapacity = getChild<LLTextBox>("total_capacity");
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterObjectWeights::onOpen(const LLSD& key)
+{
+ mSelectMgrConnection = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLFloaterObjectWeights::refresh, this));
+
+ mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+ mParcelSelection = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
+
+ refresh();
+}
+
+// virtual
+void LLFloaterObjectWeights::onClose(bool app_quitting)
+{
+ mSelectMgrConnection.disconnect();
+
+ mObjectSelection = NULL;
+ mParcelSelection = NULL;
+}
+
+// virtual
+void LLFloaterObjectWeights::onWeightsUpdate(const SelectionCost& selection_cost)
+{
+ mSelectedDownloadWeight->setText(llformat("%.1f", selection_cost.mNetworkCost));
+ mSelectedPhysicsWeight->setText(llformat("%.1f", selection_cost.mPhysicsCost));
+ mSelectedServerWeight->setText(llformat("%.1f", selection_cost.mSimulationCost));
+
+ S32 render_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectRenderCost();
+ mSelectedDisplayWeight->setText(llformat("%d", render_cost));
+
+ toggleWeightsLoadingIndicators(false);
+}
+
+//virtual
+void LLFloaterObjectWeights::setErrorStatus(U32 status, const std::string& reason)
+{
+ const std::string text = getString("nothing_selected");
+
+ mSelectedDownloadWeight->setText(text);
+ mSelectedPhysicsWeight->setText(text);
+ mSelectedServerWeight->setText(text);
+ mSelectedDisplayWeight->setText(text);
+
+ toggleWeightsLoadingIndicators(false);
+}
+
+void LLFloaterObjectWeights::updateLandImpacts()
+{
+ LLParcel *parcel = mParcelSelection->getParcel();
+ if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ updateIfNothingSelected();
+ }
+ else
+ {
+ S32 rezzed_prims = parcel->getSimWidePrimCount();
+ S32 total_capacity = parcel->getSimWideMaxPrimCapacity();
+
+ mRezzedOnLand->setText(llformat("%d", rezzed_prims));
+ mRemainingCapacity->setText(llformat("%d", total_capacity - rezzed_prims));
+ mTotalCapacity->setText(llformat("%d", total_capacity));
+
+ toggleLandImpactsLoadingIndicators(false);
+ }
+}
+
+void LLFloaterObjectWeights::refresh()
+{
+ LLSelectMgr* sel_mgr = LLSelectMgr::getInstance();
+
+ if (sel_mgr->getSelection()->isEmpty())
+ {
+ updateIfNothingSelected();
+ }
+ else
+ {
+ S32 prim_count = sel_mgr->getSelection()->getObjectCount();
+ S32 link_count = sel_mgr->getSelection()->getRootObjectCount();
+ F32 prim_equiv = sel_mgr->getSelection()->getSelectedLinksetCost();
+
+ mSelectedObjects->setText(llformat("%d", link_count));
+ mSelectedPrims->setText(llformat("%d", prim_count));
+ mSelectedOnLand->setText(llformat("%.1d", (S32)prim_equiv));
+
+ LLCrossParcelFunctor func;
+ if (sel_mgr->getSelection()->applyToRootObjects(&func, true))
+ {
+ // Some of the selected objects cross parcel bounds.
+ // We don't display object weights and land impacts in this case.
+ const std::string text = getString("nothing_selected");
+
+ mRezzedOnLand->setText(text);
+ mRemainingCapacity->setText(text);
+ mTotalCapacity->setText(text);
+
+ toggleLandImpactsLoadingIndicators(false);
+ }
+ else
+ {
+ LLViewerObject* selected_object = mObjectSelection->getFirstObject();
+ if (selected_object)
+ {
+ // Select a parcel at the currently selected object's position.
+ LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal());
+
+ toggleLandImpactsLoadingIndicators(true);
+ }
+ else
+ {
+ llwarns << "Failed to get selected object" << llendl;
+ }
+ }
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region && region->capabilitiesReceived())
+ {
+ for (LLObjectSelection::valid_root_iterator iter = sel_mgr->getSelection()->valid_root_begin();
+ iter != sel_mgr->getSelection()->valid_root_end(); ++iter)
+ {
+ LLAccountingCostManager::getInstance()->addObject((*iter)->getObject()->getID());
+ }
+
+ std::string url = region->getCapability("ResourceCostSelected");
+ if (!url.empty())
+ {
+ LLAccountingCostManager::getInstance()->fetchCosts(Roots, url, getObserverHandle());
+ toggleWeightsLoadingIndicators(true);
+ }
+ }
+ else
+ {
+ llwarns << "Failed to get region capabilities" << llendl;
+ }
+ }
+}
+
+void LLFloaterObjectWeights::toggleWeightsLoadingIndicators(bool visible)
+{
+ childSetVisible("download_loading_indicator", visible);
+ childSetVisible("physics_loading_indicator", visible);
+ childSetVisible("server_loading_indicator", visible);
+ childSetVisible("display_loading_indicator", visible);
+
+ mSelectedDownloadWeight->setVisible(!visible);
+ mSelectedPhysicsWeight->setVisible(!visible);
+ mSelectedServerWeight->setVisible(!visible);
+ mSelectedDisplayWeight->setVisible(!visible);
+}
+
+void LLFloaterObjectWeights::toggleLandImpactsLoadingIndicators(bool visible)
+{
+ childSetVisible("selected_loading_indicator", visible);
+ childSetVisible("rezzed_on_land_loading_indicator", visible);
+ childSetVisible("remaining_capacity_loading_indicator", visible);
+ childSetVisible("total_capacity_loading_indicator", visible);
+
+ mSelectedOnLand->setVisible(!visible);
+ mRezzedOnLand->setVisible(!visible);
+ mRemainingCapacity->setVisible(!visible);
+ mTotalCapacity->setVisible(!visible);
+}
+
+void LLFloaterObjectWeights::updateIfNothingSelected()
+{
+ const std::string text = getString("nothing_selected");
+
+ mSelectedObjects->setText(text);
+ mSelectedPrims->setText(text);
+
+ mSelectedDownloadWeight->setText(text);
+ mSelectedPhysicsWeight->setText(text);
+ mSelectedServerWeight->setText(text);
+ mSelectedDisplayWeight->setText(text);
+
+ mSelectedOnLand->setText(text);
+ mRezzedOnLand->setText(text);
+ mRemainingCapacity->setText(text);
+ mTotalCapacity->setText(text);
+
+ toggleWeightsLoadingIndicators(false);
+ toggleLandImpactsLoadingIndicators(false);
+}
diff --git a/indra/newview/llfloaterobjectweights.h b/indra/newview/llfloaterobjectweights.h
new file mode 100644
index 0000000000..50d028909e
--- /dev/null
+++ b/indra/newview/llfloaterobjectweights.h
@@ -0,0 +1,89 @@
+/**
+ * @file llfloaterobjectweights.h
+ * @brief Object weights advanced view floater
+ *
+ * $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_LLFLOATEROBJECTWEIGHTS_H
+#define LL_LLFLOATEROBJECTWEIGHTS_H
+
+#include "llfloater.h"
+
+#include "llaccountingcostmanager.h"
+
+class LLLandImpactsObserver;
+class LLObjectSelection;
+class LLParcelSelection;
+class LLTextBox;
+
+class LLFloaterObjectWeights : public LLFloater, LLAccountingCostObserver
+{
+public:
+ LOG_CLASS(LLFloaterObjectWeights);
+
+ typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle;
+ typedef LLSafeHandle<LLParcelSelection> LLParcelSelectionHandle;
+
+ LLFloaterObjectWeights(const LLSD& key);
+ ~LLFloaterObjectWeights();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
+
+ /*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost);
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+ void updateLandImpacts();
+
+private:
+ void refresh();
+
+ void toggleWeightsLoadingIndicators(bool visible);
+ void toggleLandImpactsLoadingIndicators(bool visible);
+
+ void updateIfNothingSelected();
+
+ LLTextBox *mSelectedObjects;
+ LLTextBox *mSelectedPrims;
+
+ LLTextBox *mSelectedDownloadWeight;
+ LLTextBox *mSelectedPhysicsWeight;
+ LLTextBox *mSelectedServerWeight;
+ LLTextBox *mSelectedDisplayWeight;
+
+ LLTextBox *mSelectedOnLand;
+ LLTextBox *mRezzedOnLand;
+ LLTextBox *mRemainingCapacity;
+ LLTextBox *mTotalCapacity;
+
+ LLLandImpactsObserver *mLandImpactsObserver;
+
+ LLObjectSelectionHandle mObjectSelection;
+ LLParcelSelectionHandle mParcelSelection;
+
+ boost::signals2::connection mSelectMgrConnection;
+};
+
+#endif //LL_LLFLOATEROBJECTWEIGHTS_H
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 9a99417e93..676059779c 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -172,30 +172,9 @@ bool estate_dispatch_initialized = false;
LLUUID LLFloaterRegionInfo::sRequestInvoice;
-void LLFloaterRegionInfo::onConsoleReplyReceived(const std::string& output)
-{
- llwarns << "here is what they're giving us: " << output << llendl;
-
- if (output.find("FALSE") != std::string::npos)
- {
- getChild<LLUICtrl>("mesh_rez_enabled_check")->setValue(FALSE);
- }
- else
- {
- getChild<LLUICtrl>("mesh_rez_enabled_check")->setValue(TRUE);
- }
-}
-
-
LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
: LLFloater(seed)
-{
- mConsoleReplySignalConnection = LLFloaterRegionDebugConsole::setConsoleReplyCallback(
- boost::bind(
- &LLFloaterRegionInfo::onConsoleReplyReceived,
- this,
- _1));
-}
+{}
BOOL LLFloaterRegionInfo::postBuild()
{
@@ -246,9 +225,7 @@ BOOL LLFloaterRegionInfo::postBuild()
}
LLFloaterRegionInfo::~LLFloaterRegionInfo()
-{
- mConsoleReplySignalConnection.disconnect();
-}
+{}
void LLFloaterRegionInfo::onOpen(const LLSD& key)
{
@@ -638,9 +615,6 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
getChildView("im_btn")->setEnabled(allow_modify);
getChildView("manage_telehub_btn")->setEnabled(allow_modify);
- const bool enable_mesh = gMeshRepo.meshRezEnabled();
- getChildView("mesh_rez_enabled_check")->setVisible(enable_mesh);
- getChildView("mesh_rez_enabled_check")->setEnabled(getChildView("mesh_rez_enabled_check")->getEnabled() && enable_mesh);
// Data gets filled in by processRegionInfo
return LLPanelRegionInfo::refreshFromRegion(region);
@@ -659,7 +633,6 @@ BOOL LLPanelRegionGeneralInfo::postBuild()
initCtrl("access_combo");
initCtrl("restrict_pushobject");
initCtrl("block_parcel_search_check");
- initCtrl("mesh_rez_enabled_check");
childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this));
childSetAction("kick_all_btn", onClickKickAll, this);
@@ -875,27 +848,6 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings);
}
- std::string sim_console_url = gAgent.getRegion()->getCapability("SimConsoleAsync");
-
- if (!sim_console_url.empty())
- {
- std::string update_str = "set mesh_rez_enabled ";
- if (getChild<LLUICtrl>("mesh_rez_enabled_check")->getValue().asBoolean())
- {
- update_str += "true";
- }
- else
- {
- update_str += "false";
- }
-
- LLHTTPClient::post(
- sim_console_url,
- LLSD(update_str),
- new ConsoleUpdateResponder);
- }
-
-
// if we changed access levels, tell user about it
LLViewerRegion* region = gAgent.getRegion();
if (region && (getChild<LLUICtrl>("access_combo")->getValue().asInteger() != region->getSimAccess()) )
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index c1fef57ac9..c402de66e8 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -100,10 +100,6 @@ private:
LLFloaterRegionInfo(const LLSD& seed);
~LLFloaterRegionInfo();
-
- void onConsoleReplyReceived(const std::string& output);
-
- boost::signals2::connection mConsoleReplySignalConnection;;
protected:
void onTabSelected(const LLSD& param);
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 84fb8bd9e7..48aeeafcfd 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -84,7 +84,6 @@
#include "llviewerwindow.h"
#include "llvovolume.h"
#include "lluictrlfactory.h"
-#include "llaccountingquotamanager.h"
#include "llmeshrepository.h"
// Globals
@@ -436,7 +435,8 @@ void LLFloaterTools::refresh()
if (sShowObjectCost)
{
std::string prim_cost_string;
- LLResMgr::getInstance()->getIntegerString(prim_cost_string, calcRenderCost());
+ S32 render_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectRenderCost();
+ LLResMgr::getInstance()->getIntegerString(prim_cost_string, render_cost);
getChild<LLUICtrl>("RenderingCost")->setTextArg("[COUNT]", prim_cost_string);
}
@@ -460,7 +460,6 @@ void LLFloaterTools::refresh()
std::ostringstream selection_info;
- bool show_adv_weight = gSavedSettings.getBOOL("ShowAdvancedBuilderOptions");
bool show_mesh_cost = gMeshRepo.meshRezEnabled();
if (show_mesh_cost)
@@ -476,22 +475,19 @@ void LLFloaterTools::refresh()
selection_info << getString("status_selectcount", selection_args);
- 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<<".";
- }
+ selection_info << ",";
+
+ S32 render_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectRenderCost();
+
+ childSetTextArg("selection_weight", "[PHYS_WEIGHT]", llformat("%.1f", link_phys_cost));
+ childSetTextArg("selection_weight", "[DISP_WEIGHT]", llformat("%.1d", render_cost));
+
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_weight", have_selection);
childSetVisible("selection_empty", !have_selection);
}
@@ -762,7 +758,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty();
getChildView("selection_count")->setVisible(!land_visible && have_selection);
- getChildView("selection_weight")->setVisible(!land_visible && have_selection && gSavedSettings.getBOOL("ShowAdvancedBuilderOptions"));
+ getChildView("selection_weight")->setVisible(!land_visible && have_selection);
getChildView("selection_empty")->setVisible(!land_visible && !have_selection);
mTab->setVisible(!land_visible);
@@ -826,6 +822,9 @@ void LLFloaterTools::onClose(bool app_quitting)
//gMenuBarView->setItemVisible("BuildTools", FALSE);
LLFloaterReg::hideInstance("media_settings");
+
+ // hide the advanced object weights floater
+ LLFloaterReg::hideInstance("object_weights");
}
void click_popup_info(void*)
@@ -1012,35 +1011,6 @@ void LLFloaterTools::onClickGridOptions()
//floaterp->addDependentFloater(LLFloaterBuildOptions::getInstance(), FALSE);
}
-S32 LLFloaterTools::calcRenderCost()
-{
- S32 cost = 0;
- std::set<LLUUID> textures;
-
- for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin();
- selection_iter != LLSelectMgr::getInstance()->getSelection()->end();
- ++selection_iter)
- {
- LLSelectNode *select_node = *selection_iter;
- if (select_node)
- {
- LLViewerObject *vobj = select_node->getObject();
- if (vobj->getVolume())
- {
- LLVOVolume* volume = (LLVOVolume*) vobj;
-
- cost += volume->getRenderCost(textures);
- cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
- textures.clear();
- }
- }
- }
-
-
- return cost;
-}
-
-
// static
void LLFloaterTools::setEditTool(void* tool_pointer)
{
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 69636190fc..8c4cb721d3 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -113,7 +113,6 @@ private:
static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response);
static void setObjectType( LLPCode pcode );
void onClickGridOptions();
- S32 calcRenderCost();
public:
LLButton *mBtnFocus;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index fc594841e3..e12f140747 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -411,7 +411,6 @@ public:
cc = llsd_from_file("fake_upload_error.xml");
}
- //assert_main_thread();
mThread->mPendingUploads--;
dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
@@ -1321,6 +1320,7 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::map<LLModel*,S32> mesh_index;
std::string model_name;
+ std::string model_metric;
S32 instance_num = 0;
@@ -1342,6 +1342,11 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
model_name = data.mBaseModel->getName();
}
+ if (model_metric.empty())
+ {
+ model_metric = data.mBaseModel->getMetric();
+ }
+
std::stringstream ostr;
LLModel::Decomposition& decomp =
@@ -1455,6 +1460,8 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
if (model_name.empty()) model_name = "mesh model";
result["name"] = model_name;
+ if (model_metric.empty()) model_metric = "MUT_Unspecified";
+ res["metric"] = model_metric;
result["asset_resources"] = res;
dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));
@@ -1463,51 +1470,57 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
void LLMeshUploadThread::generateHulls()
{
+ bool has_valid_requests = false ;
+
for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
- {
- LLMeshUploadData data;
- data.mBaseModel = iter->first;
+ {
+ LLMeshUploadData data;
+ data.mBaseModel = iter->first;
- LLModelInstance& instance = *(iter->second.begin());
+ LLModelInstance& instance = *(iter->second.begin());
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = instance.mLOD[i];
+ }
- //queue up models for hull generation
- LLModel* physics = NULL;
+ //queue up models for hull generation
+ LLModel* physics = NULL;
- 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];
- }
+ 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];
+ }
- llassert(physics != NULL);
+ llassert(physics != NULL);
- DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
- if(request->isValid())
- {
- gMeshRepo.mDecompThread->submitRequest(request);
- }
+ DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
+ if(request->isValid())
+ {
+ gMeshRepo.mDecompThread->submitRequest(request);
+ has_valid_requests = true ;
}
-
+ }
+
+ if(has_valid_requests)
+ {
while (!mPhysicsComplete)
{
apr_sleep(100);
}
+ }
}
void LLMeshUploadThread::doWholeModelUpload()
@@ -1688,6 +1701,7 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
{
LLPointer<LLVolume> volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i));
volume->copyVolumeFaces(data.mModel[i]);
+ volume->setMeshAssetLoaded(TRUE);
}
}
@@ -2141,11 +2155,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
if (volume)
{
- if (volume->getNumVolumeFaces() == 0 && !volume->isTetrahedron())
- {
- volume->makeTetrahedron();
- }
-
LLVolumeParams params = volume->getParams();
LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params);
@@ -2156,7 +2165,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
if (last_lod >= 0)
{
LLVolume* lod = group->refLOD(last_lod);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return last_lod;
@@ -2168,7 +2177,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
for (S32 i = detail-1; i >= 0; --i)
{
LLVolume* lod = group->refLOD(i);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return i;
@@ -2181,7 +2190,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
for (S32 i = detail+1; i < 4; ++i)
{
LLVolume* lod = group->refLOD(i);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return i;
@@ -2432,7 +2441,6 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
if (volume->getNumVolumeFaces() <= 0)
{
llwarns << "Mesh loading returned empty volume." << llendl;
- volume->makeTetrahedron();
}
{ //update system volume
@@ -2440,6 +2448,7 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
if (sys_volume)
{
sys_volume->copyVolumeFaces(volume);
+ sys_volume->setMeshAssetLoaded(TRUE);
LLPrimitive::getVolumeManager()->unrefVolume(sys_volume);
}
else
@@ -2496,7 +2505,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
return mThread->getActualMeshLOD(mesh_params, lod);
}
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj)
{
if (mesh_id.notNull())
{
@@ -2752,7 +2761,7 @@ void LLMeshRepository::uploadError(LLSD& args)
}
//static
-F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod)
+F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
F32 max_distance = 512.f;
@@ -2841,6 +2850,11 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32
triangles_low*low_area +
triangles_lowest*lowest_area;
+ if (unscaled_value)
+ {
+ *unscaled_value = weighted_avg;
+ }
+
return weighted_avg/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;
}
@@ -3135,32 +3149,33 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
make_box(mCurRequest);
}
+ else
+ {
+ mMutex->lock();
+ mCurRequest->mHull.clear();
+ mCurRequest->mHull.resize(1);
+ mCurRequest->mHullMesh.clear();
+ mMutex->unlock();
- mMutex->lock();
- mCurRequest->mHull.clear();
- mCurRequest->mHull.resize(1);
- mCurRequest->mHullMesh.clear();
- mMutex->unlock();
-
- std::vector<LLVector3> p;
- LLCDHull hull;
+ 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);
+ // 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;
+ 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);
- }
+ 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();
-
+ mMutex->lock();
+ mCurRequest->mHull[0] = p;
+ mMutex->unlock();
+ }
#else
setMeshData(mesh, false);
@@ -3498,8 +3513,7 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
bool LLMeshRepository::meshUploadEnabled()
{
LLViewerRegion *region = gAgent.getRegion();
- if(gSavedSettings.getBOOL("MeshEnabled") &&
- LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
region)
{
return region->meshUploadEnabled();
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 35a7314cd5..31b84ea0d9 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -445,7 +445,7 @@ public:
static U32 sCacheBytesWritten;
static U32 sPeakKbps;
- static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1);
+ static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
LLMeshRepository();
@@ -464,7 +464,7 @@ public:
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
- const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
+ const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index c222bbb191..e4b2396bc6 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1112,7 +1112,16 @@ void LLPanelObject::getState( )
if (mCtrlSculptType)
{
- mCtrlSculptType->setCurrentByIndex(sculpt_stitching);
+ if (sculpt_stitching == LL_SCULPT_TYPE_NONE)
+ {
+ // since 'None' is no longer an option in the combo box
+ // use 'Plane' as an equivalent sculpt type
+ mCtrlSculptType->setCurrentByID(LLSD(LL_SCULPT_TYPE_PLANE));
+ }
+ else
+ {
+ mCtrlSculptType->setCurrentByID(LLSD(sculpt_stitching));
+ }
mCtrlSculptType->setEnabled(editable && !isMesh);
}
@@ -1749,7 +1758,7 @@ void LLPanelObject::sendSculpt()
U8 sculpt_type = 0;
if (mCtrlSculptType)
- sculpt_type |= mCtrlSculptType->getCurrentIndex();
+ sculpt_type |= mCtrlSculptType->getValue().asInteger();
bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index bb87601d20..12eea7844d 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -351,7 +351,7 @@ void LLPanelVolume::getState( )
getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible);
if (is_flexible || (volobjp && volobjp->canBeFlexible()))
{
- getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp);
+ getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh());
}
else
{
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 26b2b0f5c3..733902ad30 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -6520,32 +6520,75 @@ U32 LLObjectSelection::getSelectedObjectTriangleCount()
return count;
}
-/*S32 LLObjectSelection::getSelectedObjectRenderCost()
+S32 LLObjectSelection::getSelectedObjectRenderCost()
{
S32 cost = 0;
LLVOVolume::texture_cost_t textures;
+ typedef std::set<LLUUID> uuid_list_t;
+ uuid_list_t computed_objects;
+
+ typedef std::list<LLPointer<LLViewerObject> > child_list_t;
+ typedef const child_list_t const_child_list_t;
+
+ // add render cost of complete linksets first, to get accurate texture counts
for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
{
LLSelectNode* node = *iter;
+
LLVOVolume* object = (LLVOVolume*)node->getObject();
- if (object)
- {
- cost += object->getRenderCost(textures);
- }
-
- for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ if (object && object->isRootEdit())
{
- // add the cost of each individual texture in the linkset
- cost += iter->second;
+ cost += object->getRenderCost(textures);
+ computed_objects.insert(object->getID());
+
+ const_child_list_t children = object->getChildren();
+ for (const_child_list_t::const_iterator child_iter = children.begin();
+ child_iter != children.end();
+ ++child_iter)
+ {
+ LLViewerObject* child_obj = *child_iter;
+ LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+ if (child)
+ {
+ cost += child->getRenderCost(textures);
+ computed_objects.insert(child->getID());
+ }
+ }
+
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
+
+ textures.clear();
}
- textures.clear();
}
+
+ // add any partial linkset objects, texture cost may be slightly misleading
+ for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
+ {
+ LLSelectNode* node = *iter;
+ LLVOVolume* object = (LLVOVolume*)node->getObject();
+
+ if (object && computed_objects.find(object->getID()) == computed_objects.end() )
+ {
+ cost += object->getRenderCost(textures);
+ computed_objects.insert(object->getID());
+ }
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
- return cost;
-}*/
+ textures.clear();
+ }
+ return cost;
+}
//-----------------------------------------------------------------------------
// getTECount()
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fd17781a2e..6c2b71dd0a 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2763,6 +2763,115 @@ void renderUpdateType(LLDrawable* drawablep)
}
}
+void renderComplexityDisplay(LLDrawable* drawablep)
+{
+ LLViewerObject* vobj = drawablep->getVObj();
+ if (!vobj)
+ {
+ return;
+ }
+
+ LLVOVolume *voVol = dynamic_cast<LLVOVolume*>(vobj);
+
+ if (!voVol)
+ {
+ return;
+ }
+
+ if (!voVol->isRoot())
+ {
+ return;
+ }
+
+ LLVOVolume::texture_cost_t textures;
+ F32 cost = (F32) voVol->getRenderCost(textures);
+
+ // add any child volumes
+ LLViewerObject::const_child_list_t children = voVol->getChildren();
+ for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
+ {
+ const LLViewerObject *child = *iter;
+ const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child);
+ if (child_volume)
+ {
+ cost += child_volume->getRenderCost(textures);
+ }
+ }
+
+ // add texture cost
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
+
+ F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax();
+
+
+
+ // allow user to set a static color scale
+ if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0)
+ {
+ cost_max = gSavedSettings.getS32("RenderComplexityStaticMax");
+ }
+
+ F32 cost_ratio = cost / cost_max;
+
+ // cap cost ratio at 1.0f in case cost_max is at a low threshold
+ cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio;
+
+ LLGLEnable blend(GL_BLEND);
+
+ LLColor4 color;
+ const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin");
+ const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid");
+ const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax");
+
+ if (cost_ratio < 0.5f)
+ {
+ color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2);
+ }
+ else
+ {
+ color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2);
+ }
+
+ LLSD color_val = color.getValue();
+
+ // don't highlight objects below the threshold
+ if (cost > gSavedSettings.getS32("RenderComplexityThreshold"))
+ {
+ glColor4f(color[0],color[1],color[2],0.5f);
+
+
+ S32 num_faces = drawablep->getNumFaces();
+ if (num_faces)
+ {
+ for (S32 i = 0; i < num_faces; ++i)
+ {
+ pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ }
+ }
+ LLViewerObject::const_child_list_t children = voVol->getChildren();
+ for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
+ {
+ const LLViewerObject *child = *iter;
+ if (child)
+ {
+ num_faces = child->getNumFaces();
+ if (num_faces)
+ {
+ for (S32 i = 0; i < num_faces; ++i)
+ {
+ pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ }
+ }
+ }
+ }
+ }
+
+ voVol->setDebugText(llformat("%4.0f", cost));
+}
void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
{
@@ -3867,6 +3976,10 @@ public:
{
renderUpdateType(drawable);
}
+ if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
+ {
+ renderComplexityDisplay(drawable);
+ }
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
@@ -4115,7 +4228,8 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
LLPipeline::RENDER_DEBUG_AGENT_TARGET |
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
- LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
+ LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
{
return;
}
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index b87ca1eaec..0f0b7d7e78 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -142,7 +142,6 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue)
LLPipeline::RENDER_TYPE_WATER,
LLPipeline::RENDER_TYPE_PASS_GRASS,
LLPipeline::RENDER_TYPE_HUD,
- LLPipeline::RENDER_TYPE_PARTICLES,
LLPipeline::RENDER_TYPE_CLOUDS,
LLPipeline::RENDER_TYPE_HUD_PARTICLES,
LLPipeline::END_RENDER_TYPES);
@@ -158,7 +157,6 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue)
LLPipeline::RENDER_TYPE_WATER,
LLPipeline::RENDER_TYPE_PASS_GRASS,
LLPipeline::RENDER_TYPE_HUD,
- LLPipeline::RENDER_TYPE_PARTICLES,
LLPipeline::RENDER_TYPE_CLOUDS,
LLPipeline::RENDER_TYPE_HUD_PARTICLES,
LLPipeline::END_RENDER_TYPES);
@@ -168,6 +166,11 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue)
return true;
}
+bool handleRenderAvatarComplexityLimitChanged(const LLSD& newvalue)
+{
+ return true;
+}
+
bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
{
LLWorld::getInstance()->updateWaterObjects();
@@ -404,7 +407,7 @@ static bool handleRenderDeferredChanged(const LLSD& newvalue)
gPipeline.releaseGLBuffers();
gPipeline.createGLBuffers();
gPipeline.resetVertexBuffers();
- if (LLPipeline::sRenderDeferred && LLRenderTarget::sUseFBO)
+ if (LLPipeline::sRenderDeferred == (BOOL)LLRenderTarget::sUseFBO)
{
LLViewerShaderMgr::instance()->setShaders();
}
@@ -611,6 +614,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _2));
+ gSavedSettings.getControl("RenderAvatarComplexityLimit")->getSignal()->connect(boost::bind(&handleRenderAvatarComplexityLimitChanged, _2));
gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2));
gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2));
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index fecc6d91bd..60f01fa746 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -79,6 +79,7 @@
#include "llfloatermodelwizard.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
+#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
#include "llfloaterpay.h"
#include "llfloaterperms.h"
@@ -226,6 +227,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
+ LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
LLFloaterPayUtil::registerFloater();
@@ -285,7 +287,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>);
LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
- LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWebContent>);
+ LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWebContent>);
LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
LLFloaterWindowSizeUtil::registerFloater();
LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index cd71b6d42a..d20b6641d3 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -100,7 +100,6 @@
#include "lltrans.h"
#include "llsdutil.h"
#include "llmediaentry.h"
-#include "llaccountingquota.h"
//#define DEBUG_UPDATE_TYPE
@@ -628,6 +627,20 @@ void LLViewerObject::constructAndAddReturnable( std::vector<PotentialReturnableO
}
}
+bool LLViewerObject::crossesParcelBounds()
+{
+ 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());
+ }
+
+ return mRegionp && mRegionp->objectsCrossParcel(boxes);
+}
+
BOOL LLViewerObject::setParent(LLViewerObject* parent)
{
if(mParent != parent)
@@ -5785,9 +5798,3 @@ public:
LLHTTPRegistration<ObjectPhysicsProperties>
gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties");
-
-void LLViewerObject::updateQuota( const SelectionQuota& quota )
-{
- //update quotas
- mSelectionQuota = quota;
-}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 1828a64917..53e951e483 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -43,7 +43,7 @@
#include "v3dmath.h"
#include "v3math.h"
#include "llvertexbuffer.h"
-#include "llaccountingquota.h"
+#include "llbbox.h"
#include "llbbox.h"
class LLAgent; // TODO: Get rid of this.
@@ -243,6 +243,10 @@ public:
void buildReturnablesForChildrenVO( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion );
void constructAndAddReturnable( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion );
+ // This method returns true if the object crosses
+ // any parcel bounds in the region.
+ bool crossesParcelBounds();
+
/*
// This method will scan through this object, and then query the
// selection manager to see if the local agent probably has the
@@ -655,9 +659,7 @@ protected:
void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
public:
- void updateQuota( const SelectionQuota& quota );
- const SelectionQuota& getQuota( void ) { return mSelectionQuota; }
-
+
private:
void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string
void deleteTEImages(); // correctly deletes list of images
@@ -719,8 +721,6 @@ protected:
F32 mPhysicsCost;
F32 mLinksetPhysicsCost;
- SelectionQuota mSelectionQuota;
-
bool mCostStale;
mutable bool mPhysicsShapeUnknown;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index db5684665b..ce88c8759f 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -58,6 +58,7 @@
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
+#include "llvovolume.h"
#include "llvoavatarself.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
@@ -993,6 +994,9 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
mNumSizeCulled = 0;
mNumVisCulled = 0;
+ // update max computed render cost
+ LLVOVolume::updateRenderComplexity();
+
// compute all sorts of time-based stats
// don't factor frames that were paused into the stats
if (! mWasPaused)
@@ -1441,15 +1445,6 @@ void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id)
mPendingObjectCost.erase(object_id);
}
-void LLViewerObjectList::updateQuota( const LLUUID& objectId, const SelectionQuota& quota )
-{
- LLViewerObject* pVO = findObject( objectId );
- if ( pVO )
- {
- pVO->updateQuota( quota );
- }
-}
-
void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object)
{
mStalePhysicsFlags.insert(object->getID());
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 9d1b5cb56f..c5f2a2c1ee 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -36,7 +36,6 @@
// project includes
#include "llviewerobject.h"
-#include "llaccountingquota.h"
class LLCamera;
class LLNetMap;
@@ -102,8 +101,6 @@ public:
F32 restitution,
F32 gravity_multiplier);
- void updateQuota( const LLUUID& objectId, const SelectionQuota& costs );
-
void shiftObjects(const LLVector3 &offset);
void repartitionObjects();
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index eff16b6a6e..e619b89f9b 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -201,6 +201,65 @@ bool LLViewerParcelOverlay::encroachesOnUnowned(const std::vector<LLBBox>& boxes
return false;
}
+bool LLViewerParcelOverlay::encroachesOnNearbyParcel(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();
+
+ // If an object crosses region borders it crosses a parcel
+ if ( min.mV[VX] < 0
+ || min.mV[VY] < 0
+ || max.mV[VX] > REGION_WIDTH_METERS
+ || max.mV[VY] > REGION_WIDTH_METERS)
+ {
+ return true;
+ }
+
+ 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 bottom = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 top = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+
+ const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
+
+ for (S32 row = bottom; row <= top; row++)
+ {
+ for (S32 col = left; col <= right; col++)
+ {
+ // This is not the rightmost column
+ if (col < GRIDS_PER_EDGE-1)
+ {
+ U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1];
+ // If the column to the east of the current one marks
+ // the other parcel's west edge and the box extends
+ // to the west it crosses the parcel border.
+ if ((east_overlay & PARCEL_WEST_LINE) && col < right)
+ {
+ return true;
+ }
+ }
+
+ // This is not the topmost column
+ if (row < GRIDS_PER_EDGE-1)
+ {
+ U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col];
+ // If the row to the north of the current one marks
+ // the other parcel's south edge and the box extends
+ // to the south it crosses the parcel border.
+ if ((north_overlay & PARCEL_SOUTH_LINE) && row < top)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
{
S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 3c6794e7d0..7445d5bf1d 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -61,6 +61,7 @@ public:
// 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 encroachesOnNearbyParcel(const std::vector<LLBBox>& boxes) const;
BOOL isSoundLocal(const LLVector3& pos) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 17f908d73f..ed943964f9 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1487,11 +1487,8 @@ void LLViewerRegion::unpackRegionHandshake()
msg->sendReliable(host);
}
-
void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
{
- capabilityNames.append("AccountingParcel");
- capabilityNames.append("AccountingSelection");
capabilityNames.append("AttachmentResources");
capabilityNames.append("AvatarPickerSearch");
capabilityNames.append("ChatSessionRequest");
@@ -1531,6 +1528,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ProvisionVoiceAccountRequest");
capabilityNames.append("RemoteParcelRequest");
capabilityNames.append("RequestTextureDownload");
+ capabilityNames.append("ResourceCostSelected");
capabilityNames.append("SearchStatRequest");
capabilityNames.append("SearchStatTracking");
capabilityNames.append("SendPostcard");
@@ -1556,10 +1554,6 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
- //prep# Finalize these!!!!!!!!!
- //capabilityNames.append("AccountingVO");
- capabilityNames.append("AccountingParcel");
- capabilityNames.append("AccountingRegion");
// Please add new capabilities alphabetically to reduce
// merge conflicts.
@@ -1790,6 +1784,11 @@ bool LLViewerRegion::childrenObjectReturnable( const std::vector<LLBBox>& boxes
return result;
}
+bool LLViewerRegion::objectsCrossParcel(const std::vector<LLBBox>& boxes) const
+{
+ return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes);
+}
+
void LLViewerRegion::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions )
{
mImpl->mLandp->getNeighboringRegions( uniqueRegions );
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index ef1a6d285c..c483c6ef52 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -322,6 +322,7 @@ public:
bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
bool childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const;
+ bool objectsCrossParcel(const std::vector<LLBBox>& boxes) const;
void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions );
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7c6a815def..e457cc3e70 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2803,7 +2803,10 @@ void LLVOAvatar::idleUpdateLoadingEffect()
LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK |
LLPartData::LL_PART_TARGET_POS_MASK );
- setParticleSource(particle_parameters, getID());
+ if (!isTooComplex()) // do not generate particles for overly-complex avatars
+ {
+ setParticleSource(particle_parameters, getID());
+ }
}
}
}
@@ -6389,6 +6392,11 @@ BOOL LLVOAvatar::getIsCloud()
{
return TRUE;
}
+
+ if (isTooComplex())
+ {
+ return TRUE;
+ }
return FALSE;
}
@@ -6483,6 +6491,16 @@ BOOL LLVOAvatar::isFullyLoaded() const
return mFullyLoaded;
}
+bool LLVOAvatar::isTooComplex() const
+{
+ if (gSavedSettings.getS32("RenderAvatarComplexityLimit") > 0 && mVisualComplexity >= gSavedSettings.getS32("RenderAvatarComplexityLimit"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
//-----------------------------------------------------------------------------
// findMotion()
@@ -8315,7 +8333,7 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
void LLVOAvatar::idleUpdateRenderCost()
{
- static const U32 ARC_BODY_PART_COST = 20;
+ static const U32 ARC_BODY_PART_COST = 200;
static const U32 ARC_LIMIT = 2048;
static std::set<LLUUID> all_textures;
@@ -8326,7 +8344,7 @@ void LLVOAvatar::idleUpdateRenderCost()
}
U32 cost = 0;
- std::set<LLUUID> textures;
+ LLVOVolume::texture_cost_t textures;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
@@ -8341,6 +8359,7 @@ void LLVOAvatar::idleUpdateRenderCost()
}
}
+
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
iter != mAttachmentPoints.end();
++iter)
@@ -8353,6 +8372,7 @@ void LLVOAvatar::idleUpdateRenderCost()
const LLViewerObject* attached_object = (*attachment_iter);
if (attached_object && !attached_object->isHUDAttachment())
{
+ textures.clear();
const LLDrawable* drawable = attached_object->mDrawable;
if (drawable)
{
@@ -8360,6 +8380,25 @@ void LLVOAvatar::idleUpdateRenderCost()
if (volume)
{
cost += volume->getRenderCost(textures);
+
+ const_child_list_t children = volume->getChildren();
+ for (const_child_list_t::const_iterator child_iter = children.begin();
+ child_iter != children.end();
+ ++child_iter)
+ {
+ LLViewerObject* child_obj = *child_iter;
+ LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+ if (child)
+ {
+ cost += child->getRenderCost(textures);
+ }
+ }
+
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
}
}
}
@@ -8367,15 +8406,17 @@ void LLVOAvatar::idleUpdateRenderCost()
}
+
+
// Diagnostic output to identify all avatar-related textures.
// Does not affect rendering cost calculation.
// Could be wrapped in a debug option if output becomes problematic.
if (isSelf())
{
// print any attachment textures we didn't already know about.
- for (std::set<LLUUID>::iterator it = textures.begin(); it != textures.end(); ++it)
+ for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
{
- LLUUID image_id = *it;
+ LLUUID image_id = it->first;
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
continue;
if (all_textures.find(image_id) == all_textures.end())
@@ -8407,9 +8448,8 @@ void LLVOAvatar::idleUpdateRenderCost()
}
}
- cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
-
setDebugText(llformat("%d", cost));
+ mVisualComplexity = cost;
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
mText->setColor(LLColor4(red,green,0,1));
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 03c0498a2a..e53b8e3f4b 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -273,6 +273,7 @@ public:
//--------------------------------------------------------------------
public:
BOOL isFullyLoaded() const;
+ bool isTooComplex() const;
bool visualParamWeightsAreDefault();
protected:
virtual BOOL getIsCloud();
@@ -285,6 +286,7 @@ private:
BOOL mPreviousFullyLoaded;
BOOL mFullyLoadedInitialized;
S32 mFullyLoadedFrameCounter;
+ S32 mVisualComplexity;
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
protected:
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 528c7acbc8..6b0a5d8642 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -90,6 +90,8 @@ F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
+S32 LLVOVolume::mRenderComplexity_last = 0;
+S32 LLVOVolume::mRenderComplexity_current = 0;
LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
@@ -367,6 +369,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Unpack texture entry data
//
+
S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
if (result & teDirtyBits)
{
@@ -969,18 +972,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
S32 lod = mLOD;
BOOL is404 = FALSE;
-
+
if (isSculpted())
{
// if it's a mesh
if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{ //meshes might not have all LODs, get the force detail to best existing LOD
-
LLUUID mesh_id = volume_params.getSculptID();
- //profile and path params don't matter for meshes
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
-
lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
if (lod == -1)
{
@@ -1036,14 +1035,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
updateSculptTexture();
-
if (isSculpted())
{
updateSculptTexture();
// if it's a mesh
if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
- if (getVolume()->getNumVolumeFaces() == 0 || getVolume()->isTetrahedron())
+ if (!getVolume()->isMeshAssetLoaded())
{
//load request not yet issued, request pipeline load this mesh
LLUUID asset_id = volume_params.getSculptID();
@@ -1662,11 +1660,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
compiled = TRUE;
sNumLODChanges += new_num_faces ;
+ if((S32)getNumTEs() != getVolume()->getNumFaces())
+ {
+ setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
+ }
+
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
{
LLFastTimer t(FTM_GEN_TRIANGLES);
- if (new_num_faces != old_num_faces)
+ if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
{
regenFaces();
}
@@ -2971,24 +2974,38 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
// total cost is returned value + 5 * size of the resulting set.
// Cannot include cost of textures, as they may be re-used in linked
// children, and cost should only be increased for unique textures -Nyx
-U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
+U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
{
- // base cost of each prim should be 10 points
- static const U32 ARC_PRIM_COST = 10;
+ // Get access to params we'll need at various points.
+ // Skip if this is object doesn't have a volume (e.g. is an avatar).
+ BOOL has_volume = (getVolume() != NULL);
+ LLVolumeParams volume_params;
+ LLPathParams path_params;
+ LLProfileParams profile_params;
+
+ U32 num_triangles = 0;
+
// per-prim costs
- static const U32 ARC_INVISI_COST = 1;
- static const U32 ARC_SHINY_COST = 1;
- static const U32 ARC_GLOW_COST = 1;
- static const U32 ARC_FLEXI_COST = 8;
- static const U32 ARC_PARTICLE_COST = 16;
- static const U32 ARC_BUMP_COST = 4;
+ static const U32 ARC_PARTICLE_COST = 1; // determined experimentally
+ static const U32 ARC_PARTICLE_MAX = 2048; // default values
+ static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested
+ static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims
+ static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face
+
- // per-face costs
- static const U32 ARC_PLANAR_COST = 1;
- static const U32 ARC_ANIM_TEX_COST = 4;
- static const U32 ARC_ALPHA_COST = 4;
+ // per-prim multipliers
+ static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance
+ static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance
+ static const F32 ARC_FLEXI_MULT = 5; // tested based on performance
+ static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance
+ static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance
+ static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance
- U32 shame = ARC_PRIM_COST;
+ static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact
+ static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance
+ static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance
+
+ F32 shame = 0;
U32 invisi = 0;
U32 shiny = 0;
@@ -2997,9 +3014,72 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
U32 flexi = 0;
U32 animtex = 0;
U32 particles = 0;
- U32 scale = 0;
U32 bump = 0;
U32 planar = 0;
+ U32 weighted_mesh = 0;
+ U32 produces_light = 0;
+ U32 media_faces = 0;
+
+ const LLDrawable* drawablep = mDrawable;
+ U32 num_faces = drawablep->getNumFaces();
+
+ if (has_volume)
+ {
+ volume_params = getVolume()->getParams();
+ path_params = volume_params.getPathParams();
+ profile_params = volume_params.getProfileParams();
+
+ F32 weighted_triangles = -1.0;
+ getStreamingCost(NULL, NULL, &weighted_triangles);
+
+ if (weighted_triangles > 0.0)
+ {
+ num_triangles = (U32)(weighted_triangles);
+ }
+ }
+
+ if (num_triangles == 0)
+ {
+ num_triangles = 4;
+ }
+
+ if (isSculpted())
+ {
+ if (isMesh())
+ {
+ // base cost is dependent on mesh complexity
+ // note that 3 is the highest LOD as of the time of this coding.
+ S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(),3);
+ if ( size > 0)
+ {
+ if (gMeshRepo.getSkinInfo(volume_params.getSculptID(), this))
+ {
+ // weighted attachment - 1 point for every 3 bytes
+ weighted_mesh = 1;
+ }
+
+ }
+ else
+ {
+ // something went wrong - user should know their content isn't render-free
+ return 0;
+ }
+ }
+ else
+ {
+ const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLUUID sculpt_id = sculpt_params->getSculptTexture();
+ if (textures.find(sculpt_id) == textures.end())
+ {
+ LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id);
+ if (texture)
+ {
+ S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f));
+ textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost));
+ }
+ }
+ }
+ }
if (isFlexible())
{
@@ -3010,19 +3090,12 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
particles = 1;
}
- const LLVector3& sc = getScale();
- scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
-
- const LLDrawable* drawablep = mDrawable;
-
- if (isSculpted())
+ if (getIsLight())
{
- const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID sculpt_id = sculpt_params->getSculptTexture();
- textures.insert(sculpt_id);
+ produces_light = 1;
}
- for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+ for (S32 i = 0; i < num_faces; ++i)
{
const LLFace* face = drawablep->getFace(i);
const LLTextureEntry* te = face->getTextureEntry();
@@ -3030,77 +3103,137 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
if (img)
{
- textures.insert(img->getID());
+ if (textures.find(img->getID()) == textures.end())
+ {
+ S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
+ textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));
+ }
}
if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
{
- alpha++;
+ alpha = 1;
}
else if (img && img->getPrimaryFormat() == GL_ALPHA)
{
invisi = 1;
}
+ if (face->hasMedia())
+ {
+ media_faces++;
+ }
if (te)
{
if (te->getBumpmap())
{
+ // bump is a multiplier, don't add per-face
bump = 1;
}
if (te->getShiny())
{
+ // shiny is a multiplier, don't add per-face
shiny = 1;
}
if (te->getGlow() > 0.f)
{
+ // glow is a multiplier, don't add per-face
glow = 1;
}
if (face->mTextureMatrix != NULL)
{
- animtex++;
+ animtex = 1;
}
if (te->getTexGen())
{
- planar++;
+ planar = 1;
}
}
}
+ // shame currently has the "base" cost of 1 point per 15 triangles, min 2.
+ shame = num_triangles * 5.f;
+ shame = shame < 2.f ? 2.f : shame;
- shame += invisi * ARC_INVISI_COST;
- shame += shiny * ARC_SHINY_COST;
- shame += glow * ARC_GLOW_COST;
- shame += alpha * ARC_ALPHA_COST;
- shame += flexi * ARC_FLEXI_COST;
- shame += animtex * ARC_ANIM_TEX_COST;
- shame += particles * ARC_PARTICLE_COST;
- shame += bump * ARC_BUMP_COST;
- shame += planar * ARC_PLANAR_COST;
- shame += scale;
+ // multiply by per-face modifiers
+ if (planar)
+ {
+ shame *= planar * ARC_PLANAR_COST;
+ }
- LLViewerObject::const_child_list_t& child_list = getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end();
- ++iter)
+ if (animtex)
{
- const LLViewerObject* child_objectp = *iter;
- const LLDrawable* child_drawablep = child_objectp->mDrawable;
- if (child_drawablep)
- {
- const LLVOVolume* child_volumep = child_drawablep->getVOVolume();
- if (child_volumep)
- {
- shame += child_volumep->getRenderCost(textures);
- }
- }
+ shame *= animtex * ARC_ANIM_TEX_COST;
}
- return shame;
+ if (alpha)
+ {
+ shame *= alpha * ARC_ALPHA_COST;
+ }
+
+ if(invisi)
+ {
+ shame *= invisi * ARC_INVISI_COST;
+ }
+
+ if (glow)
+ {
+ shame *= glow * ARC_GLOW_MULT;
+ }
+
+ if (bump)
+ {
+ shame *= bump * ARC_BUMP_MULT;
+ }
+ if (shiny)
+ {
+ shame *= shiny * ARC_SHINY_MULT;
+ }
+
+
+ // multiply shame by multipliers
+ if (weighted_mesh)
+ {
+ shame *= weighted_mesh * ARC_WEIGHTED_MESH;
+ }
+
+ if (flexi)
+ {
+ shame *= flexi * ARC_FLEXI_MULT;
+ }
+
+
+ // add additional costs
+ if (particles)
+ {
+ const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData);
+ const LLPartData *part_data = &(part_sys_data->mPartData);
+ U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate));
+ num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles;
+ F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f;
+ shame += num_particles * part_size * ARC_PARTICLE_COST;
+ }
+
+ if (produces_light)
+ {
+ shame += ARC_LIGHT_COST;
+ }
+
+ if (media_faces)
+ {
+ shame += media_faces * ARC_MEDIA_FACE_COST;
+ }
+
+ if (shame > mRenderComplexity_current)
+ {
+ mRenderComplexity_current = (S32)shame;
+ }
+
+ return (U32)shame;
}
-F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
+F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const
{
F32 radius = getScale().length()*0.5f;
@@ -3108,7 +3241,7 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
{
LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
- return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
+ return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value);
}
else
{
@@ -3122,11 +3255,18 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
header["medium_lod"]["size"] = counts[2] * 10;
header["high_lod"]["size"] = counts[3] * 10;
- return LLMeshRepository::getStreamingCost(header, radius);
+ return LLMeshRepository::getStreamingCost(header, radius, NULL, NULL, -1, unscaled_value);
}
}
-U32 LLVOVolume::getTriangleCount()
+//static
+void LLVOVolume::updateRenderComplexity()
+{
+ mRenderComplexity_last = mRenderComplexity_current;
+ mRenderComplexity_current = 0;
+}
+
+U32 LLVOVolume::getTriangleCount() const
{
U32 count = 0;
LLVolume* volume = getVolume();
@@ -3153,7 +3293,7 @@ U32 LLVOVolume::getHighLODTriangleCount()
else if (isMesh())
{
LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3);
- if (ref->isTetrahedron() || ref->getNumVolumeFaces() == 0)
+ if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0)
{
gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH);
}
@@ -3995,7 +4135,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
- if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))
+ if (vobj->isMesh() &&
+ (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))
{
continue;
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 13565cb27c..b6347526ee 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -129,9 +129,11 @@ public:
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
- U32 getRenderCost(std::set<LLUUID> &textures) const;
- /*virtual*/ F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
- /*virtual*/ U32 getTriangleCount();
+ typedef std::map<LLUUID, S32> texture_cost_t;
+ U32 getRenderCost(texture_cost_t &textures) const;
+ /*virtual*/ F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const;
+
+ /*virtual*/ U32 getTriangleCount() const;
/*virtual*/ U32 getHighLODTriangleCount();
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
@@ -320,11 +322,19 @@ protected:
LLFace* addFace(S32 face_index);
void updateTEData();
+ // stats tracking for render complexity
+ static S32 mRenderComplexity_last;
+ static S32 mRenderComplexity_current;
+
void requestMediaDataUpdate(bool isNew);
void cleanUpMediaImpls();
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
void removeMediaImpl(S32 texture_index) ;
public:
+
+ static S32 getRenderComplexityMax() {return mRenderComplexity_last;}
+ static void updateRenderComplexity();
+
LLViewerTextureAnim *mTextureAnimp;
U8 mTexAnimMode;
private:
@@ -359,8 +369,6 @@ public:
static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
- static const U32 ARC_TEXTURE_COST = 5;
-
protected:
static S32 sNumLODChanges;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 3f0640221e..27ee2745b5 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -461,6 +461,7 @@ public:
RENDER_DEBUG_PHYSICS_SHAPES = 0x1000000,
RENDER_DEBUG_NORMALS = 0x2000000,
RENDER_DEBUG_LOD_INFO = 0x4000000,
+ RENDER_DEBUG_RENDER_COMPLEXITY = 0x8000000
};
public:
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 afb7917043..c247a12e7a 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -37,7 +37,7 @@
layout="topleft"
left="10"
tool_tip="Grid opacity"
- name="grid_mode_label"
+ name="grid_opacity_label"
top_pad="30"
width="123">
Mode
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 1d4a1d4827..522ffa7232 100755
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -4,8 +4,8 @@
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>
+ <string name="status_idle"></string>
+ <string name="status_parse_error">Error: Dae parsing issue - see log for details.</string>
<string name="status_reading_file">Loading...</string>
<string name="status_generating_meshes">Generating Meshes...</string>
<string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
@@ -21,6 +21,7 @@
<string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string>
<string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string>
<string name="mesh_status_missing_lod">Missing required level of detail.</string>
+ <string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
<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>
@@ -32,6 +33,23 @@
</text>
<line_editor bottom_delta="20" follows="top|left|right" height="19" max_length_bytes="64"
name="description_form" prevalidate_callback="ascii" width="290" />
+
+ <text bottom_delta="20" left="15" follows="left|top" height="15" name="model_category_label" text_color="White">
+ What does this model represent?
+ </text>
+ <combo_box top_pad="1" follows="left|top" height="23"
+ name="model_category_combo" width="200">
+ <combo_box.drop_down_button
+ label_color="White"/>
+ <combo_item name="Choose one" label="Choose One..." value="MUT_Unspecified"/>
+ <combo_item name="Avatar shape" label="Avatar shape" value="MUT_AvatarShape"/>
+ <combo_item name="Avatar attachment" label="Avatar attachment" value="MUT_AvatarAttachment"/>
+ <combo_item name="Building Component" label="Building Component" value="MUT_BuildingComponent"/>
+ <combo_item name="Moving object (vehicle, animal)" label="Moving object (vehicle, animal)" value="MUT_MovingObject"/>
+ <combo_item name="Large, non moving etc" label="Large, non moving etc" value="MUT_LargeStationary"/>
+ <combo_item name="Smaller, non-moving etc" label="Smaller, non-moving etc" value="MUT_SmallStationary"/>
+ <combo_item name="Not really any of these" label="Not really any of these" value="MUT_Other"/>
+ </combo_box>
<text bottom_delta="20" left="15" follows="left|top" height="15" name="lod_label">
Preview:
@@ -94,33 +112,50 @@
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>
+ <text text_color="Yellow" left="10" bottom_delta="0" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text>
+
<text
- height="65"
- top_delta="45"
+ height="26"
+ top_pad="5"
left_delta="0"
- name="weights_text"
+ name="weights_text_left"
width="80"
word_wrap="true"
>
Download:
Physics:
-Server:
-
-Prim equivs:
</text>
-
<text
- height="65"
+ height="26"
top_delta="0"
- left_delta="80"
- name="weights"
+ left_pad="0"
+ name="weights_left"
width="70"
word_wrap="true"
>
[ST]
[PH]
+ </text>
+ <text
+ height="26"
+ top_delta="0"
+ left_pad="0"
+ name="weights_text_right"
+ width="80"
+ word_wrap="true"
+ >
+Server:
+Prim equivs:
+ </text>
+ <text
+ height="26"
+ top_delta="0"
+ left_pad="0"
+ name="weights_right"
+ width="70"
+ word_wrap="true"
+ >
[SIM]
-
[EQ]
</text>
@@ -173,13 +208,25 @@ L$ [MODEL]
name="lod_panel"
help_topic="upload_model_lod">
+ <!-- LOD TABLE-->
+ <panel
+ follows="top|left"
+ name="lod table"
+ left="0"
+ top="0"
+ width="300"
+ height="163"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
<text left="10" width="240" bottom="20" height="15" follows="left|top" name="lod_table_header">
Select Level of Detail:
</text>
- <text valign="center" halign="center" bg_visible="true" bottom_delta="16" left="75" width="65" height="18" follows="left|top" value="Triangles"/>
- <text valign="center" halign="center" bg_visible="true" left_pad="0" width="65" height="18" follows="left|top" value="Vertices"/>
- <text valign="center" halign="center" left_pad="0" width="65" bg_visible="true" height="18" follows="left|top" value="Status"/>
+ <text valign="center" halign="center" bg_visible="true" bottom_delta="16" left="75" name="triangles" width="65" height="18" follows="left|top" value="Triangles"/>
+ <text valign="center" halign="center" bg_visible="true" left_pad="0" width="65" name="vertices" height="18" follows="left|top" value="Vertices"/>
+ <text valign="center" halign="center" left_pad="0" name="status" width="65" bg_visible="true" height="18" follows="left|top" value="Status"/>
<text valign="center" halign="center" bg_visible="true" name="high_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="High"/>
<text valign="center" halign="center" bg_visible="true" name="high_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
@@ -210,9 +257,22 @@ L$ [MODEL]
</text>
<icon height="16" width="16" left="20" follows="left|top" name="lod_status_message_icon"/>
- <text left_pad="5" width="200" height="28" follows="left|top" top_pad="-15" wrap="true" name="lod_status_message_text"/>
+ <text left_pad="5" width="230" height="28" follows="left|top" top_pad="-15" wrap="true" name="lod_status_message_text"/>
+ </panel>
+
+ <!-- LOD MESH-->
+ <panel
+ follows="top|left"
+ name="mesh"
+ left="0"
+ top_pad="0"
+ width="300"
+ height="237"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
- <text top_pad="-3" left="10" height="15" follows="left|top">
+ <text top_pad="5" left="10" name="mesh_label" height="15" follows="left|top">
Mesh
</text>
@@ -236,10 +296,10 @@ L$ [MODEL]
<spinner follows="top|left" name="lod_triangle_limit" increment="10" left_pad="5" height="20" width="100" decimal_digits="0" enabled="true"/>
<spinner left_delta="0" bottom_delta="0" increment="0.01" follows="top|left" name="lod_error_threshold" min_val="0" max_val="100" height="20" width="100" decimal_digits="3" visible="false" enabled="true"/>
- <text follows="top|left" name="build_operator_text" left="45" top_pad="10" width="100" height="15">
+ <text follows="top|left" name="build_operator_text" left="45" top_pad="10" width="100" height="15" text_readonly_color="LabelDisabledColor">
Build Operator:
</text>
- <text follows="top|left" name="queue_mode_text" left_pad="5" width="100" height="15">
+ <text follows="top|left" name="queue_mode_text" left_pad="5" width="100" height="15" text_readonly_color="LabelDisabledColor">
Queue Mode:
</text>
<combo_box follows="top|left" name="build_operator" top_pad="5" left="45" width="100" height="20">
@@ -263,11 +323,11 @@ L$ [MODEL]
</combo_item>
</combo_box>
- <text top_pad="10" name="border_mode_text" left="45" follows="left|top" width="100" height="15">
+ <text top_pad="10" name="border_mode_text" left="45" follows="left|top" width="100" height="15" text_readonly_color="LabelDisabledColor">
Border Mode:
</text>
- <text left_pad="5" name="share_tolderance_text" follows="left|top" width="100" height="15">
+ <text left_pad="5" name="share_tolderance_text" follows="left|top" width="100" height="15" text_readonly_color="LabelDisabledColor">
Share Tolerance:
</text>
@@ -280,14 +340,28 @@ L$ [MODEL]
</combo_item>
</combo_box>
<spinner follows="left|top" name="share_tolerance" left_pad="5" width="100" decimal_digits="5" initial_value="0.00001" height="20"/>
-
- <text left="10" top_pad="35" follows="top|left" width="240" height="15">
+ </panel>
+
+ <!-- LOD GENERATE NORMALS-->
+ <panel
+ follows="top|left"
+ name="generate normals"
+ left="0"
+ top_pad="0"
+ width="300"
+ height="46"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
+ <text left="10" name="gen_normals_label" top_pad="5" follows="top|left" width="240" height="15">
Generate Normals
</text>
<text left="35" top_pad="5" follows="top|left" width="100" height="15" name="crease_label">
Crease Angle:
</text>
<spinner follows="top|left" left_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/>
+ </panel>
</panel>
<!-- PANEL -->
@@ -314,8 +388,8 @@ L$ [MODEL]
<radio_item bottom="23" name="physics_use_lod" label="Use Level of Detail:"/>
</radio_group>
- <combo_box left="180" top="10" follows="left|top" height="18"
- name="physics_lod_combo" width="110" tool_tip="LOD to use for physics shape">
+ <combo_box left="150" top="10" follows="left|top" height="18"
+ name="physics_lod_combo" width="130" tool_tip="LOD to use for physics shape">
<combo_item name="physics_lowest">
Lowest
</combo_item>
@@ -352,15 +426,15 @@ L$ [MODEL]
border="true"
bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
- <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig">
+ <text follows="left|top" bottom="40" height="30" left="10" name="method_label" font="SansSerifBig">
Step 1: Analysis
</text>
- <text top_pad="5" width="50" follows="top|left" height="15">
+ <text name="analysis_method_label" top_pad="5" width="50" follows="top|left" height="15">
Method:
</text>
<combo_box name="Method" follows="top|left" left_pad="5" bottom_delta="2" height="20" width="80"/>
- <text left="160" bottom_delta="-2" width="50" follows="top|left" height="15">
+ <text left="160" name="quality_label" bottom_delta="-2" width="50" follows="top|left" height="15">
Quality:
</text>
<combo_box name="Decompose Quality" bottom_delta="2" follows="top|left" left_pad="5" height="20" width="80"/>
@@ -386,11 +460,11 @@ L$ [MODEL]
border="true"
bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
- <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig">
+ <text follows="left|top" bottom="40" height="30" left="10" name="second_step_label" font="SansSerifBig">
Step 2: Simplification
</text>
- <text left="10" top_pad="5" height="15" width="140" follows="top|left">
+ <text left="10" name="simp_method_header" top_pad="5" height="15" width="140" follows="top|left">
Method:
</text>
@@ -439,20 +513,20 @@ L$ [MODEL]
name="modifiers_panel"
help_topic="upload_model_modifiers">
- <text left="10" width="90" bottom="30" follows="top|left" height="15">
+ <text left="10" name="scale_label" width="90" bottom="30" follows="top|left" height="15">
Scale:
</text>
- <text left_pad="5" width="140" follows="top|left" height="15">
+ <text left_pad="5" name="dimensions_label" width="140" follows="top|left" height="15">
Dimensions:
</text>
<spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/>
- <text left_pad="20" height="15" name="import_dimensions" follows="top|left">
+ <text left_pad="20" height="15" width="140" name="import_dimensions" follows="top|left">
[X] x [Y] x [Z] m
</text>
- <text left="10" top_pad="20" follows="top|left" height="15">
+ <text left="10" name="include_label" top_pad="20" follows="top|left" height="15">
Include:
</text>
@@ -460,7 +534,7 @@ L$ [MODEL]
<check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/>
<check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/>
- <text left="10" top_pad="4" width="90" bottom="30" follows="top|left" height="15">
+ <text left="10" name="pelvis_offset_label" top_pad="4" width="90" bottom="30" follows="top|left" height="15">
Pelvis Z Offset:
</text>
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 3d16ccbc45..b5a5ff5342 100644
--- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
@@ -108,7 +108,7 @@
height="22"
top_pad="15"
width="505"
- name="choose_file_header_panel"
+ name="header_panel"
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true"
@@ -117,7 +117,7 @@
width="200"
left="10"
top="3"
- name="choose_file_header_text"
+ name="header_text"
text_color="White"
height="10"
font="SansSerifBig"
@@ -130,7 +130,7 @@
left="15"
height="310"
width="505"
- name="choose_file_content_panel"
+ name="content"
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true">
@@ -163,7 +163,7 @@
height="10"
layout="topleft"
left_delta="0"
- name="choose_model_file_label"
+ name="Cache location"
width="320">
Choose model file to upload
</text>
@@ -199,7 +199,7 @@
height="10"
layout="topleft"
left="10"
- name="support_collada_text"
+ name="Cache location"
width="320">
Second Life supports COLLADA (.dae) files
</text>
@@ -221,7 +221,6 @@
width="130"
height="14"
left_delta="0"
- name="dimensions_label"
text_color="White"
word_wrap="true">
Dimensions (meters):
@@ -288,7 +287,7 @@
<panel
height="22"
top_pad="15"
- name="optimize_header_panel"
+ name="header_panel"
width="505"
bg_opaque_color="DkGray2"
background_visible="true"
@@ -297,7 +296,7 @@
<text
width="200"
left="10"
- name="optimize_header_text"
+ name="header_text"
top="3"
text_color="White"
height="10"
@@ -312,7 +311,7 @@
height="20"
font="SansSerifSmall"
layout="topleft"
- name="optimize_hint"
+ name="description"
word_wrap="true"
left_delta="5">
We have optimized the model for performance. Adjust it further if you wish.
@@ -323,12 +322,11 @@
left="15"
height="270"
width="505"
- name="optimize_content_panel"
+ name="content"
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true">
<text
- name="generating_lod_label"
top="20"
width="300"
height="12"
@@ -403,12 +401,12 @@
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true">
- <text name="optimize_performance_text" top="69" left="10" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Performance</text>
- <text name="optimize_faster_rendering_text" top="85" left="10" width="120" word_wrap="true" font="SansSerifSmall" height="40">Faster rendering
+ <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 name="optimize_accuracy_text" top="69" left="184" text_color="White" font="SansSerifSmallBold" width="120" height="16" wrap="true">Accuracy</text>
- <text name="optimize_slower_rendering_text" top="85" left="184" width="120" word_wrap="true" font="SansSerifSmall" height="40">Slower rendering
+ <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>
@@ -426,24 +424,21 @@ Higher prim weight</text>
top="130"
width="290" />
<text
- font="SansSerifSmall"
- name="accuracy_slider_mark1"
+ font="SansSerifSmall"
top_pad="0"
width="5"
left_delta="6"
height="4">'
</text>
<text
- font="SansSerifSmall"
- name="accuracy_slider_mark2"
+ font="SansSerifSmall"
top_delta="0"
width="5"
left_delta="137"
height="4">'
</text>
<text
- font="SansSerifSmall"
- name="accuracy_slider_mark3"
+ font="SansSerifSmall"
top_delta="0"
width="5"
left_delta="137"
@@ -459,7 +454,7 @@ Higher prim weight</text>
top_pad="15"
width="150">
</button>
- <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="geometry_preview_label">
+ <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label">
Geometry preview
</text>
<panel
@@ -476,16 +471,16 @@ Higher prim weight</text>
</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="preview_lod_high">
+ <combo_item name="high">
High detail
</combo_item>
- <combo_item name="preview_lod_medium">
+ <combo_item name="medium">
Medium detail
</combo_item>
- <combo_item name="preview_lod_low">
+ <combo_item name="low">
Low detail
</combo_item>
- <combo_item name="preview_lod_lowest">
+ <combo_item name="lowest">
Lowest detail
</combo_item>
</combo_box>
@@ -502,7 +497,7 @@ Higher prim weight</text>
<panel
height="22"
top_pad="15"
- name="physics_header_panel"
+ name="header_panel"
width="505"
bg_opaque_color="DkGray2"
background_visible="true"
@@ -511,7 +506,7 @@ Higher prim weight</text>
<text
width="200"
left="10"
- name="physics_header_text"
+ name="header_text"
top="3"
height="10"
font="SansSerifBig"
@@ -526,7 +521,7 @@ Higher prim weight</text>
height="50"
font="SansSerifSmall"
layout="topleft"
- name="physics_hint"
+ name="description"
word_wrap="true"
left_delta="5">
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.
@@ -536,16 +531,16 @@ Higher prim weight</text>
left="15"
height="270"
width="505"
- name="physics_content_panel"
+ name="content"
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true">
- <text name="physics_performance_text" top="10" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Performance</text>
- <text name="physics_faster_rendering_text" top="26" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Faster rendering
+ <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 name="physics_accuracy_text" top="174" left="10" text_color="White" font="SansSerifSmallBold" width="120" halign="right" height="16" wrap="true">Accuracy</text>
- <text name="physics_slower_dendering_text" top="190" left="10" width="120" word_wrap="true" font="SansSerifSmall" halign="right" height="40">Slower rendering
+ <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>
@@ -563,15 +558,15 @@ Higher prim weight</text>
show_text="false"
top="25"
width="22" />
- <text name="physics_example_1" top="10" width="120" word_wrap="true" left_pad="10" height="50">Examples:
+ <text top="10" width="120" word_wrap="true" left_pad="10" height="50">Examples:
Moving objects
Flying objects
Vehicles</text>
- <text name="physics_example_2" top="95" width="120" word_wrap="true" left_delta="0" height="50">Examples:
+ <text top="95" width="120" word_wrap="true" left_delta="0" height="50">Examples:
Small static objects
Less detailed objects
Simple furniture</text>
- <text name="physics_example_3" top="180" width="120" word_wrap="true" left_delta="0" height="50">Examples:
+ <text top="180" width="120" word_wrap="true" left_delta="0" height="50">Examples:
Static objects
Detailed objects
Buildings</text>
@@ -597,7 +592,7 @@ Buildings</text>
visible="false"
width="150">
</button>
- <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="physics_preview_label">
+ <text top="10" right="-10" width="185" text_color="White" follows="left|top" height="15" name="lod_label">
Physics preview
</text>
<panel
@@ -614,16 +609,16 @@ Buildings</text>
</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="preview_lod2_high">
+ <combo_item name="high">
High detail
</combo_item>
- <combo_item name="preview_lod2_medium">
+ <combo_item name="medium">
Medium detail
</combo_item>
- <combo_item name="preview_lod2_low">
+ <combo_item name="low">
Low detail
</combo_item>
- <combo_item name="preview_lod2_lowest">
+ <combo_item name="lowest">
Lowest detail
</combo_item>
</combo_box>
@@ -640,7 +635,7 @@ Buildings</text>
<panel
height="22"
top_pad="15"
- name="review_header_panel"
+ name="header_panel"
width="505"
bg_opaque_color="DkGray2"
background_visible="true"
@@ -649,7 +644,7 @@ Buildings</text>
<text
width="200"
left="10"
- name="review_header_text"
+ name="header_text"
text_color="White"
top="3"
height="10"
@@ -663,7 +658,7 @@ Buildings</text>
left="15"
height="310"
width="505"
- name="review_content_panel"
+ name="content"
bg_opaque_color="DkGray2"
background_visible="true"
background_opaque="true">
@@ -711,7 +706,7 @@ Buildings</text>
<panel
height="22"
top_pad="15"
- name="upload_header_panel"
+ name="header_panel"
width="505"
bg_opaque_color="DkGray2"
background_visible="true"
@@ -720,7 +715,7 @@ Buildings</text>
<text
width="200"
left="10"
- name="upload_header_text"
+ name="header_text"
top="3"
text_color="White"
height="10"
diff --git a/indra/newview/skins/default/xui/en/floater_object_weights.xml b/indra/newview/skins/default/xui/en/floater_object_weights.xml
new file mode 100644
index 0000000000..a73db3af32
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_object_weights.xml
@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_close="true"
+ can_tear_off="false"
+ height="315"
+ help_topic="objects_weight_floater"
+ layout="topleft"
+ name="object_weights"
+ save_rect="true"
+ single_instance="true"
+ title="ADVANCED"
+ width="200">
+ <floater.string
+ name="nothing_selected"
+ value="--"/>
+
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="selected_text"
+ text_color="EmphasisColor"
+ top="10"
+ value="SELECTED"
+ width="180" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="objects"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="objects_label"
+ top_delta="0"
+ value="Objects"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="prims"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="prims_label"
+ top_delta="0"
+ value="Prims"
+ width="130" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="10"
+ name="selected_text_border"
+ top_pad="5"
+ width="180"/>
+
+
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="weights_of_selected_text"
+ text_color="EmphasisColor"
+ top_pad="10"
+ value="WEIGHTS OF SELECTED"
+ width="180" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="download"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="download_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="download_label"
+ top_delta="0"
+ value="Download"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="physics"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="physics_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="physics_label"
+ top_delta="0"
+ value="Physics"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="server"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="server_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="server_label"
+ top_delta="0"
+ value="Server"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="display"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="display_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="display_label"
+ top_delta="0"
+ value="Display"
+ width="130" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="10"
+ name="weights_text_border"
+ top_pad="5"
+ width="180"/>
+
+
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="land_impacts_text"
+ text_color="EmphasisColor"
+ top_pad="10"
+ value="LAND IMPACTS"
+ width="180" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="selected"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="selected_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="selected_label"
+ top_delta="0"
+ value="Selected"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="rezzed_on_land"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="rezzed_on_land_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="rezzed_on_land_label"
+ top_delta="0"
+ value="Rezzed on land"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="remaining_capacity"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="remaining_capacity_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="remaining_capacity_label"
+ top_delta="0"
+ value="Remaining capacity"
+ width="130" />
+ <text
+ follows="left|top"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="total_capacity"
+ top_pad="3"
+ value="--"
+ width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="total_capacity_loading_indicator"
+ top_delta="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="total_capacity_label"
+ top_delta="0"
+ value="Total capacity"
+ width="130" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="10"
+ name="land_impacts_text_border"
+ top_pad="5"
+ width="180"/>
+
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="help_SLURL"
+ top_pad="10"
+ value="[secondlife:///www.secondlife.com What is all this?...]"
+ width="180" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 8901583799..03d6c84266 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -742,7 +742,7 @@
top_pad="0"
visible="false"
width="280">
- Physics weight [PHYS_WEIGHT], Render Cost [DISP_WEIGHT].
+ Physics weight [PHYS_WEIGHT], Render Cost [DISP_WEIGHT]. [secondlife:///app/openfloater/object_weights More info]
</text>
<!-- <text -->
<!-- text_color="LtGray_50" -->
@@ -2000,25 +2000,21 @@ even though the user gets a free copy.
visible="false"
width="150">
<combo_box.item
- label="(none)"
- name="None"
- value="None" />
- <combo_box.item
label="Sphere"
name="Sphere"
- value="Sphere" />
+ value="1" />
<combo_box.item
label="Torus"
name="Torus"
- value="Torus" />
+ value="2" />
<combo_box.item
label="Plane"
name="Plane"
- value="Plane" />
+ value="3" />
<combo_box.item
label="Cylinder"
name="Cylinder"
- value="Cylinder" />
+ value="4" />
</combo_box>
</panel>
<panel
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 36ebe73753..16f48f3a4e 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1277,7 +1277,7 @@
parameter="stats" />
</menu_item_check>
<menu_item_check
- label="Show Avatar Rendering Cost"
+ label="Show Draw Weight for Avatars"
name="Avatar Rendering Cost">
<menu_item_check.on_check
function="Advanced.CheckInfoDisplay"
@@ -2435,6 +2435,16 @@
function="Advanced.ToggleInfoDisplay"
parameter="raycast" />
</menu_item_check>
+ <menu_item_check
+ label="Render Complexity"
+ name="rendercomplexity">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="rendercomplexity" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="rendercomplexity" />
+ </menu_item_check>
<menu_item_check
label="Sculpt"
name="Sculpt">
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index 3f9195d092..44c84e69a1 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -133,17 +133,7 @@
tool_tip="Let people see this region and its parcels in search results"
top="190"
width="80" />
- <check_box
- visible="FALSE"
- height="20"
- label="Allow Mesh Objects"
- layout="topleft"
- left="10"
- name="mesh_rez_enabled_check"
- tool_tip="Let people rez mesh objects on this region"
- top="210"
- width="80" />
- <spinner
+ <spinner
decimal_digits="0"
follows="left|top"
height="20"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 2094275bed..f80028ec0c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3625,5 +3625,13 @@ Try enclosing path to the editor with double quotes.
<string name="BeaconSound">Viewing sound beacons (yellow)</string>
<string name="BeaconMedia">Viewing media beacons (white)</string>
<string name="ParticleHiding">Hiding Particles</string>
+
+ <!-- Mesh UI terms -->
+ <string name="Retain%">Retain%</string>
+ <string name="Detail">Detail</string>
+ <string name="Better Detail">Better Detail</string>
+ <string name="Surface">Surface</string>
+ <string name="Solid">Solid</string>
+ <string name="Wrap">Wrap</string>
</strings>