diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llagent.cpp | 17 | ||||
-rw-r--r-- | indra/newview/llagentwearables.cpp | 81 | ||||
-rw-r--r-- | indra/newview/llfloaterinventory.cpp | 35 | ||||
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 26 | ||||
-rw-r--r-- | indra/newview/llselectmgr.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llselectmgr.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewerjointattachment.cpp | 247 | ||||
-rw-r--r-- | indra/newview/llviewerjointattachment.h | 26 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 149 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 6 | ||||
-rw-r--r-- | indra/newview/llviewerobjectlist.cpp | 26 | ||||
-rw-r--r-- | indra/newview/llvoavatar.cpp | 236 | ||||
-rw-r--r-- | indra/newview/llvoavatar.h | 5 | ||||
-rw-r--r-- | indra/newview/llvoavatarself.cpp | 40 | ||||
-rw-r--r-- | indra/newview/llvoavatarself.h | 4 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 67 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 8 |
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. |