diff options
Diffstat (limited to 'indra')
104 files changed, 3030 insertions, 2169 deletions
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 6fdf9e2e07..d1eb389013 100755 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -584,8 +584,6 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent info->mRot.mV[VZ], LLQuaternion::XYZ)); joint->setScale(info->mScale); - joint->setDefaultFromCurrentXform(); - if (info->mIsJoint) { joint->setSkinOffset( info->mPivot ); @@ -677,6 +675,42 @@ void LLAvatarAppearance::clearSkeleton() mSkeleton.clear(); } +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id ) +{ + LLVector3 pos(0.0,0.0,fixup); + mPelvisFixups.add(mesh_id,pos); +} + +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id ) +{ + mPelvisFixups.remove(mesh_id); +} + +//------------------------------------------------------------------------ +// hasPelvisFixup +//------------------------------------------------------------------------ +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const +{ + LLVector3 pos; + if (mPelvisFixups.findActiveOverride(mesh_id,pos)) + { + fixup = pos[2]; + return true; + } + return false; +} + +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const +{ + LLUUID mesh_id; + return hasPelvisFixup( fixup, mesh_id ); +} //----------------------------------------------------------------------------- // LLAvatarAppearance::buildCharacter() // Deferred initialization and rebuild of the avatar. diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 1e898026c0..a0ef49b7cb 100755 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -152,11 +152,17 @@ protected: BOOL mIsBuilt; // state of deferred character building typedef std::vector<LLAvatarJoint*> avatar_joint_list_t; avatar_joint_list_t mSkeleton; - + LLPosOverrideMap mPelvisFixups; + //-------------------------------------------------------------------- // Pelvis height adjustment members. //-------------------------------------------------------------------- public: + void addPelvisFixup( F32 fixup, const LLUUID& mesh_id ); + void removePelvisFixup( const LLUUID& mesh_id ); + bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const; + bool hasPelvisFixup( F32& fixup ) const; + LLVector3 mBodySize; LLVector3 mAvatarOffset; protected: diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index ea29cbd451..fbc312c426 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -213,7 +213,7 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex ) LLVector3 scaleDelta = iter->second; newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached - joint->storeScaleForReset( newScale ); + // needed? // joint->storeScaleForReset( newScale ); joint->setScale(newScale); } diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index dbd6d48a95..6f22a7c6b7 100755 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -36,6 +36,64 @@ S32 LLJoint::sNumUpdates = 0; S32 LLJoint::sNumTouches = 0; +template <class T> +bool attachment_map_iter_compare_key(const T& a, const T& b) +{ + return a.first < b.first; +} + +bool LLPosOverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const +{ + pos = LLVector3(0,0,0); + mesh_id = LLUUID(); + bool found = false; + + map_type::const_iterator it = std::max_element(m_map.begin(), + m_map.end(), + attachment_map_iter_compare_key<map_type::value_type>); + if (it != m_map.end()) + { + found = true; + pos = it->second; + mesh_id = it->first; + } + return found; +} + +void LLPosOverrideMap::showJointPosOverrides( std::ostringstream& os ) const +{ + map_type::const_iterator max_it = std::max_element(m_map.begin(), + m_map.end(), + attachment_map_iter_compare_key<map_type::value_type>); + for (map_type::const_iterator it = m_map.begin(); + it != m_map.end(); ++it) + { + const LLVector3& pos = it->second; + os << " " << "[" << it->first <<": " << pos << "]" << ((it==max_it) ? "*" : ""); + } +} + +U32 LLPosOverrideMap::count() const +{ + return m_map.size(); +} + +void LLPosOverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos) +{ + m_map[mesh_id] = pos; +} + +bool LLPosOverrideMap::remove(const LLUUID& mesh_id) +{ + U32 remove_count = m_map.erase(mesh_id); + return (remove_count > 0); +} + +void LLPosOverrideMap::clear() +{ + m_map.clear(); +} + //----------------------------------------------------------------------------- // LLJoint() // Class Constructor @@ -48,11 +106,8 @@ void LLJoint::init() mParent = NULL; mXform.setScaleChildOffset(TRUE); mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); - mOldXform.setScaleChildOffset(TRUE); - mOldXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; - mResetAfterRestoreOldXform = false; } LLJoint::LLJoint() : @@ -233,52 +288,123 @@ const LLVector3& LLJoint::getPosition() return mXform.getPosition(); } +bool do_debug_joint(const std::string& name) +{ + return true; +} //-------------------------------------------------------------------- // setPosition() //-------------------------------------------------------------------- void LLJoint::setPosition( const LLVector3& pos ) { + if (pos != getPosition()) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL; + } + } mXform.setPosition(pos); touch(MATRIX_DIRTY | POSITION_DIRTY); } +void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info ) +{ + std::ostringstream os; + os << joint.m_posBeforeOverrides; + joint.m_attachmentOverrides.showJointPosOverrides(os); + LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL; +} //-------------------------------------------------------------------- -// setPosition() +// addAttachmentPosOverride() //-------------------------------------------------------------------- -void LLJoint::setDefaultFromCurrentXform( void ) -{ - mDefaultXform = mXform; +void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info ) +{ + if (mesh_id.isNull()) + { + return; + } + if (!m_attachmentOverrides.count()) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL; + } + m_posBeforeOverrides = getPosition(); + } + m_attachmentOverrides.add(mesh_id,pos); + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL; + } + updatePos(av_info); } //-------------------------------------------------------------------- -// storeCurrentXform() +// removeAttachmentPosOverride() //-------------------------------------------------------------------- -void LLJoint::storeCurrentXform( const LLVector3& pos ) -{ - mOldXform = mXform; - mResetAfterRestoreOldXform = true; - setPosition( pos ); - touch(ALL_DIRTY); +void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info ) +{ + if (mesh_id.isNull()) + { + return; + } + if (m_attachmentOverrides.remove(mesh_id)) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " removeAttachmentPosOverride for " << mesh_id << LL_ENDL; + showJointPosOverrides(*this, "remove", av_info); + } + updatePos(av_info); + } + } //-------------------------------------------------------------------- -// storeScaleForReset() + // hasAttachmentPosOverride() + //-------------------------------------------------------------------- +bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const +{ + return m_attachmentOverrides.findActiveOverride(mesh_id,pos); +} + +//-------------------------------------------------------------------- +// clearAttachmentPosOverrides() //-------------------------------------------------------------------- -void LLJoint::storeScaleForReset( const LLVector3& scale ) +void LLJoint::clearAttachmentPosOverrides() { - mOldXform.setScale( scale ); + if (m_attachmentOverrides.count()) + { + m_attachmentOverrides.clear(); + setPosition(m_posBeforeOverrides); + setId( LLUUID::null ); + } } + //-------------------------------------------------------------------- -// restoreOldXform() +// updatePos() //-------------------------------------------------------------------- -void LLJoint::restoreOldXform( void ) -{ - mXform = mDefaultXform; - mResetAfterRestoreOldXform = false; - mDirtyFlags = ALL_DIRTY; +void LLJoint::updatePos(const std::string& av_info) +{ + LLVector3 pos, found_pos; + LLUUID mesh_id; + if (m_attachmentOverrides.findActiveOverride(mesh_id,found_pos)) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL; + pos = found_pos; + } + else + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL; + pos = m_posBeforeOverrides; + } + setPosition(pos); } + //-------------------------------------------------------------------- // getWorldPosition() //-------------------------------------------------------------------- @@ -325,7 +451,7 @@ void LLJoint::setWorldPosition( const LLVector3& pos ) //-------------------------------------------------------------------- -// mXform.getRotation() +// getRotation() //-------------------------------------------------------------------- const LLQuaternion& LLJoint::getRotation() { @@ -432,7 +558,7 @@ const LLMatrix4 &LLJoint::getWorldMatrix() //-------------------------------------------------------------------- void LLJoint::setWorldMatrix( const LLMatrix4& mat ) { -LL_INFOS() << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << LL_ENDL; + LL_INFOS() << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << LL_ENDL; // extract global translation LLVector3 trans( mat.mMatrix[VW][VX], mat.mMatrix[VW][VY], @@ -548,20 +674,6 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot) break; } } - - // 2003.03.26 - This code was just using up cpu cycles. AB - -// LLVector3 old_axis = main_axis * old_rot; -// LLVector3 new_axis = main_axis * new_rot; - -// for (S32 i = 0; i < mConstraintSilhouette.size() - 1; i++) -// { -// LLVector3 vert1 = mConstraintSilhouette[i]; -// LLVector3 vert2 = mConstraintSilhouette[i + 1]; - - // figure out how to clamp rotation to line on 3-sphere - -// } } // End diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index b65d6979d4..2abe1d6db1 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -46,6 +46,21 @@ const U32 LL_FACE_JOINT_NUM = 30; const S32 LL_CHARACTER_MAX_PRIORITY = 7; const F32 LL_MAX_PELVIS_OFFSET = 5.f; +class LLPosOverrideMap +{ +public: + LLPosOverrideMap() {} + bool findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const; + void showJointPosOverrides(std::ostringstream& os) const; + U32 count() const; + void add(const LLUUID& mesh_id, const LLVector3& pos); + bool remove(const LLUUID& mesh_id); + void clear(); +private: + typedef std::map<LLUUID,LLVector3> map_type; + map_type m_map; +}; + //----------------------------------------------------------------------------- // class LLJoint //----------------------------------------------------------------------------- @@ -79,8 +94,6 @@ protected: // explicit transformation members LLXformMatrix mXform; - LLXformMatrix mOldXform; - LLXformMatrix mDefaultXform; LLUUID mId; @@ -88,8 +101,6 @@ public: U32 mDirtyFlags; BOOL mUpdateXform; - BOOL mResetAfterRestoreOldXform; - // describes the skin binding pose LLVector3 mSkinOffset; @@ -103,6 +114,11 @@ public: static S32 sNumTouches; static S32 sNumUpdates; + LLPosOverrideMap m_attachmentOverrides; + LLVector3 m_posBeforeOverrides; + + void updatePos(const std::string& av_info); + public: LLJoint(); LLJoint(S32 joint_num); @@ -160,7 +176,7 @@ public: // get/set local scale const LLVector3& getScale(); void setScale( const LLVector3& scale ); - void storeScaleForReset( const LLVector3& scale ); + // get/set world matrix const LLMatrix4 &getWorldMatrix(); void setWorldMatrix( const LLMatrix4& mat ); @@ -183,20 +199,16 @@ public: virtual BOOL isAnimatable() const { return TRUE; } S32 getJointNum() const { return mJointNum; } - - void restoreOldXform( void ); - void setDefaultFromCurrentXform( void ); - void storeCurrentXform( const LLVector3& pos ); + + void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info ); + void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info ); + bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const; + void clearAttachmentPosOverrides(); //Accessor for the joint id LLUUID getId( void ) { return mId; } //Setter for the joints id void setId( const LLUUID& id ) { mId = id;} - - //If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it - const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; } - void setJointResetFlag( bool val ) { mResetAfterRestoreOldXform = val; } - }; #endif // LL_LLJOINT_H diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 3d0c488768..0b9d136910 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -266,7 +266,7 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image) } else { - llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; + LL_WARNS() << "Filter unknown, cannot execute filter command : " << filter_name << LL_ENDL; } } } diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index e56929ed0f..aa0b1752f4 100755 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -71,6 +71,9 @@ public: void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization void loadIdentity(); // Loads the quaternion that represents the identity rotation + bool isEqualEps(const LLQuaternion &quat, F32 epsilon) const; + bool isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const; + const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) @@ -239,6 +242,21 @@ inline void LLQuaternion::loadIdentity() mQ[VW] = 1.0f; } +inline bool LLQuaternion::isEqualEps(const LLQuaternion &quat, F32 epsilon) const +{ + return ( fabs(mQ[VX] - quat.mQ[VX]) < epsilon + && fabs(mQ[VY] - quat.mQ[VY]) < epsilon + && fabs(mQ[VZ] - quat.mQ[VZ]) < epsilon + && fabs(mQ[VS] - quat.mQ[VS]) < epsilon ); +} + +inline bool LLQuaternion::isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const +{ + return ( fabs(mQ[VX] - quat.mQ[VX]) > epsilon + || fabs(mQ[VY] - quat.mQ[VY]) > epsilon + || fabs(mQ[VZ] - quat.mQ[VZ]) > epsilon + || fabs(mQ[VS] - quat.mQ[VS]) > epsilon ); +} inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) { diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index b4963225dc..aa8dd7697c 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -172,7 +172,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa if (!pos_source) { - llwarns << "Unable to process mesh without position data; invalid model; invalid model." << llendl; + LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; return LLModel::BAD_ELEMENT; } @@ -180,20 +180,20 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa domListOfUInts& idx = p->getValue(); domListOfFloats dummy ; - domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& v = (pos_source && pos_source->getFloat_array()) ? pos_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& tc = (tc_source && tc_source->getFloat_array()) ? tc_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& n = (norm_source && norm_source->getFloat_array()) ? norm_source->getFloat_array()->getValue() : dummy ; LLVolumeFace::VertexMapData::PointMap point_map; U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; + U32 vertex_count = (pos_source && pos_source->getFloat_array()) ? v.getCount() : 0; + U32 tc_count = (tc_source && tc_source->getFloat_array()) ? tc.getCount() : 0; + U32 norm_count = (norm_source && norm_source->getFloat_array()) ? n.getCount(): 0; - if ((vertex_count == 0) || (tc_count == 0)) + if ((vertex_count == 0)) { - llwarns << "Unable to process mesh with empty position array; invalid model." << llendl; + LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; return LLModel::BAD_ELEMENT; } @@ -229,7 +229,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa { // guard against model data specifiying out of range indices or tcs // - + if (((i + tc_offset) > index_count) || ((idx[i+tc_offset]*2+1) > tc_count)) { diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b81dd4c9a1..3ceed95248 100755 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -61,33 +61,33 @@ U64 LLGLSLShader::sTotalSamplesDrawn = 0; U32 LLGLSLShader::sTotalDrawCalls = 0; //UI shader -- declared here so llui_libtest will link properly -LLGLSLShader gUIProgram; -LLGLSLShader gSolidColorProgram; +LLGLSLShader gUIProgram; +LLGLSLShader gSolidColorProgram; BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) { - return v1 != v2; + return v1 != v2; } LLShaderFeatures::LLShaderFeatures() - : atmosphericHelpers(false) - , calculatesLighting(false) - , calculatesAtmospherics(false) - , hasLighting(false) - , isAlphaLighting(false) - , isShiny(false) - , isFullbright(false) - , isSpecular(false) - , hasWaterFog(false) - , hasTransport(false) - , hasSkinning(false) - , hasObjectSkinning(false) - , hasAtmospherics(false) - , hasGamma(false) - , mIndexedTextureChannels(0) - , disableTextureIndex(false) - , hasAlphaMask(false) - , attachNothing(false) + : atmosphericHelpers(false) + , calculatesLighting(false) + , calculatesAtmospherics(false) + , hasLighting(false) + , isAlphaLighting(false) + , isShiny(false) + , isFullbright(false) + , isSpecular(false) + , hasWaterFog(false) + , hasTransport(false) + , hasSkinning(false) + , hasObjectSkinning(false) + , hasAtmospherics(false) + , hasGamma(false) + , mIndexedTextureChannels(0) + , disableTextureIndex(false) + , hasAlphaMask(false) + , attachNothing(false) { } @@ -98,225 +98,225 @@ LLShaderFeatures::LLShaderFeatures() //static void LLGLSLShader::initProfile() { - sProfileEnabled = true; - sTotalTimeElapsed = 0; - sTotalTrianglesDrawn = 0; - sTotalSamplesDrawn = 0; - sTotalDrawCalls = 0; - - for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) - { - (*iter)->clearStats(); - } + sProfileEnabled = true; + sTotalTimeElapsed = 0; + sTotalTrianglesDrawn = 0; + sTotalSamplesDrawn = 0; + sTotalDrawCalls = 0; + + for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + (*iter)->clearStats(); + } } struct LLGLSLShaderCompareTimeElapsed { - bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) - { - return lhs->mTimeElapsed < rhs->mTimeElapsed; - } + bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) + { + return lhs->mTimeElapsed < rhs->mTimeElapsed; + } }; //static void LLGLSLShader::finishProfile(bool emit_report) { - sProfileEnabled = false; - - if (emit_report) - { - std::vector<LLGLSLShader*> sorted; - - for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) - { - sorted.push_back(*iter); - } - - std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); - - for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) - { - (*iter)->dumpStats(); - } - - LL_INFOS() << "-----------------------------------" << LL_ENDL; - LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL; - LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL; - LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL; - } + sProfileEnabled = false; + + if (emit_report) + { + std::vector<LLGLSLShader*> sorted; + + for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + sorted.push_back(*iter); + } + + std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + + for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + (*iter)->dumpStats(); + } + + LL_INFOS() << "-----------------------------------" << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL; + } } void LLGLSLShader::clearStats() { - mTrianglesDrawn = 0; - mTimeElapsed = 0; - mSamplesDrawn = 0; - mDrawCalls = 0; - mTextureStateFetched = false; - mTextureMagFilter.clear(); - mTextureMinFilter.clear(); + mTrianglesDrawn = 0; + mTimeElapsed = 0; + mSamplesDrawn = 0; + mDrawCalls = 0; + mTextureStateFetched = false; + mTextureMagFilter.clear(); + mTextureMinFilter.clear(); } void LLGLSLShader::dumpStats() { - if (mDrawCalls > 0) - { - LL_INFOS() << "=============================================" << LL_ENDL; - LL_INFOS() << mName << LL_ENDL; - for (U32 i = 0; i < mShaderFiles.size(); ++i) - { - LL_INFOS() << mShaderFiles[i].first << LL_ENDL; - } - for (U32 i = 0; i < mTexture.size(); ++i) - { - GLint idx = mTexture[i]; - - if (idx >= 0) - { - GLint uniform_idx = getUniformLocation(i); - LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL; - } - } - LL_INFOS() << "=============================================" << LL_ENDL; - - F32 ms = mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; - - F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f; - F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0); - tris_sec /= seconds; - - F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f; - F32 samples_sec = (F32) mSamplesDrawn/1000000000.0; - samples_sec /= seconds; - - F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f; - U32 avg_batch = mTrianglesDrawn/mDrawCalls; - - LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL; - LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL; - LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; - LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL; - } + if (mDrawCalls > 0) + { + LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mName << LL_ENDL; + for (U32 i = 0; i < mShaderFiles.size(); ++i) + { + LL_INFOS() << mShaderFiles[i].first << LL_ENDL; + } + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; + + if (idx >= 0) + { + GLint uniform_idx = getUniformLocation(i); + LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL; + } + } + LL_INFOS() << "=============================================" << LL_ENDL; + + F32 ms = mTimeElapsed/1000000.f; + F32 seconds = ms/1000.f; + + F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f; + F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0); + tris_sec /= seconds; + + F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f; + F32 samples_sec = (F32) mSamplesDrawn/1000000000.0; + samples_sec /= seconds; + + F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f; + U32 avg_batch = mTrianglesDrawn/mDrawCalls; + + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL; + LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL; + LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL; + } } //static void LLGLSLShader::startProfile() { - if (sProfileEnabled && sCurBoundShaderPtr) - { - sCurBoundShaderPtr->placeProfileQuery(); - } + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->placeProfileQuery(); + } } //static void LLGLSLShader::stopProfile(U32 count, U32 mode) { - if (sProfileEnabled) - { - sCurBoundShaderPtr->readProfileQuery(count, mode); - } + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(count, mode); + } } void LLGLSLShader::placeProfileQuery() { #if !LL_DARWIN - if (mTimerQuery == 0) - { - glGenQueriesARB(1, &mSamplesQuery); - glGenQueriesARB(1, &mTimerQuery); - } + if (mTimerQuery == 0) + { + glGenQueriesARB(1, &mSamplesQuery); + glGenQueriesARB(1, &mTimerQuery); + } - if (!mTextureStateFetched) - { - mTextureStateFetched = true; - mTextureMagFilter.resize(mTexture.size()); - mTextureMinFilter.resize(mTexture.size()); + if (!mTextureStateFetched) + { + mTextureStateFetched = true; + mTextureMagFilter.resize(mTexture.size()); + mTextureMinFilter.resize(mTexture.size()); - U32 cur_active = gGL.getCurrentTexUnitIndex(); + U32 cur_active = gGL.getCurrentTexUnitIndex(); - for (U32 i = 0; i < mTexture.size(); ++i) - { - GLint idx = mTexture[i]; + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; - if (idx >= 0) - { - gGL.getTexUnit(idx)->activate(); + if (idx >= 0) + { + gGL.getTexUnit(idx)->activate(); - U32 mag = 0xFFFFFFFF; - U32 min = 0xFFFFFFFF; + U32 mag = 0xFFFFFFFF; + U32 min = 0xFFFFFFFF; - U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType()); + U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType()); - glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag); - glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min); + glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag); + glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min); - mTextureMagFilter[i] = mag; - mTextureMinFilter[i] = min; - } - } + mTextureMagFilter[i] = mag; + mTextureMinFilter[i] = min; + } + } - gGL.getTexUnit(cur_active)->activate(); - } + gGL.getTexUnit(cur_active)->activate(); + } - glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery); - glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery); + glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery); + glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery); #endif } void LLGLSLShader::readProfileQuery(U32 count, U32 mode) { #if !LL_DARWIN - glEndQueryARB(GL_TIME_ELAPSED); - glEndQueryARB(GL_SAMPLES_PASSED); - - U64 time_elapsed = 0; - glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); - - U64 samples_passed = 0; - glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); - - sTotalTimeElapsed += time_elapsed; - mTimeElapsed += time_elapsed; - - sTotalSamplesDrawn += samples_passed; - mSamplesDrawn += samples_passed; - - U32 tri_count = 0; - switch (mode) - { - case LLRender::TRIANGLES: tri_count = count/3; break; - case LLRender::TRIANGLE_FAN: tri_count = count-2; break; - case LLRender::TRIANGLE_STRIP: tri_count = count-2; break; - default: tri_count = count; break; //points lines etc just use primitive count - } - - mTrianglesDrawn += tri_count; - sTotalTrianglesDrawn += tri_count; - - sTotalDrawCalls++; - mDrawCalls++; + glEndQueryARB(GL_TIME_ELAPSED); + glEndQueryARB(GL_SAMPLES_PASSED); + + U64 time_elapsed = 0; + glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); + + U64 samples_passed = 0; + glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + sTotalTimeElapsed += time_elapsed; + mTimeElapsed += time_elapsed; + + sTotalSamplesDrawn += samples_passed; + mSamplesDrawn += samples_passed; + + U32 tri_count = 0; + switch (mode) + { + case LLRender::TRIANGLES: tri_count = count/3; break; + case LLRender::TRIANGLE_FAN: tri_count = count-2; break; + case LLRender::TRIANGLE_STRIP: tri_count = count-2; break; + default: tri_count = count; break; //points lines etc just use primitive count + } + + mTrianglesDrawn += tri_count; + sTotalTrianglesDrawn += tri_count; + + sTotalDrawCalls++; + mDrawCalls++; #endif } LLGLSLShader::LLGLSLShader() - : mProgramObject(0), - mAttributeMask(0), - mTotalUniformSize(0), - mActiveTextureChannels(0), - mShaderLevel(0), - mShaderGroup(SG_DEFAULT), - mUniformsDirty(FALSE), - mTimerQuery(0), - mSamplesQuery(0) + : mProgramObject(0), + mAttributeMask(0), + mTotalUniformSize(0), + mActiveTextureChannels(0), + mShaderLevel(0), + mShaderGroup(SG_DEFAULT), + mUniformsDirty(FALSE), + mTimerQuery(0), + mSamplesQuery(0) { - + } LLGLSLShader::~LLGLSLShader() @@ -325,1077 +325,1077 @@ LLGLSLShader::~LLGLSLShader() void LLGLSLShader::unload() { - sInstances.erase(this); - - stop_glerror(); - mAttribute.clear(); - mTexture.clear(); - mUniform.clear(); - mShaderFiles.clear(); - mDefines.clear(); - - if (mProgramObject) - { - GLhandleARB obj[1024]; - GLsizei count; - - glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); - for (GLsizei i = 0; i < count; i++) - { + sInstances.erase(this); + + stop_glerror(); + mAttribute.clear(); + mTexture.clear(); + mUniform.clear(); + mShaderFiles.clear(); + mDefines.clear(); + + if (mProgramObject) + { + GLhandleARB obj[1024]; + GLsizei count; + + glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); + for (GLsizei i = 0; i < count; i++) + { #if !LL_DARWIN - if (glIsProgramARB(obj[i])) + if (glIsProgramARB(obj[i])) #endif - { - glDeleteObjectARB(obj[i]); - } - } - - glDeleteObjectARB(mProgramObject); - - mProgramObject = 0; - } - - if (mTimerQuery) - { - glDeleteQueriesARB(1, &mTimerQuery); - mTimerQuery = 0; - } - - if (mSamplesQuery) - { - glDeleteQueriesARB(1, &mSamplesQuery); - mSamplesQuery = 0; - } - - //hack to make apple not complain - glGetError(); - - stop_glerror(); + { + glDeleteObjectARB(obj[i]); + } + } + + glDeleteObjectARB(mProgramObject); + + mProgramObject = 0; + } + + if (mTimerQuery) + { + glDeleteQueriesARB(1, &mTimerQuery); + mTimerQuery = 0; + } + + if (mSamplesQuery) + { + glDeleteQueriesARB(1, &mSamplesQuery); + mSamplesQuery = 0; + } + + //hack to make apple not complain + glGetError(); + + stop_glerror(); } BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes, - std::vector<LLStaticHashedString> * uniforms, - U32 varying_count, - const char** varyings) + std::vector<LLStaticHashedString> * uniforms, + U32 varying_count, + const char** varyings) { - sInstances.insert(this); + sInstances.insert(this); - //reloading, reset matrix hash values - for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) - { - mMatHash[i] = 0xFFFFFFFF; - } - mLightHash = 0xFFFFFFFF; + //reloading, reset matrix hash values + for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) + { + mMatHash[i] = 0xFFFFFFFF; + } + mLightHash = 0xFFFFFFFF; - llassert_always(!mShaderFiles.empty()); - BOOL success = TRUE; + llassert_always(!mShaderFiles.empty()); + BOOL success = TRUE; - // Create program - mProgramObject = glCreateProgramObjectARB(); - + // Create program + mProgramObject = glCreateProgramObjectARB(); + #if LL_DARWIN // work-around missing mix(vec3,vec3,bvec3) mDefines["OLD_SELECT"] = "1"; #endif - - //compile new source - vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); - for ( ; fileIter != mShaderFiles.end(); fileIter++ ) - { - GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); - LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (shaderhandle > 0) - { - attachObject(shaderhandle); - } - else - { - success = FALSE; - } - } - - // Attach existing objects - if (!LLShaderMgr::instance()->attachShaderFeatures(this)) - { - return FALSE; - } - - if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3) - { //indexed texture rendering requires GLSL 1.3 or later - //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again - mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); - } + + //compile new source + vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); + for ( ; fileIter != mShaderFiles.end(); fileIter++ ) + { + GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); + LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; + if (shaderhandle > 0) + { + attachObject(shaderhandle); + } + else + { + success = FALSE; + } + } + + // Attach existing objects + if (!LLShaderMgr::instance()->attachShaderFeatures(this)) + { + return FALSE; + } + + if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3) + { //indexed texture rendering requires GLSL 1.3 or later + //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); + } #ifdef GL_INTERLEAVED_ATTRIBS - if (varying_count > 0 && varyings) - { - glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); - } + if (varying_count > 0 && varyings) + { + glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + } #endif - // Map attributes and uniforms - if (success) - { - success = mapAttributes(attributes); - } - if (success) - { - success = mapUniforms(uniforms); - } - if( !success ) - { - LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL; - - // Try again using a lower shader level; - if (mShaderLevel > 0) - { - LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; - mShaderLevel--; - return createShader(attributes,uniforms); - } - } - else if (mFeatures.mIndexedTextureChannels > 0) - { //override texture channels for indexed texture rendering - bind(); - S32 channel_count = mFeatures.mIndexedTextureChannels; - - for (S32 i = 0; i < channel_count; i++) - { - LLStaticHashedString uniName(llformat("tex%d", i)); - uniform1i(uniName, i); - } - - S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten - for (U32 i = 0; i < mTexture.size(); i++) - { - if (mTexture[i] > -1 && mTexture[i] < channel_count) - { - llassert(cur_tex < gGLManager.mNumTextureImageUnits); - uniform1i(i, cur_tex); - mTexture[i] = cur_tex++; - } - } - unbind(); - } - - return success; + // Map attributes and uniforms + if (success) + { + success = mapAttributes(attributes); + } + if (success) + { + success = mapUniforms(uniforms); + } + if( !success ) + { + LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL; + + // Try again using a lower shader level; + if (mShaderLevel > 0) + { + LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; + mShaderLevel--; + return createShader(attributes,uniforms); + } + } + else if (mFeatures.mIndexedTextureChannels > 0) + { //override texture channels for indexed texture rendering + bind(); + S32 channel_count = mFeatures.mIndexedTextureChannels; + + for (S32 i = 0; i < channel_count; i++) + { + LLStaticHashedString uniName(llformat("tex%d", i)); + uniform1i(uniName, i); + } + + S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1 && mTexture[i] < channel_count) + { + llassert(cur_tex < gGLManager.mNumTextureImageUnits); + uniform1i(i, cur_tex); + mTexture[i] = cur_tex++; + } + } + unbind(); + } + + return success; } BOOL LLGLSLShader::attachObject(std::string object) { - if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0) - { - stop_glerror(); - glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]); - stop_glerror(); - return TRUE; - } - else - { - LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL; - return FALSE; - } + if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0) + { + stop_glerror(); + glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]); + stop_glerror(); + return TRUE; + } + else + { + LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL; + return FALSE; + } } void LLGLSLShader::attachObject(GLhandleARB object) { - if (object != 0) - { - stop_glerror(); - glAttachObjectARB(mProgramObject, object); - stop_glerror(); - } - else - { - LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL; - } + if (object != 0) + { + stop_glerror(); + glAttachObjectARB(mProgramObject, object); + stop_glerror(); + } + else + { + LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL; + } } void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count) { - for (S32 i = 0; i < count; i++) - { - attachObject(objects[i]); - } + for (S32 i = 0; i < count; i++) + { + attachObject(objects[i]); + } } BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes) { - //before linking, make sure reserved attributes always have consistent locations - for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) - { - const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name); - } - - //link the program - BOOL res = link(); - - mAttribute.clear(); - U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); - mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); - - if (res) - { //read back channel locations - - mAttributeMask = 0; - - //read back reserved channels first - for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) - { - const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name); - if (index != -1) - { - mAttribute[i] = index; - mAttributeMask |= 1 << i; - LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - if (attributes != NULL) - { - for (U32 i = 0; i < numAttributes; i++) - { - const char* name = (*attributes)[i].String().c_str(); - S32 index = glGetAttribLocationARB(mProgramObject, name); - if (index != -1) - { - mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; - LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; - } - } - } - - return TRUE; - } - - return FALSE; + //before linking, make sure reserved attributes always have consistent locations + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) + { + const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); + glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name); + } + + //link the program + BOOL res = link(); + + mAttribute.clear(); + U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); + mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); + + if (res) + { //read back channel locations + + mAttributeMask = 0; + + //read back reserved channels first + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) + { + const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); + S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name); + if (index != -1) + { + mAttribute[i] = index; + mAttributeMask |= 1 << i; + LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; + } + } + if (attributes != NULL) + { + for (U32 i = 0; i < numAttributes; i++) + { + const char* name = (*attributes)[i].String().c_str(); + S32 index = glGetAttribLocationARB(mProgramObject, name); + if (index != -1) + { + mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index; + LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL; + } + } + } + + return TRUE; + } + + return FALSE; } void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms) { - if (index == -1) - { - return; - } + if (index == -1) + { + return; + } - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; /* Flawfinder: ignore */ - name[0] = 0; + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; /* Flawfinder: ignore */ + name[0] = 0; - glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name); + glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name); #if !LL_DARWIN - if (size > 0) - { - switch(type) - { - case GL_FLOAT_VEC2: size *= 2; break; - case GL_FLOAT_VEC3: size *= 3; break; - case GL_FLOAT_VEC4: size *= 4; break; - case GL_DOUBLE: size *= 2; break; - case GL_DOUBLE_VEC2: size *= 2; break; - case GL_DOUBLE_VEC3: size *= 6; break; - case GL_DOUBLE_VEC4: size *= 8; break; - case GL_INT_VEC2: size *= 2; break; - case GL_INT_VEC3: size *= 3; break; - case GL_INT_VEC4: size *= 4; break; - case GL_UNSIGNED_INT_VEC2: size *= 2; break; - case GL_UNSIGNED_INT_VEC3: size *= 3; break; - case GL_UNSIGNED_INT_VEC4: size *= 4; break; - case GL_BOOL_VEC2: size *= 2; break; - case GL_BOOL_VEC3: size *= 3; break; - case GL_BOOL_VEC4: size *= 4; break; - case GL_FLOAT_MAT2: size *= 4; break; - case GL_FLOAT_MAT3: size *= 9; break; - case GL_FLOAT_MAT4: size *= 16; break; - case GL_FLOAT_MAT2x3: size *= 6; break; - case GL_FLOAT_MAT2x4: size *= 8; break; - case GL_FLOAT_MAT3x2: size *= 6; break; - case GL_FLOAT_MAT3x4: size *= 12; break; - case GL_FLOAT_MAT4x2: size *= 8; break; - case GL_FLOAT_MAT4x3: size *= 12; break; - case GL_DOUBLE_MAT2: size *= 8; break; - case GL_DOUBLE_MAT3: size *= 18; break; - case GL_DOUBLE_MAT4: size *= 32; break; - case GL_DOUBLE_MAT2x3: size *= 12; break; - case GL_DOUBLE_MAT2x4: size *= 16; break; - case GL_DOUBLE_MAT3x2: size *= 12; break; - case GL_DOUBLE_MAT3x4: size *= 24; break; - case GL_DOUBLE_MAT4x2: size *= 16; break; - case GL_DOUBLE_MAT4x3: size *= 24; break; - } - mTotalUniformSize += size; - } + if (size > 0) + { + switch(type) + { + case GL_FLOAT_VEC2: size *= 2; break; + case GL_FLOAT_VEC3: size *= 3; break; + case GL_FLOAT_VEC4: size *= 4; break; + case GL_DOUBLE: size *= 2; break; + case GL_DOUBLE_VEC2: size *= 2; break; + case GL_DOUBLE_VEC3: size *= 6; break; + case GL_DOUBLE_VEC4: size *= 8; break; + case GL_INT_VEC2: size *= 2; break; + case GL_INT_VEC3: size *= 3; break; + case GL_INT_VEC4: size *= 4; break; + case GL_UNSIGNED_INT_VEC2: size *= 2; break; + case GL_UNSIGNED_INT_VEC3: size *= 3; break; + case GL_UNSIGNED_INT_VEC4: size *= 4; break; + case GL_BOOL_VEC2: size *= 2; break; + case GL_BOOL_VEC3: size *= 3; break; + case GL_BOOL_VEC4: size *= 4; break; + case GL_FLOAT_MAT2: size *= 4; break; + case GL_FLOAT_MAT3: size *= 9; break; + case GL_FLOAT_MAT4: size *= 16; break; + case GL_FLOAT_MAT2x3: size *= 6; break; + case GL_FLOAT_MAT2x4: size *= 8; break; + case GL_FLOAT_MAT3x2: size *= 6; break; + case GL_FLOAT_MAT3x4: size *= 12; break; + case GL_FLOAT_MAT4x2: size *= 8; break; + case GL_FLOAT_MAT4x3: size *= 12; break; + case GL_DOUBLE_MAT2: size *= 8; break; + case GL_DOUBLE_MAT3: size *= 18; break; + case GL_DOUBLE_MAT4: size *= 32; break; + case GL_DOUBLE_MAT2x3: size *= 12; break; + case GL_DOUBLE_MAT2x4: size *= 16; break; + case GL_DOUBLE_MAT3x2: size *= 12; break; + case GL_DOUBLE_MAT3x4: size *= 24; break; + case GL_DOUBLE_MAT4x2: size *= 16; break; + case GL_DOUBLE_MAT4x3: size *= 24; break; + } + mTotalUniformSize += size; + } #endif - S32 location = glGetUniformLocationARB(mProgramObject, name); - if (location != -1) - { - //chop off "[0]" so we can always access the first element - //of an array by the array name - char* is_array = strstr(name, "[0]"); - if (is_array) - { - is_array[0] = 0; - } - - LLStaticHashedString hashedName(name); - mUniformNameMap[location] = name; - mUniformMap[hashedName] = location; - - LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; - - //find the index of this uniform - for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++) - { - if ( (mUniform[i] == -1) - && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) - { - //found it - mUniform[i] = location; - mTexture[i] = mapUniformTextureChannel(location, type); - return; - } - } - - if (uniforms != NULL) - { - for (U32 i = 0; i < uniforms->size(); i++) - { - if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) - && ((*uniforms)[i].String() == name)) - { - //found it - mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type); - return; - } - } - } - } + S32 location = glGetUniformLocationARB(mProgramObject, name); + if (location != -1) + { + //chop off "[0]" so we can always access the first element + //of an array by the array name + char* is_array = strstr(name, "[0]"); + if (is_array) + { + is_array[0] = 0; + } + + LLStaticHashedString hashedName(name); + mUniformNameMap[location] = name; + mUniformMap[hashedName] = location; + + LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; + + //find the index of this uniform + for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++) + { + if ( (mUniform[i] == -1) + && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) + { + //found it + mUniform[i] = location; + mTexture[i] = mapUniformTextureChannel(location, type); + return; + } + } + + if (uniforms != NULL) + { + for (U32 i = 0; i < uniforms->size(); i++) + { + if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) + && ((*uniforms)[i].String() == name)) + { + //found it + mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; + mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type); + return; + } + } + } + } } void LLGLSLShader::addPermutation(std::string name, std::string value) { - mDefines[name] = value; + mDefines[name] = value; } void LLGLSLShader::removePermutation(std::string name) { - mDefines[name].erase(); + mDefines[name].erase(); } GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { - if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) || - type == GL_SAMPLER_2D_MULTISAMPLE) - { //this here is a texture - glUniform1iARB(location, mActiveTextureChannels); - LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; - return mActiveTextureChannels++; - } - return -1; + if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) || + type == GL_SAMPLER_2D_MULTISAMPLE) + { //this here is a texture + glUniform1iARB(location, mActiveTextureChannels); + LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; + return mActiveTextureChannels++; + } + return -1; } BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms) { - BOOL res = TRUE; - - mTotalUniformSize = 0; - mActiveTextureChannels = 0; - mUniform.clear(); - mUniformMap.clear(); - mUniformNameMap.clear(); - mTexture.clear(); - mValue.clear(); - //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - - bind(); - - //get the number of active uniforms - GLint activeCount; - glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); - - for (S32 i = 0; i < activeCount; i++) - { - mapUniform(i, uniforms); - } - - unbind(); - - LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; - return res; + BOOL res = TRUE; + + mTotalUniformSize = 0; + mActiveTextureChannels = 0; + mUniform.clear(); + mUniformMap.clear(); + mUniformNameMap.clear(); + mTexture.clear(); + mValue.clear(); + //initialize arrays + U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); + mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + + bind(); + + //get the number of active uniforms + GLint activeCount; + glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); + + for (S32 i = 0; i < activeCount; i++) + { + mapUniform(i, uniforms); + } + + unbind(); + + LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; + return res; } BOOL LLGLSLShader::link(BOOL suppress_errors) { - BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); + BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); - if (!suppress_errors) - { + if (!suppress_errors) + { LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName); - } + } - return success; + return success; } void LLGLSLShader::bind() { - gGL.flush(); - if (gGLManager.mHasShaderObjects) - { - LLVertexBuffer::unbind(); - glUseProgramObjectARB(mProgramObject); - sCurBoundShader = mProgramObject; - sCurBoundShaderPtr = this; - if (mUniformsDirty) - { - LLShaderMgr::instance()->updateShaderUniforms(this); - mUniformsDirty = FALSE; - } - } + gGL.flush(); + if (gGLManager.mHasShaderObjects) + { + LLVertexBuffer::unbind(); + glUseProgramObjectARB(mProgramObject); + sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; + if (mUniformsDirty) + { + LLShaderMgr::instance()->updateShaderUniforms(this); + mUniformsDirty = FALSE; + } + } } void LLGLSLShader::unbind() { - gGL.flush(); - if (gGLManager.mHasShaderObjects) - { - stop_glerror(); - if (gGLManager.mIsNVIDIA) - { - for (U32 i = 0; i < mAttribute.size(); ++i) - { - vertexAttrib4f(i, 0,0,0,1); - stop_glerror(); - } - } - LLVertexBuffer::unbind(); - glUseProgramObjectARB(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; - stop_glerror(); - } + gGL.flush(); + if (gGLManager.mHasShaderObjects) + { + stop_glerror(); + if (gGLManager.mIsNVIDIA) + { + for (U32 i = 0; i < mAttribute.size(); ++i) + { + vertexAttrib4f(i, 0,0,0,1); + stop_glerror(); + } + } + LLVertexBuffer::unbind(); + glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; + stop_glerror(); + } } void LLGLSLShader::bindNoShader(void) { - LLVertexBuffer::unbind(); - if (gGLManager.mHasShaderObjects) - { - glUseProgramObjectARB(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; - } + LLVertexBuffer::unbind(); + if (gGLManager.mHasShaderObjects) + { + glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; + } } S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode) { - S32 channel = 0; - channel = getUniformLocation(uniform); - - return bindTexture(channel, texture, mode); + S32 channel = 0; + channel = getUniformLocation(uniform); + + return bindTexture(channel, texture, mode); } S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode) { - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - - uniform = mTexture[uniform]; - - if (uniform > -1) - { - gGL.getTexUnit(uniform)->bind(texture, mode); - } - - return uniform; + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->bind(texture, mode); + } + + return uniform; } S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode) { - S32 channel = 0; - channel = getUniformLocation(uniform); - - return unbindTexture(channel); + S32 channel = 0; + channel = getUniformLocation(uniform); + + return unbindTexture(channel); } S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) { - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - - uniform = mTexture[uniform]; - - if (uniform > -1) - { - gGL.getTexUnit(uniform)->unbind(mode); - } - - return uniform; + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + + uniform = mTexture[uniform]; + + if (uniform > -1) + { + gGL.getTexUnit(uniform)->unbind(mode); + } + + return uniform; } S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) { - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - S32 index = mTexture[uniform]; - if (index != -1) - { - gGL.getTexUnit(index)->activate(); - gGL.getTexUnit(index)->enable(mode); - } - return index; + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + S32 index = mTexture[uniform]; + if (index != -1) + { + gGL.getTexUnit(index)->activate(); + gGL.getTexUnit(index)->enable(mode); + } + return index; } S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { - if (uniform < 0 || uniform >= (S32)mTexture.size()) - { - UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; - return -1; - } - S32 index = mTexture[uniform]; - if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) - { - if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) - { - if (gDebugSession) - { - gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; - ll_fail("LLGLSLShader::disableTexture failed"); - } - else - { - LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; - } - } - gGL.getTexUnit(index)->disable(); - } - return index; + if (uniform < 0 || uniform >= (S32)mTexture.size()) + { + UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; + return -1; + } + S32 index = mTexture[uniform]; + if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) + { + if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) + { + if (gDebugSession) + { + gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + ll_fail("LLGLSLShader::disableTexture failed"); + } + else + { + LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; + } + } + gGL.getTexUnit(index)->disable(); + } + return index; } void LLGLSLShader::uniform1i(U32 index, GLint x) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - if (iter == mValue.end() || iter->second.mV[0] != x) - { - glUniform1iARB(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1iARB(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); + } + } + } } void LLGLSLShader::uniform1f(U32 index, GLfloat x) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - if (iter == mValue.end() || iter->second.mV[0] != x) - { - glUniform1fARB(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1fARB(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); + } + } + } } void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform2fARB(mUniform[index], x, y); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(x,y,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform2fARB(mUniform[index], x, y); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,z,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform3fARB(mUniform[index], x, y, z); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(x,y,z,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform3fARB(mUniform[index], x, y, z); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,z,w); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform4fARB(mUniform[index], x, y, z, w); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(x,y,z,w); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform4fARB(mUniform[index], x, y, z, w); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform1ivARB(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0],0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform1ivARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform1fvARB(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0],0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform1fvARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform2fvARB(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0],v[1],0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform2fvARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],v[2],0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform3fvARB(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0],v[1],v[2],0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform3fvARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],v[2],v[3]); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform4fvARB(mUniform[index], count, v); - mValue[mUniform[index]] = vec; - } - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + LLVector4 vec(v[0],v[1],v[2],v[3]); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform4fvARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } } void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix2fvARB(mUniform[index], count, transpose, v); - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix2fvARB(mUniform[index], count, transpose, v); + } + } } void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix3fvARB(mUniform[index], count, transpose, v); - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix3fvARB(mUniform[index], count, transpose, v); + } + } } void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) { - if (mProgramObject > 0) - { - if (mUniform.size() <= index) - { - UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix4fvARB(mUniform[index], count, transpose, v); - } - } + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix4fvARB(mUniform[index], count, transpose, v); + } + } } GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) { - GLint ret = -1; - if (mProgramObject > 0) - { - LLStaticStringTable<GLint>::iterator iter = mUniformMap.find(uniform); - if (iter != mUniformMap.end()) - { - if (gDebugGL) - { - stop_glerror(); - if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str())) - { - LL_ERRS() << "Uniform does not match." << LL_ENDL; - } - stop_glerror(); - } - ret = iter->second; - } - } - - return ret; + GLint ret = -1; + if (mProgramObject > 0) + { + LLStaticStringTable<GLint>::iterator iter = mUniformMap.find(uniform); + if (iter != mUniformMap.end()) + { + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str())) + { + LL_ERRS() << "Uniform does not match." << LL_ENDL; + } + stop_glerror(); + } + ret = iter->second; + } + } + + return ret; } GLint LLGLSLShader::getUniformLocation(U32 index) { - GLint ret = -1; - if (mProgramObject > 0) - { - llassert(index < mUniform.size()); - return mUniform[index]; - } - - return ret; + GLint ret = -1; + if (mProgramObject > 0) + { + llassert(index < mUniform.size()); + return mUniform[index]; + } + + return ret; } GLint LLGLSLShader::getAttribLocation(U32 attrib) { - if (attrib < mAttribute.size()) - { - return mAttribute[attrib]; - } - else - { - return -1; - } + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } } void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(v,0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform1iARB(location, v); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v,0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform1iARB(location, v); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(i,j,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform2iARB(location, i, j); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(i,j,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform2iARB(location, i, j); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(v,0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform1fARB(location, v); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v,0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform1fARB(location, v); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(x,y,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform2fARB(location, x,y); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(x,y,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform2fARB(location, x,y); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(x,y,z,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) - { - glUniform3fARB(location, x,y,z); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(x,y,z,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform3fARB(location, x,y,z); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform1fvARB(location, count, v); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v[0],0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform1fvARB(location, count, v); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(v[0],v[1],0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform2fvARB(location, count, v); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v[0],v[1],0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform2fvARB(location, count, v); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - LLVector4 vec(v[0],v[1],v[2],0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - glUniform3fvARB(location, count, v); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v[0],v[1],v[2],0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + glUniform3fvARB(location, count, v); + mValue[location] = vec; + } + } } void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - LLVector4 vec(v); - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) - { - stop_glerror(); - glUniform4fvARB(location, count, v); - stop_glerror(); - mValue[location] = vec; - } - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + LLVector4 vec(v); + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + { + stop_glerror(); + glUniform4fvARB(location, count, v); + stop_glerror(); + mValue[location] = vec; + } + } } void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v) { - GLint location = getUniformLocation(uniform); - - if (location >= 0) - { - stop_glerror(); - glUniformMatrix4fvARB(location, count, transpose, v); - stop_glerror(); - } + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + stop_glerror(); + glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); + } } void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - if (mAttribute[index] > 0) - { - glVertexAttrib4fARB(mAttribute[index], x, y, z, w); - } + if (mAttribute[index] > 0) + { + glVertexAttrib4fARB(mAttribute[index], x, y, z, w); + } } void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) { - if (mAttribute[index] > 0) - { - glVertexAttrib4fvARB(mAttribute[index], v); - } + if (mAttribute[index] > 0) + { + glVertexAttrib4fvARB(mAttribute[index], v); + } } void LLGLSLShader::setMinimumAlpha(F32 minimum) { - gGL.flush(); - uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); + gGL.flush(); + uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 388d3a4f1a..0af402efea 100755 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1168,7 +1168,7 @@ void LLRender::syncMatrices() { stop_glerror(); - U32 name[] = + static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, LLShaderMgr::PROJECTION_MATRIX, diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index a89ec675b4..b2be3cc3b6 100755 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -674,12 +674,17 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (defines) { for (boost::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) - { - std::string define = "#define " + iter->first + " " + iter->second + "\n"; - text[count++] = (GLcharARB *) strdup(define.c_str()); - } + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); + } } + if( gGLManager.mIsATI ) + { + text[ count++ ] = strdup( "#define IS_AMD_CARD 1\n" ); + } + if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) { //use specified number of texture channels for indexed texture rendering diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index d06564df36..0fae600a90 100755 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -843,9 +843,11 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { LL_RECORD_BLOCK_TIME(FTM_GL_DRAW_ARRAYS); stop_glerror(); - LLGLSLShader::startProfile(); + LLGLSLShader::startProfile(); + stop_glerror(); glDrawArrays(sGLMode[mode], first, count); - LLGLSLShader::stopProfile(count, mode); + stop_glerror(); + LLGLSLShader::stopProfile(count, mode); } stop_glerror(); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 8e5f0b97f5..f2bb71c53b 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -260,20 +260,19 @@ BOOL LLFolderViewItem::passedFilter(S32 filter_generation) BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) { - // Item should be visible if: - // 1. item passed current filter - // 2. item was updated (gen < 0) but has descendants that passed filter - // 3. item was recently updated and was visible before update - - LLFolderViewModelItem* model = getViewModelItem(); - if (model->getLastFilterGeneration() < 0 && !getFolderViewModel()->getFilter().isModified()) + if (filter_generation < 0) { - return model->descendantsPassedFilter(filter_generation) || getVisible(); + filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); } - else + LLFolderViewModelItem* model = getViewModelItem(); + BOOL visible = model->passedFilter(filter_generation); + if (model->getMarkedDirtyGeneration() >= filter_generation) { - return model->passedFilter(filter_generation); + // unsure visibility state + // retaining previous visibility until item is updated or filter generation changes + visible |= getVisible(); } + return visible; } void LLFolderViewItem::refresh() diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 99c7c4013c..d60e36183b 100755 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -187,11 +187,13 @@ public: virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0; virtual void dirtyFilter() = 0; + virtual void dirtyDescendantsFilter() = 0; virtual bool hasFilterStringMatch() = 0; virtual std::string::size_type getFilterStringOffset() = 0; virtual std::string::size_type getFilterStringSize() = 0; virtual S32 getLastFilterGeneration() const = 0; + virtual S32 getMarkedDirtyGeneration() const = 0; virtual bool hasChildren() const = 0; virtual void addChild(LLFolderViewModelItem* child) = 0; @@ -232,6 +234,7 @@ public: mFolderViewItem(NULL), mLastFilterGeneration(-1), mLastFolderFilterGeneration(-1), + mMarkedDirtyGeneration(-1), mMostFilteredDescendantGeneration(-1), mParent(NULL), mRootViewModel(root_view_model) @@ -245,8 +248,13 @@ public: S32 getLastFilterGeneration() const { return mLastFilterGeneration; } S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } + S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } void dirtyFilter() { + if(mMarkedDirtyGeneration < 0) + { + mMarkedDirtyGeneration = mLastFilterGeneration; + } mLastFilterGeneration = -1; mLastFolderFilterGeneration = -1; @@ -256,6 +264,14 @@ public: mParent->dirtyFilter(); } } + void dirtyDescendantsFilter() + { + mMostFilteredDescendantGeneration = -1; + if (mParent) + { + mParent->dirtyDescendantsFilter(); + } + } bool hasFilterStringMatch(); std::string::size_type getFilterStringOffset(); std::string::size_type getFilterStringSize(); @@ -274,7 +290,7 @@ public: return; } } - mChildren.push_back(child); + mChildren.push_back(child); child->setParent(this); dirtyFilter(); requestSort(); @@ -282,7 +298,8 @@ public: virtual void removeChild(LLFolderViewModelItem* child) { mChildren.remove(child); - child->setParent(NULL); + child->setParent(NULL); + dirtyDescendantsFilter(); dirtyFilter(); } @@ -292,6 +309,7 @@ public: // This is different and not equivalent to calling removeChild() on each child std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); mChildren.clear(); + dirtyDescendantsFilter(); dirtyFilter(); } @@ -305,6 +323,7 @@ public: mLastFilterGeneration = filter_generation; mStringMatchOffsetFilter = string_offset; mStringFilterSize = string_size; + mMarkedDirtyGeneration = -1; } void setPassedFolderFilter(bool passed, S32 filter_generation) @@ -353,7 +372,8 @@ protected: S32 mLastFilterGeneration, mLastFolderFilterGeneration, - mMostFilteredDescendantGeneration; + mMostFilteredDescendantGeneration, + mMarkedDirtyGeneration; child_list_t mChildren; LLFolderViewModelItem* mParent; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 75773d7dfd..6750ee482a 100755 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -505,7 +505,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } // Skip white space - while( *cur && isspace(*cur) && (*cur != '\n') ) + while( *cur && iswspace(*cur) && (*cur != '\n') ) { cur++; } @@ -548,7 +548,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } // Skip white space - while( *cur && isspace(*cur) && (*cur != '\n') ) + while( *cur && iswspace(*cur) && (*cur != '\n') ) { cur++; } @@ -655,10 +655,10 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW // check against words llwchar prev = cur > base ? *(cur-1) : 0; - if( !isalnum( prev ) && (prev != '_') ) + if( !iswalnum( prev ) && (prev != '_') ) { const llwchar* p = cur; - while( isalnum( *p ) || (*p == '_') ) + while( iswalnum( *p ) || (*p == '_') ) { p++; } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 604dc92789..d3ed4a1286 100755 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1276,7 +1276,15 @@ void LLMenuItemBranchGL::openMenu() { // open upwards if menu extends past bottom // adjust by the height of the menu item branch since it is a submenu - delta_y = branch_rect.getHeight() - getRect().getHeight(); + if (y + 2 * branch_rect.getHeight() - getRect().getHeight() > menu_region_rect.mTop) + { + // overlaps with top border, align with top + delta_y = menu_region_rect.mTop - y - branch_rect.getHeight(); + } + else + { + delta_y = branch_rect.getHeight() - getRect().getHeight(); + } } if( x + branch_rect.getWidth() > menu_region_rect.mRight ) @@ -3258,6 +3266,11 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect ); + if (menu->getRect().mTop > menu_region_rect.mTop) + { + // not enough space: align with top, ignore exclusion + menu->translateIntoRect( menu_region_rect ); + } menu->getParent()->sendChildToFront(menu); } diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 1bd2bc06f4..303417c337 100755 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -638,7 +638,7 @@ void LLStatBar::drawLabelAndValue( F32 value, std::string &label, LLRect &bar_re void LLStatBar::drawTicks( F32 min, F32 max, F32 value_scale, LLRect &bar_rect ) { - if (mAutoScaleMax || mAutoScaleMin) + if (!llisnan(min) && (mAutoScaleMax || mAutoScaleMin)) { F32 u = LLSmoothInterpolation::getInterpolant(10.f); mFloatingTargetMinBar = llmin(min, lerp(mFloatingTargetMinBar, min, u)); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 6f3122e7a1..be583c83d8 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -178,6 +178,12 @@ bool LLUrlEntryBase::isLinkDisabled() const return globally_disabled; } +bool LLUrlEntryBase::isWikiLinkCorrect(std::string url) +{ + std::string label = getLabelFromWikiLink(url); + return (LLUrlRegistry::instance().hasUrl(label)) ? false : true; +} + static std::string getStringAfterToken(const std::string str, const std::string token) { size_t pos = str.find(token); diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index d4684e2e1e..ffcd45dfde 100755 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -100,6 +100,8 @@ public: bool isLinkDisabled() const; + bool isWikiLinkCorrect(std::string url); + protected: std::string getIDStringFromUrl(const std::string &url) const; std::string escapeUrl(const std::string &url) const; diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index bccc646821..ef0789e0e4 100755 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -45,7 +45,8 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(mUrlEntryIcon); registerUrl(new LLUrlEntrySLURL()); registerUrl(new LLUrlEntryHTTP()); - registerUrl(new LLUrlEntryHTTPLabel()); + mUrlEntryHTTPLabel = new LLUrlEntryHTTPLabel(); + registerUrl(mUrlEntryHTTPLabel); registerUrl(new LLUrlEntryAgentCompleteName()); registerUrl(new LLUrlEntryAgentDisplayName()); registerUrl(new LLUrlEntryAgentUserName()); @@ -64,7 +65,8 @@ LLUrlRegistry::LLUrlRegistry() //LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern, //so it should be registered in the end of list registerUrl(new LLUrlEntrySL()); - registerUrl(new LLUrlEntrySLLabel()); + mUrlEntrySLLabel = new LLUrlEntrySLLabel(); + registerUrl(mUrlEntrySLLabel); // most common pattern is a URL without any protocol, // e.g., "secondlife.com" registerUrl(new LLUrlEntryHTTPNoProtocol()); @@ -128,6 +130,11 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en end--; } + else if (text[end] == ']' && std::string(text+start, end-start).find('[') == std::string::npos) + { + end--; + } + return true; } @@ -175,6 +182,15 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL // does this match occur in the string before any other match if (start < match_start || match_entry == NULL) { + + if((mUrlEntryHTTPLabel == *it) || (mUrlEntrySLLabel == *it)) + { + if(url_entry && !url_entry->isWikiLinkCorrect(text.substr(start, end - start + 1))) + { + continue; + } + } + match_start = start; match_end = end; match_entry = url_entry; diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 6270df1bbb..1cb403dfc9 100755 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -94,6 +94,8 @@ private: std::vector<LLUrlEntryBase *> mUrlEntry; LLUrlEntryBase* mUrlEntryIcon; + LLUrlEntryBase* mUrlEntryHTTPLabel; + LLUrlEntryBase* mUrlEntrySLLabel; }; #endif diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 77c8878f4b..9e6bebc93b 100755 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -885,7 +885,7 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) handled = handleKeyHere( key, mask ); if (handled) { - LL_WARNS() << "Key handled by " << getName() << LL_ENDL; + LL_DEBUGS() << "Key handled by " << getName() << LL_ENDL; } } } diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index f1fab3b2c6..072d40f739 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -79,6 +79,7 @@ @interface LLNonInlineTextView : NSTextView { LLOpenGLView *glview; + unichar mKeyPressed; } - (void) setGLView:(LLOpenGLView*)view; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index f7031341eb..24b8406098 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -104,26 +104,34 @@ attributedStringInfo getSegments(NSAttributedString *str) - (unsigned long)getVramSize { CGLRendererInfoObj info = 0; - GLint vram_bytes = 0; + GLint vram_mbytes = 0; int num_renderers = 0; CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers); if(0 == the_err) { - CGLDescribeRenderer (info, 0, kCGLRPTextureMemory, &vram_bytes); + CGLDescribeRenderer (info, 0, kCGLRPTextureMemoryMegabytes, &vram_mbytes); CGLDestroyRendererInfo (info); } else { - vram_bytes = (256 << 20); + vram_mbytes = 256; } - return (unsigned long)vram_bytes / 1048576; // We need this in megabytes. + return (unsigned long)vram_mbytes; } - (void)viewDidMoveToWindow { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResized:) name:NSWindowDidResizeNotification + object:[self window]]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification + object:[self window]]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:[self window]]; } @@ -141,6 +149,16 @@ attributedStringInfo getSegments(NSAttributedString *str) } } +- (void)windowWillMiniaturize:(NSNotification *)notification; +{ + callWindowHide(); +} + +- (void)windowDidDeminiaturize:(NSNotification *)notification; +{ + callWindowUnhide(); +} + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -270,14 +288,14 @@ attributedStringInfo getSegments(NSAttributedString *str) !([theEvent modifierFlags] & NSFunctionKeyMask) && !([theEvent modifierFlags] & NSHelpKeyMask)) { - callRightMouseDown(mMousePos, mModifiers); + callRightMouseDown(mMousePos, [theEvent modifierFlags]); mSimulatedRightClick = true; } else { if ([theEvent clickCount] >= 2) { - callDoubleClick(mMousePos, mModifiers); + callDoubleClick(mMousePos, [theEvent modifierFlags]); } else if ([theEvent clickCount] == 1) { - callLeftMouseDown(mMousePos, mModifiers); + callLeftMouseDown(mMousePos, [theEvent modifierFlags]); } } } @@ -286,21 +304,21 @@ attributedStringInfo getSegments(NSAttributedString *str) { if (mSimulatedRightClick) { - callRightMouseUp(mMousePos, mModifiers); + callRightMouseUp(mMousePos, [theEvent modifierFlags]); mSimulatedRightClick = false; } else { - callLeftMouseUp(mMousePos, mModifiers); + callLeftMouseUp(mMousePos, [theEvent modifierFlags]); } } - (void) rightMouseDown:(NSEvent *)theEvent { - callRightMouseDown(mMousePos, mModifiers); + callRightMouseDown(mMousePos, [theEvent modifierFlags]); } - (void) rightMouseUp:(NSEvent *)theEvent { - callRightMouseUp(mMousePos, mModifiers); + callRightMouseUp(mMousePos, [theEvent modifierFlags]); } - (void)mouseMoved:(NSEvent *)theEvent @@ -341,17 +359,22 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) otherMouseDown:(NSEvent *)theEvent { - callMiddleMouseDown(mMousePos, mModifiers); + callMiddleMouseDown(mMousePos, [theEvent modifierFlags]); } - (void) otherMouseUp:(NSEvent *)theEvent { - callMiddleMouseUp(mMousePos, mModifiers); + callMiddleMouseUp(mMousePos, [theEvent modifierFlags]); +} + +- (void) rightMouseDragged:(NSEvent *)theEvent +{ + [self mouseDragged:theEvent]; } - (void) otherMouseDragged:(NSEvent *)theEvent { - + [self mouseDragged:theEvent]; } - (void) scrollWheel:(NSEvent *)theEvent @@ -366,22 +389,27 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) keyUp:(NSEvent *)theEvent { - callKeyUp([theEvent keyCode], mModifiers); + callKeyUp([theEvent keyCode], [theEvent modifierFlags]); } - (void) keyDown:(NSEvent *)theEvent { uint keycode = [theEvent keyCode]; + // We must not depend on flagsChange event to detect modifier flags changed, + // must depend on the modifire flags in the event parameter. + // Because flagsChange event handler misses event when other window is activated, + // e.g. OS Window for upload something or Input Window... + // mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit) + mModifiers = [theEvent modifierFlags]; bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers); + unichar ch; if (acceptsText && !mMarkedTextAllowed && + !(mModifiers & (NSControlKeyMask | NSCommandKeyMask)) && // commands don't invoke InputWindow ![(LLAppDelegate*)[NSApp delegate] romanScript] && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDownArrowFunctionKey && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSUpArrowFunctionKey && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSLeftArrowFunctionKey && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSRightArrowFunctionKey) + (ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]) > ' ' && + ch != NSDeleteCharacter && + (ch < 0xF700 || ch > 0xF8FF)) // 0xF700-0xF8FF: reserved for function keys on the keyboard(from NSEvent.h) { [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; } else @@ -498,31 +526,58 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { - if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) + // Apple says aString can be either an NSString or NSAttributedString instance. + // But actually it's NSConcreteMutableAttributedString or __NSCFConstantString. + // I observed aString was __NSCFConstantString only aString was null string(zero length). + // Apple also says when aString is an NSString object, + // the receiver is expected to render the marked text with distinguishing appearance. + // So I tried to make attributedStringInfo, but it won't be used... (Pell Smit) + + if (mMarkedTextAllowed) { - if (mMarkedTextAllowed) + unsigned int selected[2] = { + selectedRange.location, + selectedRange.length + }; + + unsigned int replacement[2] = { + replacementRange.location, + replacementRange.length + }; + + int string_length = [aString length]; + unichar text[string_length]; + attributedStringInfo segments; + // I used 'respondsToSelector:@selector(string)' + // to judge aString is an attributed string or not. + if ([aString respondsToSelector:@selector(string)]) + { + // aString is attibuted + [[aString string] getCharacters:text range:NSMakeRange(0, string_length)]; + segments = getSegments((NSAttributedString *)aString); + } + else + { + // aString is not attributed + [aString getCharacters:text range:NSMakeRange(0, string_length)]; + segments.seg_lengths.push_back(string_length); + segments.seg_standouts.push_back(true); + } + setMarkedText(text, selected, replacement, string_length, segments); + if (string_length > 0) { - unsigned int selected[2] = { - selectedRange.location, - selectedRange.length - }; - - unsigned int replacement[2] = { - replacementRange.location, - replacementRange.length - }; - - unichar text[[aString length]]; - [[aString mutableString] getCharacters:text range:NSMakeRange(0, [aString length])]; - attributedStringInfo segments = getSegments((NSAttributedString *)aString); - setMarkedText(text, selected, replacement, [aString length], segments); mHasMarkedText = TRUE; - mMarkedTextLength = [aString length]; - } else { - if (mHasMarkedText) - { - [self unmarkText]; - } + mMarkedTextLength = string_length; + } + else + { + // we must clear the marked text when aString is null. + [self unmarkText]; + } + } else { + if (mHasMarkedText) + { + [self unmarkText]; } } } @@ -641,37 +696,63 @@ attributedStringInfo getSegments(NSAttributedString *str) @implementation LLNonInlineTextView +/* Input Window is a legacy of 20 century, so we want to remove related classes. + But unfortunately, Viwer web browser has no support for modern inline input, + we need to leave these classes... + We will be back to get rid of Input Window after fixing viewer web browser. + + How Input Window should work: + 1) Input Window must not be empty. + It must close when it become empty result of edithing. + 2) Input Window must not close when it still has input data. + It must keep open user types next char before commit. by Pell Smit +*/ + - (void) setGLView:(LLOpenGLView *)view { glview = view; } -- (void) insertText:(id)insertString +- (void)keyDown:(NSEvent *)theEvent { - [[self inputContext] discardMarkedText]; - [self setString:@""]; - [_window orderOut:_window]; - [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])]; + // mKeyPressed is used later to determine whethere Input Window should close or not + mKeyPressed = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + // setMarkedText and insertText is called indirectly from inside keyDown: method + [super keyDown:theEvent]; } -- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange +// setMarkedText: is called for incomplete input(on the way to conversion). +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { - [glview insertText:aString replacementRange:replacementRange]; + [super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange]; + if ([aString length] == 0) // this means Input Widow becomes empty + { + [_window orderOut:_window]; // Close this to avoid empty Input Window + } } -- (void) insertNewline:(id)sender +// insertText: is called for inserting commited text. +// There are two ways to be called here: +// a) explicitly commited (must close) +// In case of user typed commit key(usually return key) or delete key or something +// b) automatically commited (must not close) +// In case of user typed next letter after conversion +- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange { - [[self textStorage] setValue:@""]; - [[self inputContext] discardMarkedText]; + [[self inputContext] discardMarkedText]; [self setString:@""]; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - if (aSelector == @selector(insertNewline:)) - { - [self insertNewline:self]; - } + [glview insertText:aString replacementRange:replacementRange]; + if (mKeyPressed == NSEnterCharacter || + mKeyPressed == NSBackspaceCharacter || + mKeyPressed == NSTabCharacter || + mKeyPressed == NSNewlineCharacter || + mKeyPressed == NSCarriageReturnCharacter || + mKeyPressed == NSDeleteCharacter || + (mKeyPressed >= 0xF700 && mKeyPressed <= 0xF8FF)) + { + // this is case a) of above comment + [_window orderOut:_window]; // to avoid empty Input Window + } } @end diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index d64525fbdd..f02052ca6a 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -116,6 +116,8 @@ void callScrollMoved(float delta); void callMouseExit(); void callWindowFocus(); void callWindowUnfocus(); +void callWindowHide(); +void callWindowUnhide(); void callDeltaUpdate(float *delta, unsigned int mask); void callMiddleMouseDown(float *pos, unsigned int mask); void callMiddleMouseUp(float *pos, unsigned int mask); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 18d5152015..d7aa47f378 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -230,7 +230,10 @@ void callFocus() void callFocusLost() { - gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); + } } void callRightMouseDown(float *pos, MASK mask) @@ -349,6 +352,22 @@ void callWindowUnfocus() gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); } +void callWindowHide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false); + } +} + +void callWindowUnhide() +{ + if ( gWindowImplementation && gWindowImplementation->getCallbacks() ) + { + gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true); + } +} + void callDeltaUpdate(float *delta, MASK mask) { gWindowImplementation->updateMouseDeltas(delta); @@ -1805,8 +1824,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) { - allowDirectMarkedTextInput(b, mGLView); - if (preeditor != mPreeditor && !b) { // This condition may occur by a call to @@ -1836,6 +1853,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) return; } mLanguageTextInputAllowed = b; + allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit } void LLWindowMacOSX::interruptLanguageTextInput() diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index c6cff55cf7..f36181278b 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.21 +3.7.24 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 287dd5d29e..4a106c08e4 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6182,7 +6182,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>30.0</real> + <real>600.0</real> </map> <key>MemoryPrivatePoolEnabled</key> <map> @@ -13565,6 +13565,28 @@ <key>Value</key> <string>0</string> </map> + <key>VivoxLogDirectory</key> + <map> + <key>Comment</key> + <string>Default log path is Application Support/SecondLife/logs specify alternate absolute path here.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string></string> + </map> + <key>VivoxShutdownTimeout</key> + <map> + <key>Comment</key> + <string>shutdown timeout in miliseconds. The amount of time to wait for the service to shutdown gracefully after the last disconnect</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>5</string> + </map> <key>VivoxDebugSIPURIHostName</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index bc63d07d72..767fad016c 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -40,4 +40,10 @@ mat4 getSkinnedTransform() ret[3] = vec4(0,0,0,1); return ret; + +#ifdef IS_AMD_CARD + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + vec4 dummy1 = matrixPalette[0]; + vec4 dummy2 = matrixPalette[44]; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 57129c3bd1..6cd38d8ef5 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -63,5 +63,14 @@ mat4 getObjectSkinnedTransform() ret[3] = vec4(trans, 1.0); return ret; + +#ifdef IS_AMD_CARD + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + mat3 dummy1 = matrixPalette[0]; + vec3 dummy2 = translationPalette[0]; + mat3 dummy3 = matrixPalette[51]; + vec3 dummy4 = translationPalette[51]; +#endif + } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index b40785bbd7..506118d381 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -111,10 +111,9 @@ void main() #ifdef USE_INDEXED_TEX passTextureIndex(); - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; -#else - vary_texcoord0 = texcoord0; #endif + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_norm = norm; vary_position = pos.xyz; diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index a4f54dff70..5264d6e1b4 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -132,5 +132,11 @@ void main() col.y *= col.y; frag_color = col; + +#ifdef IS_AMD_CARD + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + vec3 dummy1 = kern[0]; + vec3 dummy2 = kern[3]; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 236567219b..1a464fec5d 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -161,4 +161,12 @@ void main() frag_color.rgb = out_col; frag_color.a = 0.0; + +#ifdef IS_AMD_CARD + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + vec4 dummy1 = light[0]; + vec4 dummy2 = light_col[0]; + vec4 dummy3 = light[LIGHT_COUNT-1]; + vec4 dummy4 = light_col[LIGHT_COUNT-1]; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 0e6ab80d4d..c08e9d361a 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -127,13 +127,17 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) vec4 ret = texture2DLod(projectionMap, tc, lod); ret.rgb = srgb_to_linear(ret.rgb); - vec2 dist = tc-vec2(0.5); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); - float det = max(1.0-lod/(proj_lod*0.5), 0.0); + float det = min(lod/(proj_lod*0.5), 1.0); - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + float d = min(dist.x, dist.y); + + d *= min(1, d * (proj_lod - lod)); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -311,19 +315,17 @@ void main() vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - stc /= stc.w; + if (stc.z > 0.0) { - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); - - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + stc /= stc.w; if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * envIntensity; } } } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 96f9628424..018ced4cad 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -99,4 +99,10 @@ void main() col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z; frag_color.rgb = col; + +#ifdef IS_AMD_CARD + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + vec2 dummy1 = kern[0]; + vec2 dummy2 = kern[31]; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 8d8a6c9dde..f50635a139 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -130,15 +130,19 @@ vec4 correctWithGamma(vec4 col) vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret.rgb = srgb_to_linear(ret.rgb); - vec2 dist = tc-vec2(0.5); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); - float det = max(1.0-lod/(proj_lod*0.5), 0.0); + float det = min(lod/(proj_lod*0.5), 1.0); - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + float d = min(dist.x, dist.y); + + d *= min(1, d * (proj_lod - lod)); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -322,19 +326,14 @@ void main() if (stc.z > 0.0) { - stc.xy /= stc.w; - - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); - - //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + stc /= stc.w; if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * envIntensity; } } } diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index c20e00163c..94bd07bec6 100755 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -131,15 +131,19 @@ vec4 correctWithGamma(vec4 col) vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); - - vec2 dist = tc-vec2(0.5); + ret.rgb = srgb_to_linear(ret.rgb); - float det = max(1.0-lod/(proj_lod*0.5), 0.0); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + d *= min(1, d * (proj_lod - lod)); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -334,25 +338,21 @@ void main() vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - stc /= stc.w; if (stc.z > 0.0) { - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.25, 0.25, 1.0); - - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + stc /= stc.w; if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod).rgb*shadow*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; } } } } - //not sure why, but this line prevents MATBUG-194 col = max(col, vec3(0.0)); diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 7689b72d20..92e1ac95a6 100755 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -131,15 +131,19 @@ vec4 correctWithGamma(vec4 col) vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) { vec4 ret = texture2DLod(projectionMap, tc, lod); - ret = correctWithGamma(ret); + ret.rgb = srgb_to_linear(ret.rgb); - vec2 dist = tc-vec2(0.5); + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); - float det = max(1.0-lod/(proj_lod*0.5), 0.0); + float det = min(lod/(proj_lod*0.5), 1.0); - float d = dot(dist,dist); - - ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + float d = min(dist.x, dist.y); + + d *= min(1, d * (proj_lod - lod)); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); return ret; } @@ -336,19 +340,14 @@ void main() if (stc.z > 0.0) { - stc.xy /= stc.w; - - float fatten = clamp(envIntensity*envIntensity+envIntensity*0.5, 0.25, 1.0); - - //stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); - stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + stc /= stc.w; if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - col += color.rgb*texture2DLodSpecular(projectionMap, stc.xy, proj_lod-envIntensity*proj_lod).rgb*shadow*spec.rgb; + col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; } } } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 392fe8fc2e..af7b07c26e 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3808,6 +3808,10 @@ void LLAgent::restartFailedTeleportRequest() void LLAgent::clearTeleportRequest() { + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->setHidden(FALSE); + } mTeleportRequest.reset(); } @@ -3826,6 +3830,10 @@ bool LLAgent::hasPendingTeleportRequest() void LLAgent::startTeleportRequest() { + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->setHidden(TRUE); + } if (hasPendingTeleportRequest()) { if (!isMaturityPreferenceSyncedWithServer()) @@ -3877,6 +3885,11 @@ void LLAgent::handleTeleportFinished() void LLAgent::handleTeleportFailed() { + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->setHidden(FALSE); + } + if (mTeleportRequest != NULL) { mTeleportRequest->setStatus(LLTeleportRequest::kFailed); @@ -4122,8 +4135,8 @@ void LLAgent::stopCurrentAnimations() anim_it != gAgentAvatarp->mPlayingAnimations.end(); anim_it++) { - if (anim_it->first == - ANIM_AGENT_SIT_GROUND_CONSTRAINED) + if ((anim_it->first == ANIM_AGENT_DO_NOT_DISTURB)|| + (anim_it->first == ANIM_AGENT_SIT_GROUND_CONSTRAINED)) { // don't cancel a ground-sit anim, as viewers // use this animation's status in diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 49fedb8df8..f06ffb4fb3 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1009,6 +1009,10 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it continue; } + // Don't care about this case - ordering of wearables with the same asset id has no effect. + // Causes the two-alphas error case in MAINT-4158. + // We should actually disallow wearing two wearables with the same asset id. +#if 0 if (curr_wearable->getName() != new_item->getName() || curr_wearable->getItemID() != new_item->getUUID()) { @@ -1019,6 +1023,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it mismatched++; continue; } +#endif // If we got here, everything matches. matched++; } @@ -1083,7 +1088,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it if (isAgentAvatarValid()) { gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); - gAgentAvatarp->updateVisualParams(); // If we have not yet declouded, we may want to use // baked texture UUIDs sent from the first objectUpdate message @@ -1101,6 +1105,12 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it notifyLoadingFinished(); + // Copy wearable params to avatar. + gAgentAvatarp->writeWearablesToAvatar(); + + // Then update the avatar based on the copied params. + gAgentAvatarp->updateVisualParams(); + gAgentAvatarp->dumpAvatarTEs("setWearableOutfit"); LL_DEBUGS("Avatar") << "setWearableOutfit() end" << LL_ENDL; @@ -1243,9 +1253,12 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty } } -// Combines userRemoveMulipleAttachments() and userAttachMultipleAttachments() logic to -// get attachments into desired state with minimal number of adds/removes. -void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array) +// Given a desired set of attachments, find what objects need to be +// removed, and what additional inventory items need to be added. +void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array, + llvo_vec_t& objects_to_remove, + llvo_vec_t& objects_to_retain, + LLInventoryModel::item_array_t& items_to_add) { // Possible cases: // already wearing but not in request set -> take off. @@ -1264,7 +1277,6 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj } // Build up list of objects to be removed and items currently attached. - llvo_vec_t objects_to_remove; for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end();) { @@ -1299,12 +1311,12 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj { // LL_INFOS() << "found object to keep, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << LL_ENDL; current_item_ids.insert(object_item_id); + objects_to_retain.push_back(objectp); } } } } - LLInventoryModel::item_array_t items_to_add; for (LLInventoryModel::item_array_t::iterator it = obj_item_array.begin(); it != obj_item_array.end(); ++it) @@ -1323,12 +1335,6 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj // S32 remove_count = objects_to_remove.size(); // S32 add_count = items_to_add.size(); // LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL; - - // Remove everything in objects_to_remove - userRemoveMultipleAttachments(objects_to_remove); - - // Add everything in items_to_add - userAttachMultipleAttachments(items_to_add); } void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove) @@ -1348,6 +1354,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo ++it) { LLViewerObject *objectp = *it; + //gAgentAvatarp->resetJointPositionsOnDetach(objectp); gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); } diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index cdb1bdbe05..1004482020 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -178,7 +178,10 @@ public: typedef std::vector<LLViewerObject*> llvo_vec_t; - static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array); + static void findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array, + llvo_vec_t& objects_to_remove, + llvo_vec_t& objects_to_retain, + LLInventoryModel::item_array_t& items_to_add); static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 96de15bf75..9d887a61f1 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -34,6 +34,7 @@ #include "llsdutil.h" #include "llviewerregion.h" #include "llinventoryobserver.h" +#include "llviewercontrol.h" ///---------------------------------------------------------------------------- /// Classes for AISv3 support. diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 988058aad3..549df80fa1 100644..100755 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -84,6 +84,16 @@ callWindowUnfocus(); } +- (void) applicationDidHide:(NSNotification *)notification +{ + callWindowHide(); +} + +- (void) applicationDidUnhide:(NSNotification *)notification +{ + callWindowUnhide(); +} + - (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender { if (!runMainLoop()) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 29534a4382..d7ef5fcba7 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -807,15 +807,48 @@ void LLWearableHoldingPattern::onAllComplete() } } - // Update wearables. - LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; - LLAppearanceMgr::instance().updateAgentWearables(this); - - // Update attachments to match those requested. if (isAgentAvatarValid()) { LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.size() << " attachments" << LL_ENDL; - LLAgentWearables::userUpdateAttachments(mObjItems); + LLAgentWearables::llvo_vec_t objects_to_remove; + LLAgentWearables::llvo_vec_t objects_to_retain; + LLInventoryModel::item_array_t items_to_add; + + LLAgentWearables::findAttachmentsAddRemoveInfo(mObjItems, + objects_to_remove, + objects_to_retain, + items_to_add); + + LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size() + << " attachments" << LL_ENDL; + + // Here we remove the attachment pos overrides for *all* + // attachments, even those that are not being removed. This is + // needed to get joint positions all slammed down to their + // pre-attachment states. + gAgentAvatarp->clearAttachmentPosOverrides(); + + // Take off the attachments that will no longer be in the outfit. + LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); + + // Update wearables. + LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " + << mResolved << " wearable items " << LL_ENDL; + LLAppearanceMgr::instance().updateAgentWearables(this); + + // Restore attachment pos overrides for the attachments that + // are remaining in the outfit. + for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); + it != objects_to_retain.end(); + ++it) + { + LLViewerObject *objectp = *it; + gAgentAvatarp->addAttachmentPosOverridesForObject(objectp); + } + + // Add new attachments to match those requested. + LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL; + LLAgentWearables::userAttachMultipleAttachments(items_to_add); } if (isFetchCompleted() && isMissingCompleted()) @@ -2699,7 +2732,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInve const LLInventoryItem* item = item_array.at(i).get(); if (item->getIsLinkType() && item->getLinkedUUID() == item_id) { - remove_inventory_item(item->getUUID(), cb); + bool immediate_delete = false; + if (item->getType() == LLAssetType::AT_OBJECT) + { + immediate_delete = true; + } + remove_inventory_item(item->getUUID(), cb, immediate_delete); } } } @@ -4056,17 +4094,33 @@ public: bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { - LLPointer<LLInventoryCategory> category = new LLInventoryCategory(query_map["folder_id"], - LLUUID::null, - LLFolderType::FT_CLOTHING, - "Quick Appearance"); - LLSD::UUID folder_uuid = query_map["folder_id"].asUUID(); - if ( gInventory.getCategory( folder_uuid ) != NULL ) - { - LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false); + LLSD::UUID folder_uuid; - // *TODOw: This may not be necessary if initial outfit is chosen already -- josh - gAgent.setOutfitChosen(TRUE); + if (folder_uuid.isNull() && query_map.has("folder_name")) + { + std::string outfit_folder_name = query_map["folder_name"]; + folder_uuid = findDescendentCategoryIDByName( + gInventory.getLibraryRootFolderID(), + outfit_folder_name); + } + if (folder_uuid.isNull() && query_map.has("folder_id")) + { + folder_uuid = query_map["folder_id"].asUUID(); + } + + if (folder_uuid.notNull()) + { + LLPointer<LLInventoryCategory> category = new LLInventoryCategory(folder_uuid, + LLUUID::null, + LLFolderType::FT_CLOTHING, + "Quick Appearance"); + if ( gInventory.getCategory( folder_uuid ) != NULL ) + { + LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false); + + // *TODOw: This may not be necessary if initial outfit is chosen already -- josh + gAgent.setOutfitChosen(TRUE); + } } // release avatar picker keyboard focus diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3a5008507a..f6b6c71cfc 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4896,7 +4896,10 @@ void LLAppViewer::idle() // Handle the regular UI idle callbacks as well as // hover callbacks // - + +#ifdef LL_DARWIN + if (!mQuitRequested) //MAINT-4243 +#endif { // LL_RECORD_BLOCK_TIME(FTM_IDLE_CB); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 5b151bdcda..f74164aea6 100755 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -443,7 +443,7 @@ void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_ } } -void LLRenderPass::applyModelMatrix(LLDrawInfo& params) +void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) { if (params.mModelMatrix != gGLLastMatrix) { diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 3bde0d29be..bc299cc89f 100755 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -168,7 +168,7 @@ public: BOOL isDead() { return FALSE; } void resetDrawOrders() { } - static void applyModelMatrix(LLDrawInfo& params); + static void applyModelMatrix(const LLDrawInfo& params); virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); virtual void pushMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 90e6dfe351..ab96201a63 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -375,7 +375,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - const S32 actual_pass[] = + static const S32 actual_pass[] = { //map post deferred pass numbers to what render() expects 2, //skinned 4, // rigged fullbright @@ -1626,7 +1626,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* { F32 w = weight[j][k]; - idx[k] = llclamp((S32) floorf(w), 0, 63); + idx[k] = llclamp((S32) floorf(w), 0, JOINT_COUNT-1); + wght[k] = w - floorf(w); scale += wght[k]; } diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 514411aef5..f92320490a 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -96,7 +96,7 @@ void LLDrawPoolMaterials::endDeferredPass(S32 pass) void LLDrawPoolMaterials::renderDeferred(S32 pass) { - U32 type_list[] = + static const U32 type_list[] = { LLRenderPass::PASS_MATERIAL, //LLRenderPass::PASS_MATERIAL_ALPHA, diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 4db0422634..d89599cb45 100755 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -76,9 +76,6 @@ const char FEATURE_TABLE_FILENAME[] = "featuretable%s.txt"; const char FEATURE_TABLE_VER_FILENAME[] = "featuretable%s.%s.txt"; #endif -const char GPU_TABLE_FILENAME[] = "gpu_table.txt"; -const char GPU_TABLE_VER_FILENAME[] = "gpu_table.%s.txt"; - LLFeatureInfo::LLFeatureInfo(const std::string& name, const BOOL available, const F32 level) : mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level) { @@ -428,6 +425,7 @@ bool LLFeatureManager::loadGPUClass() { //couldn't bench, use GLVersion #if LL_DARWIN //GLVersion is misleading on OSX, just default to class 3 if we can't bench + LL_WARNS() << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL; mGPUClass = GPU_CLASS_3; #else if (gGLManager.mGLVersion < 2.f) @@ -452,23 +450,31 @@ bool LLFeatureManager::loadGPUClass() } #endif } - else if (gbps < 5.f) + else if (gGLManager.mGLVersion <= 2.f) + { + mGPUClass = GPU_CLASS_0; + } + else if (gGLManager.mGLVersion <= 3.f) + { + mGPUClass = GPU_CLASS_1; + } + else if (gbps <= 5.f) { mGPUClass = GPU_CLASS_0; } - else if (gbps < 10.f) + else if (gbps <= 8.f) { mGPUClass = GPU_CLASS_1; } - else if (gbps < 20.f) + else if (gbps <= 16.f) { mGPUClass = GPU_CLASS_2; } - else if (gbps < 40.f) + else if (gbps <= 40.f) { mGPUClass = GPU_CLASS_3; } - else if (gbps < 80.f) + else if (gbps <= 80.f) { mGPUClass = GPU_CLASS_4; } @@ -476,195 +482,15 @@ bool LLFeatureManager::loadGPUClass() { mGPUClass = GPU_CLASS_5; } - + // defaults mGPUString = gGLManager.getRawGLString(); mGPUSupported = TRUE; -#if 0 - // first table is in the app dir - std::string app_path = gDirUtilp->getAppRODataDir(); - app_path += gDirUtilp->getDirDelimiter(); - app_path += GPU_TABLE_FILENAME; - - // second table is downloaded with HTTP - std::string http_filename = llformat(GPU_TABLE_VER_FILENAME, LLVersionInfo::getVersion().c_str()); - std::string http_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, http_filename); - - // use HTTP table if it exists - std::string path; - bool parse_ok = false; - if (gDirUtilp->fileExists(http_path)) - { - parse_ok = parseGPUTable(http_path); - if (!parse_ok) - { - // the HTTP table failed to parse, so delete it - LLFile::remove(http_path); - LL_WARNS("RenderInit") << "Removed invalid gpu table '" << http_path << "'" << LL_ENDL; - } - } - - if (!parse_ok) - { - parse_ok = parseGPUTable(app_path); - } -#endif - return true; // indicates that the file parsed correctly, not that the gpu was recognized + return true; // indicates that a gpu value was established } -bool LLFeatureManager::parseGPUTable(std::string filename) -{ - llifstream file; - - LL_INFOS("RenderInit") << "Attempting to parse GPU table from " << filename << LL_ENDL; - file.open(filename); - - if (file) - { - const char recognizer[] = "//GPU_TABLE"; - char first_line[MAX_STRING]; - file.getline(first_line, MAX_STRING); - if (0 != strncmp(first_line, recognizer, strlen(recognizer))) - { - LL_WARNS("RenderInit") << "Invalid GPU table: " << filename << "!" << LL_ENDL; - return false; - } - } - else - { - LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL; - return false; - } - - std::string rawRenderer = gGLManager.getRawGLString(); - std::string renderer = rawRenderer; - for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i) - { - *i = tolower(*i); - } - -#if LL_EXPORT_GPU_TABLE - llofstream json; - json.open("gpu_table.json"); - - json << "var gpu_table = [" << std::endl; -#endif - - bool gpuFound; - U32 lineNumber; - for (gpuFound = false, lineNumber = 0; !gpuFound && !file.eof(); lineNumber++) - { - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - buffer[0] = 0; - - file.getline(buffer, MAX_STRING); - - if (strlen(buffer) >= 2 && /*Flawfinder: ignore*/ - buffer[0] == '/' && - buffer[1] == '/') - { - // This is a comment. - continue; - } - - if (strlen(buffer) == 0) /*Flawfinder: ignore*/ - { - // This is a blank line - continue; - } - - // setup the tokenizer - std::string buf(buffer); - std::string cls, label, expr, supported, stats_based, expected_gl_version; - boost_tokenizer tokens(buf, boost::char_separator<char>("\t\n")); - boost_tokenizer::iterator token_iter = tokens.begin(); - - // grab the label, pseudo regular expression, and class - if(token_iter != tokens.end()) - { - label = *token_iter++; - } - if(token_iter != tokens.end()) - { - expr = *token_iter++; - } - if(token_iter != tokens.end()) - { - cls = *token_iter++; - } - if(token_iter != tokens.end()) - { - supported = *token_iter++; - } - if (token_iter != tokens.end()) - { - stats_based = *token_iter++; - } - if (token_iter != tokens.end()) - { - expected_gl_version = *token_iter++; - } - - if (label.empty() || expr.empty() || cls.empty() || supported.empty()) - { - LL_WARNS("RenderInit") << "invald gpu_table.txt:" << lineNumber << ": '" << buffer << "'" << LL_ENDL; - continue; - } -#if LL_EXPORT_GPU_TABLE - json << "{'label' : '" << label << "',\n" << - "'regexp' : '" << expr << "',\n" << - "'class' : '" << cls << "',\n" << - "'supported' : '" << supported << "',\n" << - "'stats_based' : " << stats_based << ",\n" << - "'gl_version' : " << expected_gl_version << "\n},\n"; -#endif - - for (U32 i = 0; i < expr.length(); i++) /*Flawfinder: ignore*/ - { - expr[i] = tolower(expr[i]); - } - - // run the regular expression against the renderer - boost::regex re(expr.c_str()); - if(boost::regex_search(renderer, re)) - { - // if we found it, stop! -#if !LL_EXPORT_GPU_TABLE - gpuFound = true; -#endif - mGPUString = label; - mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10); - mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10); - sscanf(expected_gl_version.c_str(), "%f", &mExpectedGLVersion); - } - } -#if LL_EXPORT_GPU_TABLE - json << "];\n\n"; - json.close(); -#endif - file.close(); - - if ( gpuFound ) - { - LL_INFOS("RenderInit") << "GPU '" << rawRenderer << "' recognized as '" << mGPUString << "'" << LL_ENDL; - if (!mGPUSupported) - { - LL_INFOS("RenderInit") << "GPU '" << mGPUString << "' is not supported." << LL_ENDL; - } - } - else - { - LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL; - } - -#if LL_DARWIN // never go over "Mid" settings by default on OS X - mGPUClass = llmin(mGPUClass, GPU_CLASS_2); -#endif - return true; -} - // responder saves table into file class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder { @@ -745,26 +571,11 @@ void fetch_feature_table(std::string table) LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path)); } -void fetch_gpu_table(std::string table) -{ - const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable"); - - const std::string filename = llformat(table.c_str(), LLVersionInfo::getVersion().c_str()); - - const std::string url = base + "/" + filename; - - const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); - - LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL; - - LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path)); -} // fetch table(s) from a website (S3) void LLFeatureManager::fetchHTTPTables() { fetch_feature_table(FEATURE_TABLE_VER_FILENAME); - fetch_gpu_table(GPU_TABLE_VER_FILENAME); } diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 95141b241d..69078ccc21 100755 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -162,9 +162,6 @@ protected: bool parseFeatureTable(std::string filename); ///< @returns TRUE is file parsed correctly, FALSE if not - bool parseGPUTable(std::string filename); - ///< @returns true if file parsed correctly, false if not - does not reflect whether or not the gpu was recognized - void initBaseMask(); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 5debf71744..ef50594feb 100755 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -600,6 +600,9 @@ std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) // allowedv->push_back("slg"); break; #endif + case FFLOAD_XML: + allowedv->push_back("xml"); + break; case FFLOAD_RAW: allowedv->push_back("raw"); break; @@ -702,7 +705,14 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena creator = "\?\?\?\?"; extension = "slg"; break; -#endif +#endif + + case FFSAVE_XML: + type = "\?\?\?\?"; + creator = "\?\?\?\?"; + extension = "xml"; + break; + case FFSAVE_RAW: type = "\?\?\?\?"; creator = "\?\?\?\?"; @@ -1100,6 +1110,12 @@ static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker) return filtername; } +static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml", + LLTrans::getString("xml_files") + " (*.xml)"); +} + static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) { return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae", @@ -1293,6 +1309,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) case FFLOAD_ANIM: filtername = add_anim_filter_to_gtkchooser(picker); break; + case FFLOAD_XML: + filtername = add_xml_filter_to_gtkchooser(picker); + break; case FFLOAD_COLLADA: filtername = add_collada_filter_to_gtkchooser(picker); break; diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp index b715896264..b75660ea00 100644 --- a/indra/newview/llflickrconnect.cpp +++ b/indra/newview/llflickrconnect.cpp @@ -400,7 +400,7 @@ void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std:: } else { - llwarns << "Image to upload is not a PNG or JPEG" << llendl; + LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL; return; } diff --git a/indra/newview/llfloatergroupbulkban.cpp b/indra/newview/llfloatergroupbulkban.cpp index 54a2283b13..44074047a7 100644 --- a/indra/newview/llfloatergroupbulkban.cpp +++ b/indra/newview/llfloatergroupbulkban.cpp @@ -101,7 +101,7 @@ void LLFloaterGroupBulkBan::showForGroup(const LLUUID& group_id, uuid_vec_t* age // Make sure group_id isn't null if (group_id.isNull()) { - llwarns << "LLFloaterGroupInvite::showForGroup with null group_id!" << llendl; + LL_WARNS() << "LLFloaterGroupInvite::showForGroup with null group_id!" << LL_ENDL; return; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index fbdaca0e6f..2864f018b2 100755 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -47,7 +47,7 @@ const F32 REFRESH_INTERVAL = 1.0f; LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) -: LLTransientDockableFloater(NULL, true, session_id), +: LLTransientDockableFloater(NULL, false, session_id), mIsP2PChat(false), mExpandCollapseBtn(NULL), mTearOffBtn(NULL), diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index b17ce97a2e..0c81ab7e79 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1935,7 +1935,9 @@ bool LLModelLoader::doLoadModel() LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint ); if ( pJoint ) { - pJoint->storeCurrentXform( jointTransform.getTranslation() ); + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, gAgentAvatarp->avString()); } else { @@ -3242,7 +3244,11 @@ U32 LLModelPreview::calcResourceCost() if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() ) { - getPreviewAvatar()->setPelvisOffset( mPelvisZOffset ); + // FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail. + // see also call to addAttachmentPosOverride. + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id ); } F32 streaming_cost = 0.f; diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 9986bdbd7f..ef746d308d 100755 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -58,6 +58,8 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key) { mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this)); mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this)); + mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit", boost::bind(&LLFloaterOpenObject::onClickReplace, this)); + mCommitCallbackRegistrar.add("OpenObject.Cancel", boost::bind(&LLFloaterOpenObject::onClickCancel, this)); } LLFloaterOpenObject::~LLFloaterOpenObject() @@ -115,6 +117,7 @@ void LLFloaterOpenObject::refresh() getChild<LLUICtrl>("object_name")->setTextArg("[DESC]", name); getChildView("copy_to_inventory_button")->setEnabled(enabled); getChildView("copy_and_wear_button")->setEnabled(enabled); + getChildView("copy_and_replace_button")->setEnabled(enabled); } @@ -135,7 +138,7 @@ void LLFloaterOpenObject::dirty() -void LLFloaterOpenObject::moveToInventory(bool wear) +void LLFloaterOpenObject::moveToInventory(bool wear, bool replace) { if (mObjectSelection->getRootObjectCount() != 1) { @@ -163,7 +166,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear) parent_category_id = gInventory.getRootFolderID(); } - inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear); + inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace); LLUUID category_id = gInventory.createNewCategory(parent_category_id, LLFolderType::FT_NONE, name, @@ -177,6 +180,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear) data->mCatID = category_id; data->mWear = wear; data->mFolderResponded = false; + data->mReplace = replace; // Copy and/or move the items into the newly created folder. // Ignore any "you're going to break this item" messages. @@ -194,13 +198,14 @@ void LLFloaterOpenObject::moveToInventory(bool wear) } // static -void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear) +void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace) { LLCatAndWear* wear_data = new LLCatAndWear; wear_data->mCatID = category_id; wear_data->mWear = wear; wear_data->mFolderResponded = true; + wear_data->mReplace = replace; // Copy and/or move the items into the newly created folder. // Ignore any "you're going to break this item" messages. @@ -241,7 +246,17 @@ void LLFloaterOpenObject::onClickMoveToInventory() void LLFloaterOpenObject::onClickMoveAndWear() { - moveToInventory(true); + moveToInventory(true, false); closeFloater(); } +void LLFloaterOpenObject::onClickReplace() +{ + moveToInventory(true, true); + closeFloater(); +} + +void LLFloaterOpenObject::onClickCancel() +{ + closeFloater(); +} diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 8e472804a4..2e761f99bf 100755 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -50,6 +50,7 @@ public: LLUUID mCatID; bool mWear; bool mFolderResponded; + bool mReplace; }; protected: @@ -59,11 +60,13 @@ protected: void draw(); virtual void onOpen(const LLSD& key); - void moveToInventory(bool wear); + void moveToInventory(bool wear, bool replace = false); void onClickMoveToInventory(); void onClickMoveAndWear(); - static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear); + void onClickReplace(); + void onClickCancel(); + static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace = false); static void callbackMoveInventory(S32 result, void* data); private: diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index f0c010b545..a4d13ce1d5 100755 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -40,8 +40,10 @@ #include "lltextbox.h" #include "lllineeditor.h" #include "llmutelist.h" +#include "llnotificationsutil.h" #include "llfloaterreporter.h" #include "llslurl.h" +#include "llstatusbar.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" @@ -90,6 +92,9 @@ public: static void payDirectly(money_callback callback, const LLUUID& target_id, bool is_group); + static bool payConfirmationCallback(const LLSD& notification, + const LLSD& response, + LLGiveMoneyInfo* info); private: static void onCancel(void* data); @@ -111,14 +116,12 @@ protected: LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS]; LLSafeHandle<LLObjectSelection> mObjectSelection; - - static S32 sLastAmount; }; -S32 LLFloaterPay::sLastAmount = 0; const S32 MAX_AMOUNT_LENGTH = 10; const S32 FASTPAY_BUTTON_WIDTH = 80; +const S32 PAY_AMOUNT_NOTIFICATION = 200; LLFloaterPay::LLFloaterPay(const LLSD& key) : LLFloater(key), @@ -188,17 +191,9 @@ BOOL LLFloaterPay::postBuild() getChildView("amount text")->setVisible(FALSE); - - std::string last_amount; - if(sLastAmount > 0) - { - last_amount = llformat("%d", sLastAmount); - } - getChildView("amount")->setVisible(FALSE); getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this); - getChild<LLUICtrl>("amount")->setValue(last_amount); getChild<LLLineEditor>("amount")->setPrevalidate(LLTextValidate::validateNonNegativeS32); info = new LLGiveMoneyInfo(this, 0); @@ -207,7 +202,7 @@ BOOL LLFloaterPay::postBuild() childSetAction("pay btn",&LLFloaterPay::onGive,info); setDefaultBtn("pay btn"); getChildView("pay btn")->setVisible(FALSE); - getChildView("pay btn")->setEnabled((sLastAmount > 0)); + getChildView("pay btn")->setEnabled(FALSE); childSetAction("cancel btn",&LLFloaterPay::onCancel,this); @@ -419,7 +414,24 @@ void LLFloaterPay::payDirectly(money_callback callback, floater->finishPayUI(target_id, is_group); } - + +bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, LLGiveMoneyInfo* info) +{ + if (!info || !info->mFloater) + { + return false; + } + + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + info->mFloater->give(info->mAmount); + info->mFloater->closeFloater(); + } + + return false; +} + void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group) { std::string slurl; @@ -470,10 +482,40 @@ void LLFloaterPay::onKeystroke(LLLineEditor*, void* data) void LLFloaterPay::onGive(void* data) { LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data); - if(info && info->mFloater) + LLFloaterPay* floater = info->mFloater; + if(info && floater) { - info->mFloater->give(info->mAmount); - info->mFloater->closeFloater(); + S32 amount = info->mAmount; + if(amount == 0) + { + amount = atoi(floater->getChild<LLUICtrl>("amount")->getValue().asString().c_str()); + } + if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount) + { + LLUUID payee_id; + BOOL is_group; + if (floater->mObjectSelection.notNull()) + { + LLSelectNode* node = floater->mObjectSelection->getFirstRootNode(); + node->mPermissions->getOwnership(payee_id, is_group); + } + else + { + is_group = floater->mTargetIsGroup; + payee_id = floater->mTargetUUID; + } + + LLSD args; + args["TARGET"] = LLSLURL( is_group ? "group" : "agent", payee_id, "completename").getSLURLString(); + args["AMOUNT"] = amount; + + LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info)); + } + else + { + floater->give(amount); + floater->closeFloater(); + } } } @@ -487,7 +529,6 @@ void LLFloaterPay::give(S32 amount) { amount = atoi(getChild<LLUICtrl>("amount")->getValue().asString().c_str()); } - sLastAmount = amount; // Try to pay an object. if (mObjectSelection.notNull()) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3f3d87b564..024e315632 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -293,6 +293,7 @@ void LLFloaterWebContent::onOpen(const LLSD& key) void LLFloaterWebContent::onClose(bool app_quitting) { // If we close the web browsing window showing the facebook login, we need to signal to this object that the connection will not happen + // MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad. LLFloater* fbc_web = LLFloaterReg::findInstance("fbc_web"); if (fbc_web == this) { @@ -302,7 +303,8 @@ void LLFloaterWebContent::onClose(bool app_quitting) } } // Same with Flickr - LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web"); + // MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad. + LLFloater* flickr_web = LLFloaterReg::findInstance("flickr_web"); if (flickr_web == this) { if (!LLFlickrConnect::instance().isConnected()) @@ -311,7 +313,8 @@ void LLFloaterWebContent::onClose(bool app_quitting) } } // And Twitter - LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web"); + // MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad. + LLFloater* twitter_web = LLFloaterReg::findInstance("twitter_web"); if (twitter_web == this) { if (!LLTwitterConnect::instance().isConnected()) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 7a43477523..8c360befc3 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -130,13 +130,18 @@ void LLFolderViewModelItemInventory::requestSort() void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) { + bool generation_skip = mMarkedDirtyGeneration >= 0 + && mPrevPassedAllFilters + && mMarkedDirtyGeneration < mRootViewModel.getFilter().getFirstSuccessGeneration(); LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); bool before = mPrevPassedAllFilters; mPrevPassedAllFilters = passedFilter(filter_generation); - if (before != mPrevPassedAllFilters) + if (before != mPrevPassedAllFilters || generation_skip) { - // Need to rearrange the folder if the filtered state of the item changed + // Need to rearrange the folder if the filtered state of the item changed, + // previously passed item skipped filter generation changes while being dirty + // or previously passed not yet filtered item was marked dirty LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); if (parent_folder) { @@ -145,6 +150,9 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_gen } } + + + bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { S32 filter_generation = filter.getCurrentGeneration(); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 4b8ac2b3cf..64f796e1fd 100755 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -881,13 +881,14 @@ void LLViewerObjectList::renderObjectBeacons() F32 gpu_benchmark() { - if (!gGLManager.mHasShaderObjects) - { //don't bother benchmarking the fixed function + if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery) + { // don't bother benchmarking the fixed function + // or venerable drivers which don't support accurate timing anyway + // and are likely to be correctly identified by the GPU table already. return -1.f; } - - if (gBenchmarkProgram.mProgramObject == 0) + if (gBenchmarkProgram.mProgramObject == 0) { LLViewerShaderMgr::instance()->initAttribsAndUniforms(); @@ -920,7 +921,10 @@ F32 gpu_benchmark() //number of samples to take const S32 samples = 64; - LLGLSLShader::initProfile(); + if (gGLManager.mHasTimerQuery) + { + LLGLSLShader::initProfile(); + } LLRenderTarget dest[count]; U32 source[count]; @@ -964,16 +968,16 @@ F32 gpu_benchmark() v[0].set(-1,1,0); v[1].set(-1,-3,0); v[2].set(3,1,0); + buff->flush(); gBenchmarkProgram.bind(); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - - //wait for any previoius GL commands to finish - glFinish(); bool busted_finish = false; + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + glFinish(); + for (S32 c = -1; c < samples; ++c) { LLTimer timer; @@ -1013,6 +1017,7 @@ F32 gpu_benchmark() if (!gGLManager.mHasTimerQuery && !busted_finish && gbps > 128.f) { //unrealistically high bandwidth for a card without timer queries, glFinish is probably ignored busted_finish = true; + LL_WARNS() << "GPU Benchmark detected GL driver with broken glFinish implementation." << LL_ENDL; } else { @@ -1023,10 +1028,12 @@ F32 gpu_benchmark() gBenchmarkProgram.unbind(); - LLGLSLShader::finishProfile(false); - - LLImageGL::deleteTextures(count, source); + if (gGLManager.mHasTimerQuery) + { + LLGLSLShader::finishProfile(false); + } + LLImageGL::deleteTextures(count, source); std::sort(results.begin(), results.end()); @@ -1037,27 +1044,20 @@ F32 gpu_benchmark() #if LL_DARWIN if (gbps > 512.f) { - LL_INFOS() << "Memory bandwidth is improbably high and likely incorrect." << LL_ENDL; + LL_WARNS() << "Memory bandwidth is improbably high and likely incorrect; discarding result." << LL_ENDL; //OSX is probably lying, discard result gbps = -1.f; } #endif - if (gGLManager.mHasTimerQuery) - { - F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; + F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; + F32 seconds = ms/1000.f; - F64 samples_drawn = res*res*count*samples; - F32 samples_sec = (samples_drawn/1000000000.0)/seconds; - gbps = samples_sec*8; + F64 samples_drawn = res*res*count*samples; + F32 samples_sec = (samples_drawn/1000000000.0)/seconds; + gbps = samples_sec*8; - LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query" << LL_ENDL; - } - else - { - LL_INFOS() << "ARB_timer_query unavailable." << LL_ENDL; - } + LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query" << LL_ENDL; return gbps; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9c0c30c167..62612c1450 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -84,6 +84,8 @@ void copy_slurl_to_clipboard_callback_inv(const std::string& slurl); typedef std::pair<LLUUID, LLUUID> two_uuids_t; typedef std::list<two_uuids_t> two_uuids_list_t; +const F32 SOUND_GAIN = 1.0f; + struct LLMoveInv { LLUUID mObjectID; @@ -2935,8 +2937,8 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) class LLInventoryCopyAndWearObserver : public LLInventoryObserver { public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false) : - mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added) {} + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false, bool replace=false) : + mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added), mReplace(replace){} virtual ~LLInventoryCopyAndWearObserver() {} virtual void changed(U32 mask); @@ -2944,6 +2946,7 @@ protected: LLUUID mCatID; int mContentsCount; bool mFolderAdded; + bool mReplace; }; @@ -2982,7 +2985,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) mContentsCount) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, TRUE); + LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, !mReplace); delete this; } } @@ -4131,24 +4134,21 @@ void LLFolderBridge::modifyOutfit(BOOL append) // checking amount of items to wear U32 max_items = gSavedSettings.getU32("WearFolderLimit"); - if (cat->getDescendentCount() > max_items) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - - if (items.size() > max_items) - { - LLSD args; - args["AMOUNT"] = llformat("%d", max_items); - LLNotificationsUtil::add("TooManyWearables", args); - return; - } + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + gInventory.collectDescendentsIf(cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + not_worn); + + if (items.size() > max_items) + { + LLSD args; + args["AMOUNT"] = llformat("%d", max_items); + LLNotificationsUtil::add("TooManyWearables", args); + return; } LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append ); @@ -4168,7 +4168,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response LLInventoryObject::object_list_t inventory_objects; object->getInventoryContents(inventory_objects); int contents_count = inventory_objects.size()-1; //subtract one for containing folder - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded); + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded, + cat_and_wear->mReplace); gInventory.addObserver(inventoryObserver); } @@ -4938,6 +4939,23 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +void LLSoundBridge::performAction(LLInventoryModel* model, std::string action) +{ + if ("sound_play" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + send_sound_trigger(item->getAssetUUID(), SOUND_GAIN); + } + } + else if ("open" == action) + { + openSoundPreview((void*)this); + } + else LLItemBridge::performAction(model, action); +} + // +=================================================+ // | LLLandmarkBridge | // +=================================================+ @@ -5781,16 +5799,20 @@ std::string LLObjectBridge::getLabelSuffix() const { return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); } - std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); - if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point + std::string attachment_point_name; + if (gAgentAvatarp->getAttachedPointName(mUUID, attachment_point_name)) { - attachment_point_name = "Invalid Attachment"; - } - // e.g. "(worn on ...)" / "(attached to ...)" - LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); - return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); + } + else + { + LLStringUtil::format_map_t args; + args["[ATTACHMENT_ERROR]"] = LLTrans::getString(attachment_point_name); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("AttachmentErrorMessage", args); + } } return LLItemBridge::getLabelSuffix(); } @@ -6611,7 +6633,7 @@ public: LLViewerInventoryItem* item = getItem(); if (item) { - LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); + send_sound_trigger(item->getAssetUUID(), SOUND_GAIN); } LLInvFVBridgeAction::doIt(); } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index bb0c1bb5c7..2757f5c884 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -403,6 +403,7 @@ public: LLItemBridge(inventory, root, uuid) {} virtual void openItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual void performAction(LLInventoryModel* model, std::string action); static void openSoundPreview(void*); }; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 07835f189c..8fcfbd646f 100755 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -128,6 +128,15 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { + // Always check against the clipboard + const BOOL passed_clipboard = checkAgainstClipboard(folder_id); + + // we're showing all folders, overriding filter + if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + { + return passed_clipboard; + } + // when applying a filter, matching folders get their contents downloaded first if (isNotDefault() && !gInventory.isCategoryComplete(folder_id)) @@ -168,15 +177,6 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const } } - // Always check against the clipboard - const BOOL passed_clipboard = checkAgainstClipboard(folder_id); - - // we're showing all folders, overriding filter - if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) - { - return passed_clipboard; - } - // show folder links LLViewerInventoryItem* item = gInventory.getItem(folder_id); if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6926fa9268..86ff1aed1b 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -548,12 +548,13 @@ void LLInventoryPanel::modelChanged(U32 mask) // This item already exists in both memory and UI. It was probably reparented. else if (model_item && view_item) { + LLFolderViewFolder* old_parent = view_item->getParentFolder(); // Don't process the item if it is the root - if (view_item->getParentFolder()) + if (old_parent) { LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID()); // Item has been moved. - if (view_item->getParentFolder() != new_parent) + if (old_parent != new_parent) { if (new_parent != NULL) { @@ -579,6 +580,7 @@ void LLInventoryPanel::modelChanged(U32 mask) // doesn't include trash). Just remove the item's UI. view_item->destroyView(); } + old_parent->getViewModelItem()->dirtyDescendantsFilter(); } } } @@ -589,28 +591,16 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (!model_item && view_item && viewmodel_item) { // Remove the item's UI. - const LLUUID& idp = viewmodel_item->getUUID(); - removeItemID(idp); + LLFolderViewFolder* parent = view_item->getParentFolder(); + removeItemID(viewmodel_item->getUUID()); view_item->destroyView(); + if(parent) + { + parent->getViewModelItem()->dirtyDescendantsFilter(); + } } } } - - if (mask & (LLInventoryObserver::STRUCTURE | LLInventoryObserver::REMOVE)) - { - // STRUCTURE and REMOVE model changes usually fail to update (clean) - // mMostFilteredDescendantGeneration of parent folder and dirtyFilter() - // is not sufficient for successful filter update, so we need to check - // all already passed element over again to remove obsolete elements. - // New items or moved items should be sufficiently covered by - // dirtyFilter(). - LLInventoryFilter& filter = getFilter(); - if (filter.getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE - || filter.isNotDefault()) - { - filter.setModified(LLFolderViewFilter::FILTER_MORE_RESTRICTIVE); - } - } } LLUUID LLInventoryPanel::getRootFolderID() diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index e3ed10bd50..cadbc16f1e 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -1021,6 +1021,8 @@ void LLLoadHistoryThread::run() if(mNewLoad) { loadHistory(mFileName, mMessages, mLoadParams); + int count = mMessages->size(); + LL_INFOS() << "mMessages->size(): " << count << LL_ENDL; setFinished(); } } diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 7861573908..b2350e5a75 100755 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1240,10 +1240,10 @@ LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y ) F32 dist_from_sphere_center = sqrt(delta_x * delta_x + delta_y * delta_y); LLVector3 axis = mMouseDown % mMouseCur; + F32 angle = atan2(sqrtf(axis * axis), mMouseDown * mMouseCur); axis.normVec(); - F32 angle = acos(mMouseDown * mMouseCur); LLQuaternion sphere_rot( angle, axis ); - + if (is_approx_zero(1.f - mMouseDown * mMouseCur)) { return LLQuaternion::DEFAULT; @@ -1638,9 +1638,9 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) mInSnapRegime = FALSE; } - angle = acos(mMouseCur * mMouseDown); - - F32 dir = (mMouseDown % mMouseCur) * constraint_axis; // cross product + LLVector3 cross_product = mMouseDown % mMouseCur; + angle = atan2(sqrtf(cross_product * cross_product), mMouseCur * mMouseDown); + F32 dir = cross_product * constraint_axis; // cross product if( dir < 0.f ) { angle *= -1.f; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index e3be1312e4..02e05d3d9a 100755 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1848,6 +1848,8 @@ void LLPanelFace::onCancelNormalTexture(const LLSD& data) U8 bumpy = 0; bool identical_bumpy = false; LLSelectedTE::getBumpmap(bumpy, identical_bumpy); + LLUUID spec_map_id = getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID(); + bumpy = spec_map_id.isNull() ? bumpy : BUMPY_TEXTURE; sendBump(bumpy); } diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp index 1eafc5bd64..76792cc6fd 100644 --- a/indra/newview/llpanelgroupbulk.cpp +++ b/indra/newview/llpanelgroupbulk.cpp @@ -387,7 +387,7 @@ void LLPanelGroupBulk::addUsers(uuid_vec_t& agent_ids) } else { - llwarns << "llPanelGroupBulk: Selected avatar has no name: " << dest->getID() << llendl; + LL_WARNS() << "llPanelGroupBulk: Selected avatar has no name: " << dest->getID() << LL_ENDL; names.push_back("(Unknown)"); } } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 236ad861a5..e662a05dfc 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -492,7 +492,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) } else { - llwarns << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << llendl; + LL_WARNS() << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << LL_ENDL; names.push_back("(Unknown)"); } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index a7c9dbdf7b..eb037577be 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -153,7 +153,9 @@ BOOL LLPanelMainInventory::postBuild() recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter().markDefault(); + LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); + recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); + recent_filter.markDefault(); recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); } @@ -853,9 +855,9 @@ void LLFloaterInventoryFinder::draw() filtered_by_all_types = FALSE; } - if (!filtered_by_all_types) + if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE)) { - // don't include folders in filter, unless I've selected everything + // don't include folders in filter, unless I've selected everything or filtering by date filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 25023073a2..a7a0196770 100755 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -698,6 +698,10 @@ void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemRenameable()) { items.push_back(std::string("Task Rename")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Task Rename")); + } } if(isItemRemovable()) { diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 8eea5ea73e..a41986373e 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -663,12 +663,13 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) LLTextSegmentPtr segment = NULL; std::vector<LLTextSegmentPtr> selected_segments; mEditor->getSelectedSegments(selected_segments); - + LLKeywordToken* token; // try segments in selection range first std::vector<LLTextSegmentPtr>::iterator segment_iter; for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) { - if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::TT_WORD) + token = (*segment_iter)->getToken(); + if(token && isKeyword(token)) { segment = *segment_iter; break; @@ -679,7 +680,8 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) if (!segment) { const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment(); - if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::TT_WORD) + token = test_segment->getToken(); + if(token && isKeyword(token)) { segment = test_segment; } @@ -708,6 +710,24 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) } } +bool LLScriptEdCore::isKeyword(LLKeywordToken* token) +{ + switch(token->getType()) + { + case LLKeywordToken::TT_CONSTANT: + case LLKeywordToken::TT_CONTROL: + case LLKeywordToken::TT_EVENT: + case LLKeywordToken::TT_FUNCTION: + case LLKeywordToken::TT_SECTION: + case LLKeywordToken::TT_TYPE: + case LLKeywordToken::TT_WORD: + return true; + + default: + return false; + } +} + void LLScriptEdCore::setHelpPage(const std::string& help_string) { LLFloater* help_floater = mLiveHelpHandle.get(); diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 515f277c4a..66727bceee 100755 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -133,6 +133,7 @@ protected: void deleteBridges(); void setHelpPage(const std::string& help_string); void updateDynamicHelp(BOOL immediate = FALSE); + bool isKeyword(LLKeywordToken* token); void addHelpItemToHistory(const std::string& help_string); static void onErrorList(LLUICtrl*, void* user_data); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 0a8257f42b..5e342099d7 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1632,7 +1632,7 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) { LLDrawInfo* params = NULL; - LLColor4 colors[] = { + static const LLColor4 colors[] = { LLColor4::green, LLColor4::green1, LLColor4::green2, diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 89302c3c64..e80756e4de 100755 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -544,10 +544,18 @@ void LLSpeakerMgr::updateSpeakerList() LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); if (session->isGroupSessionType() && (mSpeakers.size() <= 1)) { - const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout"); // For groups, we need to hit the group manager. // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); + F32 large_group_delay = 0.f; + if (gdatap) + { + //This is a viewer-side bandaid for maint-4414 it does not fix the core issue. + large_group_delay = (F32)(gdatap->mMemberCount / 5000); + } + + const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout") + large_group_delay; + if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout)) { // Request the data the first time around diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index c12753acb0..a426669b5e 100755 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -118,7 +118,7 @@ public: /*virtual*/ void onClose(bool app_settings); // New functions - void setImageID( const LLUUID& image_asset_id); + void setImageID( const LLUUID& image_asset_id, bool set_selection = true); void updateImageStats(); const LLUUID& getAssetID() { return mImageAssetID; } const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); @@ -232,7 +232,7 @@ LLFloaterTexturePicker::~LLFloaterTexturePicker() { } -void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) +void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selection /*=true*/) { if( mImageAssetID != image_id && mActive) { @@ -253,6 +253,10 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id) getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE); mNoCopyTextureSelected = TRUE; } + } + + if (set_selection) + { mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); } } @@ -461,7 +465,10 @@ BOOL LLFloaterTexturePicker::postBuild() // don't put keyboard focus on selected item, because the selection callback // will assume that this was user input - mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + if(!mImageAssetID.isNull()) + { + mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + } } mModeSelector = getChild<LLRadioGroup>("mode_selection"); @@ -820,7 +827,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem { mNoCopyTextureSelected = TRUE; } - setImageID(itemp->getAssetUUID()); + setImageID(itemp->getAssetUUID(),false); mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? if (user_action && mCanPreview) { diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 696259db55..9172c896cf 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2188,23 +2188,20 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( } U32 max_items = gSavedSettings.getU32("WearFolderLimit"); - if (category->getDescendentCount()>max_items) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - if (items.size() > max_items) - { - LLStringUtil::format_map_t args; - args["AMOUNT"] = llformat("%d", max_items); - mCustomMsg = LLTrans::getString("TooltipTooManyWearables",args); - return ACCEPT_NO_CUSTOM; - } + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + gInventory.collectDescendentsIf(category->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + not_worn); + if (items.size() > max_items) + { + LLStringUtil::format_map_t args; + args["AMOUNT"] = llformat("%d", max_items); + mCustomMsg = LLTrans::getString("TooltipTooManyWearables",args); + return ACCEPT_NO_CUSTOM; } if(mSource == SOURCE_AGENT) diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp index 7088558b83..e983bc883f 100644 --- a/indra/newview/lltwitterconnect.cpp +++ b/indra/newview/lltwitterconnect.cpp @@ -397,7 +397,7 @@ void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std: } else { - llwarns << "Image to upload is not a PNG or JPEG" << llendl; + LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL; return; } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 1fbbbf7246..dcd986a5c7 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1481,7 +1481,8 @@ void update_inventory_category( void remove_inventory_items( LLInventoryObject::object_list_t& items_to_kill, - LLPointer<LLInventoryCallback> cb) + LLPointer<LLInventoryCallback> cb + ) { for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin(); it != items_to_kill.end(); @@ -1493,12 +1494,13 @@ void remove_inventory_items( void remove_inventory_item( const LLUUID& item_id, - LLPointer<LLInventoryCallback> cb) + LLPointer<LLInventoryCallback> cb, + bool immediate_delete) { LLPointer<LLInventoryObject> obj = gInventory.getItem(item_id); if (obj) { - remove_inventory_item(obj, cb); + remove_inventory_item(obj, cb, immediate_delete); } else { @@ -1508,7 +1510,8 @@ void remove_inventory_item( void remove_inventory_item( LLPointer<LLInventoryObject> obj, - LLPointer<LLInventoryCallback> cb) + LLPointer<LLInventoryCallback> cb, + bool immediate_delete) { if(obj) { @@ -1518,6 +1521,11 @@ void remove_inventory_item( { LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb); cmd_ptr->run_command(); + + if (immediate_delete) + { + gInventory.onObjectDeletedFromServer(item_id); + } } else // no cap { diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 6c8dbd0cd6..4e91e4110a 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -397,11 +397,13 @@ void remove_inventory_items( void remove_inventory_item( LLPointer<LLInventoryObject> obj, - LLPointer<LLInventoryCallback> cb); + LLPointer<LLInventoryCallback> cb, + bool immediate_delete = false); void remove_inventory_item( const LLUUID& item_id, - LLPointer<LLInventoryCallback> cb); + LLPointer<LLInventoryCallback> cb, + bool immediate_delete = false); void remove_inventory_category( const LLUUID& cat_id, diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index b0f4802e20..a4a05587d3 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -88,18 +88,25 @@ void agent_push_down( EKeystate s ) gAgent.moveUp(-1); } +static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode) +{ + if (gAgent.mDoubleTapRunMode == mode && + gAgent.getRunning() && + !gAgent.getAlwaysRun()) + { + // Turn off temporary running. + gAgent.clearRunning(); + gAgent.sendWalkRun(gAgent.getRunning()); + } +} + static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode) { if (KEYSTATE_UP == s) { - if (gAgent.mDoubleTapRunMode == mode && - gAgent.getRunning() && - !gAgent.getAlwaysRun()) - { - // Turn off temporary running. - gAgent.clearRunning(); - gAgent.sendWalkRun(gAgent.getRunning()); - } + // Note: in case shift is already released, slide left/right run + // will be released in agent_turn_left()/agent_turn_right() + agent_check_temporary_run(mode); } else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") && KEYSTATE_DOWN == s && @@ -218,7 +225,12 @@ void agent_turn_left( EKeystate s ) } else { - if (KEYSTATE_UP == s) return; + if (KEYSTATE_UP == s) + { + // Check temporary running. In case user released 'left' key with shift already released. + agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDELEFT); + return; + } F32 time = gKeyboard->getCurKeyElapsedTime(); gAgent.moveYaw( LLFloaterMove::getYawRate( time ) ); } @@ -241,7 +253,12 @@ void agent_turn_right( EKeystate s ) } else { - if (KEYSTATE_UP == s) return; + if (KEYSTATE_UP == s) + { + // Check temporary running. In case user released 'right' key with shift already released. + agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDERIGHT); + return; + } F32 time = gKeyboard->getCurKeyElapsedTime(); gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) ); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4f992fc184..820249e181 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -359,10 +359,17 @@ void LLViewerObject::markDead() //LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL; // Root object of this hierarchy unlinks itself. + LLVOAvatar *av = getAvatarAncestor(); if (getParent()) { ((LLViewerObject *)getParent())->removeChild(this); } + LLUUID mesh_id; + if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) + { + // This case is needed for indirectly attached mesh objects. + av->resetJointPositionsOnDetach(mesh_id); + } // Mark itself as dead mDead = TRUE; @@ -2274,7 +2281,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } } - if ((new_rot != getRotation()) + if ((new_rot.isNotEqualEps(getRotation(), F_ALMOST_ZERO)) || (new_angv != old_angv)) { if (new_rot != mPreviousRotation) @@ -5006,6 +5013,22 @@ LLVOAvatar* LLViewerObject::asAvatar() return NULL; } +// If this object is directly or indirectly parented by an avatar, return it. +LLVOAvatar* LLViewerObject::getAvatarAncestor() +{ + LLViewerObject *pobj = (LLViewerObject*) getParent(); + while (pobj) + { + LLVOAvatar *av = pobj->asAvatar(); + if (av) + { + return av; + } + pobj = (LLViewerObject*) pobj->getParent(); + } + return NULL; +} + BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); @@ -6193,6 +6216,17 @@ const LLUUID &LLViewerObject::extractAttachmentItemID() return getAttachmentItemID(); } +const std::string& LLViewerObject::getAttachmentItemName() +{ + static std::string empty; + LLInventoryItem *item = gInventory.getItem(getAttachmentItemID()); + if (isAttachment() && item) + { + return item->getName(); + } + return empty; +} + //virtual LLVOAvatar* LLViewerObject::getAvatar() const { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index bab107cc57..05c87c153b 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -135,6 +135,8 @@ public: virtual LLVOAvatar* asAvatar(); + LLVOAvatar* getAvatarAncestor(); + static void initVOClasses(); static void cleanupVOClasses(); @@ -170,6 +172,8 @@ public: void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } virtual BOOL isAttachment() const { return FALSE; } + const std::string& getAttachmentItemName(); + virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment virtual BOOL isHUDAttachment() const { return FALSE; } virtual BOOL isTempAttachment() const; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 22b979aa09..b54f341c31 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -464,7 +464,10 @@ public: mCharacter = character; BOOL success = true; - if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) { success = false; } + if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) + { + success = false; + } if ( success ) { @@ -708,7 +711,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisualComplexity(0), mVisualComplexityStale(TRUE), mLoadedCallbacksPaused(FALSE), - mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), @@ -770,10 +772,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthTimer.reset(); mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); - mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); - mLastPelvisToFoot = 0.0f; - mPelvisFixup = 0.0f; - mLastPelvisFixup = 0.0f; if(LLSceneMonitor::getInstance()->isEnabled()) { @@ -819,14 +817,14 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { - if (!mFullyLoaded) - { + if (!mFullyLoaded) + { debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); - } - else - { + } + else + { debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); - } + } logPendingPhases(); @@ -980,10 +978,11 @@ void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; - if (!inst) - continue; - S32 rez_status = inst->getRezzedStatus(); - counts[rez_status]++; + if (inst) + { + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + } } } @@ -1258,17 +1257,18 @@ const LLVector3 LLVOAvatar::getRenderPosition() const } else if (isRoot()) { - if ( !mHasPelvisOffset ) - { - return mDrawable->getPositionAgent(); - } - else + F32 fixup; + if ( hasPelvisFixup( fixup) ) { //Apply a pelvis fixup (as defined by the avs skin) LLVector3 pos = mDrawable->getPositionAgent(); - pos[VZ] += mPelvisFixup; + pos[VZ] += fixup; return pos; } + else + { + return mDrawable->getPositionAgent(); + } } else { @@ -1353,38 +1353,36 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { LLViewerJointAttachment* attachment = iter->second; - if (!attachment->getValid()) - { - continue ; - } - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + if (attachment->getValid()) { - const LLViewerObject* attached_object = (*attachment_iter); - if (attached_object && !attached_object->isHUDAttachment()) + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - LLDrawable* drawable = attached_object->mDrawable; - if (drawable && !drawable->isState(LLDrawable::RIGGED)) + const LLViewerObject* attached_object = (*attachment_iter); + if (attached_object && !attached_object->isHUDAttachment()) { - LLSpatialBridge* bridge = drawable->getSpatialBridge(); - if (bridge) + LLDrawable* drawable = attached_object->mDrawable; + if (drawable && !drawable->isState(LLDrawable::RIGGED)) { - const LLVector4a* ext = bridge->getSpatialExtents(); - LLVector4a distance; - distance.setSub(ext[1], ext[0]); - LLVector4a max_span(max_attachment_span); + LLSpatialBridge* bridge = drawable->getSpatialBridge(); + if (bridge) + { + const LLVector4a* ext = bridge->getSpatialExtents(); + LLVector4a distance; + distance.setSub(ext[1], ext[0]); + LLVector4a max_span(max_attachment_span); - S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; + S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; - // Only add the prim to spatial extents calculations if it isn't a megaprim. - // max_attachment_span calculated at the start of the function - // (currently 5 times our max prim size) - if (lt == 0x7) - { - update_min_max(newMin,newMax,ext[0]); - update_min_max(newMin,newMax,ext[1]); + // Only add the prim to spatial extents calculations if it isn't a megaprim. + // max_attachment_span calculated at the start of the function + // (currently 5 times our max prim size) + if (lt == 0x7) + { + update_min_max(newMin,newMax,ext[0]); + update_min_max(newMin,newMax,ext[1]); + } } } } @@ -1961,7 +1959,7 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, if (has_name && getNVPair("FirstName")) { mDebugExistenceTimer.reset(); - debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); + debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); } if(retval & LLViewerObject::INVALID_UPDATE) @@ -1973,9 +1971,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, } } - //LL_INFOS() << getRotation() << LL_ENDL; - //LL_INFOS() << getPosition() << LL_ENDL; - return retval; } @@ -1991,7 +1986,7 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU result = gTextureList.findImage(uuid); } if (!result) -{ + { const std::string url = getImageURL(te,uuid); if (url.empty()) @@ -3212,6 +3207,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { debug_line += llformat(" - cof rcv:%d", last_received_cof_version); } + debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]); addDebugText(debug_line); } if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) @@ -3335,7 +3331,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) removeAnimationData("Walk Speed"); } mMotionController.setTimeStep(time_step); -// LL_INFOS() << "Setting timestep to " << time_quantum * pixel_area_scale << LL_ENDL; + // LL_INFOS() << "Setting timestep to " << time_quantum * pixel_area_scale << LL_ENDL; } if (getParent() && !mIsSitting) @@ -3476,7 +3472,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) fwdDir.normalize(); } } - } LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion(); @@ -3592,10 +3587,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // update animations if (mSpecialRenderMode == 1) // Animation Preview + { updateMotions(LLCharacter::FORCE_UPDATE); + } else + { updateMotions(LLCharacter::NORMAL_UPDATE); - + } + // update head position updateHeadOffset(); @@ -3692,10 +3691,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) //mesh vertices need to be reskinned mNeedsSkin = TRUE; - - - - return TRUE; } //----------------------------------------------------------------------------- @@ -3723,21 +3718,6 @@ void LLVOAvatar::updateHeadOffset() } } //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup ) -{ - mHasPelvisOffset = hasOffset; - if ( mHasPelvisOffset ) - { - //Store off last pelvis to foot value - mLastPelvisToFoot = mPelvisToFoot; - mPelvisOffset = offsetAmount; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixup; - } -} -//------------------------------------------------------------------------ // postPelvisSetRecalc //------------------------------------------------------------------------ void LLVOAvatar::postPelvisSetRecalc( void ) @@ -3747,15 +3727,6 @@ void LLVOAvatar::postPelvisSetRecalc( void ) dirtyMesh(2); } //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) -{ - mHasPelvisOffset = true; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixupAmount; -} -//------------------------------------------------------------------------ // updateVisibility() //------------------------------------------------------------------------ void LLVOAvatar::updateVisibility() @@ -3975,13 +3946,13 @@ U32 LLVOAvatar::renderSkinned() if (face) { LLVertexBuffer* vb = face->getVertexBuffer(); - if (vb) - { - vb->flush(); + if (vb) + { + vb->flush(); + } } } } - } else { mNeedsSkin = FALSE; @@ -4161,7 +4132,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) { LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); if (hair_mesh) - { + { num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); } first_pass = FALSE; @@ -4884,6 +4855,12 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { sitDown(FALSE); } + if ((anim_id == ANIM_AGENT_DO_NOT_DISTURB) && gAgent.isDoNotDisturb()) + { + // re-assert DND tag animation + gAgent.sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, ANIM_REQUEST_START); + return result; + } stopMotion(anim_id); result = TRUE; } @@ -5057,10 +5034,162 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) return jointp; } + +//----------------------------------------------------------------------------- +// getRiggedMeshID +// +// If viewer object is a rigged mesh, set the mesh id and return true. +// Otherwise, null out the id and return false. +//----------------------------------------------------------------------------- +// static +bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id) +{ + mesh_id.setNull(); + + //If a VO has a skin that we'll reset the joint positions to their default + if ( pVO && pVO->mDrawable ) + { + LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); + if ( pVObj ) + { + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); + if (pSkinData + && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig + && pSkinData->mAlternateBindMatrix.size() > 0 ) + { + mesh_id = pSkinData->mMeshID; + return true; + } + } + } + return false; +} + +void LLVOAvatar::clearAttachmentPosOverrides() +{ + //Subsequent joints are relative to pelvis + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + + for (; iter != end; ++iter) + { + LLJoint* pJoint = (*iter); + pJoint->clearAttachmentPosOverrides(); + } +} + +//----------------------------------------------------------------------------- +// addAttachmentPosOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo) +{ + LLVOAvatar *av = vo->getAvatarAncestor(); + if (!av || (av != this)) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + addAttachmentPosOverridesForObject(childp); + } + + LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo); + bool pelvisGotSet = false; + + if (!vobj) + { + return; + } + if (vobj->isMesh() && + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { + return; + } + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + const LLUUID& mesh_id = pSkinData->mMeshID; + bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; + if ( fullRig ) + { + for ( int i=0; i<jointCnt; ++i ) + { + std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); + LLJoint* pJoint = getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position + pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() ); + + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pelvisGotSet = true; + } + } + } + if (pelvisZOffset != 0.0F) + { + addPelvisFixup( pelvisZOffset, mesh_id ); + pelvisGotSet = true; + } + } + } + } + + //Rebuild body data if we altered joints/pelvis + if ( pelvisGotSet ) + { + postPelvisSetRecalc(); + } +} + +//----------------------------------------------------------------------------- +// resetJointPositionsOnDetach +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsOnDetach(LLViewerObject *vo) +{ + LLVOAvatar *av = vo->getAvatarAncestor(); + if (!av || (av != this)) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + resetJointPositionsOnDetach(childp); + } + + // Process self. + LLUUID mesh_id; + if (getRiggedMeshID(vo,mesh_id)) + { + resetJointPositionsOnDetach(mesh_id); + } +} + //----------------------------------------------------------------------------- -// resetJointPositionsToDefault +// resetJointPositionsOnDetach //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointPositionsToDefault( void ) +void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id) { //Subsequent joints are relative to pelvis avatar_joint_list_t::iterator iter = mSkeleton.begin(); @@ -5072,23 +5201,18 @@ void LLVOAvatar::resetJointPositionsToDefault( void ) { LLJoint* pJoint = (*iter); //Reset joints except for pelvis - if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() ) + if ( pJoint ) { pJoint->setId( LLUUID::null ); - pJoint->restoreOldXform(); + pJoint->removeAttachmentPosOverride(mesh_id, avString()); } - else - if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() ) + if ( pJoint && pJoint == pJointPelvis) { - pJoint->setId( LLUUID::null ); + removePelvisFixup( mesh_id ); pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); - pJoint->setJointResetFlag( false ); } } - //make sure we don't apply the joint offset - mHasPelvisOffset = false; - mPelvisFixup = mLastPelvisFixup; postPelvisSetRecalc(); } //----------------------------------------------------------------------------- @@ -5213,8 +5337,8 @@ BOOL LLVOAvatar::loadSkeletonNode () { if (!LLAvatarAppearance::loadSkeletonNode()) { - return FALSE; - } + return FALSE; + } // ATTACHMENTS { @@ -5625,7 +5749,7 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o } //----------------------------------------------------------------------------- -// attachObject() +// getNumAttachments() //----------------------------------------------------------------------------- U32 LLVOAvatar::getNumAttachments() const { @@ -5735,30 +5859,18 @@ void LLVOAvatar::rebuildRiggedAttachments( void ) //----------------------------------------------------------------------------- void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) { - //If a VO has a skin that we'll reset the joint positions to their default - if ( pVO && pVO->mDrawable ) + LLUUID mesh_id; + if (getRiggedMeshID(pVO, mesh_id)) { - LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); - if ( pVObj ) + resetJointPositionsOnDetach(mesh_id); + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if (pSkinData - && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig - && pSkinData->mAlternateBindMatrix.size() > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } + } +} //----------------------------------------------------------------------------- // detachObject() @@ -5965,27 +6077,24 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const break; // Do nothing } - /* switch(type) - case LLWearableType::WT_SHIRT: - indicator_te = TEX_UPPER_SHIRT; */ for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++tex_iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; if (texture_dict->mWearableType == type) - { + { // Thus, you must check to see if the corresponding baked texture is defined. // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that // gets baked into a texture that always exists (upper or lower). if (texture_dict->mIsUsedByBakedTexture) - { + { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); - } + } return FALSE; - } + } } return FALSE; } @@ -6055,7 +6164,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color) } else if (global_color == mTexEyeColor) { -// LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; + // LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet); } updateMeshTextures(); @@ -6115,9 +6224,9 @@ void LLVOAvatar::updateRezzedStatusTimers() { // load level has decreased. start phase timers for higher load levels. for (S32 i = rez_status+1; i <= mLastRezzedStatus; i++) - { + { startPhase("load_" + LLVOAvatar::rezStatusToString(i)); - } + } } else if (rez_status > mLastRezzedStatus) { @@ -6126,16 +6235,15 @@ void LLVOAvatar::updateRezzedStatusTimers() { stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); - } + } if (rez_status == 3) - { + { // "fully loaded", mark any pending appearance change complete. selfStopPhase("update_appearance_from_cof"); selfStopPhase("wear_inventory_category", false); selfStopPhase("process_initial_wearables_update", false); } } - mLastRezzedStatus = rez_status; } } @@ -6197,7 +6305,7 @@ void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check) void LLVOAvatar::logPendingPhases() { if (!isAgentAvatarValid()) - { + { return; } @@ -6213,14 +6321,14 @@ void LLVOAvatar::logPendingPhases() if (!completed) { logMetricsTimerRecord(phase_name, elapsed, completed); - } + } } } - } +} //static void LLVOAvatar::logPendingPhasesAllAvatars() - { +{ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { @@ -6231,14 +6339,14 @@ void LLVOAvatar::logPendingPhasesAllAvatars() } inst->logPendingPhases(); } - } +} void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed) - { +{ if (!isAgentAvatarValid()) - { + { return; - } + } LLSD record; record["timer_name"] = phase_name; @@ -6247,10 +6355,10 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse record["completed"] = completed; U32 grid_x(0), grid_y(0); if (getRegion()) - { + { record["central_bake_version"] = LLSD::Integer(getRegion()->getCentralBakeVersion()); grid_from_region_handle(getRegion()->getHandle(), &grid_x, &grid_y); - } + } record["grid_x"] = LLSD::Integer(grid_x); record["grid_y"] = LLSD::Integer(grid_y); record["is_using_server_bakes"] = true; @@ -6311,8 +6419,8 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); - if (!mPreviousFullyLoaded && !loading && mFullyLoaded) - { + if (!mPreviousFullyLoaded && !loading && mFullyLoaded) + { debugAvatarRezTime("AvatarRezNotification","fully loaded"); } @@ -6368,9 +6476,7 @@ void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) LLAvatarJointMesh* mesh = (*iter); if (mesh) { - { - mesh->setColor(color); - } + mesh->setColor(color); } } } @@ -6470,7 +6576,7 @@ void LLVOAvatar::updateMeshTextures() LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) - { + { LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); mBakedTextureDatas[i].mIsUsed = TRUE; @@ -6479,12 +6585,12 @@ void LLVOAvatar::updateMeshTextures() avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); for (; iter != end; ++iter) - { + { LLAvatarJointMesh* mesh = (*iter); if (mesh) - { + { mesh->setTexture( baked_img ); - } + } } } else if (!isUsingLocalAppearance() && is_layer_baked[i]) @@ -6513,9 +6619,9 @@ void LLVOAvatar::updateMeshTextures() baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); - // this could add paused texture callbacks - mLoadedCallbacksPaused |= paused; - checkTextureLoading(); + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; + checkTextureLoading(); } } else if (layerset && isUsingLocalAppearance()) @@ -6534,7 +6640,7 @@ void LLVOAvatar::updateMeshTextures() if (mesh) { mesh->setLayerSet( layerset ); - } + } } } else @@ -6556,7 +6662,7 @@ void LLVOAvatar::updateMeshTextures() { LLAvatarJointMesh* mesh = (*iter); if (mesh) - { + { mesh->setColor( color ); mesh->setTexture( hair_img ); } @@ -6652,13 +6758,13 @@ void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) -{ + { const LLMaskedMorph* maskedMorph = (*iter); LLPolyMorphTarget* morph_target = dynamic_cast<LLPolyMorphTarget*>(maskedMorph->mMorphTarget); if (morph_target) - { + { morph_target->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); -} + } } } @@ -6957,9 +7063,9 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, outfile.open(fullpath, LL_APR_WB ); apr_file_t* file = outfile.getFileHandle(); if (!file) - { - return; - } + { + return; + } else { LL_DEBUGS("Avatar") << "dumping appearance message to " << fullpath << LL_ENDL; @@ -6994,7 +7100,7 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", i, uuid_str.c_str()); } apr_file_printf(file, "</textures>\n"); - } +} void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& contents) { @@ -7523,12 +7629,12 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); for (; iter != end; ++iter) - { + { LLAvatarJointMesh* mesh = (*iter); if (mesh) - { + { mesh->setTexture( image_baked ); - } + } } } @@ -7552,14 +7658,13 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) { LLAvatarJointMesh* mesh = (*iter); if (mesh) - { + { mesh->setColor( LLColor4::white ); } } } } } - dirtyMesh(); } @@ -7571,7 +7676,7 @@ std::string get_sequential_numbered_file_name(const std::string& prefix, file_num_type::iterator it = file_nums.find(prefix); S32 num = 0; if (it != file_nums.end()) -{ + { num = it->second; } file_nums[prefix] = num+1; @@ -7604,44 +7709,61 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara LLAPRFile outfile; std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); - outfile.open(fullpath, LL_APR_WB ); - apr_file_t* file = outfile.getFileHandle(); - if (!file) - { - return; - } - else + if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) { + apr_file_t* file = outfile.getFileHandle(); LL_INFOS() << "xmlfile write handle obtained : " << fullpath << LL_ENDL; - } - apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" ); - apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" ); - apr_file_printf( file, "\n\t<archetype name=\"???\">\n" ); + apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" ); + apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" ); + apr_file_printf( file, "\n\t<archetype name=\"???\">\n" ); - if (group_by_wearables) - { - for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) - { - const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); - apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() ); - - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + if (group_by_wearables) { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - if( (viewer_param->getWearableType() == type) && - (viewer_param->isTweakable() ) ) + for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) { - dump_visual_param(file, viewer_param, viewer_param->getWeight()); + const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); + apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() ); + + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + if( (viewer_param->getWearableType() == type) && + (viewer_param->isTweakable() ) ) + { + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + std::string uuid_str; + te_image->getID().toString( uuid_str ); + apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, uuid_str.c_str()); + } + } + } } } - - for (U8 te = 0; te < TEX_NUM_INDICES; te++) + else { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + // Just dump all params sequentially. + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) { // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); if( te_image ) { std::string uuid_str; @@ -7650,40 +7772,48 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara } } } - } - } - else - { - // Just dump all params sequentially. - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - dump_visual_param(file, viewer_param, viewer_param->getWeight()); + LLJoint* pJoint = (*iter); + const LLVector3& pos = pJoint->getPosition(); + const LLVector3& scale = pJoint->getScale(); + apr_file_printf( file, "\t\t<joint name=\"%s\" position=\"%f %f %f\" scale=\"%f %f %f\"/>\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); } - for (U8 te = 0; te < TEX_NUM_INDICES; te++) + for (iter = mSkeleton.begin(); iter != end; ++iter) { + LLJoint* pJoint = (*iter); + + LLVector3 pos; + LLUUID mesh_id; + + if (pJoint->hasAttachmentPosOverride(pos,mesh_id)) { - // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); - if( te_image ) - { - std::string uuid_str; - te_image->getID().toString( uuid_str ); - apr_file_printf( file, "\t\t<texture te=\"%i\" uuid=\"%s\"/>\n", te, uuid_str.c_str()); - } + apr_file_printf( file, "\t\t<joint_offset name=\"%s\" position=\"%f %f %f\" mesh_id=\"%s\"/>\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], mesh_id.asString().c_str()); } } + F32 pelvis_fixup; + LLUUID mesh_id; + if (hasPelvisFixup(pelvis_fixup, mesh_id)) + { + apr_file_printf( file, "\t\t<pelvis_fixup z=\"%f\" mesh_id=\"%s\"/>\n", + pelvis_fixup, mesh_id.asString().c_str()); + } - } - apr_file_printf( file, "\t</archetype>\n" ); - apr_file_printf( file, "\n</linden_genepool>\n" ); + apr_file_printf( file, "\t</archetype>\n" ); + apr_file_printf( file, "\n</linden_genepool>\n" ); - bool ultra_verbose = false; - if (isSelf() && ultra_verbose) - { - // show the cloned params inside the wearables as well. - gAgentAvatarp->dumpWearableInfo(outfile); + bool ultra_verbose = false; + if (isSelf() && ultra_verbose) + { + // show the cloned params inside the wearables as well. + gAgentAvatarp->dumpWearableInfo(outfile); + } } // File will close when handle goes out of scope } @@ -7799,7 +7929,7 @@ void LLVOAvatar::startAppearanceAnimation() // virtual void LLVOAvatar::removeMissingBakedTextures() - { +{ } //virtual @@ -8053,7 +8183,6 @@ void LLVOAvatar::calculateUpdateRenderCost() } } } - } // Diagnostic output to identify all avatar-related textures. @@ -8065,9 +8194,8 @@ void LLVOAvatar::calculateUpdateRenderCost() for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) { LLUUID image_id = it->first; - if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) - continue; - if (all_textures.find(image_id) == all_textures.end()) + if( ! (image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) + && (all_textures.find(image_id) == all_textures.end())) { // attachment texture not previously seen. LL_INFOS() << "attachment_texture: " << image_id.asString() << LL_ENDL; @@ -8133,15 +8261,17 @@ LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high) // static BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { - if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; } // static BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { - if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const @@ -8191,7 +8321,7 @@ BOOL LLVOAvatar::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U { return FALSE; } - + if( !getImage( te, index ) ) { LL_WARNS() << "getImage( " << te << ", " << index << " ) returned 0" << LL_ENDL; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 42ff7bff92..9a2aaf8aa3 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -199,7 +199,10 @@ public: virtual LLJoint* getJoint(const std::string &name); - void resetJointPositionsToDefault( void ); + void addAttachmentPosOverridesForObject(LLViewerObject *vo); + void resetJointPositionsOnDetach(const LLUUID& mesh_id); + void resetJointPositionsOnDetach(LLViewerObject *vo); + void clearAttachmentPosOverrides(); /*virtual*/ const LLUUID& getID() const; /*virtual*/ void addDebugText(const std::string& text); @@ -356,19 +359,11 @@ protected: /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); - void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; - bool hasPelvisOffset( void ) { return mHasPelvisOffset; } void postPelvisSetRecalc( void ); - void setPelvisOffset( F32 pelvixFixupAmount ); /*virtual*/ BOOL loadSkeletonNode(); /*virtual*/ void buildCharacter(); - bool mHasPelvisOffset; - LLVector3 mPelvisOffset; - F32 mLastPelvisToFoot; - F32 mPelvisFixup; - F32 mLastPelvisFixup; LLVector3 mCurRootToHeadOffset; LLVector3 mTargetRootToHeadOffset; @@ -719,6 +714,7 @@ public: void clampAttachmentPositions(); virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); virtual BOOL detachObject(LLViewerObject *viewer_object); + static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id ); void cleanupAttachedMesh( LLViewerObject* pVO ); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 42a7c2e576..0be8df349d 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -262,7 +262,7 @@ void LLVOAvatarSelf::markDead() { BOOL success = LLVOAvatar::loadAvatar(); - // set all parameters sotred directly in the avatar to have + // set all parameters stored directly in the avatar to have // the isSelfParam to be TRUE - this is used to prevent // them from being animated or trigger accidental rebakes // when we copy params from the wearable to the base avatar. @@ -718,13 +718,8 @@ void LLVOAvatarSelf::updateVisualParams() LLVOAvatar::updateVisualParams(); } -/*virtual*/ -void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +void LLVOAvatarSelf::writeWearablesToAvatar() { - // Animate all top-level wearable visual parameters - gAgentWearables.animateAllWearableParams(calcMorphAmount()); - - // apply wearable visual params to avatar for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) { LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); @@ -734,6 +729,17 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation() } } +} + +/*virtual*/ +void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +{ + // Animate all top-level wearable visual parameters + gAgentWearables.animateAllWearableParams(calcMorphAmount()); + + // Apply wearable visual params to avatar + writeWearablesToAvatar(); + //allow avatar to process updates LLVOAvatar::idleUpdateAppearanceAnimation(); @@ -1093,9 +1099,19 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) return NULL; } -const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const +bool LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const { + if (!gInventory.getItem(inv_item_id)) + { + name = "ATTACHMENT_MISSING_ITEM"; + return false; + } const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + if (!gInventory.getItem(base_inv_item_id)) + { + name = "ATTACHMENT_MISSING_BASE_ITEM"; + return false; + } for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -1103,11 +1119,13 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id const LLViewerJointAttachment* attachment = iter->second; if (attachment->getAttachedObject(base_inv_item_id)) { - return attachment->getName(); + name = attachment->getName(); + return true; } } - return LLStringUtil::null; + name = "ATTACHMENT_NOT_ATTACHED"; + return false; } //virtual @@ -1142,8 +1160,6 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) const LLUUID attachment_id = viewer_object->getAttachmentItemID(); if ( LLVOAvatar::detachObject(viewer_object) ) { - LLVOAvatar::cleanupAttachedMesh( viewer_object ); - // the simulator should automatically handle permission revocation stopMotionFromSource(attachment_id); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index e03de9fa0b..13ffc057b0 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -86,12 +86,11 @@ public: /*virtual*/ void requestStopMotion(LLMotion* motion); /*virtual*/ LLJoint* getJoint(const std::string &name); - void resetJointPositions( void ); - /*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight); /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight); /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight); /*virtual*/ void updateVisualParams(); + void writeWearablesToAvatar(); /*virtual*/ void idleUpdateAppearanceAnimation(); private: @@ -293,7 +292,7 @@ public: void addAttachmentRequest(const LLUUID& inv_item_id); void removeAttachmentRequest(const LLUUID& inv_item_id); LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); - const std::string getAttachedPointName(const LLUUID& inv_item_id) const; + bool getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 9a84cae403..426ca332e4 100755 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -725,6 +725,8 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status) // do not notify user when leaving proximal channel return; case STATUS_VOICE_DISABLED: + LLVoiceClient::getInstance()->setUserPTTState(false); + gAgent.setVoiceConnected(false); //skip showing "Voice not available at your current location" when agent voice is disabled (EXT-4749) if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()) { diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 0bf373f478..962cdf0268 100755 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -161,6 +161,13 @@ void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &age mVoiceModule->userAuthorized(user_id, agentID); } +void LLVoiceClient::setHidden(bool hidden) +{ + if (mVoiceModule) + { + mVoiceModule->setHidden(hidden); + } +} void LLVoiceClient::terminate() { diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 1e20a814a0..fb387301be 100755 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -105,6 +105,8 @@ public: virtual void updateSettings()=0; // call after loading settings and whenever they change virtual bool isVoiceWorking() const = 0; // connected to a voice server and voice channel + + virtual void setHidden(bool hidden)=0; // Hides the user from voice. virtual const LLVoiceVersionInfo& getVersion()=0; @@ -342,6 +344,7 @@ public: void setCaptureDevice(const std::string& name); void setRenderDevice(const std::string& name); + void setHidden(bool hidden); const LLVoiceDeviceList& getCaptureDevices(); const LLVoiceDeviceList& getRenderDevices(); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 54b4119331..b6aecb4aaa 100755 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -70,6 +70,7 @@ #include "apr_base64.h" #define USE_SESSION_GROUPS 0 +#define VX_NULL_POSITION -2147483648.0 /*The Silence*/ extern LLMenuBarGL* gMenuBarView; extern void handle_voice_morphing_subscribe(); @@ -322,6 +323,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mCaptureBufferRecording(false), mCaptureBufferRecorded(false), mCaptureBufferPlaying(false), + mShutdownComplete(true), mPlayRequestCount(0), mAvatarNameCacheConnection() @@ -376,7 +378,16 @@ void LLVivoxVoiceClient::terminate() if(mConnected) { logout(); - connectorShutdown(); + connectorShutdown(); +#ifdef LL_WINDOWS + int count=0; + while (!mShutdownComplete && 10 > count++) + { + stateMachine(); + _sleep(1000); + } + +#endif closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. cleanUp(); } @@ -476,10 +487,9 @@ void LLVivoxVoiceClient::connectorCreate() std::string savedLogLevel = gSavedSettings.getString("VivoxDebugLevel"); - if(savedLogLevel != "-0") + if(savedLogLevel != "0") { LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL; - loglevel = "0"; } stream @@ -488,13 +498,14 @@ void LLVivoxVoiceClient::connectorCreate() << "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>" << "<Mode>Normal</Mode>" << "<Logging>" - << "<Folder>" << logpath << "</Folder>" - << "<FileNamePrefix>Connector</FileNamePrefix>" - << "<FileNameSuffix>.log</FileNameSuffix>" - << "<LogLevel>" << loglevel << "</LogLevel>" + << "<Folder>" << logpath << "</Folder>" + << "<FileNamePrefix>Connector</FileNamePrefix>" + << "<FileNameSuffix>.log</FileNameSuffix>" + << "<LogLevel>" << loglevel << "</LogLevel>" << "</Logging>" - << "<Application>SecondLifeViewer.1</Application>" - << "</Request>\n\n\n"; + << "<Application></Application>" //Name can cause problems per vivox. + << "<MaxCalls>12</MaxCalls>" + << "</Request>\n\n\n"; writeString(stream.str()); } @@ -512,6 +523,7 @@ void LLVivoxVoiceClient::connectorShutdown() << "</Request>" << "\n\n\n"; + mShutdownComplete = false; mConnectorHandle.clear(); writeString(stream.str()); @@ -788,15 +800,32 @@ void LLVivoxVoiceClient::stateMachine() // vivox executable exists. Build the command line and launch the daemon. LLProcess::Params params; params.executable = exe_path; - // SLIM SDK: these arguments are no longer necessary. -// std::string args = " -p tcp -h -c"; + std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); + std::string shutdown_timeout = gSavedSettings.getString("VivoxShutdownTimeout"); if(loglevel.empty()) { loglevel = "0"; // turn logging off completely } + params.args.add("-ll"); params.args.add(loglevel); + + std::string log_folder = gSavedSettings.getString("VivoxLogDirectory"); + + if (log_folder.empty()) + { + log_folder = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + } + + params.args.add("-lf"); + params.args.add(log_folder); + + if(!shutdown_timeout.empty()) + { + params.args.add("-st"); + params.args.add(shutdown_timeout); + } params.cwd = gDirUtilp->getAppRODataDir(); sGatewayPtr = LLProcess::create(params); @@ -1334,7 +1363,7 @@ void LLVivoxVoiceClient::stateMachine() { // Connect to a session by URI sessionCreateSendMessage(mAudioSession, true, false); - } + } notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING); setState(stateJoiningSession); @@ -1510,7 +1539,7 @@ void LLVivoxVoiceClient::stateMachine() // Always reset the terminate request flag when we get here. mSessionTerminateRequested = false; - if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested) + if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !LLApp::isExiting()) { // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state). setState(stateNoChannel); @@ -1553,6 +1582,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateConnectorStopping case stateConnectorStopping: // waiting for connector stop // The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped. + mShutdownComplete = true; break; //MARK: stateConnectorStopped @@ -2318,6 +2348,14 @@ static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVe #endif } +void LLVivoxVoiceClient::setHidden(bool hidden) +{ + mHidden = hidden; + + sendPositionalUpdate(); + return; +} + void LLVivoxVoiceClient::sendPositionalUpdate(void) { std::ostringstream stream; @@ -2339,14 +2377,23 @@ void LLVivoxVoiceClient::sendPositionalUpdate(void) l = mAvatarRot.getLeftRow(); u = mAvatarRot.getUpRow(); a = mAvatarRot.getFwdRow(); - pos = mAvatarPosition; + + pos = mAvatarPosition; vel = mAvatarVelocity; // SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore. // The old transform is replicated by this function. oldSDKTransform(l, u, a, pos, vel); + + if (mHidden) + { + for (int i=0;i<3;++i) + { + pos.mdV[i] = VX_NULL_POSITION; + } + } - stream + stream << "<Position>" << "<X>" << pos.mdV[VX] << "</X>" << "<Y>" << pos.mdV[VY] << "</Y>" @@ -2406,14 +2453,23 @@ void LLVivoxVoiceClient::sendPositionalUpdate(void) l = earRot.getLeftRow(); u = earRot.getUpRow(); a = earRot.getFwdRow(); - pos = earPosition; + + pos = earPosition; vel = earVelocity; // LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL; oldSDKTransform(l, u, a, pos, vel); - stream + if (mHidden) + { + for (int i=0;i<3;++i) + { + pos.mdV[i] = VX_NULL_POSITION; + } + } + + stream << "<Position>" << "<X>" << pos.mdV[VX] << "</X>" << "<Y>" << pos.mdV[VY] << "</Y>" @@ -3169,7 +3225,7 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( session->mErrorStatusCode = statusCode; break; } - + switch(state) { case streamStateIdle: @@ -5433,7 +5489,8 @@ void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESta // skipped to avoid speak button blinking if ( status != LLVoiceClientStatusObserver::STATUS_JOINING - && status != LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL) + && status != LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL + && status != LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED) { bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 5e876fa2ef..a4ec9f2a69 100755 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -723,6 +723,7 @@ private: bool mRenderDeviceDirty; bool mIsInitialized; + bool mShutdownComplete; bool checkParcelChanged(bool update = false); @@ -747,6 +748,7 @@ private: std::string getAudioSessionURI(); std::string getAudioSessionHandle(); + void setHidden(bool hidden); //virtual void sendPositionalUpdate(void); void buildSetCaptureDevice(std::ostringstream &stream); @@ -775,6 +777,7 @@ private: bool mMuteMic; bool mMuteMicDirty; + bool mHidden; //Set to true during teleport to hide the agent's position. // Set to true when the friends list is known to have changed. bool mFriendsListDirty; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a83e2e020e..66ee386874 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2040,7 +2040,18 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); + S32 res = 0; + + if (pMaterialParams && getTEImage(te) && 3 == getTEImage(te)->getComponents() && pMaterialParams->getDiffuseAlphaMode()) + { + LLViewerObject::setTEMaterialID(te, LLMaterialID::null); + res = LLViewerObject::setTEMaterialParams(te, NULL); + } + else + { + res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); + } + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" ) << LL_ENDL; @@ -4328,7 +4339,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mBump = bump; draw_info->mShiny = shiny; - float alpha[4] = + static const float alpha[4] = { 0.00f, 0.25f, @@ -4517,7 +4528,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //Determine if we've received skininfo that contains an //alternate bind matrix - if it does then apply the translational component //to the joints of the avatar. +#if 0 bool pelvisGotSet = false; +#endif { LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); @@ -4602,53 +4615,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //get drawpool of avatar with rigged face LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + // FIXME should this be inside the face loop? + // doesn't seem to depend on any per-face state. if ( pAvatarVO ) { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - if ( pSkinData ) - { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; - if ( fullRig ) - { - for ( int i=0; i<jointCnt; ++i ) - { - std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); - LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - pelvisGotSet = true; - } - } - } - } - } - } - } + pAvatarVO->addAttachmentPosOverridesForObject(vobj); } - - //Rebuild body data if we altered joints/pelvis - if ( pelvisGotSet && pAvatarVO ) - { - pAvatarVO->postPelvisSetRecalc(); - } if (pool) { @@ -5006,14 +4978,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } - - - - - - - - } group->mBufferUsage = useage; @@ -5652,7 +5616,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac if (material_pass) { - U32 pass[] = + static const U32 pass[] = { LLRenderPass::PASS_MATERIAL, LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index ca60b79f9d..fac0fd63ee 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -364,8 +364,14 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name, LLViewerInventoryItem* inv_item = getItem(); if (inv_item && isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(inv_item->getLinkedUUID())) { - std::string joint = LLTrans::getString(gAgentAvatarp->getAttachedPointName(inv_item->getLinkedUUID())); - title_joint = title_joint + " (" + joint + ")"; + std::string found_name; + bool found = gAgentAvatarp->getAttachedPointName(inv_item->getLinkedUUID(),found_name); + std::string trans_name = LLTrans::getString(found_name); + if (!found) + { + LL_WARNS() << "invalid attachment joint, err " << found_name << LL_ENDL; + } + title_joint = title_joint + " (" + trans_name + ")"; } LLPanelInventoryListItemBase::updateItem(title_joint, item_state); diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index 259acccb68..3dfdf8e1a5 100755 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -4,7 +4,7 @@ height="500" layout="topleft" name="Joystick" - help_topic="joystick" + help_topic="Viewerhelp:Joystick_Configuration" title="JOYSTICK CONFIGURATION" width="569"> <floater.string diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index bf6e0c4917..912db80bcc 100755 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -3,10 +3,10 @@ legacy_header_height="18" can_resize="true" default_tab_group="1" - height="350" + height="370" layout="topleft" - min_height="160" - min_width="280" + min_height="190" + min_width="285" name="objectcontents" help_topic="objectcontents" save_rect="true" @@ -31,36 +31,81 @@ background_visible="false" draw_border="false" follows="all" - height="276" + height="240" layout="topleft" left="10" name="object_contents" top_pad="0" width="284" /> + <view_border + bevel_style="none" + follows="bottom|left" + height="50" + highlight_light_color="0.6 0.6 0.6" + layout="topleft" + left="10" + name="border" + top_pad="5" + width="270"/> + <text + follows="bottom|left" + height="15" + layout="topleft" + left="15" + name="border_note" + text_color="White" + top_delta="5"> + Copy to inventory and wear + </text> + <button + follows="bottom|left" + height="23" + label="Add to outfit" + label_selected="Add to outfit" + layout="topleft" + left="15" + name="copy_and_wear_button" + top_pad="3" + width="135"> + <button.commit_callback + function="OpenObject.MoveAndWear" /> + </button> + <button + follows="bottom|left" + height="23" + label="Replace outfit" + label_selected="Replace outfit" + layout="topleft" + left_pad="5" + name="copy_and_replace_button" + width="120"> + <button.commit_callback + function="OpenObject.ReplaceOutfit" /> + </button> <button follows="bottom|left" height="23" - label="Copy to inventory" - label_selected="Copy to inventory" + label="Only copy to inventory" + label_selected="Only copy to inventory" layout="topleft" left="15" name="copy_to_inventory_button" tab_group="1" - top_pad="5" - width="120"> + top_pad="9" + width="135"> <button.commit_callback function="OpenObject.MoveToInventory" /> </button> <button follows="bottom|left" height="23" - label="Copy and add to outfit" - label_selected="Copy and add to outfit" + label="Cancel" + label_selected="Cancel" layout="topleft" left_pad="5" - name="copy_and_wear_button" - width="135"> + name="cancel_button" + width="120"> <button.commit_callback - function="OpenObject.MoveAndWear" /> + function="OpenObject.Cancel" /> </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml index 41a7134b1d..9d91f801a6 100755 --- a/indra/newview/skins/default/xui/en/floater_pay.xml +++ b/indra/newview/skins/default/xui/en/floater_pay.xml @@ -2,12 +2,12 @@ <floater legacy_header_height="18" can_minimize="false" - height="200" + height="186" layout="topleft" name="Give Money" help_topic="give_money" save_rect="true" - width="250"> + width="261"> <string name="payee_group"> Pay Group @@ -21,88 +21,129 @@ type="string" length="1" follows="left|top" - font="SansSerifSmall" height="16" layout="topleft" left="10" - name="payee_name" - top="25" - use_ellipses="true" - width="230"> - Test Name That Is Extremely Long To Check Clipping + top="24" + name="paying_text" + width="180"> + You are paying: </text> - <button - height="23" - label="L$1" - label_selected="L$1" - layout="topleft" - left="35" - name="fastpay 1" - top_pad="8" - width="80" /> - <button - height="23" - label="L$5" - label_selected="L$5" - layout="topleft" - left_pad="15" - name="fastpay 5" - width="80" /> - <button - height="23" - label="L$10" - label_selected="L$10" - layout="topleft" - left="35" - name="fastpay 10" - top_pad="8" - width="80" /> - <button - height="23" - label="L$20" - label_selected="L$20" - layout="topleft" - left_pad="15" - name="fastpay 20" - width="80" /> <text type="string" length="1" follows="left|top" - height="18" + font="SansSerifSmall" + height="16" layout="topleft" - left="35" - name="amount text" - top_pad="8" + left="10" + top_pad="5" + name="payee_name" + use_ellipses="true" width="180"> - Or, choose amount: + Test Name That Is Extremely Long To Check Clipping </text> - <line_editor - border_style="line" - follows="left|top|right" - height="19" - top_pad="0" - layout="topleft" - left="130" - max_length_bytes="9" - name="amount" - width="80" /> - <button - enabled="false" - height="23" - label="Pay" - label_selected="Pay" - layout="topleft" - left="20" - name="pay btn" - top_pad="15" - width="100" /> - <button - height="23" - label="Cancel" - label_selected="Cancel" + <panel + border_thickness="0" + height="104" + label="Search" layout="topleft" + left="0" + top_pad="10" + help_topic="avatarpicker" + name="PatternsPanel" + width="120"> + <button + height="23" + label="Pay L$ 1" + label_selected="Pay L$ 1" + layout="topleft" + left="10" + top="0" + name="fastpay 1" + width="110" /> + <button + height="23" + label="Pay L$ 5" + label_selected="Pay L$ 5" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 5" + width="110" /> + <button + height="23" + label="Pay L$ 10" + label_selected="Pay L$ 10" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 10" + width="110" /> + <button + height="23" + label="Pay L$ 20" + label_selected="Pay L$ 20" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 20" + width="110" /> + </panel> + <view_border + bevel_style="in" + width="1" + height="104" left_pad="10" - name="cancel btn" - width="100" /> + layout="topleft" /> + <panel + border_thickness="0" + height="104" + label="Search" + layout="topleft" + left_pad="0" + name="InputPanel" + width="120"> + <text + type="string" + length="1" + follows="left|top" + height="18" + layout="topleft" + left="10" + top="0" + name="amount text" + width="110"> + Other amount: + </text> + <line_editor + border_style="line" + follows="left|top|right" + height="19" + layout="topleft" + left="10" + top_pad="0" + max_length_bytes="9" + name="amount" + width="90" /> + <button + enabled="false" + height="23" + label="Pay" + label_selected="Pay" + layout="topleft" + left="10" + top_pad="17" + name="pay btn" + width="110" /> + <button + height="23" + label="Cancel" + label_selected="Cancel" + layout="topleft" + left="10" + top_pad="4" + name="cancel btn" + width="110" /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml index d3a35c2051..f1e27b918e 100755 --- a/indra/newview/skins/default/xui/en/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml @@ -2,12 +2,12 @@ <floater legacy_header_height="18" can_minimize="false" - height="225" + height="228" layout="topleft" name="Give Money" help_topic="give_money" save_rect="true" - width="250"> + width="261"> <string name="payee_group"> Pay Group @@ -16,12 +16,25 @@ name="payee_resident"> Pay Resident </string> + <text + type="string" + length="1" follows="left|top" height="16" layout="topleft" left="10" - top_pad="24" + top="24" + name="paying_text" + width="180"> + You are paying: + </text> + <text + follows="left|top" + height="16" + layout="topleft" + left="10" + top_pad="5" name="payee_name" use_ellipses="true" width="225"> @@ -40,7 +53,7 @@ width="180"> Via object: </text> - <icon + <icon height="16" width="16" image_name="Inv_Object" @@ -64,78 +77,107 @@ width="188"> My awesome object with a really damn long name </text> - <button - height="23" - label="L$1" - label_selected="L$1" - layout="topleft" - left="25" - name="fastpay 1" - top_pad="8" - width="80" /> - <button - height="23" - label="L$5" - label_selected="L$5" - layout="topleft" - left_pad="15" - name="fastpay 5" - width="80" /> - <button - height="23" - label="L$10" - label_selected="L$10" - layout="topleft" - left="25" - name="fastpay 10" - top_pad="8" - width="80" /> - <button - height="23" - label="L$20" - label_selected="L$20" + <panel + border_thickness="0" + height="104" + label="Search" layout="topleft" - left_pad="15" - name="fastpay 20" - width="80" /> - <text - type="string" - length="1" - follows="left|top" - height="14" - layout="topleft" - left="25" - name="amount text" - top_pad="8" - width="180"> - Or, choose amount: - </text> - <line_editor - border_style="line" - follows="left|top|right" - height="21" - top_pad="0" - layout="topleft" - left="120" - max_length_bytes="9" - name="amount" - width="80" /> - <button - enabled="false" - height="23" - label="Pay" - label_selected="Pay" - layout="topleft" - left="10" - name="pay btn" - top_pad="5" - width="100" /> - <button - height="23" - label="Cancel" - label_selected="Cancel" + left="0" + top_pad="10" + help_topic="avatarpicker" + name="PatternsPanel" + width="120"> + <button + height="23" + label="Pay L$ 1" + label_selected="Pay L$ 1" + layout="topleft" + left="10" + top="0" + name="fastpay 1" + width="110" /> + <button + height="23" + label="Pay L$ 5" + label_selected="Pay L$ 5" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 5" + width="110" /> + <button + height="23" + label="Pay L$ 10" + label_selected="Pay L$ 10" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 10" + width="110" /> + <button + height="23" + label="Pay L$ 20" + label_selected="Pay L$ 20" + layout="topleft" + left="10" + top_pad="4" + name="fastpay 20" + width="110" /> + </panel> + <view_border + bevel_style="in" + width="1" + height="104" + left_pad="10" + layout="topleft" /> + <panel + border_thickness="0" + height="104" + label="Search" layout="topleft" - left_pad="5" - name="cancel btn" - width="100" /> + left_pad="0" + name="InputPanel" + width="120"> + <text + type="string" + length="1" + follows="left|top" + height="18" + layout="topleft" + left="10" + top="0" + name="amount text" + width="180"> + Other amount: + </text> + <line_editor + border_style="line" + follows="left|top|right" + height="19" + layout="topleft" + left="10" + top_pad="0" + max_length_bytes="9" + name="amount" + width="90" /> + <button + enabled="false" + height="23" + label="Pay" + label_selected="Pay" + layout="topleft" + left="10" + top_pad="17" + name="pay btn" + width="110" /> + <button + height="23" + label="Cancel" + label_selected="Cancel" + layout="topleft" + left="10" + top_pad="4" + name="cancel btn" + width="110" /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index df85a8c666..e28a02550f 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -606,7 +606,7 @@ name="Sound Play"> <menu_item_call.on_click function="Inventory.DoToSelected" - parameter="open" /> + parameter="sound_play" /> </menu_item_call> <menu_item_separator layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index d3e008f559..08c4151dbb 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2112,6 +2112,18 @@ parameter="notifications_console" /> </menu_item_call> <menu_item_check + label="Region Debug Console" + name="Region Debug Console" + shortcut="control|shift|`" + use_mac_ctrl="true"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="region_debug_console" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="region_debug_console" /> + </menu_item_check> + <menu_item_check label="Fast Timers" name="Fast Timers" shortcut="control|shift|9" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index cce166a8bd..5b0bdc4a0d 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5383,6 +5383,19 @@ Warning: The 'Pay object' click action has been set, but it will only <notification icon="alertmodal.tga" + name="PayConfirmation" + type="alertmodal"> + Confirm that you want to pay L$[AMOUNT] to [TARGET]. + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before paying (sums over L$200)" + name="okcancelignore" + notext="Cancel" + yestext="Pay"/> + </notification> + + <notification + icon="alertmodal.tga" name="OpenObjectCannotCopy" type="alertmodal"> There are no items in this object that you are allowed to copy. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 5db178a556..0b4bbf0105 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2337,6 +2337,7 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f <string name="LoadingContents">Loading contents...</string> <string name="NoContents">No contents</string> <string name="WornOnAttachmentPoint" value=" (worn on [ATTACHMENT_POINT])" /> + <string name="AttachmentErrorMessage" value=" ([ATTACHMENT_ERROR])" /> <string name="ActiveGesture" value="[GESLABEL] (active)"/> <!-- Inventory permissions --> <string name="PermYes">Yes</string> @@ -2463,9 +2464,12 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f <string name="Stomach">Stomach</string> <string name="Left Pec">Left Pec</string> <string name="Right Pec">Right Pec</string> - <string name="Neck">Neck</string> - <string name="Avatar Center">Avatar Center</string> + <string name="Neck">Neck</string> + <string name="Avatar Center">Avatar Center</string> <string name="Invalid Attachment">Invalid Attachment Point</string> + <string name="ATTACHMENT_MISSING_ITEM">Error: missing item</string> + <string name="ATTACHMENT_MISSING_BASE_ITEM">Error: missing base item</string> + <string name="ATTACHMENT_NOT_ATTACHED">Error: object is in current outfit but not attached</string> <!-- Avatar age computation, see LLDateUtil::ageFromDate --> <string name="YearsMonthsOld">[AGEYEARS] [AGEMONTHS] old</string> |