summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llagent.cpp17
-rw-r--r--indra/newview/llagentwearables.cpp81
-rw-r--r--indra/newview/llfloaterinventory.cpp35
-rw-r--r--indra/newview/llinventorybridge.cpp26
-rw-r--r--indra/newview/llselectmgr.cpp3
-rw-r--r--indra/newview/llselectmgr.h2
-rw-r--r--indra/newview/llviewerjointattachment.cpp247
-rw-r--r--indra/newview/llviewerjointattachment.h26
-rw-r--r--indra/newview/llviewermenu.cpp149
-rw-r--r--indra/newview/llviewerobject.cpp3
-rw-r--r--indra/newview/llviewerobject.h6
-rw-r--r--indra/newview/llviewerobjectlist.cpp26
-rw-r--r--indra/newview/llvoavatar.cpp236
-rw-r--r--indra/newview/llvoavatar.h5
-rw-r--r--indra/newview/llvoavatarself.cpp40
-rw-r--r--indra/newview/llvoavatarself.h4
-rw-r--r--indra/newview/pipeline.cpp67
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml8
18 files changed, 607 insertions, 374 deletions
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index fa60c5afc1..c67beda361 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3378,13 +3378,18 @@ void LLAgent::updateCamera()
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
- if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // clear any existing "early" movements of attachment
- attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
- gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
- attached_object->updateText();
+ LLViewerObject *attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
+ {
+ // clear any existing "early" movements of attachment
+ attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
+ gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
+ attached_object->updateText();
+ }
}
}
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index a26b799d3d..223f8779ec 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1203,25 +1203,30 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
S32 attachment_pt = attachments_to_include[i];
LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL);
if (!attachment) continue;
- LLViewerObject* attached_object = attachment->getObject();
- if (!attached_object) continue;
- const LLUUID& item_id = attachment->getItemID();
- if (item_id.isNull()) continue;
- LLInventoryItem* item = gInventory.getItem(item_id);
- if (!item) continue;
- if (!msg_started)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- msg_started = TRUE;
- msg->newMessage("CreateNewOutfitAttachments");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("HeaderData");
- msg->addUUID("NewFolderID", folder_id);
+ LLViewerObject *attached_object = (*attachment_iter);
+ if(!attached_object) continue;
+ const LLUUID& item_id = (*attachment_iter)->getItemID();
+ if(item_id.isNull()) continue;
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if(!item) continue;
+ if(!msg_started)
+ {
+ msg_started = TRUE;
+ msg->newMessage("CreateNewOutfitAttachments");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("HeaderData");
+ msg->addUUID("NewFolderID", folder_id);
+ }
+ msg->nextBlock("ObjectData");
+ msg->addUUID("OldItemID", item_id);
+ msg->addUUID("OldFolderID", item->getParentUUID());
}
- msg->nextBlock("ObjectData");
- msg->addUUID("OldItemID", item_id);
- msg->addUUID("OldFolderID", item->getParentUUID());
}
if (msg_started)
@@ -1766,20 +1771,25 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject* objectp = attachment->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLUUID object_item_id = attachment->getItemID();
- if (requested_item_ids.find(object_item_id) != requested_item_ids.end())
- {
- // Object currently worn, was requested.
- // Flag as currently worn so we won't have to add it again.
- current_item_ids.insert(object_item_id);
- }
- else
+ LLViewerObject *objectp = (*attachment_iter);
+ if (objectp)
{
- // object currently worn, not requested.
- objects_to_remove.push_back(objectp);
+ LLUUID object_item_id = objectp->getItemID();
+ if (requested_item_ids.find(object_item_id) != requested_item_ids.end())
+ {
+ // Object currently worn, was requested.
+ // Flag as currently worn so we won't have to add it again.
+ current_item_ids.insert(object_item_id);
+ }
+ else
+ {
+ // object currently worn, not requested.
+ objects_to_remove.push_back(objectp);
+ }
}
}
}
@@ -1855,9 +1865,16 @@ void LLAgentWearables::userRemoveAllAttachments()
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject* objectp = attachment->getObject();
- if (objectp)
- objects_to_remove.push_back(objectp);
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = (*attachment_iter);
+ if (attached_object)
+ {
+ objects_to_remove.push_back(attached_object);
+ }
+ }
}
userRemoveMultipleAttachments(objects_to_remove);
}
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index 126dcc6f76..a8ab4303ba 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1837,7 +1837,6 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata)
{
std::set<LLUUID> selected_items;
mFolders->getSelectionList(selected_items);
- LLUUID id = *selected_items.begin();
std::string joint_name = userdata.asString();
LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject());
@@ -1857,22 +1856,28 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata)
{
return true;
}
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
- if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();
+ set_iter != selected_items.end();
+ ++set_iter)
{
- rez_attachment(item, attachmentp);
- }
- else if(item && item->isComplete())
- {
- // must be in library. copy it to our inventory and put it on.
- LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
- copy_inventory_item(gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
+ const LLUUID &id = *set_iter;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
+ if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, attachmentp);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
+ copy_inventory_item(gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
}
gFocusMgr.setKeyboardFocus(NULL);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 5067f88e58..e807240e4e 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3737,11 +3737,13 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
payload["attachment_point"] = attach_pt;
- if (attachment && attachment->getObject())
+#if !ENABLE_MULTIATTACHMENTS
+ if (attachment && attachment->getNumObjects() > 0)
{
LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
}
else
+#endif
{
LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
}
@@ -3749,6 +3751,16 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
{
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0/*YES*/)
{
@@ -3764,7 +3776,11 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
- msg->addU8Fast(_PREHASH_AttachmentPt, notification["payload"]["attachment_point"].asInteger());
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+#if ENABLE_MULTIATTACHMENTS
+ attachment_pt |= ATTACHMENT_ADD;
+#endif
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
msg->addStringFast(_PREHASH_Name, itemp->getName());
msg->addStringFast(_PREHASH_Description, itemp->getDescription());
@@ -3825,6 +3841,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// commented out for DEV-32347
//items.push_back(std::string("Restore to Last Position"));
+ if (!avatarp->canAttachMoreObjects())
+ {
+ disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Attach To"));
+ disabled_items.push_back(std::string("Attach To HUD"));
+ }
LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
LLVOAvatar *avatarp = gAgent.getAvatarObject();
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 288cf728b9..5630e8a0e9 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3590,6 +3590,9 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
return;
}
+#if ENABLE_MULTIATTACHMENTS
+ attachment_point |= ATTACHMENT_ADD;
+#endif
BOOL build_mode = LLToolMgr::getInstance()->inEdit();
// Special case: Attach to default location for this object.
if (0 == attachment_point ||
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 296502ff16..6e757ef976 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -660,7 +660,7 @@ private:
static void packDeRezHeader(void* user_data);
static void packObjectID( LLSelectNode* node, void *);
static void packObjectIDAsParam(LLSelectNode* node, void *);
- static void packObjectIDAndRotation( LLSelectNode* node, void *);
+ static void packObjectIDAndRotation(LLSelectNode* node, void *);
static void packObjectLocalID(LLSelectNode* node, void *);
static void packObjectClickAction(LLSelectNode* node, void* data);
static void packObjectIncludeInSearch(LLSelectNode* node, void* data);
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index 63c63e5546..2b4b78d82d 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -57,14 +57,14 @@ extern LLPipeline gPipeline;
// LLViewerJointAttachment()
//-----------------------------------------------------------------------------
LLViewerJointAttachment::LLViewerJointAttachment() :
-mAttachedObject(NULL),
-mVisibleInFirst(FALSE),
-mGroup(0),
-mIsHUDAttachment(FALSE),
-mPieSlice(-1)
+ mVisibleInFirst(FALSE),
+ mGroup(0),
+ mIsHUDAttachment(FALSE),
+ mPieSlice(-1)
{
mValid = FALSE;
mUpdateXform = FALSE;
+ mAttachedObjects.clear();
}
//-----------------------------------------------------------------------------
@@ -103,36 +103,43 @@ U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_
return 0;
}
-void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
+void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
{
- drawablep->mXform.setParent(&mXform); // LLViewerJointAttachment::lazyAttach
- drawablep->makeActive();
- LLVector3 current_pos = mAttachedObject->getRenderPosition();
- LLQuaternion current_rot = mAttachedObject->getRenderRotation();
- LLQuaternion attachment_pt_inv_rot = ~getWorldRotation();
+ if (!object->mDrawable)
+ return;
+ if (object->mDrawable->isActive())
+ {
+ object->mDrawable->makeStatic(FALSE);
+ }
+
+ object->mDrawable->mXform.setParent(getXform()); // LLViewerJointAttachment::lazyAttach
+ object->mDrawable->makeActive();
+ LLVector3 current_pos = object->getRenderPosition();
+ LLQuaternion current_rot = object->getRenderRotation();
+ LLQuaternion attachment_pt_inv_rot = ~(getWorldRotation());
current_pos -= getWorldPosition();
current_pos.rotVec(attachment_pt_inv_rot);
current_rot = current_rot * attachment_pt_inv_rot;
- drawablep->mXform.setPosition(current_pos);
- drawablep->mXform.setRotation(current_rot);
- gPipeline.markMoved(drawablep);
- gPipeline.markTextured(drawablep); // face may need to change draw pool to/from POOL_HUD
- drawablep->setState(LLDrawable::USE_BACKLIGHT);
+ object->mDrawable->mXform.setPosition(current_pos);
+ object->mDrawable->mXform.setRotation(current_rot);
+ gPipeline.markMoved(object->mDrawable);
+ gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD
+ object->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
if(mIsHUDAttachment)
{
- for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
+ for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)
{
- drawablep->getFace(face_num)->setState(LLFace::HUD_RENDER);
+ object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER);
}
}
- LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
+ LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mDrawable.notNull())
@@ -157,27 +164,13 @@ void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
//-----------------------------------------------------------------------------
BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
{
- if (mAttachedObject)
+ if (isObjectAttached(object))
{
- llwarns << "Attempted to attach object where an attachment already exists!" << llendl;
-
- if (mAttachedObject == object) {
- llinfos << "(same object re-attached)" << llendl;
- removeObject(mAttachedObject);
- // Pass through anyway to let setupDrawable()
- // re-connect object to the joint correctly
- }
- else {
- llinfos << "(objects differ, removing existing object)" << llendl;
- // Rather hacky, but no-one can think of something
- // better to do for this case.
- gObjectList.killObject(mAttachedObject);
- // Proceed with new object attachment
- }
+ llinfos << "(same object re-attached)" << llendl;
+ removeObject(object);
+ // Pass through anyway to let setupDrawable()
+ // re-connect object to the joint correctly
}
- mAttachedObject = object;
-
- LLUUID item_id;
// Find the inventory item ID of the attached object
LLNameValue* item_id_nv = object->getNVPair("AttachItemID");
@@ -186,26 +179,15 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
const char* s = item_id_nv->getString();
if( s )
{
- item_id.set( s );
+ LLUUID item_id;
+ item_id.set(s);
+ object->setItemID(item_id);
lldebugs << "getNVPair( AttachItemID ) = " << item_id << llendl;
}
}
-
- mItemID = item_id;
-
- LLDrawable* drawablep = object->mDrawable;
-
- if (drawablep)
- {
- //if object is active, make it static
- if(drawablep->isActive())
- {
- drawablep->makeStatic(FALSE) ;
- }
-
- setupDrawable(drawablep);
- }
-
+ mAttachedObjects.push_back(object);
+ setupDrawable(object);
+
if (mIsHUDAttachment)
{
if (object->mText.notNull())
@@ -214,7 +196,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
}
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mText.notNull())
@@ -234,15 +216,33 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::removeObject(LLViewerObject *object)
{
+ attachedobjs_vec_t::iterator iter;
+ for (iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ LLViewerObject *attached_object = (*iter);
+ if (attached_object == object)
+ {
+ break;
+ }
+ }
+ if (iter == mAttachedObjects.end())
+ {
+ llwarns << "Could not find object to detach" << llendl;
+ return;
+ }
+
// force object visibile
setAttachmentVisibility(TRUE);
+ mAttachedObjects.erase(iter);
if (object->mDrawable.notNull())
{
//if object is active, make it static
if(object->mDrawable->isActive())
{
- object->mDrawable->makeStatic(FALSE) ;
+ object->mDrawable->makeStatic(FALSE);
}
LLVector3 cur_position = object->getRenderPosition();
@@ -265,7 +265,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mDrawable.notNull())
@@ -290,7 +290,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
}
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp->mText.notNull())
@@ -299,10 +299,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
}
}
}
-
- mAttachedObject = NULL;
- mUpdateXform = FALSE;
- mItemID.setNull();
+ if (mAttachedObjects.size() == 0)
+ {
+ mUpdateXform = FALSE;
+ }
+ object->setItemID(LLUUID::null);
}
//-----------------------------------------------------------------------------
@@ -310,20 +311,26 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
{
- if (!mAttachedObject || mAttachedObject->mDrawable.isNull() ||
- !(mAttachedObject->mDrawable->getSpatialBridge()))
- return;
-
- if (visible)
- {
- // Hack to make attachments not visible by disabling their type mask!
- // This will break if you can ever attach non-volumes! - djs 02/14/03
- mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType =
- mAttachedObject->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
- }
- else
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = 0;
+ LLViewerObject *attached_obj = (*iter);
+ if (!attached_obj || attached_obj->mDrawable.isNull() ||
+ !(attached_obj->mDrawable->getSpatialBridge()))
+ continue;
+
+ if (visible)
+ {
+ // Hack to make attachments not visible by disabling their type mask!
+ // This will break if you can ever attach non-volumes! - djs 02/14/03
+ attached_obj->mDrawable->getSpatialBridge()->mDrawableType =
+ attached_obj->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
+ }
+ else
+ {
+ attached_obj->mDrawable->getSpatialBridge()->mDrawableType = 0;
+ }
}
}
@@ -341,14 +348,19 @@ void LLViewerJointAttachment::setOriginalPosition(LLVector3& position)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::clampObjectPosition()
{
- if (mAttachedObject)
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- // *NOTE: object can drift when hitting maximum radius
- LLVector3 attachmentPos = mAttachedObject->getPosition();
- F32 dist = attachmentPos.normVec();
- dist = llmin(dist, MAX_ATTACHMENT_DIST);
- attachmentPos *= dist;
- mAttachedObject->setPosition(attachmentPos);
+ if (LLViewerObject *attached_object = (*iter))
+ {
+ // *NOTE: object can drift when hitting maximum radius
+ LLVector3 attachmentPos = attached_object->getPosition();
+ F32 dist = attachmentPos.normVec();
+ dist = llmin(dist, MAX_ATTACHMENT_DIST);
+ attachmentPos *= dist;
+ attached_object->setPosition(attachmentPos);
+ }
}
}
@@ -357,14 +369,23 @@ void LLViewerJointAttachment::clampObjectPosition()
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::calcLOD()
{
- F32 maxarea = mAttachedObject->getMaxScale() * mAttachedObject->getMidScale();
- LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ F32 maxarea = 0;
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- LLViewerObject* childp = *iter;
- F32 area = childp->getMaxScale() * childp->getMidScale();
- maxarea = llmax(maxarea, area);
+ if (LLViewerObject *attached_object = (*iter))
+ {
+ maxarea = llmax(maxarea,attached_object->getMaxScale() * attached_object->getMidScale());
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ F32 area = childp->getMaxScale() * childp->getMidScale();
+ maxarea = llmax(maxarea, area);
+ }
+ }
}
maxarea = llclamp(maxarea, .01f*.01f, 1.f);
F32 avatar_area = (4.f * 4.f); // pixels for an avatar sized attachment
@@ -386,3 +407,47 @@ BOOL LLViewerJointAttachment::updateLOD(F32 pixel_area, BOOL activate)
return res;
}
+BOOL LLViewerJointAttachment::isObjectAttached(const LLViewerObject *viewer_object) const
+{
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ const LLViewerObject* attached_object = (*iter);
+ if (attached_object == viewer_object)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id) const
+{
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ const LLViewerObject* attached_object = (*iter);
+ if (attached_object->getItemID() == object_id)
+ {
+ return attached_object;
+ }
+ }
+ return NULL;
+}
+
+LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id)
+{
+ for (attachedobjs_vec_t::iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ LLViewerObject* attached_object = (*iter);
+ if (attached_object->getItemID() == object_id)
+ {
+ return attached_object;
+ }
+ }
+ return NULL;
+}
diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h
index c003579684..221b5460f1 100644
--- a/indra/newview/llviewerjointattachment.h
+++ b/indra/newview/llviewerjointattachment.h
@@ -82,9 +82,9 @@ public:
S32 getGroup() const { return mGroup; }
S32 getPieSlice() const { return mPieSlice; }
- LLViewerObject *getObject() const { return mAttachedObject; }
- S32 getNumObjects() const { return (mAttachedObject ? 1 : 0); }
- const LLUUID& getItemID() const { return mItemID; }
+ S32 getNumObjects() const { return mAttachedObjects.size(); }
+
+ void clampObjectPosition();
//
// unique methods
@@ -92,21 +92,27 @@ public:
BOOL addObject(LLViewerObject* object);
void removeObject(LLViewerObject *object);
- void setupDrawable(LLDrawable* drawable);
- void clampObjectPosition();
+ //
+ // attachments operations
+ //
+ BOOL isObjectAttached(const LLViewerObject *viewer_object) const;
+ const LLViewerObject *getAttachedObject(const LLUUID &object_id) const;
+ LLViewerObject *getAttachedObject(const LLUUID &object_id);
+
+ // list of attachments for this joint
+ typedef std::vector<LLViewerObject *> attachedobjs_vec_t;
+ attachedobjs_vec_t mAttachedObjects;
protected:
void calcLOD();
-
-protected:
- // Backlink only; don't make this an LLPointer.
- LLViewerObject* mAttachedObject;
+ void setupDrawable(LLViewerObject *object);
+
+private:
BOOL mVisibleInFirst;
LLVector3 mOriginalPos;
S32 mGroup;
BOOL mIsHUDAttachment;
S32 mPieSlice;
- LLUUID mItemID; // Inventory item id of the attached item (null if not in inventory)
};
#endif // LL_LLVIEWERJOINTATTACHMENT_H
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2e45a61f1b..9652a7104d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2806,7 +2806,7 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getObject())
+ if (attachment->getNumObjects() > 0)
{
new_value = true;
break;
@@ -3063,7 +3063,7 @@ class LLAvatarDebug : public view_listener_t
strings.push_back(avatar->getID().asString());
LLUUID invoice;
send_generic_message("dumptempassetdata", strings, invoice);
- LLFloaterReg::showInstance( "avatar_tetures", LLSD(avatar->getID()) );
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
}
return true;
}
@@ -5897,12 +5897,12 @@ void near_attach_object(BOOL success, void *user_data)
{
if (success)
{
- LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
+ const LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
U8 attachment_id = 0;
if (attachment)
{
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
{
if (iter->second == attachment)
@@ -6002,24 +6002,27 @@ class LLAttachmentDrop : public view_listener_t
class LLAttachmentDetachFromPoint : public view_listener_t
{
bool handleEvent(const LLSD& user_data)
-{
- LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
-
- LLViewerObject* attached_object = attachment ? attachment->getObject() : NULL;
-
- if (attached_object)
{
- gMessageSystem->newMessage("ObjectDetach");
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
- gMessageSystem->sendReliable( gAgent.getRegionHost() );
- }
+ const LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment->getNumObjects() > 0)
+ {
+ gMessageSystem->newMessage("ObjectDetach");
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
+ iter != attachment->mAttachedObjects.end();
+ iter++)
+ {
+ LLViewerObject *attached_object = (*iter);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
+ }
+ gMessageSystem->sendReliable( gAgent.getRegionHost() );
+ }
return true;
-}
+ }
};
static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
@@ -6028,25 +6031,31 @@ static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
if (menu)
{
- LLViewerJointAttachment *attachmentp = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
- if (attachmentp)
- {
- label = data["label"].asString();
- if (attachmentp->getObject())
+ const LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
- if (itemp)
+ label = data["label"].asString();
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- label += std::string(" (") + itemp->getName() + std::string(")");
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getItemID());
+ if (itemp)
+ {
+ label += std::string(" (") + itemp->getName() + std::string(")");
+ break;
+ }
+ }
}
}
- }
menu->setLabel(label);
-}
+ }
return true;
}
-
class LLAttachmentDetach : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -6133,33 +6142,37 @@ class LLAttachmentEnableDrop : public view_listener_t
// item is in your inventory
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- LLViewerJointAttachment* attachment_pt = NULL;
+ LLViewerJointAttachment* attachment = NULL;
LLInventoryItem* item = NULL;
- if ( object )
+ if (object)
{
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getState());
- attachment_pt = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
+ attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
- if ( attachment_pt )
+ if (attachment)
{
- // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
- // so check to see if the item is in the inventory already
- item = gInventory.getItem(attachment_pt->getItemID());
-
- if ( !item )
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // Item does not exist, make an observer to enable the pie menu
- // when the item finishes fetching worst case scenario
- // if a fetch is already out there (being sent from a slow sim)
- // we refetch and there are 2 fetches
- LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
- LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
-
- items.push_back(attachment_pt->getItemID());
-
- wornItemFetched->fetchItems(items);
- gInventory.addObserver(wornItemFetched);
+ // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
+ // so check to see if the item is in the inventory already
+ item = gInventory.getItem((*attachment_iter)->getItemID());
+ if (!item)
+ {
+ // Item does not exist, make an observer to enable the pie menu
+ // when the item finishes fetching worst case scenario
+ // if a fetch is already out there (being sent from a slow sim)
+ // we refetch and there are 2 fetches
+ LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
+ LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
+
+ items.push_back((*attachment_iter)->getItemID());
+
+ wornItemFetched->fetchItems(items);
+ gInventory.addObserver(wornItemFetched);
+ }
}
}
}
@@ -6262,11 +6275,11 @@ class LLAttachmentPointFilled : public view_listener_t
bool enable = false;
LLVOAvatar::attachment_map_t::iterator found_it = gAgent.getAvatarObject()->mAttachmentPoints.find(user_data.asInteger());
if (found_it != gAgent.getAvatarObject()->mAttachmentPoints.end())
-{
- enable = found_it->second->getObject() != NULL;
+ {
+ enable = found_it->second->getNumObjects() > 0;
}
return enable;
-}
+ }
};
class LLAvatarSendIM : public view_listener_t
@@ -6489,17 +6502,23 @@ void handle_dump_attachments(void*)
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
S32 key = curiter->first;
- BOOL visible = (attachment->getObject() != NULL &&
- attachment->getObject()->mDrawable.notNull() &&
- !attachment->getObject()->mDrawable->isRenderType(0));
- LLVector3 pos;
- if (visible) pos = attachment->getObject()->mDrawable->getPosition();
- llinfos << "ATTACHMENT " << key << ": item_id=" << attachment->getItemID()
- << (attachment->getObject() ? " present " : " absent ")
- << (visible ? "visible " : "invisible ")
- << " at " << pos
- << " and " << (visible ? attachment->getObject()->getPosition() : LLVector3::zero)
- << llendl;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = (*attachment_iter);
+ BOOL visible = (attached_object != NULL &&
+ attached_object->mDrawable.notNull() &&
+ !attached_object->mDrawable->isRenderType(0));
+ LLVector3 pos;
+ if (visible) pos = attached_object->mDrawable->getPosition();
+ llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getItemID()
+ << (attached_object ? " present " : " absent ")
+ << (visible ? "visible " : "invisible ")
+ << " at " << pos
+ << " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
+ << llendl;
+ }
}
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1f4f1322fd..20cd516fa0 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -219,7 +219,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mJointInfo(NULL),
mState(0),
mMedia(NULL),
- mClickAction(0)
+ mClickAction(0),
+ mAttachmentItemID(LLUUID::null)
{
if(!is_global)
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bec36f9da7..b8ae31118c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -676,6 +676,12 @@ protected:
private:
static S32 sNumObjects;
+
+public:
+ const LLUUID &getItemID() const { return mAttachmentItemID; }
+ void setItemID(const LLUUID &id) { mAttachmentItemID = id; }
+private:
+ LLUUID mAttachmentItemID; // ItemID when item is in user inventory.
};
///////////////////
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 1d982265ca..2927ca5292 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1216,21 +1216,25 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachmentp = curiter->second;
- if (attachmentp->getIsHUDAttachment())
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* objectp = attachmentp->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- mSelectPickList.insert(objectp);
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ if (LLViewerObject* attached_object = (*attachment_iter))
{
- LLViewerObject* childp = *iter;
- if (childp)
+ mSelectPickList.insert(attached_object);
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
{
- mSelectPickList.insert(childp);
+ LLViewerObject* childp = *iter;
+ if (childp)
+ {
+ mSelectPickList.insert(childp);
+ }
}
}
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2c578ebd2b..398c311808 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -612,7 +612,7 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f;
// Helper functions
//-----------------------------------------------------------------------------
static F32 calc_bouncy_animation(F32 x);
-static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
+static U32 calc_shame(const LLVOVolume* volume, std::set<LLUUID> &textures);
//-----------------------------------------------------------------------------
// LLVOAvatar()
@@ -1346,27 +1346,32 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
continue ;
}
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- LLSpatialBridge* bridge = drawable->getSpatialBridge();
- if (bridge)
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- const LLVector3* ext = bridge->getSpatialExtents();
- LLVector3 distance = (ext[1] - ext[0]);
-
- // Only add the prim to spatial extents calculations if it isn't a megaprim.
- // max_attachment_span calculated at the start of the function
- // (currently 5 times our max prim size)
- if (distance.mV[0] < max_attachment_span
- && distance.mV[1] < max_attachment_span
- && distance.mV[2] < max_attachment_span)
+ LLSpatialBridge* bridge = drawable->getSpatialBridge();
+ if (bridge)
{
- update_min_max(newMin,newMax,ext[0]);
- update_min_max(newMin,newMax,ext[1]);
+ const LLVector3* ext = bridge->getSpatialExtents();
+ LLVector3 distance = (ext[1] - ext[0]);
+
+ // Only add the prim to spatial extents calculations if it isn't a megaprim.
+ // max_attachment_span calculated at the start of the function
+ // (currently 5 times our max prim size)
+ if (distance.mV[0] < max_attachment_span
+ && distance.mV[1] < max_attachment_span
+ && distance.mV[2] < max_attachment_span)
+ {
+ update_min_max(newMin,newMax,ext[0]);
+ update_min_max(newMin,newMax,ext[1]);
+ }
}
}
}
@@ -2316,30 +2321,35 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
{
attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
-
- BOOL visibleAttachment = visible || (attached_object &&
- !(attached_object->mDrawable->getSpatialBridge() &&
- attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
- if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // if selecting any attachments, update all of them as non-damped
- if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
- {
- gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
- }
- else
- {
- gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
- }
-
- LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
- if (bridge)
+ LLViewerObject* attached_object = (*attachment_iter);
+ BOOL visibleAttachment = visible || (attached_object &&
+ !(attached_object->mDrawable->getSpatialBridge() &&
+ attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+
+ if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
{
- gPipeline.updateMoveNormalAsync(bridge);
+ // if selecting any attachments, update all of them as non-damped
+ if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
+ {
+ gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
+ }
+ else
+ {
+ gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
+ }
+
+ LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
+ if (bridge)
+ {
+ gPipeline.updateMoveNormalAsync(bridge);
+ }
+ attached_object->updateText();
}
- attached_object->updateText();
}
}
}
@@ -3537,15 +3547,21 @@ void LLVOAvatar::updateVisibility()
{
attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getObject())
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- if(attachment->getObject()->mDrawable->isVisible())
+ if (LLViewerObject *attached_object = (*attachment_iter))
{
- llinfos << attachment->getName() << " visible" << llendl;
- }
- else
- {
- llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ if(attached_object->mDrawable->isVisible())
+ {
+ llinfos << attachment->getName() << " visible" << llendl;
+ }
+ else
+ {
+ llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ }
}
}
}
@@ -5385,7 +5401,10 @@ void LLVOAvatar::addChild(LLViewerObject *childp)
void LLVOAvatar::removeChild(LLViewerObject *childp)
{
LLViewerObject::removeChild(childp);
- detachObject(childp);
+ if (!detachObject(childp))
+ {
+ llwarns << "Calling detach on non-attached object " << llendl;
+ }
}
LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
@@ -5405,7 +5424,7 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
//-----------------------------------------------------------------------------
// attachObject()
//-----------------------------------------------------------------------------
-LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
{
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
@@ -5424,6 +5443,30 @@ LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
}
//-----------------------------------------------------------------------------
+// attachObject()
+//-----------------------------------------------------------------------------
+U32 LLVOAvatar::getNumAttachments() const
+{
+ U32 num_attachments = 0;
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ iter++)
+ {
+ const LLViewerJointAttachment *attachment_pt = (*iter).second;
+ num_attachments += attachment_pt->getNumObjects();
+ }
+ return num_attachments;
+}
+
+//-----------------------------------------------------------------------------
+// canAttachMoreObjects()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::canAttachMoreObjects() const
+{
+ return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
+}
+
+//-----------------------------------------------------------------------------
// lazyAttach()
//-----------------------------------------------------------------------------
void LLVOAvatar::lazyAttach()
@@ -5454,10 +5497,15 @@ void LLVOAvatar::resetHUDAttachments()
LLViewerJointAttachment* attachment = curiter->second;
if (attachment->getIsHUDAttachment())
{
- LLViewerObject* obj = attachment->getObject();
- if (obj && obj->mDrawable.notNull())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- gPipeline.markMoved(obj->mDrawable);
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && attached_object->mDrawable.notNull())
+ {
+ gPipeline.markMoved(attached_object->mDrawable);
+ }
}
}
}
@@ -5473,19 +5521,19 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
{
attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- // only one object per attachment point for now
- if (attachment->getObject() == viewer_object)
+
+ if (attachment->isObjectAttached(viewer_object))
{
- LLUUID item_id = attachment->getItemID();
+ LLUUID item_id = viewer_object->getItemID();
attachment->removeObject(viewer_object);
if (isSelf())
{
// the simulator should automatically handle
// permission revocation
-
+
stopMotionFromSource(viewer_object->getID());
LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE);
-
+
LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); iter++)
@@ -5493,17 +5541,16 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
LLViewerObject* child_objectp = *iter;
// the simulator should automatically handle
// permissions revocation
-
+
stopMotionFromSource(child_objectp->getID());
LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE);
}
-
}
lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
if (isSelf())
{
// Then make sure the inventory is in sync with the avatar.
-
+
// Update COF contents, don't trigger appearance update.
if (gAgent.getAvatarObject() == NULL)
{
@@ -5513,9 +5560,8 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
{
LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:");
LLAppearanceManager::removeItemLinks(item_id, false);
-
}
-
+
// BAP - needs to change for label to track link.
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
gInventory.notifyObservers();
@@ -5523,7 +5569,6 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
return TRUE;
}
}
-
return FALSE;
}
@@ -6319,7 +6364,7 @@ BOOL LLVOAvatar::hasHUDAttachment() const
{
attachment_map_t::const_iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0)
{
return TRUE;
}
@@ -6335,20 +6380,24 @@ LLBBox LLVOAvatar::getHUDBBox() const
{
attachment_map_t::const_iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* hud_object = attachment->getObject();
-
- // initialize bounding box to contain identity orientation and center point for attached object
- bbox.addPointLocal(hud_object->getPosition());
- // add rotated bounding box for attached object
- bbox.addBBoxAgent(hud_object->getBoundingBoxAgent());
- LLViewerObject::const_child_list_t& child_list = hud_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLViewerObject* child_objectp = *iter;
- bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ const LLViewerObject* attached_object = (*attachment_iter);
+ // initialize bounding box to contain identity orientation and center point for attached object
+ bbox.addPointLocal(attached_object->getPosition());
+ // add rotated bounding box for attached object
+ bbox.addBBoxAgent(attached_object->getBoundingBoxAgent());
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
+ {
+ const LLViewerObject* child_objectp = *iter;
+ bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ }
}
}
}
@@ -7582,21 +7631,26 @@ void LLVOAvatar::idleUpdateRenderCost()
++iter)
{
LLViewerJointAttachment* attachment = iter->second;
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- shame += 10;
- LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- shame += calc_shame(volume, textures);
+ shame += 10;
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ shame += calc_shame(volume, textures);
+ }
}
}
}
- }
+ }
shame += textures.size() * 5;
@@ -7644,7 +7698,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
}
-U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
+U32 calc_shame(const LLVOVolume* volume, std::set<LLUUID> &textures)
{
if (!volume)
{
@@ -7676,20 +7730,20 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
const LLVector3& sc = volume->getScale();
scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
- LLDrawable* drawablep = volume->mDrawable;
+ const LLDrawable* drawablep = volume->mDrawable;
if (volume->isSculpted())
{
- LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ const LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID sculpt_id = sculpt_params->getSculptTexture();
textures.insert(sculpt_id);
}
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
{
- LLFace* face = drawablep->getFace(i);
+ const LLFace* face = drawablep->getFace(i);
const LLTextureEntry* te = face->getTextureEntry();
- LLViewerTexture* img = face->getTexture();
+ const LLViewerTexture* img = face->getTexture();
textures.insert(img->getID());
@@ -7733,11 +7787,11 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); iter++)
{
- LLViewerObject* child_objectp = *iter;
- LLDrawable* child_drawablep = child_objectp->mDrawable;
+ const LLViewerObject* child_objectp = *iter;
+ const LLDrawable* child_drawablep = child_objectp->mDrawable;
if (child_drawablep)
{
- LLVOVolume* child_volumep = child_drawablep->getVOVolume();
+ const LLVOVolume* child_volumep = child_drawablep->getVOVolume();
if (child_volumep)
{
shame += calc_shame(child_volumep, textures);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 1529beeac9..1180d43438 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -648,7 +648,7 @@ public:
//--------------------------------------------------------------------
public:
void clampAttachmentPositions();
- virtual LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
+ virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
BOOL detachObject(LLViewerObject *viewer_object);
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
protected:
@@ -672,6 +672,9 @@ public:
LLBBox getHUDBBox() const;
void rebuildHUD();
void resetHUDAttachments();
+ BOOL canAttachMoreObjects() const;
+protected:
+ U32 getNumAttachments() const; // O(N), not O(1)
/** Wearables
** **
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 457c6fe93e..03f9bd4b7c 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -976,7 +976,7 @@ BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL inclu
{
attachment_map_t::const_iterator curiter = iter++;
const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ if (attachment->getAttachedObject(inv_item_id))
{
return TRUE;
}
@@ -997,7 +997,7 @@ BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL inclu
{
attachment_map_t::const_iterator curiter = iter++;
const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == item_id )
+ if (attachment->getAttachedObject(item_id))
{
return TRUE;
}
@@ -1011,16 +1011,16 @@ BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL inclu
//-----------------------------------------------------------------------------
// getWornAttachment()
//-----------------------------------------------------------------------------
-LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id ) const
+LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id )
{
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
iter != mAttachmentPoints.end(); )
{
- attachment_map_t::const_iterator curiter = iter++;
- const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (LLViewerObject *attached_object = attachment->getAttachedObject(inv_item_id))
{
- return attachment->getObject();
+ return attached_object;
}
}
return NULL;
@@ -1033,7 +1033,7 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id
{
attachment_map_t::const_iterator curiter = iter++;
const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ if (attachment->getAttachedObject(inv_item_id))
{
return attachment->getName();
}
@@ -1043,9 +1043,9 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id
}
//virtual
-LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object)
{
- LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object);
+ const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object);
if (!attachment)
{
return 0;
@@ -1054,14 +1054,20 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj
updateAttachmentVisibility(gAgent.getCameraMode());
// Then make sure the inventory is in sync with the avatar.
- LLViewerInventoryItem *item = gInventory.getItem(attachment->getItemID());
- if (item)
- {
- LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:");
- LLAppearanceManager::wearItem(item,false); // Add COF link for item.
+ // Should just be the last object added
+ if (attachment->isObjectAttached(viewer_object))
+ {
+ const LLUUID& attachment_id = viewer_object->getItemID();
+ LLViewerInventoryItem *item = gInventory.getItem(attachment_id);
+ if (item)
+ {
+ LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:");
+ LLAppearanceManager::wearItem(item,false); // Add COF link for item.
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment_id);
+ }
}
- gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment->getItemID());
+
gInventory.notifyObservers();
return attachment;
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 88eb491f35..0b76d3e960 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -276,9 +276,9 @@ public:
public:
void updateAttachmentVisibility(U32 camera_mode);
BOOL isWearingAttachment(const LLUUID& inv_item_id, BOOL include_linked_items = FALSE) const;
- LLViewerObject* getWornAttachment(const LLUUID& inv_item_id ) const;
+ LLViewerObject* getWornAttachment(const LLUUID& inv_item_id );
const std::string getAttachedPointName(const LLUUID& inv_item_id) const;
- /*virtual*/ LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
+ /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
void getAllAttachmentsArray(LLDynamicArray<S32>& attachments);
//--------------------------------------------------------------------
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 3800b9223d..b50e71bf48 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3872,44 +3872,48 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachmentp = curiter->second;
- if (attachmentp->getIsHUDAttachment())
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* objectp = attachmentp->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = objectp->mDrawable;
- if (drawable->isDead())
+ if (LLViewerObject* attached_object = (*attachment_iter))
{
- continue;
- }
-
- for (S32 j = 0; j < drawable->getNumFaces(); ++j)
- {
- LLFace* facep = drawable->getFace(j);
- if (!facep->getPool())
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable->isDead())
{
- facep->renderForSelect(prim_mask);
+ continue;
}
- }
-
- //render child faces
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- LLDrawable* child_drawable = child->mDrawable;
- for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
+
+ for (S32 j = 0; j < drawable->getNumFaces(); ++j)
{
- LLFace* facep = child_drawable->getFace(l);
+ LLFace* facep = drawable->getFace(j);
if (!facep->getPool())
{
facep->renderForSelect(prim_mask);
}
}
+
+ //render child faces
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ LLDrawable* child_drawable = child->mDrawable;
+ for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
+ {
+ LLFace* facep = child_drawable->getFace(l);
+ if (!facep->getPool())
+ {
+ facep->renderForSelect(prim_mask);
+ }
+ }
+ }
}
- }
+ }
}
}
@@ -8682,10 +8686,15 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
iter != avatar->mAttachmentPoints.end();
++iter)
{
- LLViewerObject* object = iter->second->getObject();
- if (object)
+ LLViewerJointAttachment *attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- markVisible(object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
+ if (LLViewerObject* attached_object = (*attachment_iter))
+ {
+ markVisible(attached_object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
+ }
}
}
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 95dd8677b4..4d987dbc90 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -757,6 +757,14 @@ You can not wear clothes or body parts that are in the trash
<notification
icon="alertmodal.tga"
+ name="MaxAttachmentsOnOutfit"
+ type="alertmodal">
+Could not attach object.
+Exceeds the attachments limit of [MAX_ATTACHMENTS] objects. Please detach another object first.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CannotWearInfoNotComplete"
type="alertmodal">
You can not wear that item because it has not yet loaded. Please try again in a minute.