From 554d543b020cfd8e99322c57806b19247bce2f8b Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Mon, 9 Aug 2010 18:10:36 +0300 Subject: EXT-8577 FIXED Context menu items for multi-attachments Changes: * Implemented bulk-add from My Appearance SP. * Made sure there's no memleak when you click Wear/Attach in the in-world object context menu and the callback isn't invoked (because e.g. avatar fails to get close enough to the object). I stated that in comments. Reviewed by Seraph at https://codereview.productengine.com/secondlife/r/844/ --HG-- branch : product-engine --- indra/newview/llviewermenu.cpp | 3 +- indra/newview/llvoavatar.cpp | 9 ++++++ indra/newview/llvoavatar.h | 1 + indra/newview/llwearableitemslist.cpp | 56 +++++++++++++++++++++++++++-------- indra/newview/llwearableitemslist.h | 2 +- 5 files changed, 56 insertions(+), 15 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 92195f0a4d..a289a0eb7a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -5950,7 +5950,8 @@ void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointA delta = delta * 0.5f; walkToSpot -= delta; - CallbackData* user_data = new CallbackData(attachment_point, mReplace); // *TODO: leak if the callback isn't called? + // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak. + CallbackData* user_data = new CallbackData(attachment_point, mReplace); gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance); gAgentCamera.clearFocusObject(); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 298ac28ca8..6392aad248 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5641,6 +5641,15 @@ BOOL LLVOAvatar::canAttachMoreObjects() const return (getNumAttachments() < MAX_AGENT_ATTACHMENTS); } +//----------------------------------------------------------------------------- +// canAttachMoreObjects() +// Returns true if we can attach more objects. +//----------------------------------------------------------------------------- +BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const +{ + return (getNumAttachments() + n) <= MAX_AGENT_ATTACHMENTS; +} + //----------------------------------------------------------------------------- // lazyAttach() //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5de08e8e27..3f603dda8b 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -687,6 +687,7 @@ public: void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; + BOOL canAttachMoreObjects(U32 n) const; protected: U32 getNumAttachments() const; // O(N), not O(1) diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 194213f880..e2a5489fcf 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -869,7 +869,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu setMenuItemVisible(menu, "wear_wear", n_already_worn == 0 && n_worn == 0 && can_be_worn); setMenuItemEnabled(menu, "wear_wear", n_already_worn == 0 && n_worn == 0); setMenuItemVisible(menu, "wear_add", wear_add_visible); - setMenuItemEnabled(menu, "wear_add", n_items == 1 && canAddWearable(ids.front())); + setMenuItemEnabled(menu, "wear_add", canAddWearables(ids)); setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn); //visible only when one item selected and this item is worn setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1); @@ -978,31 +978,61 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id) LLAgentWearables::createWearable(item->getWearableType(), true); } -// Can we wear another wearable of the given item's wearable type? +// Returns true if all the given objects and clothes can be added. // static -bool LLWearableItemsList::ContextMenu::canAddWearable(const LLUUID& item_id) +bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids) { // TODO: investigate wearables may not be loaded at this point EXT-8231 - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (!item) + U32 n_objects = 0; + boost::unordered_map clothes_by_type; + + // Count given clothes (by wearable type) and objects. + for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) { - return false; + LLViewerInventoryItem* item = gInventory.getItem(*it); + if (!item) + { + return false; + } + + if (item->getType() == LLAssetType::AT_OBJECT) + { + ++n_objects; + } + else if (item->getType() == LLAssetType::AT_CLOTHING) + { + ++clothes_by_type[item->getWearableType()]; + } + else + { + llwarns << "Unexpected wearable type" << llendl; + return false; + } } - if (item->getType() == LLAssetType::AT_OBJECT) + // Check whether we can add all the objects. + if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects)) { - // *TODO: is this the right check? - return isAgentAvatarValid() && gAgentAvatarp->canAttachMoreObjects(); + return false; } - if (item->getType() != LLAssetType::AT_CLOTHING) + // Check whether we can add all the clothes. + boost::unordered_map::const_iterator m_it; + for (m_it = clothes_by_type.begin(); m_it != clothes_by_type.end(); ++m_it) { - return false; + LLWearableType::EType w_type = m_it->first; + U32 n_clothes = m_it->second; + + U32 wearable_count = gAgentWearables.getWearableCount(w_type); + if ((wearable_count + n_clothes) > LLAgentWearables::MAX_CLOTHING_PER_TYPE) + { + return false; + } + } - U32 wearable_count = gAgentWearables.getWearableCount(item->getWearableType()); - return wearable_count < LLAgentWearables::MAX_CLOTHING_PER_TYPE; + return true; } // EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 81f1cd1b40..d7970e0838 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -431,7 +431,7 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); - static bool canAddWearable(const LLUUID& item_id); + static bool canAddWearables(const uuid_vec_t& item_ids); LLWearableItemsList* mParent; }; -- cgit v1.2.3