summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/llappearance/llavatarappearance.cpp38
-rwxr-xr-xindra/llappearance/llavatarappearance.h8
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.cpp2
-rwxr-xr-xindra/llcharacter/lljoint.cpp154
-rwxr-xr-xindra/llcharacter/lljoint.h38
-rwxr-xr-xindra/newview/llagentwearables.cpp5
-rwxr-xr-xindra/newview/llaisapi.cpp1
-rwxr-xr-xindra/newview/llappearancemgr.cpp7
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp10
-rwxr-xr-xindra/newview/llinventorybridge.cpp20
-rwxr-xr-xindra/newview/llviewerinventory.cpp16
-rwxr-xr-xindra/newview/llviewerinventory.h6
-rwxr-xr-xindra/newview/llviewerobject.cpp34
-rwxr-xr-xindra/newview/llviewerobject.h4
-rwxr-xr-xindra/newview/llvoavatar.cpp155
-rwxr-xr-xindra/newview/llvoavatar.h11
-rwxr-xr-xindra/newview/llvoavatarself.cpp20
-rwxr-xr-xindra/newview/llvoavatarself.h2
-rwxr-xr-xindra/newview/llvovolume.cpp14
-rwxr-xr-xindra/newview/llwearableitemslist.cpp10
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml8
21 files changed, 395 insertions, 168 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..af5393ef03 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -36,6 +36,59 @@
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);
+}
+
//-----------------------------------------------------------------------------
// LLJoint()
// Class Constructor
@@ -48,11 +101,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() :
@@ -243,42 +293,80 @@ void LLJoint::setPosition( const LLVector3& 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())
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
+ m_posBeforeOverrides = getPosition();
+ }
+ m_attachmentOverrides.add(mesh_id,pos);
+ 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))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
+ << " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
+ showJointPosOverrides(*this, "remove", av_info);
+ updatePos(av_info);
+ }
+
}
//--------------------------------------------------------------------
-// storeScaleForReset()
-//--------------------------------------------------------------------
-void LLJoint::storeScaleForReset( const LLVector3& scale )
+ // hasAttachmentPosOverride()
+ //--------------------------------------------------------------------
+bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
{
- mOldXform.setScale( scale );
+ return m_attachmentOverrides.findActiveOverride(mesh_id,pos);
}
+
//--------------------------------------------------------------------
-// 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 +413,7 @@ void LLJoint::setWorldPosition( const LLVector3& pos )
//--------------------------------------------------------------------
-// mXform.getRotation()
+// getRotation()
//--------------------------------------------------------------------
const LLQuaternion& LLJoint::getRotation()
{
@@ -432,7 +520,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 +636,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..56da8e83b2 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -46,6 +46,20 @@ 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);
+private:
+ typedef std::map<LLUUID,LLVector3> map_type;
+ map_type m_map;
+};
+
//-----------------------------------------------------------------------------
// class LLJoint
//-----------------------------------------------------------------------------
@@ -79,8 +93,6 @@ protected:
// explicit transformation members
LLXformMatrix mXform;
- LLXformMatrix mOldXform;
- LLXformMatrix mDefaultXform;
LLUUID mId;
@@ -88,8 +100,6 @@ public:
U32 mDirtyFlags;
BOOL mUpdateXform;
- BOOL mResetAfterRestoreOldXform;
-
// describes the skin binding pose
LLVector3 mSkinOffset;
@@ -103,6 +113,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 +175,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 +198,15 @@ 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;
//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/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 49fedb8df8..3928bbadc8 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++;
}
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/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 29534a4382..fba2b9d3a4 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2699,7 +2699,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);
}
}
}
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/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 33e557cddd..1b44049067 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -5326,16 +5326,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();
}
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/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 4f992fc184..344a7f5ce1 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;
@@ -5006,6 +5013,22 @@ LLVOAvatar* LLViewerObject::asAvatar()
return NULL;
}
+// If this object is directly or indirectly parented by an avatar, return it.
+LLVOAvatar* LLViewerObject::getAvatarAncestor()
+{
+ LLViewerObject *pobj = (LLViewerObject*) getParent();
+ while (pobj)
+ {
+ LLVOAvatar *av = pobj->asAvatar();
+ if (av)
+ {
+ return av;
+ }
+ pobj = (LLViewerObject*) pobj->getParent();
+ }
+ return NULL;
+}
+
BOOL LLViewerObject::isParticleSource() const
{
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
@@ -6193,6 +6216,17 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()
return getAttachmentItemID();
}
+const std::string& LLViewerObject::getAttachmentItemName()
+{
+ static std::string empty;
+ LLInventoryItem *item = gInventory.getItem(getAttachmentItemID());
+ if (isAttachment() && item)
+ {
+ return item->getName();
+ }
+ return empty;
+}
+
//virtual
LLVOAvatar* LLViewerObject::getAvatar() const
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bab107cc57..05c87c153b 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -135,6 +135,8 @@ public:
virtual LLVOAvatar* asAvatar();
+ LLVOAvatar* getAvatarAncestor();
+
static void initVOClasses();
static void cleanupVOClasses();
@@ -170,6 +172,8 @@ public:
void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; }
virtual BOOL isAttachment() const { return FALSE; }
+ const std::string& getAttachmentItemName();
+
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
virtual BOOL isHUDAttachment() const { return FALSE; }
virtual BOOL isTempAttachment() const;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 22b979aa09..dd5941191a 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -708,7 +708,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mVisualComplexity(0),
mVisualComplexityStale(TRUE),
mLoadedCallbacksPaused(FALSE),
- mHasPelvisOffset( FALSE ),
mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)),
mLastRezzedStatus(-1),
mIsEditingAppearance(FALSE),
@@ -770,10 +769,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRuthTimer.reset();
mRuthDebugTimer.reset();
mDebugExistenceTimer.reset();
- mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
- mLastPelvisToFoot = 0.0f;
- mPelvisFixup = 0.0f;
- mLastPelvisFixup = 0.0f;
if(LLSceneMonitor::getInstance()->isEnabled())
{
@@ -1258,17 +1253,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
{
@@ -3212,6 +3208,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{
debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
}
+ debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]);
addDebugText(debug_line);
}
if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
@@ -3723,21 +3720,6 @@ void LLVOAvatar::updateHeadOffset()
}
}
//------------------------------------------------------------------------
-// setPelvisOffset
-//------------------------------------------------------------------------
-void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup )
-{
- mHasPelvisOffset = hasOffset;
- if ( mHasPelvisOffset )
- {
- //Store off last pelvis to foot value
- mLastPelvisToFoot = mPelvisToFoot;
- mPelvisOffset = offsetAmount;
- mLastPelvisFixup = mPelvisFixup;
- mPelvisFixup = pelvisFixup;
- }
-}
-//------------------------------------------------------------------------
// postPelvisSetRecalc
//------------------------------------------------------------------------
void LLVOAvatar::postPelvisSetRecalc( void )
@@ -3747,15 +3729,6 @@ void LLVOAvatar::postPelvisSetRecalc( void )
dirtyMesh(2);
}
//------------------------------------------------------------------------
-// setPelvisOffset
-//------------------------------------------------------------------------
-void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
-{
- mHasPelvisOffset = true;
- mLastPelvisFixup = mPelvisFixup;
- mPelvisFixup = pelvisFixupAmount;
-}
-//------------------------------------------------------------------------
// updateVisibility()
//------------------------------------------------------------------------
void LLVOAvatar::updateVisibility()
@@ -5057,10 +5030,41 @@ 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;
+}
+
//-----------------------------------------------------------------------------
-// resetJointPositionsToDefault
+// resetJointPositionsOnDetach
//-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointPositionsToDefault( void )
+void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id)
{
//Subsequent joints are relative to pelvis
avatar_joint_list_t::iterator iter = mSkeleton.begin();
@@ -5072,23 +5076,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();
}
//-----------------------------------------------------------------------------
@@ -5625,7 +5624,7 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
}
//-----------------------------------------------------------------------------
-// attachObject()
+// getNumAttachments()
//-----------------------------------------------------------------------------
U32 LLVOAvatar::getNumAttachments() const
{
@@ -5735,30 +5734,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()
@@ -7676,6 +7663,38 @@ 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" );
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 42ff7bff92..d7cf4a2c0c 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -199,7 +199,7 @@ public:
virtual LLJoint* getJoint(const std::string &name);
- void resetJointPositionsToDefault( void );
+ void resetJointPositionsOnDetach(const LLUUID& mesh_id);
/*virtual*/ const LLUUID& getID() const;
/*virtual*/ void addDebugText(const std::string& text);
@@ -356,19 +356,11 @@ protected:
/*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh
public:
void updateHeadOffset();
- void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ;
- bool hasPelvisOffset( void ) { return mHasPelvisOffset; }
void postPelvisSetRecalc( void );
- void setPelvisOffset( F32 pelvixFixupAmount );
/*virtual*/ BOOL loadSkeletonNode();
/*virtual*/ void buildCharacter();
- bool mHasPelvisOffset;
- LLVector3 mPelvisOffset;
- F32 mLastPelvisToFoot;
- F32 mPelvisFixup;
- F32 mLastPelvisFixup;
LLVector3 mCurRootToHeadOffset;
LLVector3 mTargetRootToHeadOffset;
@@ -719,6 +711,7 @@ public:
void clampAttachmentPositions();
virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
virtual BOOL detachObject(LLViewerObject *viewer_object);
+ static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id );
void cleanupAttachedMesh( LLViewerObject* pVO );
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
/*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const;
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 42a7c2e576..77fda25537 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1093,9 +1093,19 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)
return NULL;
}
-const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const
+bool LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const
{
+ if (!gInventory.getItem(inv_item_id))
+ {
+ name = "ATTACHMENT_MISSING_ITEM";
+ return false;
+ }
const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
+ if (!gInventory.getItem(base_inv_item_id))
+ {
+ name = "ATTACHMENT_MISSING_BASE_ITEM";
+ return false;
+ }
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
iter != mAttachmentPoints.end();
++iter)
@@ -1103,11 +1113,13 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id
const LLViewerJointAttachment* attachment = iter->second;
if (attachment->getAttachedObject(base_inv_item_id))
{
- return attachment->getName();
+ name = attachment->getName();
+ return true;
}
}
- return LLStringUtil::null;
+ name = "ATTACHMENT_NOT_ATTACHED";
+ return false;
}
//virtual
@@ -1142,8 +1154,6 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)
const LLUUID attachment_id = viewer_object->getAttachmentItemID();
if ( LLVOAvatar::detachObject(viewer_object) )
{
- LLVOAvatar::cleanupAttachedMesh( viewer_object );
-
// the simulator should automatically handle permission revocation
stopMotionFromSource(attachment_id);
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index e03de9fa0b..369c15d0f9 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -293,7 +293,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/llvovolume.cpp b/indra/newview/llvovolume.cpp
index a83e2e020e..aebd9f470d 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4613,6 +4613,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
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 )
{
@@ -4626,19 +4627,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();
//Set the joint position
- pJoint->storeCurrentXform( jointPos );
+ pJoint->addAttachmentPosOverride( jointPos, mesh_id, pAvatarVO->avString() );
//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;
- }
+ pelvisGotSet = true;
}
}
}
+ if (pelvisZOffset != 0.0F)
+ {
+ pAvatarVO->addPelvisFixup( pelvisZOffset, mesh_id );
+ pelvisGotSet = true;
+ }
}
}
}
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/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>