From 26b0d657f5a2c054aae6e1a1a9a4382bb2c984db Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Aug 2010 11:00:39 -0400 Subject: DEV-52580 WIP: disallow multiple links to the same attachment in updateAppearanceFromCOF() --- indra/newview/llappearancemgr.cpp | 88 ++++++++++++++++++++++----------------- indra/newview/llappearancemgr.h | 6 ++- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index cecb2ee6ad..5a076845da 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1012,7 +1012,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up addCOFItemLink(item_to_wear, do_update, cb); break; case LLAssetType::AT_OBJECT: - rez_attachment(item_to_wear, NULL, replace); + rez_attachment(item_to_wear, NULL); break; default: return false;; } @@ -1608,46 +1608,56 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list, } } -void LLAppearanceMgr::enforceItemCountLimits() +S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, + LLAssetType::EType type, + S32 max_items, + LLInventoryModel::item_array_t& items_to_kill) { - S32 purge_count = 0; - - LLInventoryModel::item_array_t body_items; - getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false); - LLInventoryModel::item_array_t curr_body_items = body_items; - removeDuplicateItems(body_items); - filterWearableItems(body_items, 1); - LLInventoryModel::item_array_t kill_body_items; - item_array_diff(curr_body_items,body_items,kill_body_items); - for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin(); - it != kill_body_items.end(); - ++it) + S32 to_kill_count = 0; + + LLInventoryModel::item_array_t items; + getDescendentsOfAssetType(cat_id, items, type, false); + LLInventoryModel::item_array_t curr_items = items; + removeDuplicateItems(items); + if (max_items > 0) { - LLViewerInventoryItem *item = *it; - llinfos << "purging dup body part " << item->getName() << llendl; - gInventory.purgeObject(item->getUUID()); - purge_count++; + filterWearableItems(items, max_items); } - - LLInventoryModel::item_array_t wear_items; - getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false); - LLInventoryModel::item_array_t curr_wear_items = wear_items; - removeDuplicateItems(wear_items); - filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); - LLInventoryModel::item_array_t kill_wear_items; - item_array_diff(curr_wear_items,wear_items,kill_wear_items); - for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin(); - it != kill_wear_items.end(); + LLInventoryModel::item_array_t kill_items; + item_array_diff(curr_items,items,kill_items); + for (LLInventoryModel::item_array_t::iterator it = kill_items.begin(); + it != kill_items.end(); ++it) { - LLViewerInventoryItem *item = *it; - llinfos << "purging excess clothing item " << item->getName() << llendl; - gInventory.purgeObject(item->getUUID()); - purge_count++; + items_to_kill.push_back(*it); + to_kill_count++; } + return to_kill_count; +} + + +void LLAppearanceMgr::enforceItemRestrictions() +{ + S32 purge_count = 0; + LLInventoryModel::item_array_t items_to_kill; - if (purge_count>0) + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART, + 1, items_to_kill); + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING, + LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); + purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT, + -1, items_to_kill); + + if (items_to_kill.size()>0) { + for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); + it != items_to_kill.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + llinfos << "purging duplicate or excess item " << item->getName() << llendl; + gInventory.purgeObject(item->getUUID()); + } gInventory.notifyObservers(); } } @@ -1670,7 +1680,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but // this should catch anything that gets through. - enforceItemCountLimits(); + enforceItemRestrictions(); // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link @@ -1836,9 +1846,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool llinfos << "wearInventoryCategory( " << category->getName() << " )" << llendl; - callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, - &LLAppearanceMgr::instance(), - category->getUUID(), copy, append)); + callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal, + &LLAppearanceMgr::instance(), + category->getUUID(), copy, append)); } void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) @@ -2741,8 +2751,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) LLInventoryModel::item_array_t items; LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - cats, - items, + cats, + items, LLInventoryModel::EXCLUDE_TRASH, find_links); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index eb495bd274..796ac5c572 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -66,7 +66,11 @@ public: void renameOutfit(const LLUUID& outfit_id); void takeOffOutfit(const LLUUID& cat_id); void addCategoryToCurrentOutfit(const LLUUID& cat_id); - void enforceItemCountLimits(); + S32 findExcessOrDuplicateItems(const LLUUID& cat_id, + LLAssetType::EType type, + S32 max_items, + LLInventoryModel::item_array_t& items_to_kill); + void enforceItemRestrictions(); // Copy all items and the src category itself. void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, -- cgit v1.2.3 From 2f77724a48b51a97091a0e27f20767cfb14e78e5 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 13 Aug 2010 11:12:51 -0400 Subject: EXT-8650 Can wear multiple copies of no-copy item via object links * EXT-8688 Automatically detach same object is detected * EXT-8689 Cleanup detachAttachmentIntoInventory code When an object arrives as an attachment, if it's already attached then it's automatically detached. --- indra/newview/llappearancemgr.cpp | 32 ++++++++----------------- indra/newview/llinventorybridge.cpp | 27 ++------------------- indra/newview/llviewerjointattachment.cpp | 37 +++++++++++++++-------------- indra/newview/llvoavatarself.cpp | 39 ++++++++++++++++++++++++------- indra/newview/llvoavatarself.h | 1 + 5 files changed, 63 insertions(+), 73 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6fdd71bfbf..21a635e738 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2496,29 +2496,17 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) switch (item_to_remove->getType()) { - case LLAssetType::AT_CLOTHING: - if (get_is_item_worn(id_to_remove)) - { - //*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future - LLWearableBridge::removeItemFromAvatar(item_to_remove); - } - break; - case LLAssetType::AT_OBJECT: - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_to_remove->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - - { - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item_to_remove->getLinkedUUID()); - if (found_obj) + case LLAssetType::AT_CLOTHING: + if (get_is_item_worn(id_to_remove)) { - LLSelectMgr::getInstance()->remove(found_obj); - }; - } - default: break; + //*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future + LLWearableBridge::removeItemFromAvatar(item_to_remove); + } + break; + case LLAssetType::AT_OBJECT: + LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID()); + default: + break; } // *HACK: Force to remove garbage from COF. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9bbc6514b4..66bf325f04 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3957,18 +3957,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* item = gInventory.getItem(mUUID); if(item) { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } + LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID()); } } else LLItemBridge::performAction(model, action); @@ -4321,19 +4310,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ LLViewerInventoryItem *obj_item = obj_item_array.get(i); if (get_is_item_worn(obj_item->getUUID())) { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } + LLVOAvatarSelf::detachAttachmentIntoInventory(obj_item->getLinkedUUID()); } } } diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 2b4b78d82d..c9335366cd 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -35,12 +35,11 @@ #include "llviewerjointattachment.h" #include "llagentconstants.h" - #include "llviewercontrol.h" #include "lldrawable.h" #include "llgl.h" #include "llrender.h" -#include "llvoavatar.h" +#include "llvoavatarself.h" #include "llvolume.h" #include "pipeline.h" #include "llspatialpartition.h" @@ -164,6 +163,9 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) //----------------------------------------------------------------------------- BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) { + object->extractAttachmentItemID(); + + // Same object reattached if (isObjectAttached(object)) { llinfos << "(same object re-attached)" << llendl; @@ -171,20 +173,19 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) // Pass through anyway to let setupDrawable() // re-connect object to the joint correctly } - - // Find the inventory item ID of the attached object - LLNameValue* item_id_nv = object->getNVPair("AttachItemID"); - if( item_id_nv ) + + // Two instances of the same inventory item attached -- + // Request detach, and kill the object in the meantime. + if (getAttachedObject(object->getAttachmentItemID())) { - const char* s = item_id_nv->getString(); - if( s ) - { - LLUUID item_id; - item_id.set(s); - object->setItemID(item_id); - lldebugs << "getNVPair( AttachItemID ) = " << item_id << llendl; - } + llinfos << "(same object re-attached)" << llendl; + object->markDead(); + + // If this happens to be attached to self, then detach. + LLVOAvatarSelf::detachAttachmentIntoInventory(object->getAttachmentItemID()); + return FALSE; } + mAttachedObjects.push_back(object); setupDrawable(object); @@ -207,7 +208,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) } calcLOD(); mUpdateXform = TRUE; - + return TRUE; } @@ -303,7 +304,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) { mUpdateXform = FALSE; } - object->setItemID(LLUUID::null); + object->setAttachmentItemID(LLUUID::null); } //----------------------------------------------------------------------------- @@ -429,7 +430,7 @@ const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &o ++iter) { const LLViewerObject* attached_object = (*iter); - if (attached_object->getItemID() == object_id) + if (attached_object->getAttachmentItemID() == object_id) { return attached_object; } @@ -444,7 +445,7 @@ LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_ ++iter) { LLViewerObject* attached_object = (*iter); - if (attached_object->getItemID() == object_id) + if (attached_object->getAttachmentItemID() == object_id) { return attached_object; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index bddde08ca9..09e50dcb90 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1067,7 +1067,7 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view // Should just be the last object added if (attachment->isObjectAttached(viewer_object)) { - const LLUUID& attachment_id = viewer_object->getItemID(); + const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); LLAppearanceMgr::instance().registerAttachment(attachment_id); } @@ -1077,7 +1077,7 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view //virtual BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) { - const LLUUID attachment_id = viewer_object->getItemID(); + const LLUUID attachment_id = viewer_object->getAttachmentItemID(); if (LLVOAvatar::detachObject(viewer_object)) { // the simulator should automatically handle permission revocation @@ -1115,6 +1115,29 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) return FALSE; } +// static +BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) +{ + LLInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); + gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item_id); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + return TRUE; + } + return FALSE; +} + U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const { LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); @@ -1625,15 +1648,15 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te if (isSelf()) { if (gAgentAvatarp->isUsingBakedTextures()) - { - requestLayerSetUpdate(type); - } + { + requestLayerSetUpdate(type); + } else - { - LLVisualParamHint::requestHintUpdates(); + { + LLVisualParamHint::requestHintUpdates(); + } } } - } else { tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 630afe7a0f..37d24d138f 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -295,6 +295,7 @@ public: const std::string getAttachedPointName(const LLUUID& inv_item_id) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); + static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); //-------------------------------------------------------------------- // HUDs -- cgit v1.2.3 From 6b53458b8477e542ddc5cc1f9fb41cc4a98819b1 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Fri, 13 Aug 2010 18:13:37 +0300 Subject: EXT-8662 FIXED Crash on renaming incomplete inventory items. I couldn't reproduce this problem, but from what I've seen in the crash reporter, this is a very old bug affecting viewers 1.2x and 2.x. When user tries to rename an incomplete inventory item, viewer crashes. The fix is to disallow renaming incomplete items. Reviewed by Seraph at https://codereview.productengine.com/secondlife/r/857/ --HG-- branch : product-engine --- indra/newview/llinventorybridge.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9bbc6514b4..4e1274645f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1270,6 +1270,12 @@ BOOL LLItemBridge::isItemRenameable() const { return FALSE; } + + if (!item->isFinished()) // EXT-8662 + { + return FALSE; + } + return (item->getPermissions().allowModifyBy(gAgent.getID())); } return FALSE; -- cgit v1.2.3 From 21ba693ad4ab8f7341c346fedfc2d7668a437eb1 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 13 Aug 2010 11:26:22 -0400 Subject: EXT-8650 Can wear multiple copies of no-copy item via object links * EXT-8661 Take out unused mRegisteredAttachments in LLAppearanceMgr Removed unused mRegisteredAttachments. Not sure what this was used for, but it's no longer used. --- indra/newview/llappearancemgr.cpp | 15 --------------- indra/newview/llappearancemgr.h | 2 -- 2 files changed, 17 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 21a635e738..5c713e60f9 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2646,7 +2646,6 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) mAttachmentInvLinkEnabled = val; } -// BAP TODO - mRegisteredAttachments is currently maintained but not used for anything. Consider yanking. void dumpAttachmentSet(const std::set& atts, const std::string& msg) { llinfos << msg << llendl; @@ -2666,7 +2665,6 @@ void dumpAttachmentSet(const std::set& atts, const std::string& msg) void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) { - mRegisteredAttachments.insert(item_id); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (mAttachmentInvLinkEnabled) @@ -2684,7 +2682,6 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { - mRegisteredAttachments.erase(item_id); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (mAttachmentInvLinkEnabled) @@ -2697,18 +2694,6 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) } } -void LLAppearanceMgr::linkRegisteredAttachments() -{ - for (std::set::iterator it = mRegisteredAttachments.begin(); - it != mRegisteredAttachments.end(); - ++it) - { - LLUUID item_id = *it; - addCOFItemLink(item_id, false); - } - mRegisteredAttachments.clear(); -} - BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const { return gInventory.isObjectDescendentOf(obj_id, getCOF()); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index eb495bd274..73b05ff7cd 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -119,7 +119,6 @@ public: void unregisterAttachment(const LLUUID& item_id); void registerAttachment(const LLUUID& item_id); void setAttachmentInvLinkEnable(bool val); - void linkRegisteredAttachments(); // utility function for bulk linking. void linkAll(const LLUUID& category, @@ -206,7 +205,6 @@ private: void setOutfitLocked(bool locked); - std::set mRegisteredAttachments; bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. -- cgit v1.2.3 From 9dcea327605870637e4a45823a1cd3540ef98d69 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Aug 2010 14:33:30 -0400 Subject: DEV-52580 FIX --- indra/newview/llinventorybridge.cpp | 43 ++++++++++++++-------------- indra/newview/llvoavatarself.cpp | 56 +++++++++++++++++++++++++++++++------ indra/newview/llvoavatarself.h | 7 +++++ 3 files changed, 76 insertions(+), 30 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 53622f7188..531d4c3ee9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3936,7 +3936,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) item = (LLViewerInventoryItem*)gInventory.getItem(object_id); if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) { - rez_attachment(item, NULL, true); // Replace if "Wear"ing. + rez_attachment(item, NULL); } else if(item && item->isFinished()) { @@ -3952,10 +3952,6 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) } gFocusMgr.setKeyboardFocus(NULL); } - else if ("wear_add" == action) - { - LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. - } else if (isRemoveAction(action)) { LLInventoryItem* item = gInventory.getItem(mUUID); @@ -3989,11 +3985,6 @@ std::string LLObjectBridge::getLabelSuffix() const { if (get_is_item_worn(mUUID)) { - if (!isAgentAvatarValid()) - { - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); // e.g. "(worn on ...)" / "(attached to ...)" @@ -4007,10 +3998,19 @@ std::string LLObjectBridge::getLabelSuffix() const } } -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment, bool replace) +void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) { - LLSD payload; - payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. + const LLUUID& item_id = item->getLinkedUUID(); + + // Check for duplicate request. + if (isAgentAvatarValid() && + (gAgentAvatarp->attachmentWasRequested(item_id) || + gAgentAvatarp->isWearingAttachment(item_id))) + { + llwarns << "duplicate attachment request, ignoring" << llendl; + return; + } + gAgentAvatarp->addAttachmentRequest(item_id); S32 attach_pt = 0; if (isAgentAvatarValid() && attachment) @@ -4026,14 +4026,11 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach } } - if (!replace) - { - attach_pt |= ATTACHMENT_ADD; - } - + LLSD payload; + payload["item_id"] = item_id; // Wear the base object in case this is a link. payload["attachment_point"] = attach_pt; - if (replace && + if (!gSavedSettings.getBOOL("MultipleAttachments") && (attachment && attachment->getNumObjects() > 0)) { LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); @@ -4057,11 +4054,15 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0/*YES*/) { - LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLUUID item_id = notification["payload"]["item_id"].asUUID(); + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); if (itemp) { U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); + + if (gSavedSettings.getBOOL("MultipleAttachments")) + attachment_pt |= ATTACHMENT_ADD; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); @@ -4118,7 +4119,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Wearable And Object Separator")); items.push_back(std::string("Wearable And Object Wear")); - items.push_back(std::string("Wearable Add")); items.push_back(std::string("Attach To")); items.push_back(std::string("Attach To HUD")); // commented out for DEV-32347 @@ -4127,7 +4127,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (!gAgentAvatarp->canAttachMoreObjects()) { disabled_items.push_back(std::string("Wearable And Object Wear")); - disabled_items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Attach To")); disabled_items.push_back(std::string("Attach To HUD")); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index bddde08ca9..7e6591a194 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1015,6 +1015,44 @@ BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const return FALSE; } +//----------------------------------------------------------------------------- +BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const +{ + const F32 REQUEST_EXPIRATION_SECONDS = 5.0; // any request older than this is ignored/removed. + std::map::iterator it = mAttachmentRequests.find(inv_item_id); + if (it != mAttachmentRequests.end()) + { + const LLTimer& request_time = it->second; + F32 request_time_elapsed = request_time.getElapsedTimeF32(); + if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS) + { + mAttachmentRequests.erase(it); + return FALSE; + } + else + { + return TRUE; + } + } + else + { + return FALSE; + } +} + +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id) +{ + LLTimer current_time; + mAttachmentRequests[inv_item_id] = current_time; +} + +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id) +{ + mAttachmentRequests.erase(inv_item_id); +} + //----------------------------------------------------------------------------- // getWornAttachment() //----------------------------------------------------------------------------- @@ -1067,8 +1105,10 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view // Should just be the last object added if (attachment->isObjectAttached(viewer_object)) { - const LLUUID& attachment_id = viewer_object->getItemID(); + const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); LLAppearanceMgr::instance().registerAttachment(attachment_id); + // Clear any pending requests once the attachment arrives. + removeAttachmentRequest(attachment_id); } return attachment; @@ -1077,7 +1117,7 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view //virtual BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) { - const LLUUID attachment_id = viewer_object->getItemID(); + const LLUUID attachment_id = viewer_object->getAttachmentItemID(); if (LLVOAvatar::detachObject(viewer_object)) { // the simulator should automatically handle permission revocation @@ -1625,15 +1665,15 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te if (isSelf()) { if (gAgentAvatarp->isUsingBakedTextures()) - { - requestLayerSetUpdate(type); - } + { + requestLayerSetUpdate(type); + } else - { - LLVisualParamHint::requestHintUpdates(); + { + LLVisualParamHint::requestHintUpdates(); + } } } - } else { tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 630afe7a0f..b129ffd986 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -291,11 +291,18 @@ protected: public: void updateAttachmentVisibility(U32 camera_mode); BOOL isWearingAttachment(const LLUUID& inv_item_id) const; + BOOL attachmentWasRequested(const LLUUID& inv_item_id) const; + void addAttachmentRequest(const LLUUID& inv_item_id); + void removeAttachmentRequest(const LLUUID& inv_item_id); LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); const std::string getAttachedPointName(const LLUUID& inv_item_id) const; /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); +private: + // Track attachments that have been requested but have not arrived yet. + mutable std::map mAttachmentRequests; + //-------------------------------------------------------------------- // HUDs //-------------------------------------------------------------------- -- cgit v1.2.3 From 30f9bc7c9ce9f652c3ccd6ce005f34a6c1ac124d Mon Sep 17 00:00:00 2001 From: Eli Linden Date: Mon, 16 Aug 2010 12:36:55 -0700 Subject: CT-575 FR linguistic --- indra/newview/skins/default/xui/fr/floater_postcard.xml | 2 +- indra/newview/skins/default/xui/fr/floater_preview_gesture.xml | 2 +- indra/newview/skins/default/xui/fr/floater_tools.xml | 4 ++-- indra/newview/skins/default/xui/fr/menu_picks.xml | 2 +- indra/newview/skins/default/xui/fr/notifications.xml | 6 +++--- indra/newview/skins/default/xui/fr/panel_pick_info.xml | 2 +- indra/newview/skins/default/xui/fr/panel_script_ed.xml | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/indra/newview/skins/default/xui/fr/floater_postcard.xml b/indra/newview/skins/default/xui/fr/floater_postcard.xml index 91a943ef15..a4b0675fe4 100644 --- a/indra/newview/skins/default/xui/fr/floater_postcard.xml +++ b/indra/newview/skins/default/xui/fr/floater_postcard.xml @@ -24,7 +24,7 @@