From 3e80fa3dbc943de9b784fedc202ba38cf238f46d Mon Sep 17 00:00:00 2001 From: David Parks Date: Mon, 2 Nov 2009 19:55:37 +0000 Subject: Sync up with render-pipeline-7 ignore-dead-branch --- indra/cmake/00-Common.cmake | 5 +- indra/cmake/LLPrimitive.cmake | 22 +- indra/llcommon/llassettype.cpp | 1 + indra/llcommon/llassettype.h | 6 +- indra/llcommon/llthread.cpp | 2 +- indra/llcommon/stdenums.h | 3 +- indra/llinventory/llinventorytype.cpp | 7 +- indra/llinventory/llinventorytype.h | 3 +- indra/llmath/llvolume.cpp | 350 ++++++++++- indra/llmath/llvolume.h | 22 +- indra/llmath/llvolumemgr.cpp | 2 +- indra/llmath/m4math.cpp | 11 + indra/llmath/m4math.h | 1 + indra/llmath/v2math.cpp | 15 + indra/llmath/v2math.h | 3 + indra/llmessage/llassetstorage.cpp | 2 +- indra/llmessage/lltransfermanager.cpp | 2 +- indra/llmessage/lltransfersourceasset.cpp | 2 + indra/llprimitive/CMakeLists.txt | 4 + indra/llprimitive/llprimitive.cpp | 15 +- indra/llprimitive/llprimitive.h | 2 +- indra/llvfs/llvfile.cpp | 2 +- indra/llvfs/llvfs.cpp | 3 + indra/newview/CMakeLists.txt | 10 + indra/newview/app_settings/settings.xml | 14 +- .../shaders/class2/deferred/multiSpotLightF.glsl | 2 +- .../shaders/class2/deferred/sunLightF.glsl | 4 +- indra/newview/licenses-win32.txt | 69 +++ indra/newview/llassetuploadresponders.cpp | 661 +++++++++++++++++---- indra/newview/llassetuploadresponders.h | 51 +- indra/newview/lldrawable.h | 6 +- indra/newview/lldrawpoolbump.cpp | 12 + indra/newview/lldrawpoolbump.h | 2 +- indra/newview/llface.cpp | 2 +- indra/newview/llfilepicker.cpp | 5 + indra/newview/llfilepicker.h | 3 + indra/newview/llfloaterinventory.cpp | 3 + indra/newview/llhudtext.cpp | 12 + indra/newview/llhudtext.h | 1 + indra/newview/llinventorybridge.cpp | 94 ++- indra/newview/llinventorybridge.h | 35 +- indra/newview/llpanelgroupnotices.cpp | 1 + indra/newview/llselectmgr.cpp | 80 ++- indra/newview/llselectmgr.h | 1 + indra/newview/llspatialpartition.cpp | 1 - indra/newview/llspatialpartition.h | 1 + indra/newview/lltexturectrl.cpp | 6 +- indra/newview/lltooldraganddrop.cpp | 11 + indra/newview/llviewerdisplay.cpp | 8 +- indra/newview/llviewerfloaterreg.cpp | 4 +- indra/newview/llviewermenu.cpp | 2 +- indra/newview/llviewermenufile.cpp | 330 +++++++--- indra/newview/llviewermenufile.h | 77 ++- indra/newview/llviewermessage.cpp | 1 + indra/newview/llviewerregion.cpp | 2 + indra/newview/llviewertexteditor.cpp | 1 + indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewerwindow.cpp | 134 ----- indra/newview/llvovolume.cpp | 183 +++++- indra/newview/llvovolume.h | 9 + indra/newview/pipeline.cpp | 241 +++++++- indra/newview/pipeline.h | 33 + indra/newview/skins/default/textures/textures.xml | 2 + .../newview/skins/default/xui/en/floater_about.xml | 3 + .../skins/default/xui/en/floater_inventory.xml | 10 + .../newview/skins/default/xui/en/floater_tools.xml | 3 + indra/newview/skins/default/xui/en/menu_viewer.xml | 4 +- .../newview/skins/default/xui/en/notifications.xml | 25 +- indra/newview/skins/default/xui/en/strings.xml | 1 + indra/newview/viewer_manifest.py | 6 + 70 files changed, 2185 insertions(+), 468 deletions(-) (limited to 'indra') diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 173e650961..3bd10ea9ee 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -49,11 +49,12 @@ if (WINDOWS) add_definitions( /DLL_WINDOWS=1 + /DDOM_DYNAMIC /DUNICODE /D_UNICODE /GS /TP - /W3 + /W2 /c /Zc:forScope /nologo @@ -195,7 +196,7 @@ endif (DARWIN) if (LINUX OR DARWIN) - set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor -Woverloaded-virtual") + set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor") if (NOT GCC_DISABLE_FATAL_WARNINGS) set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake index d397b78f1c..9f8d99a0bf 100644 --- a/indra/cmake/LLPrimitive.cmake +++ b/indra/cmake/LLPrimitive.cmake @@ -1,7 +1,27 @@ # -*- cmake -*- +# these should be moved to their own cmake file +include(Prebuilt) +use_prebuilt_binary(colladadom) +use_prebuilt_binary(pcre) +use_prebuilt_binary(libxml) + set(LLPRIMITIVE_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llprimitive ) -set(LLPRIMITIVE_LIBRARIES llprimitive) +if (WINDOWS) + set(LLPRIMITIVE_LIBRARIES + llprimitive + libcollada14dom21 + ) +else (WINDOWS) + set(LLPRIMITIVE_LIBRARIES + llprimitive + collada14dom + xml2 + pcrecpp + pcre + ) +endif (WINDOWS) + diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 0b016b81fb..d57494b444 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -107,6 +107,7 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE)); addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE)); + addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", "Meshes", DAD_MESH, FALSE, TRUE)); for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START); ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END); diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 5e51188541..a1154d16e3 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -147,9 +147,11 @@ public: AT_MY_OUTFITS = 48, // Folder that holds your outfits. + + AT_MESH = 49, + // Mesh data in our proprietary SLM format - - AT_COUNT = 49, + AT_COUNT = 50, // +*********************************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | // +*********************************************************+ diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 920d8c0977..e3906bc86e 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -75,7 +75,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // Run the user supplied function threadp->run(); - llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl; + //llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl; // We're done with the run function, this thread is done executing now. threadp->mStatus = STOPPED; diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 1a5678dde1..6eead924da 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -55,7 +55,8 @@ enum EDragAndDropType DAD_ANIMATION = 12, DAD_GESTURE = 13, DAD_LINK = 14, - DAD_COUNT = 15, // number of types in this enum + DAD_MESH = 15, + DAD_COUNT = 16, // number of types in this enum }; // Reasons for drags to be denied. diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a445466b26..ae3cb2697b 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -96,7 +96,9 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART)); addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION)); addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); - addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE)); + addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE)); + addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH)); + } @@ -132,7 +134,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_LINK LLInventoryType::IT_NONE, // AT_LINK_FOLDER - + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE @@ -157,6 +159,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT LLInventoryType::IT_CATEGORY, // AT_OUTFIT LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS + LLInventoryType::IT_MESH, // AT_MESH }; // static diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 14b28bfe4b..0d580d3000 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -68,7 +68,8 @@ public: IT_ANIMATION = 19, IT_GESTURE = 20, IT_FAVORITE = 21, - IT_COUNT = 22, + IT_MESH = 22, + IT_COUNT = 23, IT_NONE = -1 }; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b8ef92f9a9..afa82ed399 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -46,6 +46,9 @@ #include "lldarray.h" #include "llvolume.h" #include "llstl.h" +#include "llsdserialize.h" +#include "zlib/zlib.h" + #define DEBUG_SILHOUETTE_BINORMALS 0 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette @@ -1688,7 +1691,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; generate(); - if (mParams.getSculptID().isNull()) + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } @@ -1839,6 +1842,295 @@ BOOL LLVolume::generate() return FALSE; } +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return r[i] < l[i]; + } + } + + return false; +} + +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return false; + } + } + + return true; +} + + +BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) +{ + std::ifstream is; + + is.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary); + + BOOL success = createVolumeFacesFromStream(is); + + is.close(); + + return success; +} + +BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) +{ + mSculptLevel = -1; // default is an error occured + + LLSD header; + { + if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) + { + llwarns << "not a valid mesh asset!" << llendl; + return FALSE; + } + } + + std::string nm[] = + { + "impostor", + "low_lod", + "medium_lod", + "high_lod" + }; + + S32 lod = llclamp((S32) mDetail, 0, 3); + + while (lod < 4 && header[nm[lod]]["offset"].asInteger() == -1) + { + ++lod; + } + + if (lod >= 4) + { + llwarns << "Couldn't load model for given lod" << llendl; + return FALSE; + } + + is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + + + U8* result = NULL; + U32 cur_size = 0; + + { + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + z_stream strm; + + const U32 CHUNK = 65536; + + S32 size = header[nm[lod]]["size"].asInteger(); + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + S32 ret = inflateInit(&strm); + + if (ret != Z_OK) + { + llerrs << "WTF?" << llendl; + } + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + return FALSE; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + return FALSE; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (strm.avail_out == 0); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + return FALSE; + } + } + + //result now points to the decompressed LLSD block + + LLSD mdl; + + { + std::string res_str((char*) result, cur_size); + std::istringstream istr(res_str); + + if (!LLSDSerialize::deserialize(mdl, istr, cur_size)) + { + llwarns << "not a valid mesh asset!" << llendl; + return FALSE; + } + } + + + free(result); + + + { + U32 face_count = mdl.size(); + + mVolumeFaces.resize(face_count); + + for (U32 i = 0; i < face_count; ++i) + { + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; + + LLVolumeFace& face = mVolumeFaces[i]; + + face.mHasBinormals = FALSE; + + //copy out indices + face.mIndices.resize(idx.size()/2); + if (idx.empty()) + { //why is there an empty index list? + continue; + } + + U16* indices = (U16*) &(idx[0]); + for (U32 j = 0; j < idx.size()/2; ++j) + { + face.mIndices[j] = indices[j]; + } + + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.mVertices.resize(num_verts); + + LLVector3 min_pos; + LLVector3 max_pos; + LLVector2 min_tc; + LLVector2 max_tc; + + min_pos.setValue(mdl[i]["PositionDomain"]["Min"]); + max_pos.setValue(mdl[i]["PositionDomain"]["Max"]); + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + + F32 scale = llclamp((F32) mdl[i]["Scale"].asReal(), 1.f, 10.f); + + LLVector3 pos_range = max_pos - min_pos; + LLVector2 tc_range = max_tc - min_tc; + + LLVector3& min = face.mExtents[0]; + LLVector3& max = face.mExtents[1]; + + min = max = LLVector3(0,0,0); + + for (U32 j = 0; j < num_verts; ++j) + { + U16* v = (U16*) &(pos[j*3*2]); + + face.mVertices[j].mPosition.setVec( + (F32) v[0] / 65535.f * pos_range.mV[0] + min_pos.mV[0], + (F32) v[1] / 65535.f * pos_range.mV[1] + min_pos.mV[1], + (F32) v[2] / 65535.f * pos_range.mV[2] + min_pos.mV[2]); + + face.mVertices[j].mPosition *= scale; + + if (j == 0) + { + min = max = face.mVertices[j].mPosition; + } + else + { + update_min_max(min,max,face.mVertices[j].mPosition); + } + + U16* n = (U16*) &(norm[j*3*2]); + + face.mVertices[j].mNormal.setVec( + (F32) n[0] / 65535.f * 2.f - 1.f, + (F32) n[1] / 65535.f * 2.f - 1.f, + (F32) n[2] / 65535.f * 2.f - 1.f); + + U16* t = (U16*) &(tc[j*2*2]); + + face.mVertices[j].mTexCoord.setVec( + (F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0], + (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]); + } + + } + } + + mSculptLevel = 0; // success! + return TRUE; +} + +void LLVolume::copyVolumeFaces(LLVolume* volume) +{ + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; +} + +S32 const LL_SCULPT_MESH_MAX_FACES = 8; + +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(); +} + void LLVolume::createVolumeFaces() { @@ -1864,6 +2156,11 @@ void LLVolume::createVolumeFaces() LLProfile::Face& face = mProfilep->mFaces[i]; vf.mBeginS = face.mIndex; vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + vf.mBeginT = 0; vf.mNumT= getPath().mPath.size(); vf.mID = i; @@ -1907,6 +2204,10 @@ void LLVolume::createVolumeFaces() if (face.mFlat && vf.mNumS > 2) { //flat inner faces have to copy vert normals vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } } } else @@ -2309,7 +2610,6 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const return mSculptID < params.mSculptID; } - return mSculptType < params.mSculptType; @@ -3379,22 +3679,29 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, S32 face_mask) { LLMemType m1(LLMemType::MTYPE_VOLUME); - + vertices.clear(); normals.clear(); segments.clear(); + if (mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + { + return; + } + S32 cur_index = 0; //for each face for (face_list_t::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ++iter) { - const LLVolumeFace& face = *iter; + LLVolumeFace& face = *iter; - if (!(face_mask & (0x1 << cur_index++))) + if (!(face_mask & (0x1 << cur_index++)) || + face.mIndices.empty() || face.mEdge.empty()) { continue; } + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { } @@ -3594,6 +3901,8 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, F32 closest_t = 2.f; // must be larger than 1 + end_face = llmin(end_face, getNumVolumeFaces()-1); + for (S32 i = start_face; i <= end_face; i++) { const LLVolumeFace &face = getVolumeFace((U32)i); @@ -4103,11 +4412,28 @@ BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const return TRUE; } +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; +} + LLSD LLVolumeParams::asLLSD() const { LLSD sd = LLSD(); sd["path"] = mPathParams; sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + return sd; } @@ -4115,6 +4441,8 @@ bool LLVolumeParams::fromLLSD(LLSD& sd) { mPathParams.fromLLSD(sd["path"]); mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + return true; } @@ -4157,6 +4485,12 @@ const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity // for collison purposes BOOL LLVolumeParams::isConvex() const { + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return FALSE; + } + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); F32 hollow = mProfileParams.getHollow(); @@ -5011,7 +5345,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { mIndices.resize(num_indices); - mEdge.resize(num_indices); + + if (volume->getParams().getSculptType() != LL_SCULPT_TYPE_MESH) + { + mEdge.resize(num_indices); + } } else { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 871b334452..9f595ccbc4 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -186,6 +186,9 @@ const U8 LL_SCULPT_TYPE_CYLINDER = 4; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER; +// need to change this (these) names +const U8 LL_SCULPT_TYPE_MESH = 5; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; @@ -575,6 +578,9 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; + LLSD sculptAsLLSD() const; + bool sculptFromLLSD(LLSD& sd); + LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); @@ -634,7 +640,6 @@ public: const F32& getSkew() const { return mPathParams.getSkew(); } const LLUUID& getSculptID() const { return mSculptID; } const U8& getSculptType() const { return mSculptType; } - BOOL isConvex() const; // 'begin' and 'end' should be in range [0, 1] (they will be clamped) @@ -798,7 +803,7 @@ public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); - + class VertexData { public: @@ -806,6 +811,9 @@ public: LLVector3 mNormal; LLVector3 mBinormal; LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; }; enum @@ -851,8 +859,7 @@ class LLVolume : public LLRefCount { friend class LLVolumeLODGroup; -private: - LLVolume(const LLVolume&); // Don't implement +protected: ~LLVolume(); // use unref public: @@ -874,7 +881,7 @@ public: U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } + S32 getNumFaces() const; S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } F32 getDetail() const { return mDetail; } const LLVolumeParams& getParams() const { return mParams; } @@ -946,6 +953,8 @@ public: LLVector3 mLODScaleBias; // vector for biasing LOD based on scale void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); + void copyVolumeFaces(LLVolume* volume); + private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); @@ -956,6 +965,9 @@ private: protected: BOOL generate(); void createVolumeFaces(); +public: + virtual BOOL createVolumeFacesFromFile(const std::string& file_name); + virtual BOOL createVolumeFacesFromStream(std::istream& is); protected: BOOL mUnique; diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 53641fceab..61c5a0adc9 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) { llassert_always(mLODRefs[i] > 0); mLODRefs[i]--; -#if 1 // SJB: Possible opt: keep other lods around +#if 0 // SJB: Possible opt: keep other lods around if (!mLODRefs[i]) { mVolumeLODs[i] = NULL; diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index d8e7b4aaf9..7c7f60154d 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -428,6 +428,17 @@ const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector return (*this); } +const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale) +{ + setIdentity(); + + mMatrix[VX][VX] = scale.mV[VX]; + mMatrix[VY][VY] = scale.mV[VY]; + mMatrix[VZ][VZ] = scale.mV[VZ]; + + return (*this); +} + const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos) { F32 sx, sy, sz; diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index e74b7afe9b..de981b7646 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -159,6 +159,7 @@ public: const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position + const LLMatrix4& initScale(const LLVector3 &scale); // Set all const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos); diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 555e1f92bb..220336e0c2 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -115,3 +115,18 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u ); } + +LLSD LLVector2::getValue() const +{ + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + return ret; +} + +void LLVector2::setValue(LLSD& sd) +{ + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); +} + diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 9fef8851cc..f9f1c024f2 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -66,6 +66,9 @@ class LLVector2 void set(const LLVector2 &vec); // Sets LLVector2 to vec void set(const F32 *vec); // Sets LLVector2 to vec + LLSD getValue() const; + void setValue(LLSD& sd); + void setVec(F32 x, F32 y); // deprecated void setVec(const LLVector2 &vec); // deprecated void setVec(const F32 *vec); // deprecated diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index b3087bcc3f..eeb903de6a 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -502,7 +502,7 @@ void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType at tpvf.setAsset(uuid, atype); tpvf.setCallback(downloadCompleteCallback, req); - llinfos << "Starting transfer for " << uuid << llendl; + //llinfos << "Starting transfer for " << uuid << llendl; LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); } diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index d67911e8e2..72662bb782 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -344,7 +344,7 @@ void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **) } } - llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl; + //llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl; ttp->setSize(size); ttp->setGotInfo(TRUE); diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index 5a1cd95ffc..f255a2cf7e 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -271,6 +271,7 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type) case LLAssetType::AT_ANIMATION: case LLAssetType::AT_GESTURE: case LLAssetType::AT_FAVORITE: + case LLAssetType::AT_MESH: rv = true; break; default: @@ -296,6 +297,7 @@ bool is_asset_id_knowable(LLAssetType::EType type) case LLAssetType::AT_FAVORITE: case LLAssetType::AT_LINK: case LLAssetType::AT_LINK_FOLDER: + case LLAssetType::AT_MESH: rv = true; break; default: diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index d130513637..f9392a2b75 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -13,11 +13,14 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LIBS_PREBUILT_DIR}/include/collada + ${LIBS_PREBUILT_DIR}/include/collada/1.4 ) set(llprimitive_SOURCE_FILES llmaterialtable.cpp llmediaentry.cpp + llmodel.cpp llprimitive.cpp llprimtexturelist.cpp lltextureanim.cpp @@ -33,6 +36,7 @@ set(llprimitive_HEADER_FILES legacy_object_types.h llmaterialtable.h llmediaentry.h + llmodel.h llprimitive.h llprimtexturelist.h lltextureanim.h diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index b102254b62..2675a27c08 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -744,18 +744,11 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai return TRUE; } - U32 old_face_mask = mVolumep->mFaceMask; - // build the new object sVolumeManager->unrefVolume(mVolumep); mVolumep = volumep; - - U32 new_face_mask = mVolumep->mFaceMask; - if (old_face_mask != new_face_mask) - { - setNumTEs(mVolumep->getNumFaces()); - } - + setNumTEs(mVolumep->getNumFaces()); + return TRUE; } @@ -898,7 +891,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const U8 packed_buffer[MAX_TE_BUFFER]; U8 *cur_ptr = packed_buffer; - S32 last_face_index = getNumTEs() - 1; + S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1; if (last_face_index > -1) { @@ -1179,7 +1172,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) return retval; } - face_count = getNumTEs(); + face_count = llmin((U32) getNumTEs(), MAX_TES); U32 i; cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 4f828186cb..4db7aa7261 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -328,7 +328,7 @@ public: const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume LLVolume *getVolume() const { return mVolumep; } virtual BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); - + // Modify texture entry properties inline BOOL validTE(const U8 te_num) const; LLTextureEntry* getTE(const U8 te_num) const; diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index 5fdf41188d..e0e282d7af 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -428,7 +428,7 @@ bool LLVFile::isLocked(EVFSLock lock) void LLVFile::waitForLock(EVFSLock lock) { - LLFastTimer t(FTM_VFILE_WAIT); + //LLFastTimer t(FTM_VFILE_WAIT); // spin until the lock clears while (isLocked(lock)) { diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 9ce1e75d06..ddb76fb2ba 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2041,6 +2041,9 @@ std::string get_extension(LLAssetType::EType type) case LLAssetType::AT_ANIMATION: extension = ".lla"; break; + case LLAssetType::AT_MESH: + extension = ".slm"; + break; default: // Just use the asset server filename extension in most cases extension += "."; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 26170d1713..3cee6394e0 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -36,6 +36,7 @@ include(UI) include(UnixInstall) include(LLKDU) include(ViewerMiscLibs) +include(GLOD) if (WINDOWS) include(CopyWinLibs) @@ -44,6 +45,7 @@ endif (WINDOWS) include_directories( ${DBUSGLIB_INCLUDE_DIRS} ${ELFIO_INCLUDE_DIR} + ${GLOD_INCLUDE_DIR} ${LLAUDIO_INCLUDE_DIRS} ${LLCHARACTER_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} @@ -61,6 +63,8 @@ include_directories( ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile + ${LIBS_PREBUILT_DIR}/include/collada + ${LIBS_PREBUILT_DIR}/include/collada/1.4 ) set(viewer_SOURCE_FILES @@ -175,6 +179,7 @@ set(viewer_SOURCE_FILES llfloatermediasettings.cpp llfloaterhud.cpp llfloaterimagepreview.cpp + llfloaterimportcollada.cpp llfloaterinspect.cpp llfloaterinventory.cpp llfloaterjoystick.cpp @@ -183,6 +188,7 @@ set(viewer_SOURCE_FILES llfloaterlandholdings.cpp llfloatermap.cpp llfloatermemleak.cpp + llfloatermodelpreview.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloateropenobject.cpp @@ -647,6 +653,7 @@ set(viewer_HEADER_FILES llfloatermediasettings.h llfloaterhud.h llfloaterimagepreview.h + llfloaterimportcollada.h llfloaterinspect.h llfloaterinventory.h llfloaterjoystick.h @@ -655,6 +662,7 @@ set(viewer_HEADER_FILES llfloaterlandholdings.h llfloatermap.h llfloatermemleak.h + llfloatermodelpreview.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloateropenobject.h @@ -1139,6 +1147,7 @@ if (WINDOWS) ${DXGUID_LIBRARY} fmodvc kernel32 + libboost_system odbc32 odbccp32 ole32 @@ -1405,6 +1414,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${DBUSGLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${FMODWRAPPER_LIBRARY} + ${GLOD_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL_LIBRARY} ${SMARTHEAP_LIBRARY} diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7e368b0c9c..073ea766fe 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7252,7 +7252,19 @@ Value 0 - SafeMode + MeshThreadCount + + Comment + Number of threads to use for loading meshes. + Persist + 1 + Type + U32 + Value + 8 + + + SafeMode Comment Reset preferences, run in safe mode. diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 651959413c..45884d5732 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -137,7 +137,7 @@ void main() } //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*proj_ambiance; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index a0026edcd2..4333cc64a7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -224,11 +224,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt index 7e6d4b4561..8736626907 100644 --- a/indra/newview/licenses-win32.txt +++ b/indra/newview/licenses-win32.txt @@ -769,3 +769,72 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +============= +GLOD license +============= +The GLOD Open-Source License Version 1.0 June 16, 2004 + +Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns +Hopkins University and David Luebke, Brenden Schubert, University of +Virginia. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer and + request. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer and + request in the documentation and/or other materials provided with + the distribution. + +3. The name "GLOD" must not be used to endorse or promote products + derived from this software without prior written permission. + +4. Redistributions of any modified version of this source, whether in + source or binary form , must include a form of the following + acknowledgment: "This product is derived from the GLOD library, + which is available from http://www.cs.jhu.edu/~graphics/GLOD." + +5. Redistributions of any modified version of this source in binary + form must provide, free of charge, access to the modified version + of the code. + +6. This license shall be governed by and construed and enforced in + accordance with the laws of the State of Maryland, without + reference to its conflicts of law provisions. The exclusive + jurisdiction and venue for all legal actions relating to this + license shall be in courts of competent subject matter jurisdiction + located in the State of Maryland. + +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, GLOD IS PROVIDED +UNDER THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +THAT GLOD IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR +PURPOSE OR NON-INFRINGING. ALL WARRANTIES ARE DISCLAIMED AND THE +ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE CODE IS WITH +YOU. SHOULD ANY CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE +COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY +NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY +CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY CODE IS +AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY +SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES FOR LOSS OF +PROFITS, REVENUE, OR FOR LOSS OF INFORMATION OR ANY OTHER LOSS. + +YOU EXPRESSLY AGREE TO FOREVER INDEMNIFY, DEFEND AND HOLD HARMLESS THE +COPYRIGHT HOLDERS AND CONTRIBUTORS OF GLOD AGAINST ALL CLAIMS, +DEMANDS, SUITS OR OTHER ACTIONS ARISING DIRECTLY OR INDIRECTLY FROM +YOUR ACCEPTANCE AND USE OF GLOD. + +Although NOT REQUIRED, we would appreciate it if active users of GLOD +put a link on their web site to the GLOD web site when possible. + + diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index cd3963050f..cb03379b23 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -64,6 +64,7 @@ #include "llfocusmgr.h" #include "llscrolllistctrl.h" #include "llsdserialize.h" +#include "llsdutil.h" #include "llvfs.h" // When uploading multiple files, don't display any of them when uploading more than this number. @@ -71,6 +72,120 @@ static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5; void dialog_refresh_all(); +void on_new_single_inventory_upload_complete( + LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + const std::string inventory_type_string, + const LLUUID& item_folder_id, + const std::string& item_name, + const std::string& item_description, + const LLSD& server_response, + S32 upload_price) +{ + if ( upload_price > 0 ) + { + // this upload costed us L$, update our balance + // and display something saying that it cost L$ + LLStatusBar::sendMoneyBalanceRequest(); + + LLSD args; + args["AMOUNT"] = llformat("%d", upload_price); + LLNotifications::instance().add("UploadPayment", args); + } + + // Actually add the upload to viewer inventory + llinfos << "Adding " << server_response["new_inventory_item"].asUUID() + << " " << server_response["new_asset"].asUUID() + << " to inventory." << llendl; + + if( item_folder_id.notNull() ) + { + U32 everyone_perms = PERM_NONE; + U32 group_perms = PERM_NONE; + U32 next_owner_perms = PERM_ALL; + if( server_response.has("new_next_owner_mask") ) + { + // The server provided creation perms so use them. + // Do not assume we got the perms we asked for in + // since the server may not have granted them all. + everyone_perms = server_response["new_everyone_mask"].asInteger(); + group_perms = server_response["new_group_mask"].asInteger(); + next_owner_perms = server_response["new_next_owner_mask"].asInteger(); + } + else + { + // The server doesn't provide creation perms + // so use old assumption-based perms. + if( inventory_type_string != "snapshot") + { + next_owner_perms = PERM_MOVE | PERM_TRANSFER; + } + } + + LLPermissions new_perms; + new_perms.init( + gAgent.getID(), + gAgent.getID(), + LLUUID::null, + LLUUID::null); + + new_perms.initMasks( + PERM_ALL, + PERM_ALL, + everyone_perms, + group_perms, + next_owner_perms); + + S32 creation_date_now = time_corrected(); + LLPointer item = new LLViewerInventoryItem( + server_response["new_inventory_item"].asUUID(), + item_folder_id, + new_perms, + server_response["new_asset"].asUUID(), + asset_type, + inventory_type, + item_name, + item_description, + LLSaleInfo::DEFAULT, + LLInventoryItem::II_FLAGS_NONE, + creation_date_now); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + + // Show the preview panel for textures and sounds to let + // user know that the image (or snapshot) arrived intact. + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); + if ( view ) + { + LLFocusableElement* focus = gFocusMgr.getKeyboardFocus(); + + view->getPanel()->setSelection( + server_response["new_inventory_item"].asUUID(), + TAKE_FOCUS_NO); + + if( + (LLAssetType::AT_TEXTURE == asset_type || + LLAssetType::AT_SOUND == asset_type) && + (LLFilePicker::instance().getFileCount() <= + FILE_COUNT_DISPLAY_THRESHOLD) ) + { + view->getPanel()->openSelected(); + } + + // restore keyboard focus + gFocusMgr.setKeyboardFocus(focus); + } + } + else + { + llwarns << "Can't find a folder to put it in" << llendl; + } + + // remove the "Uploading..." message + LLUploadDialog::modalUploadFinished(); +} + LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, const LLUUID& vfile_id, LLAssetType::EType asset_type) @@ -88,9 +203,10 @@ LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, } } -LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, - const std::string& file_name, - LLAssetType::EType asset_type) +LLAssetUploadResponder::LLAssetUploadResponder( + const LLSD &post_data, + const std::string& file_name, + LLAssetType::EType asset_type) : LLHTTPClient::Responder(), mPostData(post_data), mFileName(file_name), @@ -196,15 +312,19 @@ void LLAssetUploadResponder::uploadComplete(const LLSD& content) { } -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, vfile_id, asset_type) +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( + const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) + : LLAssetUploadResponder(post_data, vfile_id, asset_type) { } -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, file_name, asset_type) +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( + const LLSD& post_data, + const std::string& file_name, + LLAssetType::EType asset_type) + : LLAssetUploadResponder(post_data, file_name, asset_type) { } @@ -219,96 +339,31 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = 0; // Update L$ and ownership credit information // since it probably changed on the server if (asset_type == LLAssetType::AT_TEXTURE || asset_type == LLAssetType::AT_SOUND || - asset_type == LLAssetType::AT_ANIMATION) + asset_type == LLAssetType::AT_ANIMATION || + asset_type == LLAssetType::AT_MESH) { - LLStatusBar::sendMoneyBalanceRequest(); - - LLSD args; - args["AMOUNT"] = llformat("%d", expected_upload_cost); - LLNotifications::instance().add("UploadPayment", args); + expected_upload_cost = + LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); } - // Actually add the upload to viewer inventory - llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " - << content["new_asset"].asUUID() << " to inventory." << llendl; - if(mPostData["folder_id"].asUUID().notNull()) - { - //std::ostringstream out; - //LLSDXMLFormatter *formatter = new LLSDXMLFormatter; - //formatter->format(mPostData, out, LLSDFormatter::OPTIONS_PRETTY); - //llinfos << "Post Data: " << out.str() << llendl; - - U32 everyone_perms = PERM_NONE; - U32 group_perms = PERM_NONE; - U32 next_owner_perms = PERM_ALL; - if(content.has("new_next_owner_mask")) - { - // This is a new sim that provides creation perms so use them. - // Do not assume we got the perms we asked for in mPostData - // since the sim may not have granted them all. - everyone_perms = content["new_everyone_mask"].asInteger(); - group_perms = content["new_group_mask"].asInteger(); - next_owner_perms = content["new_next_owner_mask"].asInteger(); - } - else - { - // This old sim doesn't provide creation perms so use old assumption-based perms. - if(mPostData["inventory_type"].asString() != "snapshot") - { - next_owner_perms = PERM_MOVE | PERM_TRANSFER; - } - } - LLPermissions new_perms; - new_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms); - S32 creation_date_now = time_corrected(); - LLPointer item - = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), - mPostData["folder_id"].asUUID(), - new_perms, - content["new_asset"].asUUID(), - asset_type, - inventory_type, - mPostData["name"].asString(), - mPostData["description"].asString(), - LLSaleInfo::DEFAULT, - LLInventoryItem::II_FLAGS_NONE, - creation_date_now); - gInventory.updateItem(item); - gInventory.notifyObservers(); - - // Show the preview panel for textures and sounds to let - // user know that the image (or snapshot) arrived intact. - LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); - if(view) - { - LLFocusableElement* focus = gFocusMgr.getKeyboardFocus(); + on_new_single_inventory_upload_complete( + asset_type, + inventory_type, + mPostData["asset_type"].asString(), + mPostData["folder_id"].asUUID(), + mPostData["name"], + mPostData["description"], + content, + expected_upload_cost); - view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); - if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type) - && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD) - { - view->getPanel()->openSelected(); - } - //LLFloaterInventory::dumpSelectionInformation((void*)view); - // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus); - } - } - else - { - llwarns << "Can't find a folder to put it in" << llendl; - } + // continue uploading for bulk uploads - // remove the "Uploading..." message - LLUploadDialog::modalUploadFinished(); - // *FIX: This is a pretty big hack. What this does is check the // file picker if there are any more pending uploads. If so, // upload that file. @@ -325,18 +380,39 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) // Continuing the horrible hack above, we need to extract the originally requested permissions data, if any, // and use them for each next file to be uploaded. Note the requested perms are not the same as the - // granted ones found in the given "content" structure but can still be found in mPostData. -MG - U32 everyone_perms = mPostData.has("everyone_mask") ? mPostData.get("everyone_mask" ).asInteger() : PERM_NONE; - U32 group_perms = mPostData.has("group_mask") ? mPostData.get("group_mask" ).asInteger() : PERM_NONE; - U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE; + U32 everyone_perms = + content.has("everyone_mask") ? + content["everyone_mask"].asInteger() : + PERM_NONE; + + U32 group_perms = + content.has("group_mask") ? + content["group_mask"].asInteger() : + PERM_NONE; + + U32 next_owner_perms = + content.has("next_owner_mask") ? + content["next_owner_mask"].asInteger() : + PERM_NONE; + std::string display_name = LLStringUtil::null; LLAssetStorage::LLStoreAssetCallback callback = NULL; void *userdata = NULL; - upload_new_resource(next_file, asset_name, asset_name, - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - next_owner_perms, group_perms, - everyone_perms, display_name, - callback, expected_upload_cost, userdata); + + upload_new_resource( + next_file, + asset_name, + asset_name, + 0, + LLAssetType::AT_NONE, + LLInventoryType::IT_NONE, + next_owner_perms, + group_perms, + everyone_perms, + display_name, + callback, + LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), + userdata); } } @@ -383,17 +459,19 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) } -LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, vfile_id, asset_type) +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder( + const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) + : LLAssetUploadResponder(post_data, vfile_id, asset_type) { } -LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, file_name, asset_type) +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder( + const LLSD& post_data, + const std::string& file_name, + LLAssetType::EType asset_type) + : LLAssetUploadResponder(post_data, file_name, asset_type) { } @@ -576,3 +654,374 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) break; } } + + +///////////////////////////////////////////////////// +// LLNewAgentInventoryVariablePriceResponder::Impl // +///////////////////////////////////////////////////// +class LLNewAgentInventoryVariablePriceResponder::Impl +{ +public: + Impl( + const LLUUID& vfile_id, + const LLSD& inventory_data) : + mVFileID(vfile_id), + mInventoryData(inventory_data) + { + } + + Impl( + const std::string& file_name, + const LLSD& inventory_data) : + mFileName(file_name), + mInventoryData(inventory_data) + { + } + + std::string getFilenameOrIDString() const + { + return (mFileName.empty() ? mVFileID.asString() : mFileName); + } + + LLUUID getVFileID() const + { + return mVFileID; + } + + std::string getFilename() const + { + return mFileName; + } + + LLAssetType::EType getAssetType() const + { + return LLAssetType::lookup( + mInventoryData["asset_type"].asString()); + } + + LLInventoryType::EType getInventoryType() const + { + return LLInventoryType::lookup( + mInventoryData["inventory_type"].asString()); + } + + std::string getInventoryTypeString() const + { + return mInventoryData["inventory_type"].asString(); + } + + LLUUID getFolderID() const + { + return mInventoryData["folder_id"].asUUID(); + } + + std::string getItemName() const + { + return mInventoryData["name"].asString(); + } + + std::string getItemDescription() const + { + return mInventoryData["description"].asString(); + } + + void displayCannotUploadReason(const std::string& reason) + { + LLSD args; + args["FILE"] = getFilenameOrIDString(); + args["REASON"] = reason; + + + LLNotifications::instance().add("CannotUploadReason", args); + LLUploadDialog::modalUploadFinished(); + } + + void onApplicationLevelError(const std::string& error_identifier) + { + // TODO*: Pull these user visible strings from an xml file + // to be localized + static const std::string _INSUFFICIENT_FUNDS = + "NewAgentInventory_InsufficientLindenDollarBalance"; + + + if ( _INSUFFICIENT_FUNDS == error_identifier ) + { + displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload."); + } + else + { + displayCannotUploadReason("Unknown Error"); + + } + } + + void onTransportError() + { + displayCannotUploadReason( + "The server is experiencing unexpected difficulties."); + } + + void onTransportError(const std::string& error_identifier) + { + // TODO*: Pull these user visible strings from an xml file + // to be localized + + static const std::string _SERVER_ERROR_AFTER_CHARGE = + "NewAgentInventory_ServerErrorAfterCharge"; + + if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier ) + { + displayCannotUploadReason( + "The server is experiencing unexpected difficulties. You may have been charged for the upload."); + } + else + { + displayCannotUploadReason( + "The server is experiencing unexpected difficulties."); + } + + } + + bool uploadConfirmationCallback( + const LLSD& notification, + const LLSD& response, + boost::intrusive_ptr responder) + { + S32 option; + std::string confirmation_url; + + option = LLNotification::getSelectedOption( + notification, + response); + + confirmation_url = + notification["payload"]["confirmation_url"].asString(); + + // Yay! We are confirming or cancelling our upload + LLSD body; + + body["confirm_upload"] = false; + + switch(option) + { + case 0: + { + body["confirm_upload"] = true; + body["expected_upload_price"] = + notification["payload"]["expected_upload_price"]; + } + break; + case 1: + default: + break; + } + + LLHTTPClient::post(confirmation_url, body, responder); + + return false; + } + +private: + std::string mFileName; + + LLSD mInventoryData; + LLUUID mVFileID; +}; + +/////////////////////////////////////////////// +// LLNewAgentInventoryVariablePriceResponder // +/////////////////////////////////////////////// +LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( + const LLUUID& vfile_id, + const LLSD& inventory_info) +{ + mImpl = new Impl( + vfile_id, + inventory_info); +} + +LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( + const std::string& file_name, + const LLSD& inventory_info) +{ + mImpl = new Impl( + file_name, + inventory_info); +} + +LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResponder() +{ + delete mImpl; +} + +void LLNewAgentInventoryVariablePriceResponder::errorWithContent( + U32 statusNum, + const std::string& reason, + const LLSD& content) +{ + llinfos << "LLNewAgentInventoryVariablePrice::error " << statusNum + << " reason: " << reason << llendl; + + if ( content.has("error") ) + { + static const std::string _ERROR = "error"; + static const std::string _IDENTIFIER = "identifier"; + + mImpl->onTransportError(content[_ERROR][_IDENTIFIER].asString()); + } + else + { + mImpl->onTransportError(); + } +} + +void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) +{ + // Parse out application level errors and the appropriate + // responses for them + static const std::string _ERROR = "error"; + static const std::string _IDENTIFIER = "identifier"; + static const std::string _STATE = "state"; + + static const std::string _COMPLETE = "complete"; + static const std::string _COST_ANALYSIS = "cost_analysis"; + static const std::string _NEEDS_CONFIRMATION = "needs_confirmation"; + static const std::string _CANCEL = "cancel"; + + static const std::string _RESOURCE_COST = "resource_cost"; + static const std::string _UPLOAD_PRICE = "upload_price"; + + static const std::string _ANALYZER = "analyzer"; + static const std::string _RSVP = "rsvp"; + + // Check for application level errors + if ( content.has(_ERROR) ) + { + onApplicationLevelError(content[_ERROR][_IDENTIFIER].asString()); + return; + } + + std::string state = content[_STATE]; + LLAssetType::EType asset_type = mImpl->getAssetType(); + + if ( _COST_ANALYSIS == state ) + { + std::string analyzer_url = content[_ANALYZER]; + + if ( mImpl->getFilename().empty() ) + { + // we have no filename, use virtual file ID instead + LLHTTPClient::postFile( + analyzer_url, + mImpl->getVFileID(), + asset_type, + this); + } + else + { + LLHTTPClient::postFile( + analyzer_url, + mImpl->getFilename(), + this); + } + } + else if ( _COMPLETE == state ) + { + // rename file in VFS with new asset id + if (mImpl->getFilename().empty()) + { + // rename the file in the VFS to the actual asset id + // llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl; + gVFS->renameFile( + mImpl->getVFileID(), + asset_type, + content["new_asset"].asUUID(), + asset_type); + } + + on_new_single_inventory_upload_complete( + asset_type, + mImpl->getInventoryType(), + mImpl->getInventoryTypeString(), + mImpl->getFolderID(), + mImpl->getItemName(), + mImpl->getItemDescription(), + content, + content["upload_price"].asInteger()); + + // TODO* Add bulk (serial) uploading or add + // a super class of this that does so + } + else if ( _NEEDS_CONFIRMATION == state ) + { + showConfirmationDialog( + content[_UPLOAD_PRICE].asInteger(), + content[_RESOURCE_COST].asInteger(), + content[_RSVP].asString()); + } + else if ( _CANCEL == state ) + { + // cancelled, do nothing + } + else + { + onApplicationLevelError(""); + } +} + +void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError( + const std::string& error_identifier) +{ + mImpl->onApplicationLevelError(error_identifier); +} + +void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( + S32 upload_price, + S32 resource_cost, + const std::string& confirmation_url) +{ + if ( 0 == upload_price ) + { + // don't show confirmation dialog for free uploads, I mean, + // they're free! + LLSD body; + body["confirm_upload"] = true; + body["expected_upload_price"] = upload_price; + + LLHTTPClient::post(confirmation_url, body, this); + } + else + { + LLSD substitutions; + LLSD payload; + + substitutions["PRICE"] = upload_price; + + payload["confirmation_url"] = confirmation_url; + payload["expected_upload_price"] = upload_price; + + // The creating of a new instrusive_ptr(this) + // creates a new boost::intrusive_ptr + // which is a copy of this. This code is required because + // 'this' is always of type Class* and not the intrusive_ptr, + // and thus, a reference to 'this' is not registered + // by using just plain 'this'. + + // Since LLNewAgentInventoryVariablePriceResponder is a + // reference counted class, it is possible (since the + // reference to a plain 'this' would be missed here) that, + // when using plain ol' 'this', that this object + // would be deleted before the callback is triggered + // and cause sadness. + LLNotifications::instance().add( + "UploadCostConfirmation", + substitutions, + payload, + boost::bind( + &LLNewAgentInventoryVariablePriceResponder::Impl::uploadConfirmationCallback, + mImpl, + _1, + _2, + boost::intrusive_ptr(this))); + } +} diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index a08d70213c..adbf13519b 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -61,17 +61,58 @@ protected: std::string mFileName; }; + +// TODO*: Remove this once deprecated class LLNewAgentInventoryResponder : public LLAssetUploadResponder { public: - LLNewAgentInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type); - LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, - LLAssetType::EType asset_type); + LLNewAgentInventoryResponder( + const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLNewAgentInventoryResponder( + const LLSD& post_data, + const std::string& file_name, + LLAssetType::EType asset_type); virtual void uploadComplete(const LLSD& content); }; +// A base class which goes through and performs some default +// actions for variable price uploads. If more specific actions +// are needed (such as different confirmation messages, etc.) +// the functions onApplicationLevelError and showConfirmationDialog. +class LLNewAgentInventoryVariablePriceResponder : + public LLHTTPClient::Responder +{ +public: + LLNewAgentInventoryVariablePriceResponder( + const LLUUID& vfile_id, + const LLSD& inventory_info); + + LLNewAgentInventoryVariablePriceResponder( + const std::string& file_name, + const LLSD& inventory_info); + + virtual ~LLNewAgentInventoryVariablePriceResponder(); + + void errorWithContent( + U32 statusNum, + const std::string& reason, + const LLSD& content); + void result(const LLSD& content); + + virtual void onApplicationLevelError( + const std::string& error_identifier); + virtual void showConfirmationDialog( + S32 upload_price, + S32 resource_cost, + const std::string& confirmation_url); + +private: + class Impl; + Impl* mImpl; +}; + class LLBakedUploadData; class LLSendTexLayerResponder : public LLAssetUploadResponder { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 5a10b688da..27c9ab319a 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -314,8 +314,10 @@ private: inline LLFace* LLDrawable::getFace(const S32 i) const { - llassert((U32)i < mFaces.size()); - llassert(mFaces[i]); + if ((U32) i >= mFaces.size()) + { + return NULL; + } return mFaces[i]; } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index e087feeaec..e74b488be9 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -701,6 +701,18 @@ void LLDrawPoolBump::endBump() gGL.setSceneBlendType(LLRender::BT_ALPHA); } +S32 LLDrawPoolBump::getNumDeferredPasses() +{ + if (gSavedSettings.getBOOL("RenderObjectBump")) + { + return 1; + } + else + { + return 0; + } +} + void LLDrawPoolBump::beginDeferredPass(S32 pass) { if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index bf940cf1e4..2019f1df26 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -79,7 +79,7 @@ public: void renderBump(); void endBump(); - virtual S32 getNumDeferredPasses() { return 1; } + virtual S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); /*virtual*/ void endDeferredPass(S32 pass); /*virtual*/ void renderDeferred(S32 pass); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4246cbc27f..e49ef8b969 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1040,7 +1040,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); - for (U16 i = 0; i < num_indices; i++) + for (S32 i = 0; i < num_indices; i++) { *indicesp++ = vf.mIndices[i] + index_offset; } diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 028e1cc098..e12db901bd 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -61,6 +61,7 @@ LLFilePicker LLFilePicker::sInstance; #define XML_FILTER L"XML files (*.xml)\0*.xml\0" #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0" #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" +#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #endif // @@ -193,6 +194,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = RAW_FILTER \ L"\0"; break; + case FFLOAD_MODEL: + mOFN.lpstrFilter = MODEL_FILTER \ + L"\0"; + break; default: res = FALSE; break; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index ab2455620f..7600922e9c 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -93,6 +93,7 @@ public: FFLOAD_XML = 6, FFLOAD_SLOBJECT = 7, FFLOAD_RAW = 8, + FFLOAD_MODEL = 9, }; enum ESaveFilter @@ -198,4 +199,6 @@ public: ~LLFilePicker(); }; +const std::string upload_pick(void* data); + #endif diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index c890f9f122..364c79e3c1 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -1143,6 +1143,9 @@ const std::string& get_item_icon_name(LLAssetType::EType asset_type, case LLAssetType::AT_LINK_FOLDER: idx = LINKFOLDER_ICON_NAME; break; + case LLAssetType::AT_MESH: + idx = MESH_ICON_NAME; + break; default: break; } diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 55019f91f8..58637329d7 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -567,6 +567,18 @@ void LLHUDText::setStringUTF8(const std::string &wtext) setString(utf8str_to_wstring(wtext)); } +std::string LLHUDText::getString() +{ + std::ostringstream ostr; + for (U32 i = 0; i < mTextSegments.size(); ++i) + { + const std::string str = wstring_to_utf8str(mTextSegments[i].getText()); + ostr << str; + } + + return ostr.str(); +} + void LLHUDText::setString(const LLWString &wtext) { mTextSegments.clear(); diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h index dc14a8c764..4787a15eaf 100644 --- a/indra/newview/llhudtext.h +++ b/indra/newview/llhudtext.h @@ -90,6 +90,7 @@ public: public: void setStringUTF8(const std::string &utf8string); + std::string getString(); void setString(const LLWString &wstring); void clearString(); void addLine(const std::string &text, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ca9ebf8dc1..028505456b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -154,7 +154,9 @@ std::string ICON_NAME[ICON_NAME_COUNT] = "Inv_Gesture", "inv_item_linkitem.tga", - "inv_item_linkfolder.tga" + "inv_item_linkfolder.tga", + + "inv_item_mesh.tga" }; @@ -891,6 +893,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, // Only should happen for broken links. new_listener = new LLLinkItemBridge(inventory, uuid); break; + case LLAssetType::AT_MESH: + if(!(inv_type == LLInventoryType::IT_MESH)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLMeshBridge(inventory, uuid); + break; + default: llinfos << "Unhandled asset type (llassetstorage.h): " << (S32)asset_type << llendl; @@ -2189,6 +2199,9 @@ LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type) { // we only have one folder image now return LLUI::getUIImage("Inv_FolderClosed"); + /*case LLAssetType::AT_MESH: + control = "inv_folder_mesh.tga"; + break;*/ } BOOL LLFolderBridge::renameItem(const std::string& new_name) @@ -2558,6 +2571,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_LINK: + case DAD_MESH: accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, drop); break; @@ -3457,6 +3471,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_BODYPART: case DAD_ANIMATION: case DAD_GESTURE: + case DAD_MESH: { LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; const LLPermissions& perm = inv_item->getPermissions(); @@ -4713,6 +4728,65 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, delete on_remove_struct; } + +// +=================================================+ +// | LLMeshBridge | +// +=================================================+ + +LLUIImagePtr LLMeshBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE); +} + +void LLMeshBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + // open mesh + } +} + +void LLMeshBridge::previewItem() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + // preview mesh + } +} + + +void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + + hideContextEntries(menu, items, disabled_items); +} + + + LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, const LLUUID& uuid,LLInventoryModel* model) { @@ -4761,6 +4835,12 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ break; + case LLAssetType::AT_MESH: + action = new LLMeshBridgeAction(uuid,model); + break; + + + default: break; } @@ -4998,6 +5078,18 @@ void LLWearableBridgeAction::doIt() LLInvFVBridgeAction::doIt(); } +//virtual +void LLMeshBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + // do it + } + + LLInvFVBridgeAction::doIt(); +} + // +=================================================+ // | LLLinkItemBridge | // +=================================================+ diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 6b2a2d32de..95a5f97e7b 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -79,6 +79,8 @@ enum EInventoryIcon LINKITEM_ICON_NAME, LINKFOLDER_ICON_NAME, + + MESH_ICON_NAME, ICON_NAME_COUNT }; @@ -609,7 +611,6 @@ protected: static std::string sPrefix; }; - class LLLinkFolderBridge : public LLItemBridge { friend class LLInvFVBridge; @@ -630,6 +631,25 @@ protected: static std::string sPrefix; }; + + +class LLMeshBridge : public LLItemBridge +{ + friend class LLInvFVBridge; +public: + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual void previewItem(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + +protected: + LLMeshBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : + LLItemBridge(inventory, uuid) {} +}; + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInvFVBridgeAction (& its derived classes) // @@ -790,6 +810,19 @@ protected: }; +class LLMeshBridgeAction: public LLInvFVBridgeAction +{ + friend class LLInvFVBridgeAction; +public: + virtual void doIt() ; + virtual ~LLMeshBridgeAction(){} +protected: + LLMeshBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){} + +}; + + + void wear_inventory_item_on_avatar(LLInventoryItem* item); class LLViewerJointAttachment; diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 0ce85818dd..a824025723 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -157,6 +157,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: + case DAD_MESH: { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a7f0ce16d3..a5e3a0492b 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -173,7 +173,6 @@ LLObjectSelection *get_null_object_selection() return sNullSelection; } - //----------------------------------------------------------------------------- // LLSelectMgr() //----------------------------------------------------------------------------- @@ -5301,6 +5300,78 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); } +void LLSelectNode::renderOneWireframe(const LLColor4& color) +{ + LLViewerObject* objectp = getObject(); + if (!objectp) + { + return; + } + + LLDrawable* drawable = objectp->mDrawable; + if(!drawable) + { + return; + } + + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + + BOOL is_hud_object = objectp->isHUDAttachment(); + + if (!is_hud_object) + { + glLoadIdentity(); + glMultMatrixd(gGLModelView); + } + + if (drawable->isActive()) + { + glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix); + } + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) + { + gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); + LLGLEnable fog(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec(); + LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0); + glFogf(GL_FOG_START, d); + glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); + glFogfv(GL_FOG_COLOR, fogCol.mV); + + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + { + glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } + } + } + + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + glColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(3.f, 2.f); + glLineWidth(3.f); + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } + glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.popMatrix(); +} + //----------------------------------------------------------------------------- // renderOneSilhouette() //----------------------------------------------------------------------------- @@ -5318,6 +5389,13 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) return; } + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj && vobj->isMesh()) + { + renderOneWireframe(color); + return; + } + if (!mSilhouetteExists) { return; diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 6e757ef976..b518765946 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -140,6 +140,7 @@ public: BOOL isTESelected(S32 te_index); S32 getLastSelectedTE(); S32 getTESelectMask() { return mTESelectMask; } + void renderOneWireframe(const LLColor4& color); void renderOneSilhouette(const LLColor4 &color); void setTransient(BOOL transient) { mTransient = transient; } BOOL isTransient() { return mTransient; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 9f317803ce..9704fe71b7 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2294,7 +2294,6 @@ void pushVerts(LLFace* face, U32 mask) U16 offset = face->getIndicesStart(); buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); } - } void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 64c2a9acbc..1d9127639a 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -59,6 +59,7 @@ class LLTextureAtlasSlot; S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); +void pushVerts(LLFace* face, U32 mask); // get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index b5aec1b80b..ae4ec75a1b 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -289,7 +289,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( { BOOL handled = FALSE; - if (cargo_type == DAD_TEXTURE) + if ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) { LLInventoryItem *item = (LLInventoryItem *)cargo_data; @@ -1152,7 +1152,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, // returns true, then the cast was valid, and we can perform // the third test without problems. LLInventoryItem* item = (LLInventoryItem*)cargo_data; - if (getEnabled() && (cargo_type == DAD_TEXTURE) && allowDrop(item)) + if (getEnabled() && + ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) && + allowDrop(item)) { if (drop) { diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 9a63f07a7e..643a81be1f 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -483,6 +483,16 @@ LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT] &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND }, + + +// Source: DAD_MESH + { + &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE + &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF + &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR + &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT + &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND + }, }; LLToolDragAndDrop::LLToolDragAndDrop() @@ -2007,6 +2017,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: + case DAD_MESH: { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index a6a72e9666..3b727e2861 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -869,12 +869,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } } - /// We copy the frame buffer straight into a texture here, - /// and then display it again with compositor effects. - /// Using render to texture would be faster/better, but I don't have a - /// grasp of their full display stack just yet. - // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.renderDeferredLighting(); @@ -1097,7 +1091,7 @@ void render_ui(F32 zoom_factor, int subfield) { gPipeline.renderBloom(gSnapshot, zoom_factor, subfield); } - + render_hud_elements(); render_hud_attachments(); } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dace3f875f..7c5f5e8b2f 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -122,6 +122,8 @@ #include "llpreviewsound.h" #include "llpreviewtexture.h" #include "llsyswellwindow.h" +#include "llfloatermodelpreview.h" + // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -236,7 +238,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); - + LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "upload"); LLFloaterReg::add("voice_call", "floater_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index dc291d6c34..56f70e0f5d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -268,7 +268,6 @@ LLMenuItemCallGL* gBusyMenu = NULL; // Local prototypes // File Menu -const char* upload_pick(void* data); void handle_compress_image(void*); @@ -557,6 +556,7 @@ void init_menus() gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost); gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost); + gMenuHolder->childSetLabelArg("Upload Model", "[COST]", upload_cost); gAFKMenu = gMenuBarView->getChild("Set Away", TRUE); gBusyMenu = gMenuBarView->getChild("Set Busy", TRUE); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index d3a9e1cef8..836ac79a87 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -39,6 +39,7 @@ #include "llfilepicker.h" #include "llfloaterreg.h" #include "llfloaterbuycurrency.h" +#include "llfloatermodelpreview.h" #include "llfloatersnapshot.h" #include "llinventorymodel.h" // gInventory #include "llresourcedata.h" @@ -62,6 +63,7 @@ #include "lleconomy.h" #include "llhttpclient.h" #include "llsdserialize.h" +#include "llsdutil.h" #include "llstring.h" #include "lltransactiontypes.h" #include "lluuid.h" @@ -101,6 +103,7 @@ static std::string XML_EXTENSIONS = "xml"; static std::string SLOBJECT_EXTENSIONS = "slobject"; #endif static std::string ALL_FILE_EXTENSIONS = "*.*"; +static std::string MODEL_EXTENSIONS = "dae"; std::string build_extensions_string(LLFilePicker::ELoadFilter filter) { @@ -115,6 +118,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) return ANIM_EXTENSIONS; case LLFilePicker::FFLOAD_SLOBJECT: return SLOBJECT_EXTENSIONS; + case LLFilePicker::FFLOAD_MODEL: + return MODEL_EXTENSIONS; #ifdef _CORY_TESTING case LLFilePicker::FFLOAD_GEOMETRY: return GEOMETRY_EXTENSIONS; @@ -258,6 +263,16 @@ class LLFileUploadImage : public view_listener_t } }; +class LLFileUploadModel : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloaterReg::showInstance("upload_model"); + + return TRUE; + } +}; + class LLFileUploadSound : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -319,10 +334,21 @@ class LLFileUploadBulk : public view_listener_t LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); void *userdata = NULL; - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), - display_name, - callback, expected_upload_cost, userdata); + + upload_new_resource( + filename, + asset_name, + asset_name, + 0, + LLAssetType::AT_NONE, + LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms(), + LLFloaterPerms::getGroupPerms(), + LLFloaterPerms::getEveryonePerms(), + display_name, + callback, + expected_upload_cost, + userdata); // *NOTE: Ew, we don't iterate over the file list here, // we handle the next files in upload_done_callback() @@ -491,17 +517,20 @@ void handle_compress_image(void*) } } -void upload_new_resource(const std::string& src_filename, std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata) +void upload_new_resource( + const std::string& src_filename, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata) { // Generate the temporary UUID. std::string filename = gDirUtilp->getTempFilename(); @@ -783,9 +812,21 @@ void upload_new_resource(const std::string& src_filename, std::string name, { t_disp_name = src_filename; } - upload_new_resource(tid, asset_type, name, desc, compression_info, // tid - destination_folder_type, inv_type, next_owner_perms, group_perms, everyone_perms, - display_name, callback, expected_upload_cost, userdata); + upload_new_resource( + tid, + asset_type, + name, + desc, + compression_info, // tid + destination_folder_type, + inv_type, + next_owner_perms, + group_perms, + everyone_perms, + display_name, + callback, + expected_upload_cost, + userdata); } else { @@ -801,7 +842,11 @@ void upload_new_resource(const std::string& src_filename, std::string name, } } -void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) +void upload_done_callback( + const LLUUID& uuid, + void* user_data, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (fixed) { LLResourceData* data = (LLResourceData*)user_data; S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0; @@ -902,71 +947,134 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt std::string display_name = LLStringUtil::null; LLAssetStorage::LLStoreAssetCallback callback = NULL; void *userdata = NULL; - upload_new_resource(next_file, asset_name, asset_name, // file - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - PERM_NONE, PERM_NONE, PERM_NONE, - display_name, - callback, - expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost - userdata); + upload_new_resource( + next_file, + asset_name, + asset_name, // file + 0, + LLAssetType::AT_NONE, + LLInventoryType::IT_NONE, + PERM_NONE, + PERM_NONE, + PERM_NONE, + display_name, + callback, + expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost + userdata); } } -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, - std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata) +LLAssetID upload_new_resource_prep( + const LLTransactionID &tid, + LLAssetType::EType asset_type, + LLInventoryType::EType& inventory_type, + std::string& name, + const std::string& display_name, + std::string& description) { - if(gDisconnected) + if ( gDisconnected ) { - return ; + LLAssetID rv; + + rv.setNull(); + return rv; } LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - if( LLAssetType::AT_SOUND == asset_type ) + if ( LLAssetType::AT_SOUND == asset_type ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_SOUND_COUNT ); } - else - if( LLAssetType::AT_TEXTURE == asset_type ) + else if ( LLAssetType::AT_TEXTURE == asset_type ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); } - else - if( LLAssetType::AT_ANIMATION == asset_type) + else if ( LLAssetType::AT_ANIMATION == asset_type ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_ANIM_COUNT ); } - if(LLInventoryType::IT_NONE == inv_type) + if ( LLInventoryType::IT_NONE == inventory_type ) { - inv_type = LLInventoryType::defaultForAssetType(asset_type); + inventory_type = LLInventoryType::defaultForAssetType(asset_type); } LLStringUtil::stripNonprintable(name); - LLStringUtil::stripNonprintable(desc); - if(name.empty()) + LLStringUtil::stripNonprintable(description); + + if ( name.empty() ) { name = "(No Name)"; } - if(desc.empty()) + if ( description.empty() ) { - desc = "(No Description)"; + description = "(No Description)"; } - + // At this point, we're ready for the upload. std::string upload_message = "Uploading...\n\n"; upload_message.append(display_name); LLUploadDialog::modalUploadDialog(upload_message); + return uuid; +} + +LLSD generate_new_resource_upload_capability_body( + LLAssetType::EType asset_type, + const std::string& name, + const std::string& desc, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms) +{ + LLSD body; + + body["folder_id"] = gInventory.findCategoryUUIDForType( + (destination_folder_type == LLAssetType::AT_NONE) ? + asset_type : + destination_folder_type); + + body["asset_type"] = LLAssetType::lookup(asset_type); + body["inventory_type"] = LLInventoryType::lookup(inv_type); + body["name"] = name; + body["description"] = desc; + body["next_owner_mask"] = LLSD::Integer(next_owner_perms); + body["group_mask"] = LLSD::Integer(group_perms); + body["everyone_mask"] = LLSD::Integer(everyone_perms); + + return body; +} + +void upload_new_resource( + const LLTransactionID &tid, + LLAssetType::EType asset_type, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata) +{ + LLAssetID uuid = + upload_new_resource_prep( + tid, + asset_type, + inv_type, + name, + display_name, + desc); + llinfos << "*** Uploading: " << llendl; llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; llinfos << "UUID: " << uuid << llendl; @@ -975,26 +1083,32 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl; lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl; lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); - if (!url.empty()) + + std::string url = gAgent.getRegion()->getCapability( + "NewFileAgentInventory"); + + if ( !url.empty() ) { llinfos << "New Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); - body["asset_type"] = LLAssetType::lookup(asset_type); - body["inventory_type"] = LLInventoryType::lookup(inv_type); - body["name"] = name; - body["description"] = desc; - body["next_owner_mask"] = LLSD::Integer(next_owner_perms); - body["group_mask"] = LLSD::Integer(group_perms); - body["everyone_mask"] = LLSD::Integer(everyone_perms); - body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost); - - //std::ostringstream llsdxml; - //LLSDSerialize::toPrettyXML(body, llsdxml); - //llinfos << "posting body to capability: " << llsdxml.str() << llendl; - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); + LLSD body; + body = generate_new_resource_upload_capability_body( + asset_type, + name, + desc, + destination_folder_type, + inv_type, + next_owner_perms, + group_perms, + everyone_perms); + + LLHTTPClient::post( + url, + body, + new LLNewAgentInventoryResponder( + body, + uuid, + asset_type)); } else { @@ -1039,11 +1153,83 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty } } +BOOL upload_new_variable_cost_resource( + const LLTransactionID &tid, + LLAssetType::EType asset_type, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata) +{ + LLAssetID uuid = + upload_new_resource_prep( + tid, + asset_type, + inv_type, + name, + display_name, + desc); + + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; + llinfos << "UUID: " << uuid << llendl; + llinfos << "Name: " << name << llendl; + llinfos << "Desc: " << desc << llendl; + lldebugs << "Folder: " + << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl; + lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; + + std::string url = gAgent.getRegion()->getCapability( + "NewFileAgentInventoryVariablePrice"); + + if ( !url.empty() ) + { + llinfos << "New Agent Inventory variable price upload" + << llendl; + + // Each of the two capabilities has similar data, so + // let's reuse that code + + LLSD body; + + body = generate_new_resource_upload_capability_body( + asset_type, + name, + desc, + destination_folder_type, + inv_type, + next_owner_perms, + group_perms, + everyone_perms); + + LLHTTPClient::post( + url, + body, + new LLNewAgentInventoryVariablePriceResponder( + uuid, + body)); + + return TRUE; + } + else + { + return FALSE; + } +} + void init_menu_file() { view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage"); view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); + view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index bf21292082..b51192b499 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -41,33 +41,56 @@ class LLTransactionID; void init_menu_file(); -void upload_new_resource(const std::string& src_filename, - std::string name, - std::string desc, - S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata); +void upload_new_resource( + const std::string& src_filename, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata); + +void upload_new_resource( + const LLTransactionID &tid, + LLAssetType::EType type, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata); + +// TODO* : Move all uploads to use this new function +// since at some point, that upload path will be deprecated and no longer +// used + +// We make a new function here to ensure that previous code is not broken +BOOL upload_new_variable_cost_resource( + const LLTransactionID &tid, + LLAssetType::EType type, + std::string name, + std::string desc, + S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata); -void upload_new_resource(const LLTransactionID &tid, - LLAssetType::EType type, - std::string name, - std::string desc, - S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata); #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 791ec07349..f16465acba 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4530,6 +4530,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost)); + gMenuHolder->childSetLabelArg("Upload Model", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost)); } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 7ea55b49e8..986264ad34 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1437,6 +1437,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("NewFileAgentInventoryVariablePrice"); + capabilityNames.append("ObjectAdd"); capabilityNames.append("ParcelPropertiesUpdate"); capabilityNames.append("ParcelMediaURLFilterList"); capabilityNames.append("ParcelNavigateMedia"); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 65994dfb30..ed8d820844 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -477,6 +477,7 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break; //TODO need img_name case LLAssetType::AT_FAVORITE: img_name = "Inv_Landmark"; break; + case LLAssetType::AT_MESH: img_name = "inv_item_mesh.tga"; break; default: llassert(0); } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a0ab4cb1e6..32baa29afb 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -583,7 +583,7 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image llassert_always(mGLTexturep.notNull()) ; BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename) ; - + if(ret) { mFullWidth = mGLTexturep->getCurrentWidth() ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5f95e9ccf1..72e40e3030 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3733,140 +3733,6 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); - - // *TODO below code was broken in deferred pipeline - /* - if ((!raw) || preview_width < 10 || preview_height < 10) - { - return FALSE; - } - - if(gResizeScreenTexture) //the window is resizing - { - return FALSE ; - } - - setCursor(UI_CURSOR_WAIT); - - // Hide all the UI widgets first and draw a frame - BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - - if ( prev_draw_ui != show_ui) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } - - S32 render_name = gSavedSettings.getS32("RenderName"); - gSavedSettings.setS32("RenderName", 0); - LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame - - S32 w = preview_width ; - S32 h = preview_height ; - LLVector2 display_scale = mDisplayScale ; - mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ; - LLRect window_rect = mWindowRect; - mWindowRect.set(0, h, w, 0); - - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - setup3DRender(); - - LLFontGL::setFontDisplay(FALSE) ; - LLHUDText::setDisplayText(FALSE) ; - if (type == SNAPSHOT_TYPE_OBJECT_ID) - { - gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); - } - else - { - display(do_rebuild, 1.0f, 0, TRUE); - render_ui(); - } - - S32 glformat, gltype, glpixel_length ; - if(SNAPSHOT_TYPE_DEPTH == type) - { - glpixel_length = 4 ; - glformat = GL_DEPTH_COMPONENT ; - gltype = GL_FLOAT ; - } - else - { - glpixel_length = 3 ; - glformat = GL_RGB ; - gltype = GL_UNSIGNED_BYTE ; - } - - raw->resize(w, h, glpixel_length); - glReadPixels(0, 0, w, h, glformat, gltype, raw->getData()); - - if(SNAPSHOT_TYPE_DEPTH == type) - { - LLViewerCamera* camerap = LLViewerCamera::getInstance(); - F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - - //calculate the depth - for (S32 y = 0 ; y < h ; y++) - { - for(S32 x = 0 ; x < w ; x++) - { - S32 i = (w * y + x) << 2 ; - - F32 depth_float_i = *(F32*)(raw->getData() + i); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar()); - *(raw->getData() + i + 0) = depth_byte; - *(raw->getData() + i + 1) = depth_byte; - *(raw->getData() + i + 2) = depth_byte; - *(raw->getData() + i + 3) = 255; - } - } - } - - LLFontGL::setFontDisplay(TRUE) ; - LLHUDText::setDisplayText(TRUE) ; - mDisplayScale.setVec(display_scale) ; - mWindowRect = window_rect; - setup3DRender(); - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - - // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } - - setCursor(UI_CURSOR_ARROW); - - if (do_rebuild) - { - // If we had to do a rebuild, that means that the lists of drawables to be rendered - // was empty before we started. - // Need to reset these, otherwise we call state sort on it again when render gets called the next time - // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of - // objects on them. - gPipeline.resetDrawOrders(); - } - - gSavedSettings.setS32("RenderName", render_name); - - return TRUE;*/ } // Saves the image from the screen to the specified filename and path. diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 583246c23e..ef3244b199 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -36,6 +36,8 @@ #include "llvovolume.h" +#include + #include "llviewercontrol.h" #include "lldir.h" #include "llflexibleobject.h" @@ -61,6 +63,7 @@ #include "llsky.h" #include "llviewercamera.h" #include "llviewertexturelist.h" +#include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewertextureanim.h" #include "llworld.h" @@ -90,6 +93,12 @@ LLPointer LLVOVolume::sObjectMediaNavigateClient = static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); +static LLFastTimer::DeclareTimer FTM_BUILD_MESH("Mesh"); +static LLFastTimer::DeclareTimer FTM_MESH_VFS("VFS"); +static LLFastTimer::DeclareTimer FTM_MESH_STREAM("Stream"); +static LLFastTimer::DeclareTimer FTM_MESH_FACES("Faces"); +static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); + LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLViewerObject(id, pcode, regionp), @@ -513,6 +522,7 @@ void LLVOVolume::updateTextures(LLAgent &agent) void LLVOVolume::updateTextures() { + LLFastTimer ftm(FTM_VOLUME_TEXTURES); // Update the pixel area of all faces if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) @@ -599,36 +609,60 @@ void LLVOVolume::updateTextures() if (isSculpted()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - if (mSculptTexture.notNull()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * MAX_SCULPT_REZ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size); - mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLViewerTexture::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - } - - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture - S32 current_discard = mSculptLevel; + LLUUID id = sculpt_params->getSculptTexture(); + U8 sculpt_type = sculpt_params->getSculptType(); - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; + if (mSculptLevel == -2) + { + // get the asset please + gPipeline.loadMesh(this, id); + /*gAssetStorage->getAssetData(id, LLAssetType::AT_MESH, (LLGetAssetCallback)NULL, NULL, TRUE); + + if (gAssetStorage->hasLocalAsset(id, LLAssetType::AT_MESH)) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + }*/ + } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + else + // mesh is a sculptie + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + + if (mSculptTexture.notNull()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * MAX_SCULPT_REZ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size); + mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), + (S32)LLViewerTexture::BOOST_SCULPTED)); + mSculptTexture->setForSculpt() ; + } + + S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture + S32 current_discard = mSculptLevel; + + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) { setDebugText(llformat("T%d C%d V%d\n%dx%d", texture_discard, current_discard, getVolume()->getSculptLevel(), mSculptTexture->getHeight(), mSculptTexture->getWidth())); } + } } if (getLightTextureID().notNull()) @@ -771,8 +805,10 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) } -BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) +BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool unique_volume) { + LLVolumeParams volume_params = params; + // Check if we need to change implementations bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); if (is_flexible) @@ -811,21 +847,39 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail if (isSculpted()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - if (mSculptTexture.notNull()) + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { - //ignore sculpt GL usage since bao fixed this in a separate branch - if (!gGLActive) + if (getVolume()->getNumVolumeFaces() == 0) { - gGLActive = TRUE; - sculpt(); - gGLActive = FALSE; + //mesh is not loaded, request pipeline load this mesh + LLUUID asset_id = volume_params.getSculptID(); + gPipeline.loadMesh(this, asset_id); } else { - sculpt(); + mSculptLevel = 1; + } + } + else // otherwise is sculptie + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + + if (mSculptTexture.notNull()) + { + //ignore sculpt GL usage since bao fixed this in a separate branch + if (!gGLActive) + { + gGLActive = TRUE; + sculpt(); + gGLActive = FALSE; + } + else + { + sculpt(); + } + mSculptLevel = getVolume()->getSculptLevel(); } - mSculptLevel = getVolume()->getSculptLevel(); } } else @@ -838,6 +892,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail return FALSE; } + + +void LLVOVolume::notifyMeshLoaded() +{ + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); +} + // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() { @@ -1039,6 +1101,11 @@ void LLVOVolume::updateFaceFlags() for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); + if (!face) + { + return; + } + BOOL fullbright = getTE(i)->getFullbright(); face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); @@ -1111,6 +1178,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); + if (!face) + { + continue; + } res &= face->genVolumeBBoxes(*getVolume(), i, mRelativeXform, mRelativeXformInvTrans, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); @@ -2218,6 +2289,23 @@ BOOL LLVOVolume::isSculpted() const return FALSE; } +BOOL LLVOVolume::isMesh() const +{ + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } + + return FALSE; +} + BOOL LLVOVolume::hasLightTexture() const { if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) @@ -2423,6 +2511,30 @@ F32 LLVOVolume::getBinRadius() { F32 radius; + F32 scale = 1.f; + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + LLVolume* volume = getVolume(); + U32 vert_count = 0; + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + vert_count += face.mVertices.size(); + } + + scale = 1.f/llmax(vert_count/1024.f, 1.f); + } + } + const LLVector3* ext = mDrawable->getSpatialExtents(); BOOL shrink_wrap = mDrawable->isAnimating(); @@ -2481,7 +2593,7 @@ F32 LLVOVolume::getBinRadius() radius = 8.f; } - return llclamp(radius, 0.5f, 256.f); + return llclamp(radius*scale, 0.5f, 256.f); } const LLVector3 LLVOVolume::getPivotPositionAgent() const @@ -3071,6 +3183,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) face->getGeometryVolume(*volume, face->getTEOffset(), vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); } + + if (!face) + { + llerrs << "WTF?" << llendl; + } } drawablep->clearState(LLDrawable::REBUILD_ALL); @@ -3354,7 +3471,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - if (LLPipeline::sRenderDeferred && te->getBumpmap()) + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) { registerFace(group, facep, LLRenderPass::PASS_BUMP); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 250c3ed917..6aaf5b2fdd 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -182,6 +182,11 @@ public: /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); void sculpt(); + static void rebuildMeshAssetCallback(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + void updateRelativeXform(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateFaceSize(S32 idx); @@ -227,6 +232,7 @@ public: U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; + virtual BOOL isMesh() const; virtual BOOL hasLightTexture() const; BOOL isVolumeGlobal() const; @@ -235,6 +241,7 @@ public: void updateObjectMediaData(const LLSD &media_data_duples); void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event); + // Sync the given media data with the impl and the given te void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent); @@ -247,6 +254,8 @@ public: bool hasMedia() const; + void notifyMeshLoaded(); + protected: S32 computeLODDetail(F32 distance, F32 radius); BOOL calcLOD(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b50e71bf48..7cf5cf75ad 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -342,6 +342,8 @@ LLPipeline::LLPipeline() : mGlowPool(NULL), mBumpPool(NULL), mWLSkyPool(NULL), + mMeshMutex(NULL), + mMeshThreadCount(0), mLightMask(0), mLightMovingMask(0), mLightingDetail(0) @@ -399,6 +401,7 @@ void LLPipeline::init() stop_glerror(); + mMeshMutex = new LLMutex(NULL); for (U32 i = 0; i < 2; ++i) { mSpotLightFade[i] = 1.f; @@ -473,6 +476,9 @@ void LLPipeline::cleanup() //delete mWLSkyPool; mWLSkyPool = NULL; + delete mMeshMutex; + mMeshMutex = NULL; + releaseGLBuffers(); mBloomImagep = NULL; @@ -1783,6 +1789,8 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); + notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1793,6 +1801,7 @@ void LLPipeline::rebuildPriorityGroups() } mGroupQ1.clear(); + } void LLPipeline::rebuildGroups() @@ -3419,27 +3428,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); - renderHighlights(); - mHighlightFaces.clear(); - - renderDebug(); - - LLVertexBuffer::unbind(); - - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - LLHUDObject::renderAll(); - gObjectList.resetObjectBeacons(); - } - if (occlude) { occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); doOcclusion(camera); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); } } @@ -5836,6 +5832,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } @@ -6912,6 +6914,24 @@ void LLPipeline::renderDeferredLighting() mRenderTypeMask = render_mask; } + { + //render highlights, etc. + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); + } + } + mScreen.flush(); } @@ -7241,18 +7261,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLDisable cull(GL_CULL_FACE); updateCull(camera, ref_result, 1); stateSort(camera, ref_result); - gGL.setColorMask(true, true); - mWaterRef.clear(); - gGL.setColorMask(true, false); - - } - else - { - gGL.setColorMask(true, true); - mWaterRef.clear(); - gGL.setColorMask(true, false); - } - + } + + gGL.setColorMask(true, true); + mWaterRef.clear(); + gGL.setColorMask(true, false); + ref_mask = mRenderTypeMask; mRenderTypeMask = mask; } @@ -7907,6 +7921,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) mHighlight.flush(); gGL.setColorMask(true, false); + gViewerWindow->setup3DViewport(); } } @@ -8886,3 +8901,175 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() } +void LLPipeline::loadMesh(LLVOVolume* volume, LLUUID mesh_id) +{ + + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); + if (iter != mLoadingMeshes.end()) + { //request pending for this mesh, append volume id to list + iter->second.insert(volume->getID()); + return; + } + + //first request for this mesh + mLoadingMeshes[mesh_id].insert(volume->getID()); + } + + if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) + { //already have asset, load desired LOD in background + mPendingMeshes.push_back(new LLMeshThread(mesh_id, volume->getVolume())); + } + else + { //fetch asset and load when done + gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, + getMeshAssetCallback, volume->getVolume(), TRUE); + } + +} + +//static +void LLPipeline::getMeshAssetCallback(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + gPipeline.mPendingMeshes.push_back(new LLMeshThread(asset_uuid, (LLVolume*) user_data)); +} + + +LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target) +: LLThread("mesh_loading_thread") +{ + mMeshID = mesh_id; + mVolume = NULL; + mDetail = target->getDetail(); + mTargetVolume = target; +} + +LLPipeline::LLMeshThread::~LLMeshThread() +{ + +} + +void LLPipeline::LLMeshThread::run() +{ + if (!gAssetStorage || LLApp::instance()->isQuitting()) + { + return; + } + + char* buffer = NULL; + S32 size = 0; + + LLVFS* vfs = gAssetStorage->mVFS; + + { + LLVFile file(vfs, mMeshID, LLAssetType::AT_MESH, LLVFile::READ); + file.waitForLock(VFSLOCK_READ); + size = file.getSize(); + + if (size == 0) + { + gPipeline.meshLoaded(this); + return; + } + + buffer = new char[size]; + file.read((U8*)&buffer[0], size); + } + + { + std::string buffer_string(buffer, size); + std::istringstream buffer_stream(buffer_string); + + { + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + mVolume = new LLVolume(volume_params, mDetail); + mVolume->createVolumeFacesFromStream(buffer_stream); + } + } + delete[] buffer; + + gPipeline.meshLoaded(this); +} + +void LLPipeline::meshLoaded(LLPipeline::LLMeshThread* mesh_thread) +{ + LLMutexLock lock(mMeshMutex); + mLoadedMeshes.push_back(mesh_thread); +} + +void LLPipeline::notifyLoadedMeshes() +{ //called from main thread + + U32 max_thread_count = llmax(gSavedSettings.getU32("MeshThreadCount"), (U32) 1); + while (mMeshThreadCount < max_thread_count && !mPendingMeshes.empty()) + { + LLMeshThread* mesh_thread = mPendingMeshes.front(); + mesh_thread->start(); + ++mMeshThreadCount; + mPendingMeshes.pop_front(); + } + + LLMutexLock lock(mMeshMutex); + std::list stopping_threads; + + for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) + { //for each mesh done loading + LLMeshThread* mesh = *iter; + + if (!mesh->isStopped()) + { //don't process a LLMeshThread until it's stopped + stopping_threads.push_back(mesh); + continue; + } + + //get list of objects waiting to be notified this mesh is loaded + mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID); + + if (mesh->mVolume && obj_iter != mLoadingMeshes.end()) + { + //make sure target volume is still valid + BOOL valid = FALSE; + + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + + if (vobj) + { + if (vobj->getVolume() == mesh->mTargetVolume) + { + valid = TRUE; + } + } + } + + + if (valid) + { + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + vobj->notifyMeshLoaded(); + } + } + } + + mLoadingMeshes.erase(mesh->mMeshID); + } + + delete mesh; + --mMeshThreadCount; + } + + mLoadedMeshes = stopping_threads; +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index ce50a37405..bf654f88b1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -278,6 +278,10 @@ public: LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); + + //mesh management functions + void loadMesh(LLVOVolume* volume, LLUUID mesh_id); + void addTrianglesDrawn(S32 count); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< mSelectedFaces; + typedef std::map > mesh_load_map; + mesh_load_map mLoadingMeshes; + + LLMutex* mMeshMutex; + + class LLMeshThread : public LLThread + { + public: + LLPointer mVolume; + LLVolume* mTargetVolume; + LLUUID mMeshID; + F32 mDetail; + LLMeshThread(LLUUID mesh_id, LLVolume* target); + ~LLMeshThread(); + void run(); + }; + + static void getMeshAssetCallback(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + + std::list mLoadedMeshes; + std::list mPendingMeshes; + U32 mMeshThreadCount; + + void meshLoaded(LLMeshThread* mesh_thread); + void notifyLoadedMeshes(); + LLPointer mFaceSelectImagep; LLPointer mBloomImagep; LLPointer mBloomImage2p; diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 01976c9a5c..26b0b39a68 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -568,6 +568,7 @@ + @@ -591,6 +592,7 @@ + diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 4d7433233a..09240a3e27 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -152,16 +152,19 @@ It is a rare mind indeed that can render the hitherto non-existent blindingly ob word_wrap="true"> 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation + Collada DOM Copyright 2005 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). GL Copyright (C) 1999-2004 Brian Paul. + GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. ogg/vorbis Copyright (C) 2001, Xiphophorus OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. + PCRE Copyright (c) 1997-2008 University of Cambridge SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index 0f06558dd1..6afeb4e82d 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -123,6 +123,16 @@ + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 284594426c..d90d1f0635 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2210,10 +2210,10 @@ name="Fast Alpha"> + parameter="RenderFastAlpha" /> + parameter="RenderFastAlpha" /> - @@ -6551,6 +6551,29 @@ Server Error: Media update or get failed. yestext="OK"/> + + +Are you sure you want to delete your teleport history? + + + + +This upload will cost L$[PRICE], do you wish to continue with the upload? + + + Favorites Current Outfit My Outfits + Meshes Friends diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 045990811b..db4b68e9d6 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -194,6 +194,12 @@ class WindowsManifest(ViewerManifest): # For using FMOD for sound... DJS self.path("fmod.dll") + # For automatic level of detail generation in mesh importer + self.path("glod.dll") + + # For reading collada files + self.path("libcollada14dom21.dll") + # For textures if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): self.path("openjpeg.dll") -- cgit v1.2.3 From 63b9bd43ff41da01d549f630bd838caff0dffd97 Mon Sep 17 00:00:00 2001 From: Palmer Date: Mon, 2 Nov 2009 14:56:46 -0800 Subject: Repairing things that didn't quite merge properly. --- indra/llprimitive/llprimitive.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index c30ef0350f..da1cfc2074 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -743,6 +743,8 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai setNumTEs(mVolumep->getNumFaces()); return TRUE; } + + U32 old_face_mask = mVolumep->mFaceMask; S32 face_bit = 0; S32 cur_mask = 0; -- cgit v1.2.3 From 9c3595465972ba4be916e871f6b0a62cc0c13d4a Mon Sep 17 00:00:00 2001 From: Jon Wolk Date: Tue, 3 Nov 2009 19:36:39 +0000 Subject: Changed variable price upload responders to reflect server changes. I hope this gets pulled into the hg repository --- indra/newview/llassetuploadresponders.cpp | 176 ++++++++++++++++++++---------- indra/newview/llassetuploadresponders.h | 3 +- indra/newview/llviewermenufile.cpp | 138 ++++++++++++++--------- indra/newview/llviewermenufile.h | 16 ++- 4 files changed, 212 insertions(+), 121 deletions(-) (limited to 'indra') diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index cb03379b23..680d1acd81 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -72,7 +72,7 @@ static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5; void dialog_refresh_all(); -void on_new_single_inventory_upload_complete( +static void on_new_single_inventory_upload_complete( LLAssetType::EType asset_type, LLInventoryType::EType inventory_type, const std::string inventory_type_string, @@ -736,22 +736,103 @@ public: LLUploadDialog::modalUploadFinished(); } - void onApplicationLevelError(const std::string& error_identifier) + void onApplicationLevelError(const LLSD& error) { - // TODO*: Pull these user visible strings from an xml file - // to be localized + static const std::string _IDENTIFIER = "identifier"; + static const std::string _INSUFFICIENT_FUNDS = "NewAgentInventory_InsufficientLindenDollarBalance"; + static const std::string _MISSING_REQUIRED_PARAMETER = + "NewAgentInventory_MissingRequiredParamater"; + static const std::string _INVALID_REQUEST_BODY = + "NewAgentInventory_InvalidRequestBody"; + static const std::string _RESOURCE_COST_DIFFERS = + "NewAgentInventory_ResourceCostDiffers"; + + static const std::string _MISSING_PARAMETER = "missing_parameter"; + static const std::string _INVALID_PARAMETER = "invalid_parameter"; + static const std::string _MISSING_RESOURCE = "missing_resource"; + static const std::string _INVALID_RESOURCE = "invalid_resource"; + + // TODO* Add the other error_identifiers + std::string error_identifier = error[_IDENTIFIER].asString(); + // TODO*: Pull these user visible strings from an xml file + // to be localized if ( _INSUFFICIENT_FUNDS == error_identifier ) { displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload."); } + else if ( _MISSING_REQUIRED_PARAMETER == error_identifier ) + { + // Missing parameters + if (error.has(_MISSING_PARAMETER) ) + { + std::string message = + "Upload request was missing required parameter '[P]'"; + LLStringUtil::replaceString( + message, + "[P]", + error[_MISSING_PARAMETER].asString()); + + displayCannotUploadReason(message); + } + else + { + std::string message = + "Upload request was missing a required parameter"; + displayCannotUploadReason(message); + } + } + else if ( _INVALID_REQUEST_BODY == error_identifier ) + { + // Invalid request body, check to see if + // a particular parameter was invalid + if ( error.has(_INVALID_PARAMETER) ) + { + std::string message = "Upload parameter '[P]' is invalid."; + LLStringUtil::replaceString( + message, + "[P]", + error[_INVALID_PARAMETER].asString()); + + // See if the server also responds with what resource + // is missing. + if ( error.has(_MISSING_RESOURCE) ) + { + message += "\nMissing resource '[R]'."; + + LLStringUtil::replaceString( + message, + "[R]", + error[_MISSING_RESOURCE].asString()); + } + else if ( error.has(_INVALID_RESOURCE) ) + { + message += "\nInvalid resource '[R]'."; + + LLStringUtil::replaceString( + message, + "[R]", + error[_INVALID_RESOURCE].asString()); + } + + displayCannotUploadReason(message); + } + else + { + std::string message = "Upload request was malformed"; + displayCannotUploadReason(message); + } + } + else if ( _RESOURCE_COST_DIFFERS == error_identifier ) + { + displayCannotUploadReason("The resource cost associated with this upload is not consistent with the server."); + } else { displayCannotUploadReason("Unknown Error"); - } } @@ -761,14 +842,18 @@ public: "The server is experiencing unexpected difficulties."); } - void onTransportError(const std::string& error_identifier) + void onTransportError(const LLSD& error) { - // TODO*: Pull these user visible strings from an xml file - // to be localized + static const std::string _IDENTIFIER = "identifier"; static const std::string _SERVER_ERROR_AFTER_CHARGE = "NewAgentInventory_ServerErrorAfterCharge"; + std::string error_identifier = error[_IDENTIFIER].asString(); + + // TODO*: Pull the user visible strings from an xml file + // to be localized + if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier ) { displayCannotUploadReason( @@ -779,7 +864,6 @@ public: displayCannotUploadReason( "The server is experiencing unexpected difficulties."); } - } bool uploadConfirmationCallback( @@ -798,17 +882,26 @@ public: notification["payload"]["confirmation_url"].asString(); // Yay! We are confirming or cancelling our upload - LLSD body; - - body["confirm_upload"] = false; - switch(option) { case 0: { - body["confirm_upload"] = true; - body["expected_upload_price"] = - notification["payload"]["expected_upload_price"]; + if ( getFilename().empty() ) + { + // we have no filename, use virtual file ID instead + LLHTTPClient::postFile( + confirmation_url, + getVFileID(), + getAssetType(), + responder); + } + else + { + LLHTTPClient::postFile( + confirmation_url, + getFilename(), + responder); + } } break; case 1: @@ -816,8 +909,6 @@ public: break; } - LLHTTPClient::post(confirmation_url, body, responder); - return false; } @@ -865,9 +956,8 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent( if ( content.has("error") ) { static const std::string _ERROR = "error"; - static const std::string _IDENTIFIER = "identifier"; - mImpl->onTransportError(content[_ERROR][_IDENTIFIER].asString()); + mImpl->onTransportError(content[_ERROR]); } else { @@ -880,52 +970,25 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) // Parse out application level errors and the appropriate // responses for them static const std::string _ERROR = "error"; - static const std::string _IDENTIFIER = "identifier"; static const std::string _STATE = "state"; static const std::string _COMPLETE = "complete"; - static const std::string _COST_ANALYSIS = "cost_analysis"; - static const std::string _NEEDS_CONFIRMATION = "needs_confirmation"; - static const std::string _CANCEL = "cancel"; + static const std::string _CONFIRM_UPLOAD = "confirm_upload"; - static const std::string _RESOURCE_COST = "resource_cost"; static const std::string _UPLOAD_PRICE = "upload_price"; - - static const std::string _ANALYZER = "analyzer"; static const std::string _RSVP = "rsvp"; // Check for application level errors if ( content.has(_ERROR) ) { - onApplicationLevelError(content[_ERROR][_IDENTIFIER].asString()); + onApplicationLevelError(content[_ERROR]); return; } std::string state = content[_STATE]; LLAssetType::EType asset_type = mImpl->getAssetType(); - if ( _COST_ANALYSIS == state ) - { - std::string analyzer_url = content[_ANALYZER]; - - if ( mImpl->getFilename().empty() ) - { - // we have no filename, use virtual file ID instead - LLHTTPClient::postFile( - analyzer_url, - mImpl->getVFileID(), - asset_type, - this); - } - else - { - LLHTTPClient::postFile( - analyzer_url, - mImpl->getFilename(), - this); - } - } - else if ( _COMPLETE == state ) + if ( _COMPLETE == state ) { // rename file in VFS with new asset id if (mImpl->getFilename().empty()) @@ -952,17 +1015,12 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) // TODO* Add bulk (serial) uploading or add // a super class of this that does so } - else if ( _NEEDS_CONFIRMATION == state ) + else if ( _CONFIRM_UPLOAD == state ) { showConfirmationDialog( content[_UPLOAD_PRICE].asInteger(), - content[_RESOURCE_COST].asInteger(), content[_RSVP].asString()); } - else if ( _CANCEL == state ) - { - // cancelled, do nothing - } else { onApplicationLevelError(""); @@ -970,14 +1028,13 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) } void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError( - const std::string& error_identifier) + const LLSD& error) { - mImpl->onApplicationLevelError(error_identifier); + mImpl->onApplicationLevelError(error); } void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( S32 upload_price, - S32 resource_cost, const std::string& confirmation_url) { if ( 0 == upload_price ) @@ -998,7 +1055,6 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( substitutions["PRICE"] = upload_price; payload["confirmation_url"] = confirmation_url; - payload["expected_upload_price"] = upload_price; // The creating of a new instrusive_ptr(this) // creates a new boost::intrusive_ptr diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index adbf13519b..04636d4977 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -102,10 +102,9 @@ public: void result(const LLSD& content); virtual void onApplicationLevelError( - const std::string& error_identifier); + const LLSD& error); virtual void showConfirmationDialog( S32 upload_price, - S32 resource_cost, const std::string& confirmation_url); private: diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 836ac79a87..7b9494c02a 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -964,60 +964,24 @@ void upload_done_callback( } } -LLAssetID upload_new_resource_prep( - const LLTransactionID &tid, +static LLAssetID upload_new_resource_prep( + const LLTransactionID& tid, LLAssetType::EType asset_type, LLInventoryType::EType& inventory_type, std::string& name, const std::string& display_name, std::string& description) { - if ( gDisconnected ) - { - LLAssetID rv; + LLAssetID uuid = generate_asset_id_for_new_upload(tid); - rv.setNull(); - return rv; - } + increase_new_upload_stats(asset_type); - LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - - if ( LLAssetType::AT_SOUND == asset_type ) - { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_SOUND_COUNT ); - } - else if ( LLAssetType::AT_TEXTURE == asset_type ) - { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); - } - else if ( LLAssetType::AT_ANIMATION == asset_type ) - { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_ANIM_COUNT ); - } - - if ( LLInventoryType::IT_NONE == inventory_type ) - { - inventory_type = LLInventoryType::defaultForAssetType(asset_type); - } - LLStringUtil::stripNonprintable(name); - LLStringUtil::stripNonprintable(description); - - if ( name.empty() ) - { - name = "(No Name)"; - } - if ( description.empty() ) - { - description = "(No Description)"; - } - - // At this point, we're ready for the upload. - std::string upload_message = "Uploading...\n\n"; - upload_message.append(display_name); - LLUploadDialog::modalUploadDialog(upload_message); + assign_defaults_and_show_upload_message( + asset_type, + inventory_type, + name, + display_name, + description); return uuid; } @@ -1146,27 +1110,27 @@ void upload_new_resource( { asset_callback = callback; } - gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, - asset_callback, - (void*)data, - FALSE); + gAssetStorage->storeAssetData( + data->mAssetInfo.mTransactionID, + data->mAssetInfo.mType, + asset_callback, + (void*)data, + FALSE); } } -BOOL upload_new_variable_cost_resource( +BOOL upload_new_variable_price_resource( const LLTransactionID &tid, LLAssetType::EType asset_type, std::string name, std::string desc, - S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata) + const LLSD& asset_resources) { LLAssetID uuid = upload_new_resource_prep( @@ -1209,6 +1173,8 @@ BOOL upload_new_variable_cost_resource( group_perms, everyone_perms); + body["asset_resources"] = asset_resources; + LLHTTPClient::post( url, body, @@ -1224,6 +1190,70 @@ BOOL upload_new_variable_cost_resource( } } +LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid) +{ + if ( gDisconnected ) + { + LLAssetID rv; + + rv.setNull(); + return rv; + } + + LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); + + return uuid; +} + +void increase_new_upload_stats(LLAssetType::EType asset_type) +{ + if ( LLAssetType::AT_SOUND == asset_type ) + { + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + } + else if ( LLAssetType::AT_TEXTURE == asset_type ) + { + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + } + else if ( LLAssetType::AT_ANIMATION == asset_type ) + { + LLViewerStats::getInstance()->incStat( + LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + } +} + +void assign_defaults_and_show_upload_message( + LLAssetType::EType asset_type, + LLInventoryType::EType& inventory_type, + std::string& name, + const std::string& display_name, + std::string& description) +{ + if ( LLInventoryType::IT_NONE == inventory_type ) + { + inventory_type = LLInventoryType::defaultForAssetType(asset_type); + } + LLStringUtil::stripNonprintable(name); + LLStringUtil::stripNonprintable(description); + + if ( name.empty() ) + { + name = "(No Name)"; + } + if ( description.empty() ) + { + description = "(No Description)"; + } + + // At this point, we're ready for the upload. + std::string upload_message = "Uploading...\n\n"; + upload_message.append(display_name); + LLUploadDialog::modalUploadDialog(upload_message); +} + + void init_menu_file() { view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index b51192b499..858fcd51de 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -77,20 +77,26 @@ void upload_new_resource( // used // We make a new function here to ensure that previous code is not broken -BOOL upload_new_variable_cost_resource( - const LLTransactionID &tid, +BOOL upload_new_variable_price_resource( + const LLTransactionID& tid, LLAssetType::EType type, std::string name, std::string desc, - S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata); + const LLSD& asset_resources); +LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid); +void increase_new_upload_stats(LLAssetType::EType asset_type); +void assign_defaults_and_show_upload_message( + LLAssetType::EType asset_type, + LLInventoryType::EType& inventory_type, + std::string& name, + const std::string& display_name, + std::string& description); #endif -- cgit v1.2.3 From c3bb2669ce30681449f7fe68f0822878565c273f Mon Sep 17 00:00:00 2001 From: "palmer@sansome-guest-196.lindenlab.com" Date: Tue, 3 Nov 2009 17:43:47 -0800 Subject: fix to make build run on mac --- indra/cmake/00-Common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index e7afe0ecba..5c0e639947 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -208,7 +208,7 @@ if (LINUX OR DARWIN) set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") endif (NOT GCC_DISABLE_FATAL_WARNINGS) - set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual") + set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor") set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}") -- cgit v1.2.3 From 88292104d9a2332e6169f2add8f0b590bb22dbff Mon Sep 17 00:00:00 2001 From: David Parks Date: Wed, 4 Nov 2009 14:19:05 +0000 Subject: Fix for crash when loading some meshes. Added button to auto-fill LODs. --- indra/llmath/llvolume.cpp | 4 +++- indra/newview/pipeline.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index afa82ed399..ddd1b4b3db 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1690,9 +1690,11 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - generate(); + mLODScaleBias.setVec(1,1,1); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { + generate(); createVolumeFaces(); } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7cf5cf75ad..4fc94c08bc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8988,6 +8988,7 @@ void LLPipeline::LLMeshThread::run() { LLVolumeParams volume_params; volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH); mVolume = new LLVolume(volume_params, mDetail); mVolume->createVolumeFacesFromStream(buffer_stream); } -- cgit v1.2.3 From 1c495c56c1011f4514d96b75cbcfb5a8256de78f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 5 Nov 2009 17:12:18 -0600 Subject: Fix for crash on teleport to mesh enabled region. Fix for flashing meshes on LOD switch. --- indra/llprimitive/llprimitive.cpp | 4 ++++ indra/newview/pipeline.cpp | 47 ++++++++++++++++++++++++++++++++++----- indra/newview/pipeline.h | 2 +- 3 files changed, 46 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index da1cfc2074..52265e7ad5 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -744,6 +744,7 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai return TRUE; } +#if 0 U32 old_face_mask = mVolumep->mFaceMask; S32 face_bit = 0; @@ -941,6 +942,9 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); } } +#else + setNumTEs(mVolumep->getNumFaces()); +#endif return TRUE; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1a1d29ac32..4ac95fa939 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8902,33 +8902,68 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() } -void LLPipeline::loadMesh(LLVOVolume* volume, LLUUID mesh_id) +void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { - { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); if (iter != mLoadingMeshes.end()) { //request pending for this mesh, append volume id to list - iter->second.insert(volume->getID()); + iter->second.insert(vobj->getID()); return; } //first request for this mesh - mLoadingMeshes[mesh_id].insert(volume->getID()); + mLoadingMeshes[mesh_id].insert(vobj->getID()); } if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, volume->getVolume())); + mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume())); } else { //fetch asset and load when done gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, - getMeshAssetCallback, volume->getVolume(), TRUE); + getMeshAssetCallback, vobj->getVolume(), TRUE); } + //do a quick search to see if we can't display something while we wait for this mesh to load + LLVolume* volume = vobj->getVolume(); + + if (volume) + { + LLVolumeParams params = volume->getParams(); + + LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); + + if (group) + { + //first see what the next lowest LOD available might be + for (S32 i = detail-1; i >= 0; --i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->getNumVolumeFaces() > 0) + { + volume->copyVolumeFaces(lod); + group->derefLOD(lod); + return; + } + } + + //no lower LOD is a available, is a higher lod available? + for (S32 i = detail+1; i < 4; ++i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->getNumVolumeFaces() > 0) + { + volume->copyVolumeFaces(lod); + group->derefLOD(lod); + return; + } + } + } + } } //static diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bf654f88b1..3300f866e3 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -280,7 +280,7 @@ public: //mesh management functions - void loadMesh(LLVOVolume* volume, LLUUID mesh_id); + void loadMesh(LLVOVolume* volume, LLUUID mesh_id, S32 detail = 0); void addTrianglesDrawn(S32 count); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< Date: Thu, 5 Nov 2009 19:58:10 -0600 Subject: Fix for prims all being 0 lod. Fix for dangling prim references. --- indra/llmath/llvolume.cpp | 3 ++- indra/llprimitive/llprimitive.cpp | 8 +++++++- indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 2 ++ 4 files changed, 12 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ddd1b4b3db..33a8d33ce1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,9 +1692,10 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mLODScaleBias.setVec(1,1,1); + generate(); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { - generate(); createVolumeFaces(); } } diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 52265e7ad5..340f60ed1a 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -744,7 +744,10 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai return TRUE; } -#if 0 +#if 0 + // #if 0'd out by davep + // this is a lot of cruft to set texture entry values that just stay the same for LOD switch + // or immediately get overridden by an object update message, also crashes occasionally U32 old_face_mask = mVolumep->mFaceMask; S32 face_bit = 0; @@ -943,6 +946,9 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai } } #else + // build the new object + sVolumeManager->unrefVolume(mVolumep); + mVolumep = volumep; setNumTEs(mVolumep->getNumFaces()); #endif return TRUE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 78fd371087..7666009a62 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -919,7 +919,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { //mesh is not loaded, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gPipeline.loadMesh(this, asset_id); + gPipeline.loadMesh(this, asset_id, detail); } else { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4ac95fa939..3554ceb7f0 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } //no lower LOD is a available, is a higher lod available? @@ -8961,6 +8962,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } } -- cgit v1.2.3 From 4e420a36c67e611cd7d85652b43d9cd65315e563 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 7 Nov 2009 08:22:39 -0600 Subject: Fix for missing LOD spam. --- indra/llmath/llvolume.cpp | 21 +++++++++++++++------ indra/llprimitive/llprimitive.cpp | 3 ++- indra/newview/pipeline.cpp | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 33a8d33ce1..c8ef911cc1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1676,7 +1676,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; - + mLODScaleBias.setVec(1,1,1); + // set defaults if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) { @@ -1690,8 +1691,6 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - mLODScaleBias.setVec(1,1,1); - generate(); if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) @@ -1899,7 +1898,7 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) { - llwarns << "not a valid mesh asset!" << llendl; + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; return FALSE; } } @@ -1921,8 +1920,18 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) if (lod >= 4) { - llwarns << "Couldn't load model for given lod" << llendl; - return FALSE; + lod = llclamp((S32) mDetail, 0, 3); + + while (lod >= 0 && header[nm[lod]]["offset"].asInteger() == -1) + { + --lod; + } + + if (lod < 0) + { + llwarns << "Mesh header missing LOD offsets. Not a valid mesh asset!" << llendl; + return FALSE; + } } is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 340f60ed1a..4c6d244f3c 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -948,7 +948,8 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai #else // build the new object sVolumeManager->unrefVolume(mVolumep); - mVolumep = volumep; + mVolumep = volumep; + setNumTEs(mVolumep->getNumFaces()); #endif return TRUE; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3554ceb7f0..f13bb73acf 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } @@ -8962,6 +8963,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } -- cgit v1.2.3 From 7fa698252060a72be6b5ebc52f0ff01bcea6134c Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Mon, 9 Nov 2009 17:57:21 -0600 Subject: super importer stuff (gui, texture upload, etc.) --- indra/newview/llassetuploadresponders.cpp | 3 ++ indra/newview/llfilepicker.cpp | 23 ++++++++++++ indra/newview/llfilepicker.h | 1 + indra/newview/llviewerfloaterreg.cpp | 2 ++ indra/newview/llviewermenufile.cpp | 41 +++++++++++++++------- indra/newview/llviewermenufile.h | 2 +- .../skins/default/xui/en/floater_inventory.xml | 10 ++++++ 7 files changed, 69 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 680d1acd81..2da40ba4b5 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -42,6 +42,7 @@ #include "llnotify.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" +#include "llfloaterimportcollada.h" #include "llpermissionsflags.h" #include "llpreviewnotecard.h" #include "llpreviewscript.h" @@ -414,6 +415,8 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), userdata); } + + LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE); } LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index e12db901bd..8dfb333530 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -55,6 +55,7 @@ LLFilePicker LLFilePicker::sInstance; #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0" #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0" +#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" #ifdef _CORY_TESTING #define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" #endif @@ -176,6 +177,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = ANIM_FILTER \ L"\0"; break; + case FFLOAD_COLLADA: + mOFN.lpstrFilter = COLLADA_FILTER \ + L"\0"; + break; #ifdef _CORY_TESTING case FFLOAD_GEOMETRY: mOFN.lpstrFilter = GEOMETRY_FILTER \ @@ -547,6 +552,15 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB result = false; } } + else if (filter == FFLOAD_COLLADA) + { + if (fileInfo.filetype != 'DAE ' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + ) + { + result = false; + } + } #ifdef _CORY_TESTING else if (filter == FFLOAD_GEOMETRY) { @@ -1093,6 +1107,12 @@ static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker) LLTrans::getString("animation_files") + " (*.bvh)"); } +static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae", + LLTrans::getString("scene_files") + " (*.dae)"); +} + static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) { GtkFileFilter *gfilter = gtk_file_filter_new(); @@ -1217,6 +1237,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) case FFLOAD_ANIM: filtername = add_bvh_filter_to_gtkchooser(picker); break; + case FFLOAD_COLLADA: + filtername = add_collada_filter_to_gtkchooser(picker); + break; case FFLOAD_IMAGE: filtername = add_imageload_filter_to_gtkchooser(picker); break; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 7600922e9c..10736c7dd0 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -94,6 +94,7 @@ public: FFLOAD_SLOBJECT = 7, FFLOAD_RAW = 8, FFLOAD_MODEL = 9, + FFLOAD_COLLADA = 10, }; enum ESaveFilter diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4ff1e6c703..f3bf6b70a3 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -73,6 +73,7 @@ #include "llimpanel.h" #include "llfloaterinspect.h" #include "llfloaterinventory.h" +#include "llfloaterimportcollada.h" #include "llfloaterjoystick.h" #include "llfloaterlagmeter.h" #include "llfloaterland.h" @@ -172,6 +173,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("import_collada", "floater_import_collada.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLInspectAvatarUtil::registerFloater(); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 7b9494c02a..53067c5c93 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -39,6 +39,7 @@ #include "llfilepicker.h" #include "llfloaterreg.h" #include "llfloaterbuycurrency.h" +#include "llfloaterimportcollada.h" #include "llfloatermodelpreview.h" #include "llfloatersnapshot.h" #include "llinventorymodel.h" // gInventory @@ -56,7 +57,7 @@ #include "llappviewer.h" #include "lluploaddialog.h" #include "lltrans.h" - +#include "llfloaterimportcollada.h" // linden libraries #include "llassetuploadresponders.h" @@ -263,6 +264,19 @@ class LLFileUploadImage : public view_listener_t } }; +class LLFileUploadScene : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string filename = upload_pick((void *)LLFilePicker::FFLOAD_COLLADA); + if (!filename.empty()) + { + LLImportCollada::getInstance()->importFile(filename); + } + return TRUE; + } +}; + class LLFileUploadModel : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -517,7 +531,7 @@ void handle_compress_image(void*) } } -void upload_new_resource( +LLUUID upload_new_resource( const std::string& src_filename, std::string name, std::string desc, @@ -555,7 +569,7 @@ void upload_new_resource( short_name.c_str()); args["FILE"] = short_name; upload_error(error_message, "NofileExtension", filename, args); - return; + return LLUUID(); } else if( exten == "bmp") { @@ -569,7 +583,7 @@ void upload_new_resource( args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); - return; + return LLUUID(); } } else if( exten == "tga") @@ -584,7 +598,7 @@ void upload_new_resource( args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); - return; + return LLUUID(); } } else if( exten == "jpg" || exten == "jpeg") @@ -599,7 +613,7 @@ void upload_new_resource( args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); - return; + return LLUUID(); } } else if( exten == "png") @@ -614,7 +628,7 @@ void upload_new_resource( args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); - return; + return LLUUID(); } } else if(exten == "wav") @@ -642,7 +656,7 @@ void upload_new_resource( upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); break; } - return; + return LLUUID(); } } else if(exten == "tmp") @@ -682,7 +696,7 @@ void upload_new_resource( error_message = llformat("corrupt resource file: %s", src_filename.c_str()); args["FILE"] = src_filename; upload_error(error_message, "CorruptResourceFile", filename, args); - return; + return LLUUID(); } if (2 == tokens_read) @@ -710,7 +724,7 @@ void upload_new_resource( error_message = llformat("unknown linden resource file version in file: %s", src_filename.c_str()); args["FILE"] = src_filename; upload_error(error_message, "UnknownResourceFileVersion", filename, args); - return; + return LLUUID(); } } else @@ -752,7 +766,7 @@ void upload_new_resource( error_message = llformat( "Unable to create output file: %s", filename.c_str()); args["FILE"] = filename; upload_error(error_message, "UnableToCreateOutputFile", filename, args); - return; + return LLUUID(); } fclose(in); @@ -766,7 +780,7 @@ void upload_new_resource( { error_message = llformat("We do not currently support bulk upload of animation files\n"); upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); - return; + return LLUUID(); } else { @@ -840,6 +854,8 @@ void upload_new_resource( } LLFilePicker::instance().reset(); } + + return uuid; } void upload_done_callback( @@ -1260,6 +1276,7 @@ void init_menu_file() view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); + view_listener_t::addCommit(new LLFileUploadScene(), "File.UploadScene"); view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 858fcd51de..25469e0168 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -41,7 +41,7 @@ class LLTransactionID; void init_menu_file(); -void upload_new_resource( +LLUUID upload_new_resource( const std::string& src_filename, std::string name, std::string desc, diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index c7fcacab8b..5e324f1c6e 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -135,6 +135,16 @@ parameter="" /> + + + + Date: Thu, 12 Nov 2009 15:02:08 +0000 Subject: newlineorama. --- indra/llui/lluictrlfactory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 8ab015f2bb..0d1c486a4b 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -454,4 +454,5 @@ const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_ty void LLUICtrlFactory::connect(LLView* parent, LLView* child) { parent->addChild(child); -} \ No newline at end of file +} + -- cgit v1.2.3 From 596d3cfb6018789e3ffca5bf3ae9fa4e1e8a707a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 12 Nov 2009 13:23:48 -0600 Subject: CTS-15 Force loading of high LOD when opening model import floater. CTS-9 Auto-fill description field with --- indra/newview/llviewermenufile.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 505d2afb69..2ce37612b2 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -281,7 +281,11 @@ class LLFileUploadModel : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLFloaterReg::showInstance("upload_model"); + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::showInstance("upload_model"); + if (fmp) + { + fmp->loadModel(3); + } return TRUE; } -- cgit v1.2.3 From bb72788392ea6d25adb045abd555419cd60c4888 Mon Sep 17 00:00:00 2001 From: Palmer Date: Thu, 12 Nov 2009 14:05:01 -0800 Subject: Fixes for mesh inventory type correctness. --- indra/llinventory/llinventorytype.cpp | 28 +++++++++++++++++++++++++++- indra/newview/llinventoryfunctions.cpp | 3 +++ 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 2460a2777a..caf8e11929 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -125,7 +125,33 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_LINK LLInventoryType::IT_NONE, // AT_LINK_FOLDER - LLInventoryType::IT_MESH, // AT_MESH + + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + LLInventoryType::IT_NONE, // AT_NONE + + LLInventoryType::IT_MESH // AT_MESH }; // static diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 75218e98e0..01c7f0974d 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -323,6 +323,9 @@ const std::string& get_item_icon_name(LLAssetType::EType asset_type, case LLAssetType::AT_LINK_FOLDER: idx = LINKFOLDER_ICON_NAME; break; + case LLAssetType::AT_MESH: + idx = MESH_ICON_NAME; + break; default: break; } -- cgit v1.2.3 From 0c50236a944898502405a31aa1f0b6ae61ae38ae Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 13 Nov 2009 08:59:12 -0600 Subject: CTS-26 Fix for LOD generation always using first file specified. --- indra/llrender/llvertexbuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index db4189dfea..6e77bb2aab 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -566,7 +566,7 @@ void LLVertexBuffer::destroyGLBuffer() } mGLBuffer = 0; - unbind(); + //unbind(); } void LLVertexBuffer::destroyGLIndices() @@ -593,7 +593,7 @@ void LLVertexBuffer::destroyGLIndices() } mGLIndices = 0; - unbind(); + //unbind(); } void LLVertexBuffer::updateNumVerts(S32 nverts) -- cgit v1.2.3 From c02702f3871979cb7745b49aa502ac3c71f77681 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 13 Nov 2009 17:01:56 -0600 Subject: CTS-7 Add hard edge threshold capability to normal generation. --- indra/llmath/llvolume.cpp | 12 ++++++++++++ indra/llmath/llvolume.h | 1 + 2 files changed, 13 insertions(+) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 6286d1bcea..f252b2a232 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1876,6 +1876,18 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co return true; } +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +{ + bool retval = false; + if (rhs.mPosition == mPosition && rhs.mTexCoord == mTexCoord) + { + F32 cur_angle = rhs.mNormal*mNormal; + + retval = cur_angle > angle_cutoff; + } + + return retval; +} BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 9f595ccbc4..d2727d8f21 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -814,6 +814,7 @@ public: bool operator<(const VertexData& rhs) const; bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; }; enum -- cgit v1.2.3 From a056423e62ad8525919526abb95e8b23f0681064 Mon Sep 17 00:00:00 2001 From: Palmer Date: Tue, 17 Nov 2009 13:42:19 -0800 Subject: Merge of latest viewer 2 changes --- indra/newview/llviewerwindow.cpp | 134 --------------------------------------- 1 file changed, 134 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 7b35125b5b..a1539e24a4 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3704,140 +3704,6 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); - - // *TODO below code was broken in deferred pipeline - /* - if ((!raw) || preview_width < 10 || preview_height < 10) - { - return FALSE; - } - - if(gResizeScreenTexture) //the window is resizing - { - return FALSE ; - } - - setCursor(UI_CURSOR_WAIT); - - // Hide all the UI widgets first and draw a frame - BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - - if ( prev_draw_ui != show_ui) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } - - S32 render_name = gSavedSettings.getS32("RenderName"); - gSavedSettings.setS32("RenderName", 0); - LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame - - S32 w = preview_width ; - S32 h = preview_height ; - LLVector2 display_scale = mDisplayScale ; - mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ; - LLRect window_rect = mWindowRectRaw; - mWindowRectRaw.set(0, h, w, 0); - - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - setup3DRender(); - - LLFontGL::setFontDisplay(FALSE) ; - LLHUDText::setDisplayText(FALSE) ; - if (type == SNAPSHOT_TYPE_OBJECT_ID) - { - gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE); - } - else - { - display(do_rebuild, 1.0f, 0, TRUE); - render_ui(); - } - - S32 glformat, gltype, glpixel_length ; - if(SNAPSHOT_TYPE_DEPTH == type) - { - glpixel_length = 4 ; - glformat = GL_DEPTH_COMPONENT ; - gltype = GL_FLOAT ; - } - else - { - glpixel_length = 3 ; - glformat = GL_RGB ; - gltype = GL_UNSIGNED_BYTE ; - } - - raw->resize(w, h, glpixel_length); - glReadPixels(0, 0, w, h, glformat, gltype, raw->getData()); - - if(SNAPSHOT_TYPE_DEPTH == type) - { - LLViewerCamera* camerap = LLViewerCamera::getInstance(); - F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear()); - - //calculate the depth - for (S32 y = 0 ; y < h ; y++) - { - for(S32 x = 0 ; x < w ; x++) - { - S32 i = (w * y + x) << 2 ; - - F32 depth_float_i = *(F32*)(raw->getData() + i); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar()); - *(raw->getData() + i + 0) = depth_byte; - *(raw->getData() + i + 1) = depth_byte; - *(raw->getData() + i + 2) = depth_byte; - *(raw->getData() + i + 3) = 255; - } - } - } - - LLFontGL::setFontDisplay(TRUE) ; - LLHUDText::setDisplayText(TRUE) ; - mDisplayScale.setVec(display_scale) ; - mWindowRectRaw = window_rect; - setup3DRender(); - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - - // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } - - setCursor(UI_CURSOR_ARROW); - - if (do_rebuild) - { - // If we had to do a rebuild, that means that the lists of drawables to be rendered - // was empty before we started. - // Need to reset these, otherwise we call state sort on it again when render gets called the next time - // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of - // objects on them. - gPipeline.resetDrawOrders(); - } - - gSavedSettings.setS32("RenderName", render_name); - - return TRUE;*/ } // Saves the image from the screen to the specified filename and path. -- cgit v1.2.3 From 1f71cd20e831983aa5f4682958a3619b9f37a6f1 Mon Sep 17 00:00:00 2001 From: "Jonathan@Chomp.lindenlab.com" Date: Wed, 18 Nov 2009 11:38:31 -0800 Subject: Fixed variable price upload path. --- indra/newview/llassetuploadresponders.cpp | 98 ++++++++++++++++++++++--------- indra/newview/llassetuploadresponders.h | 3 + indra/newview/llviewermenufile.cpp | 7 ++- 3 files changed, 77 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index f3dbe6fa31..dddc6fef1c 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -676,18 +676,32 @@ class LLNewAgentInventoryVariablePriceResponder::Impl public: Impl( const LLUUID& vfile_id, + LLAssetType::EType asset_type, const LLSD& inventory_data) : mVFileID(vfile_id), - mInventoryData(inventory_data) + mAssetType(asset_type), + mInventoryData(inventory_data), + mFileName("") { + if (!gVFS->getExists(vfile_id, asset_type)) + { + llwarns + << "LLAssetUploadResponder called with nonexistant " + << "vfile_id " << vfile_id << llendl; + mVFileID.setNull(); + mAssetType = LLAssetType::AT_NONE; + } } Impl( const std::string& file_name, + LLAssetType::EType asset_type, const LLSD& inventory_data) : mFileName(file_name), + mAssetType(asset_type), mInventoryData(inventory_data) { + mVFileID.setNull(); } std::string getFilenameOrIDString() const @@ -707,8 +721,7 @@ public: LLAssetType::EType getAssetType() const { - return LLAssetType::lookup( - mInventoryData["asset_type"].asString()); + return mAssetType; } LLInventoryType::EType getInventoryType() const @@ -898,22 +911,7 @@ public: { case 0: { - if ( getFilename().empty() ) - { - // we have no filename, use virtual file ID instead - LLHTTPClient::postFile( - confirmation_url, - getVFileID(), - getAssetType(), - responder); - } - else - { - LLHTTPClient::postFile( - confirmation_url, - getFilename(), - responder); - } + confirmUpload(confirmation_url, responder); } break; case 1: @@ -923,11 +921,35 @@ public: return false; } - + + void confirmUpload( + const std::string& confirmation_url, + boost::intrusive_ptr responder) + { + if ( getFilename().empty() ) + { + // we have no filename, use virtual file ID instead + LLHTTPClient::postFile( + confirmation_url, + getVFileID(), + getAssetType(), + responder); + } + else + { + LLHTTPClient::postFile( + confirmation_url, + getFilename(), + responder); + } + } + + private: std::string mFileName; LLSD mInventoryData; + LLAssetType::EType mAssetType; LLUUID mVFileID; }; @@ -936,19 +958,23 @@ private: /////////////////////////////////////////////// LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( const LLUUID& vfile_id, + LLAssetType::EType asset_type, const LLSD& inventory_info) { mImpl = new Impl( vfile_id, + asset_type, inventory_info); } LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( const std::string& file_name, + LLAssetType::EType asset_type, const LLSD& inventory_info) { mImpl = new Impl( file_name, + asset_type, inventory_info); } @@ -962,8 +988,9 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent( const std::string& reason, const LLSD& content) { - llinfos << "LLNewAgentInventoryVariablePrice::error " << statusNum - << " reason: " << reason << llendl; + lldebugs + << "LLNewAgentInventoryVariablePrice::error " << statusNum + << " reason: " << reason << llendl; if ( content.has("error") ) { @@ -988,6 +1015,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) static const std::string _CONFIRM_UPLOAD = "confirm_upload"; static const std::string _UPLOAD_PRICE = "upload_price"; + static const std::string _RESOURCE_COST = "resource_cost"; static const std::string _RSVP = "rsvp"; // Check for application level errors @@ -1022,7 +1050,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) mImpl->getItemName(), mImpl->getItemDescription(), content, - content["upload_price"].asInteger()); + content[_UPLOAD_PRICE].asInteger()); // TODO* Add bulk (serial) uploading or add // a super class of this that does so @@ -1031,6 +1059,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) { showConfirmationDialog( content[_UPLOAD_PRICE].asInteger(), + content[_RESOURCE_COST].asInteger(), content[_RSVP].asString()); } else @@ -1047,17 +1076,30 @@ void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError( void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( S32 upload_price, + S32 resource_cost, const std::string& confirmation_url) { - if ( 0 == upload_price ) + if ( 0 == upload_price ) { // don't show confirmation dialog for free uploads, I mean, // they're free! - LLSD body; - body["confirm_upload"] = true; - body["expected_upload_price"] = upload_price; - LLHTTPClient::post(confirmation_url, body, this); + // The creating of a new instrusive_ptr(this) + // creates a new boost::intrusive_ptr + // which is a copy of this. This code is required because + // 'this' is always of type Class* and not the intrusive_ptr, + // and thus, a reference to 'this' is not registered + // by using just plain 'this'. + + // Since LLNewAgentInventoryVariablePriceResponder is a + // reference counted class, it is possible (since the + // reference to a plain 'this' would be missed here) that, + // when using plain ol' 'this', that this object + // would be deleted before the callback is triggered + // and cause sadness. + mImpl->confirmUpload( + confirmation_url, + boost::intrusive_ptr(this)); } else { diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 9102f1597e..929a7a5f74 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -87,10 +87,12 @@ class LLNewAgentInventoryVariablePriceResponder : public: LLNewAgentInventoryVariablePriceResponder( const LLUUID& vfile_id, + LLAssetType::EType asset_type, const LLSD& inventory_info); LLNewAgentInventoryVariablePriceResponder( const std::string& file_name, + LLAssetType::EType asset_type, const LLSD& inventory_info); virtual ~LLNewAgentInventoryVariablePriceResponder(); @@ -105,6 +107,7 @@ public: const LLSD& error); virtual void showConfirmationDialog( S32 upload_price, + S32 resource_cost, const std::string& confirmation_url); private: diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 8b101748a3..2c0a41e1ff 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -1175,9 +1175,9 @@ BOOL upload_new_variable_price_resource( if ( !url.empty() ) { - llinfos << "New Agent Inventory variable price upload" - << llendl; - + lldebugs + << "New Agent Inventory variable price upload" << llendl; + // Each of the two capabilities has similar data, so // let's reuse that code @@ -1200,6 +1200,7 @@ BOOL upload_new_variable_price_resource( body, new LLNewAgentInventoryVariablePriceResponder( uuid, + asset_type, body)); return TRUE; -- cgit v1.2.3 From 81bfdcbfae4f203e60f00794966383b01475995b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 18 Nov 2009 18:10:48 -0600 Subject: Tetrahedron displays in place of unloaded mesh. Still has some LOD issues. --- indra/llmath/llvolume.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++- indra/llmath/llvolume.h | 1 + indra/newview/pipeline.cpp | 9 ++++- 3 files changed, 103 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index f252b2a232..84da1b3c62 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1925,7 +1925,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) S32 lod = llclamp((S32) mDetail, 0, 3); - while (lod < 4 && header[nm[lod]]["offset"].asInteger() == -1) + while (lod < 4 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0 )) { ++lod; } @@ -1934,7 +1936,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { lod = llclamp((S32) mDetail, 0, 3); - while (lod >= 0 && header[nm[lod]]["offset"].asInteger() == -1) + while (lod >= 0 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0) ) { --lod; } @@ -2135,6 +2139,94 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) return TRUE; } +void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) +{ + LLVector3 nrm = (cv[1].mPosition-cv[0].mPosition)%(cv[2].mPosition-cv[0].mPosition); + + nrm.normVec(); + + cv[0].mNormal = nrm; + cv[1].mNormal = nrm; + cv[2].mNormal = nrm; +} + +void LLVolume::makeTetrahedron() +{ + mVolumeFaces.clear(); + + LLVolumeFace face; + + F32 x = 0.5f; + LLVector3 p[] = + { //unit tetrahedron corners + LLVector3(x,x,x), + LLVector3(-x,-x,x), + LLVector3(-x,x,-x), + LLVector3(x,-x,-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].mPosition = p[1]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 2 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[1]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 3 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[1]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 4 + cv[0].mPosition = p[2]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[3]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //set index buffer + for (U32 i = 0; i < 12; i++) + { + face.mIndices.push_back(i); + } + + mVolumeFaces.push_back(face); + mSculptLevel = 0; +} + void LLVolume::copyVolumeFaces(LLVolume* volume) { mVolumeFaces = volume->mVolumeFaces; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index d2727d8f21..bf2854ede9 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -969,6 +969,7 @@ protected: public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); + virtual void makeTetrahedron(); protected: BOOL mUnique; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c262e94ff4..3410ad6559 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8976,6 +8976,9 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + + //nothing found, so make a tetrahedron + volume->makeTetrahedron(); } } @@ -9102,7 +9105,11 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + if (mesh->mVolume->getNumVolumeFaces() > 0) + { + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + } + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); -- cgit v1.2.3 From 62233f22469cdc66042fc7bbbbd367dbb7212fde Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Nov 2009 07:38:04 -0600 Subject: Fix for copying of tetrahedrons in place of mesh LODs. Fix for bad tetrahedron bounding box. Bad fix for simultaneous loading of multiple LODs. --- indra/llmath/llvolume.cpp | 31 +++++++++++++++++++++++++-- indra/llmath/llvolume.h | 5 ++++- indra/llmath/llvolumemgr.cpp | 13 ++++++++++++ indra/llmath/llvolumemgr.h | 1 + indra/newview/llvovolume.cpp | 31 ++++----------------------- indra/newview/llvovolume.h | 1 - indra/newview/pipeline.cpp | 50 +++++++++++++++++++++++++++++++++++--------- indra/newview/pipeline.h | 6 ++++-- 8 files changed, 95 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 84da1b3c62..515b1061f9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1676,6 +1676,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; + mIsTetrahedron = FALSE; mLODScaleBias.setVec(1,1,1); // set defaults @@ -1905,7 +1906,7 @@ BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { mSculptLevel = -1; // default is an error occured - + LLSD header; { if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) @@ -2048,6 +2049,11 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { U32 face_count = mdl.size(); + if (face_count == 0) + { + llerrs << "WTF?" << llendl; + } + mVolumeFaces.resize(face_count); for (U32 i = 0; i < face_count; ++i) @@ -2063,8 +2069,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) //copy out indices face.mIndices.resize(idx.size()/2); - if (idx.empty()) + if (idx.empty() || face.mIndices.size() < 3) { //why is there an empty index list? + llerrs <<"WTF?" << llendl; continue; } @@ -2150,6 +2157,11 @@ void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) cv[2].mNormal = nrm; } +BOOL LLVolume::isTetrahedron() +{ + return mIsTetrahedron; +} + void LLVolume::makeTetrahedron() { mVolumeFaces.clear(); @@ -2165,6 +2177,9 @@ void LLVolume::makeTetrahedron() LLVector3(x,-x,-x) }; + face.mExtents[0].setVec(-x,-x,-x); + face.mExtents[1].setVec(x,x,x); + LLVolumeFace::VertexData cv[3]; //set texture coordinates @@ -2225,12 +2240,19 @@ void LLVolume::makeTetrahedron() mVolumeFaces.push_back(face); mSculptLevel = 0; + mIsTetrahedron = TRUE; } void LLVolume::copyVolumeFaces(LLVolume* volume) { + if (volume->isTetrahedron()) + { + llerrs << "WTF?" << llendl; + } + mVolumeFaces = volume->mVolumeFaces; mSculptLevel = 0; + mIsTetrahedron = FALSE; } S32 const LL_SCULPT_MESH_MAX_FACES = 8; @@ -2615,6 +2637,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, LLMemType m1(LLMemType::MTYPE_VOLUME); U8 sculpt_type = mParams.getSculptType(); + if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH) + { + llerrs << "WTF?" << llendl; + } + BOOL data_is_empty = FALSE; if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index bf2854ede9..8e57f2e280 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -904,7 +904,8 @@ public: BOOL isUnique() const { return mUnique; } S32 getSculptLevel() const { return mSculptLevel; } - + void setSculptLevel(S32 level) { mSculptLevel = level; } + S32 *getTriangleIndices(U32 &num_indices) const; // returns number of triangle indeces required for path/profile mesh @@ -970,11 +971,13 @@ public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); virtual void makeTetrahedron(); + virtual BOOL isTetrahedron(); protected: BOOL mUnique; F32 mDetail; S32 mSculptLevel; + BOOL mIsTetrahedron; LLVolumeParams mParams; LLPath *mPathp; diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 61c5a0adc9..419e0015ba 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) return mDetailScales[detail]; } +S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail) +{ + for (S32 i = 1; i < 4; i++) + { + if (mDetailScales[i] > detail) + { + return i-1; + } + } + + return 3; +} + F32 LLVolumeLODGroup::dump() { F32 usage = 0.f; diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index a78ea76a1a..f5dc4cd748 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -59,6 +59,7 @@ public: static S32 getDetailFromTan(const F32 tan_angle); static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher); static F32 getVolumeScaleFromDetail(const S32 detail); + static S32 getVolumeDetailFromScale(F32 scale); LLVolume* refLOD(const S32 detail); BOOL derefLOD(LLVolume *volumep); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4c126d8fd9..64c2e9e8ec 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -163,7 +163,6 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXformInvTrans.setIdentity(); mLOD = MIN_LOD; - mMeshSculptLevel = -2; mTextureAnimp = NULL; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; @@ -682,25 +681,7 @@ void LLVOVolume::updateTextureVirtualSize() LLUUID id = sculpt_params->getSculptTexture(); U8 sculpt_type = sculpt_params->getSculptType(); - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - if (mMeshSculptLevel == -2) - { - // get the asset please - gPipeline.loadMesh(this, id); - /*gAssetStorage->getAssetData(id, LLAssetType::AT_MESH, (LLGetAssetCallback)NULL, NULL, TRUE); - - if (gAssetStorage->hasLocalAsset(id, LLAssetType::AT_MESH)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - }*/ - } - } - - else - // mesh is a sculptie + if ((sculpt_type & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); @@ -902,14 +883,10 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { if (getVolume()->getNumVolumeFaces() == 0) - { - //mesh is not loaded, request pipeline load this mesh + { + //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gPipeline.loadMesh(this, asset_id, detail); - } - else - { - mMeshSculptLevel = 1; + gPipeline.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); } } else // otherwise is sculptie diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4b247f3778..f14a71130b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,7 +298,6 @@ private: LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; - S32 mMeshSculptLevel; BOOL mSculptChanged; F32 mSpotLightPriority; LLMatrix4 mRelativeXform; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3410ad6559..0ee619244b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8913,23 +8913,29 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { + + if (detail < 0 || detail > 4) + { + return; + } + { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); - if (iter != mLoadingMeshes.end()) + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); + if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list iter->second.insert(vobj->getID()); return; } //first request for this mesh - mLoadingMeshes[mesh_id].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_id].insert(vobj->getID()); } if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume())); + mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume(), detail)); } else { //fetch asset and load when done @@ -8952,7 +8958,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail-1; i >= 0; --i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8966,7 +8972,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail+1; i < 4; ++i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8976,6 +8982,10 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + else + { + llerrs << "WTF?" << llendl; + } //nothing found, so make a tetrahedron volume->makeTetrahedron(); @@ -8992,12 +9002,22 @@ void LLPipeline::getMeshAssetCallback(LLVFS *vfs, } -LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target) +LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail) : LLThread("mesh_loading_thread") { mMeshID = mesh_id; mVolume = NULL; mDetail = target->getDetail(); + + if (detail == -1) + { + mDetailIndex = LLVolumeLODGroup::getVolumeDetailFromScale(target->getDetail()); + } + else + { + mDetailIndex = detail; + } + mTargetVolume = target; } @@ -9073,6 +9093,10 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading + + + + LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9081,10 +9105,12 @@ void LLPipeline::notifyLoadedMeshes() continue; } + S32 detail = mesh->mDetailIndex; + //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID); + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh->mMeshID); - if (mesh->mVolume && obj_iter != mLoadingMeshes.end()) + if (mesh->mVolume && obj_iter != mLoadingMeshes[detail].end()) { //make sure target volume is still valid BOOL valid = FALSE; @@ -9109,6 +9135,10 @@ void LLPipeline::notifyLoadedMeshes() { mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); } + else + { + llwarns << "Mesh loading returned empty volume." << llendl; + } for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { @@ -9120,7 +9150,7 @@ void LLPipeline::notifyLoadedMeshes() } } - mLoadingMeshes.erase(mesh->mMeshID); + mLoadingMeshes[detail].erase(mesh->mMeshID); } delete mesh; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 23e98aa0d6..a31379a209 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -676,8 +676,9 @@ public: protected: std::vector mSelectedFaces; + typedef std::map > mesh_load_map; - mesh_load_map mLoadingMeshes; + mesh_load_map mLoadingMeshes[4]; LLMutex* mMeshMutex; @@ -688,7 +689,8 @@ protected: LLVolume* mTargetVolume; LLUUID mMeshID; F32 mDetail; - LLMeshThread(LLUUID mesh_id, LLVolume* target); + S32 mDetailIndex; + LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail = -1); ~LLMeshThread(); void run(); }; -- cgit v1.2.3 From 6d66910c6e2fbb25bf8b5c7b90e795f350342104 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 25 Nov 2009 11:35:41 -0600 Subject: Fix for spam on invalid mesh asset. Fix for index buffer overflow spam and crash in llvertexbuffer. --- indra/llmath/llvolume.cpp | 5 ----- indra/newview/llvovolume.cpp | 5 +++-- indra/newview/pipeline.cpp | 18 ++++++------------ 3 files changed, 9 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 515b1061f9..3e547aec6f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2245,11 +2245,6 @@ void LLVolume::makeTetrahedron() void LLVolume::copyVolumeFaces(LLVolume* volume) { - if (volume->isTetrahedron()) - { - llerrs << "WTF?" << llendl; - } - mVolumeFaces = volume->mVolumeFaces; mSculptLevel = 0; mIsTetrahedron = FALSE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 64c2e9e8ec..3e9db86cfa 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -882,7 +882,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { - if (getVolume()->getNumVolumeFaces() == 0) + if (getVolume()->getNumVolumeFaces() == 0 || getVolume()->isTetrahedron()) { //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); @@ -924,7 +924,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool void LLVOVolume::notifyMeshLoaded() { mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + dirtySpatialGroup(TRUE); } // sculpt replaces generate() for sculpted surfaces diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0ee619244b..af3a35615c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1807,8 +1807,6 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); - notifyLoadedMeshes(); - // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1888,6 +1886,8 @@ void LLPipeline::updateGeom(F32 max_dtime) // for now, only LLVOVolume does this to throttle LOD changes LLVOVolume::preUpdateGeom(); + notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); iter != mBuildQ1.end();) @@ -8913,7 +8913,6 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { - if (detail < 0 || detail > 4) { return; @@ -9093,10 +9092,6 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading - - - - LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9131,14 +9126,13 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - if (mesh->mVolume->getNumVolumeFaces() > 0) - { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); - } - else + if (mesh->mVolume->getNumVolumeFaces() <= 0) { llwarns << "Mesh loading returned empty volume." << llendl; + mesh->mVolume->makeTetrahedron(); } + + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { -- cgit v1.2.3 From f31f817ee61fa0f8fc05d2caa24f7674852629e5 Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Wed, 25 Nov 2009 13:10:09 -0600 Subject: retry asset upload failures. --- indra/newview/llassetuploadresponders.cpp | 17 +++++++++++++++++ indra/newview/llassetuploadresponders.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'indra') diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index dddc6fef1c..6e32a91078 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -256,6 +256,7 @@ void LLAssetUploadResponder::result(const LLSD& content) lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; std::string state = content["state"]; + if (state == "upload") { uploadUpload(content); @@ -330,6 +331,22 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( { } +// virtual +void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reason) +{ + LLAssetUploadResponder::error(statusNum, reason); + LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); +} + + +//virtual +void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content) +{ + LLAssetUploadResponder::uploadFailure(content); + + LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], FALSE); +} + //virtual void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) { diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 929a7a5f74..c869988203 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -74,7 +74,9 @@ public: const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type); + virtual void error(U32 statusNum, const std::string& reason); virtual void uploadComplete(const LLSD& content); + virtual void uploadFailure(const LLSD& content); }; // A base class which goes through and performs some default -- cgit v1.2.3 From 062a2dd309ca5521d4045eb721496476f43d24dc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Nov 2009 15:32:10 -0600 Subject: Remove zero area triangles from meshes post-import. --- indra/llmath/llvolume.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 3e547aec6f..1d36da7f52 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,10 +1692,9 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - generate(); - if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { + generate(); createVolumeFaces(); } } -- cgit v1.2.3 From f039fa98efedc91965338ef53624279f99914205 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Nov 2009 17:02:38 -0600 Subject: Fix for silly crash due to LLPrimitive having 0 texture entries. --- indra/llmath/llvolume.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 1d36da7f52..858bd9edea 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,9 +1692,10 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; + generate(); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { - generate(); createVolumeFaces(); } } -- cgit v1.2.3 From bb2631180a85df343e6d816fc37d881af31d49fb Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Tue, 1 Dec 2009 17:40:52 -0600 Subject: CTS-4 Only part of an uploaded mesh renders. --- indra/llmath/llvolume.cpp | 1 - indra/llmath/llvolume.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 858bd9edea..fb2de92e35 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2250,7 +2250,6 @@ void LLVolume::copyVolumeFaces(LLVolume* volume) mIsTetrahedron = FALSE; } -S32 const LL_SCULPT_MESH_MAX_FACES = 8; S32 LLVolume::getNumFaces() const { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 8e57f2e280..59c60ccd92 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -192,6 +192,7 @@ const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +const S32 LL_SCULPT_MESH_MAX_FACES = 8; class LLProfileParams { -- cgit v1.2.3 From 00962a68e24c4b628716aaa4390468dc5cc6194e Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Wed, 2 Dec 2009 11:56:21 -0600 Subject: CTS-37 Mesh-type assets can't be added to the inventory of a prim --- indra/newview/llpanelobjectinventory.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 0c2e87aa3d..7a7372af6e 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1593,6 +1593,11 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* object->getUUID(), object->getName()); break; + case LLAssetType::AT_MESH: + new_bridge = new LLTaskMeshBridge(panel, + object->getUUID(), + object->getName()); + break; break; default: -- cgit v1.2.3