diff options
author | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2014-12-22 15:02:25 -0500 |
---|---|---|
committer | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2014-12-22 15:02:25 -0500 |
commit | 655c2bd33757ce7ad5da2772f2cae8785898cbdb (patch) | |
tree | 319ef56eab5b71af7ce5e94ab6f16b739d83edb8 /indra | |
parent | 87a033d3bf1af2b3cba1047b720e7d93f535dc46 (diff) | |
parent | 79a89f5d921f99ba7a990a1dbf7428d1d3758bc6 (diff) |
merge
Diffstat (limited to 'indra')
81 files changed, 1577 insertions, 609 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..40695bfa24 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 false; +} //-------------------------------------------------------------------- // 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/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 b19df0200d..aa8dd7697c 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -180,18 +180,18 @@ 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)) { 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/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/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 7c88f8fb9b..6dd6f94d02 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -258,20 +258,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 8d98363c5f..f6550eae42 100755 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -185,11 +185,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; @@ -230,6 +232,7 @@ public: mFolderViewItem(NULL), mLastFilterGeneration(-1), mLastFolderFilterGeneration(-1), + mMarkedDirtyGeneration(-1), mMostFilteredDescendantGeneration(-1), mParent(NULL), mRootViewModel(root_view_model) @@ -243,8 +246,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; @@ -254,6 +262,14 @@ public: mParent->dirtyFilter(); } } + void dirtyDescendantsFilter() + { + mMostFilteredDescendantGeneration = -1; + if (mParent) + { + mParent->dirtyDescendantsFilter(); + } + } bool hasFilterStringMatch(); std::string::size_type getFilterStringOffset(); std::string::size_type getFilterStringSize(); @@ -272,7 +288,7 @@ public: return; } } - mChildren.push_back(child); + mChildren.push_back(child); child->setParent(this); dirtyFilter(); requestSort(); @@ -280,7 +296,8 @@ public: virtual void removeChild(LLFolderViewModelItem* child) { mChildren.remove(child); - child->setParent(NULL); + child->setParent(NULL); + dirtyDescendantsFilter(); dirtyFilter(); } @@ -290,6 +307,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(); } @@ -303,6 +321,7 @@ public: mLastFilterGeneration = filter_generation; mStringMatchOffsetFilter = string_offset; mStringFilterSize = string_size; + mMarkedDirtyGeneration = -1; } void setPassedFolderFilter(bool passed, S32 filter_generation) @@ -351,7 +370,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.mm b/indra/llwindow/llopenglview-objc.mm index ff312945b6..24b8406098 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -124,6 +124,14 @@ attributedStringInfo getSegments(NSAttributedString *str) { [[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]; @@ -349,9 +367,14 @@ attributedStringInfo getSegments(NSAttributedString *str) callMiddleMouseUp(mMousePos, [theEvent modifierFlags]); } +- (void) rightMouseDragged:(NSEvent *)theEvent +{ + [self mouseDragged:theEvent]; +} + - (void) otherMouseDragged:(NSEvent *)theEvent { - + [self mouseDragged:theEvent]; } - (void) scrollWheel:(NSEvent *)theEvent 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 aca8bb6527..d7aa47f378 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -352,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); diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index a4de059bbc..f36181278b 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.23 +3.7.24 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ca74b759ff..138bdde9e9 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6186,7 +6186,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>30.0</real> + <real>600.0</real> </map> <key>MemoryPrivatePoolEnabled</key> <map> @@ -13569,6 +13569,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/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index fc6f1f6395..7975fe9e3a 100755 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -1,5 +1,20 @@ <llsd> <map> + <key>AvatarPosFinalOffset</key> + <map> + <key>Comment</key> + <string>After-everything-else fixup for avatar position.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.0</real> + <real>0.0</real> + <real>0.0</real> + </array> + </map> <key>DoNotDisturbResponseChanged</key> <map> <key>Comment</key> 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/llagent.cpp b/indra/newview/llagent.cpp index e5a90e8a28..5cb03cd2ae 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()) @@ -3871,6 +3879,11 @@ void LLAgent::handleTeleportFinished() void LLAgent::handleTeleportFailed() { + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->setHidden(FALSE); + } + if (mTeleportRequest != NULL) { mTeleportRequest->setStatus(LLTeleportRequest::kFailed); @@ -4116,8 +4129,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 aad5dbae7d..549df80fa1 100644..100755 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -84,7 +84,17 @@ callWindowUnfocus(); } -- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender +- (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 e7420f32f0..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 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/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp index bcdab6b3a0..9efb168b55 100755 --- a/indra/newview/llfloaterhoverheight.cpp +++ b/indra/newview/llfloaterhoverheight.cpp @@ -42,7 +42,7 @@ LLFloaterHoverHeight::LLFloaterHoverHeight(const LLSD& key) : LLFloater(key) void LLFloaterHoverHeight::syncFromPreferenceSetting(void *user_data) { - LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset"); + LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset"); F32 value = offset[2]; LLFloaterHoverHeight *self = static_cast<LLFloaterHoverHeight*>(user_data); @@ -64,7 +64,14 @@ BOOL LLFloaterHoverHeight::postBuild() // Initialize slider from pref setting. syncFromPreferenceSetting(this); // Update slider on future pref changes. - gSavedSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this)); + if (gSavedPerAccountSettings.getControl("AvatarPosFinalOffset")) + { + gSavedPerAccountSettings.getControl("AvatarPosFinalOffset")->getCommitSignal()->connect(boost::bind(&syncFromPreferenceSetting, this)); + } + else + { + LL_WARNS() << "Control not found for AvatarPosFinalOffset" << LL_ENDL; + } return TRUE; } @@ -74,7 +81,7 @@ void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData) { LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); F32 value = sldrCtrl->getValueF32(); - LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset"); + LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset"); offset[2] = value; gAgentAvatarp->mHoverOffset = offset; } @@ -85,9 +92,9 @@ void LLFloaterHoverHeight::onFinalCommit() { LLSliderCtrl* sldrCtrl = getChild<LLSliderCtrl>("HoverHeightSlider"); F32 value = sldrCtrl->getValueF32(); - LLVector3 offset = gSavedSettings.getVector3("AvatarPosFinalOffset"); + LLVector3 offset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset"); offset[2] = value; - gSavedSettings.setVector3("AvatarPosFinalOffset",offset); + gSavedPerAccountSettings.setVector3("AvatarPosFinalOffset",offset); } 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 7615c12043..3271a40ea0 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -129,13 +129,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) { @@ -144,6 +149,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/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 33e557cddd..1910656066 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -87,6 +87,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; @@ -2785,8 +2787,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); @@ -2794,6 +2796,7 @@ protected: LLUUID mCatID; int mContentsCount; bool mFolderAdded; + bool mReplace; }; @@ -2832,7 +2835,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) mContentsCount) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, TRUE); + LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, !mReplace); delete this; } } @@ -3779,24 +3782,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 ); @@ -3816,7 +3816,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); } @@ -4526,6 +4527,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 | // +=================================================+ @@ -5326,16 +5344,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(); } @@ -6138,7 +6160,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 833fbbadbb..e8d5db4437 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -389,6 +389,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 f211acedf0..dc8b15a5bf 100755 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -126,13 +126,6 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { - // when applying a filter, matching folders get their contents downloaded first - if (isNotDefault() - && !gInventory.isCategoryComplete(folder_id)) - { - LLInventoryModelBackgroundFetch::instance().start(folder_id); - } - // Always check against the clipboard const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -142,6 +135,13 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return passed_clipboard; } + // when applying a filter, matching folders get their contents downloaded first + if (mFilterSubString.size() + && !gInventory.isCategoryComplete(folder_id)) + { + LLInventoryModelBackgroundFetch::instance().start(folder_id); + } + // 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 e18ecd2e2a..3546317471 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -542,12 +542,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) { @@ -573,6 +574,7 @@ void LLInventoryPanel::modelChanged(U32 mask) // doesn't include trash). Just remove the item's UI. view_item->destroyView(); } + old_parent->getViewModelItem()->dirtyDescendantsFilter(); } } } @@ -583,27 +585,16 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (!model_item && view_item && viewmodel_item) { // Remove the item's UI. - removeItemID(viewmodel_item->getUUID()); + 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/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/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 6b74d90708..6354b5a02b 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 575e5c5c52..8561d265de 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2173,23 +2173,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/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d364fce45a..d6c8ba10f6 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1456,7 +1456,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(); @@ -1468,12 +1469,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 { @@ -1483,7 +1485,8 @@ void remove_inventory_item( void remove_inventory_item( LLPointer<LLInventoryObject> obj, - LLPointer<LLInventoryCallback> cb) + LLPointer<LLInventoryCallback> cb, + bool immediate_delete) { if(obj) { @@ -1493,6 +1496,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 d345c49cfb..ca92565600 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -394,11 +394,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 25c7120a19..aeb9c8bbf6 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -713,7 +713,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisualComplexity(0), mVisualComplexityStale(TRUE), mLoadedCallbacksPaused(FALSE), - mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), @@ -777,10 +776,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); mLastAppearanceMessageTimer.reset(); - mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); - mLastPelvisToFoot = 0.0f; - mPelvisFixup = 0.0f; - mLastPelvisFixup = 0.0f; if(LLSceneMonitor::getInstance()->isEnabled()) { @@ -1266,17 +1261,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 { @@ -3220,6 +3216,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]); if (mHoverOffset[2] != 0.0) { debug_line += llformat(" hov_z: %f", mHoverOffset[2]); @@ -3745,21 +3742,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 ) @@ -3769,15 +3751,6 @@ void LLVOAvatar::postPelvisSetRecalc( void ) dirtyMesh(2); } //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) -{ - mHasPelvisOffset = true; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixupAmount; -} -//------------------------------------------------------------------------ // updateVisibility() //------------------------------------------------------------------------ void LLVOAvatar::updateVisibility() @@ -4906,6 +4879,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; } @@ -5079,10 +5058,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(); + } +} + //----------------------------------------------------------------------------- -// resetJointPositionsToDefault +// resetJointPositionsOnDetach //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointPositionsToDefault( void ) +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); + } +} + +//----------------------------------------------------------------------------- +// resetJointPositionsOnDetach +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id) { //Subsequent joints are relative to pelvis avatar_joint_list_t::iterator iter = mSkeleton.begin(); @@ -5094,23 +5225,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(); } //----------------------------------------------------------------------------- @@ -5647,7 +5773,7 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o } //----------------------------------------------------------------------------- -// attachObject() +// getNumAttachments() //----------------------------------------------------------------------------- U32 LLVOAvatar::getNumAttachments() const { @@ -5757,30 +5883,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() @@ -7343,7 +7457,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) if (isSelf()) { - LL_INFOS("Avatar") << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL; + LL_INFOS("Avatar") << avString() << "hover was set: " << contents.mHoverOffsetWasSet << " value_z " << contents.mHoverOffset[2] << LL_ENDL; } if (contents.mHoverOffsetWasSet && !isSelf()) @@ -7357,7 +7471,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { // If we don't get a value at all, we are presumably in a // region that does not support hover height. -// FIXME RESTORE AFTER TESTING LL_WARNS() << "zeroing hover because not defined in appearance message" << LL_ENDL; mHoverOffset = LLVector3(0.0, 0.0, 0.0); } @@ -7716,6 +7829,39 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara } } } + + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) + { + 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 (iter = mSkeleton.begin(); iter != end; ++iter) + { + LLJoint* pJoint = (*iter); + + LLVector3 pos; + LLUUID mesh_id; + + if (pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { + 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" ); @@ -7725,8 +7871,8 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara // show the cloned params inside the wearables as well. gAgentAvatarp->dumpWearableInfo(outfile); } - outfile.close(); } + // File will close when handle goes out of scope } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 8135c3d4d8..a3f599e2d7 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); @@ -357,19 +360,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; @@ -720,6 +715,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 a5379f24ba..6e0c9cb68c 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -239,7 +239,8 @@ void LLVOAvatarSelf::initInstance() return; } - mHoverOffset = gSavedSettings.getVector3("AvatarPosFinalOffset"); + mHoverOffset = gSavedPerAccountSettings.getVector3("AvatarPosFinalOffset"); + LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << mHoverOffset[2] << LL_ENDL; //doPeriodically(output_self_av_texture_diagnostics, 30.0); doPeriodically(update_avatar_rez_metrics, 5.0); @@ -283,7 +284,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. @@ -739,13 +740,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); @@ -755,6 +751,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(); @@ -1114,9 +1121,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) @@ -1124,11 +1141,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 @@ -1163,8 +1182,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); @@ -2718,7 +2735,7 @@ void LLVOAvatarSelf::sendHoverHeight() const LLSD update = LLSD::emptyMap(); update["hover_height"] = mHoverOffset[2]; - LL_DEBUGS("Avatar") << "sending hover height value " << mHoverOffset[2] << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "sending hover height value " << mHoverOffset[2] << LL_ENDL; LLHTTPClient::post(url, update, new LLHoverHeightResponder); } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 7b932abd44..a47b6c3463 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 6fa45d7d66..7099db63ab 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -531,7 +531,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 de441983d0..560f81a6fd 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2105,6 +2105,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 f1d34a1449..ea1bc66236 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5246,6 +5246,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 5dcb8e2cdf..945a77c071 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2307,6 +2307,7 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. <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> @@ -2433,9 +2434,12 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. <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> |