diff options
Diffstat (limited to 'indra/newview/lloutfitslist.cpp')
-rw-r--r-- | indra/newview/lloutfitslist.cpp | 222 |
1 files changed, 114 insertions, 108 deletions
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 8147a97317..db9d386b6b 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -2,30 +2,25 @@ * @file lloutfitslist.cpp * @brief List of agent's outfits for My Appearance side panel. * - * $LicenseInfo:firstyear=2010&license=viewergpl$ - * - * Copyright (c) 2010, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -68,6 +63,39 @@ bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LL return name1 < name2; } +struct outfit_accordion_tab_params : public LLInitParam::Block<outfit_accordion_tab_params, LLAccordionCtrlTab::Params> +{ + Mandatory<LLWearableItemsList::Params> wearable_list; + + outfit_accordion_tab_params() + : wearable_list("wearable_items_list") + {} +}; + +const outfit_accordion_tab_params& get_accordion_tab_params() +{ + static outfit_accordion_tab_params tab_params; + static bool initialized = false; + if (!initialized) + { + initialized = true; + + LLXMLNodePtr xmlNode; + if (LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode)) + { + LLXUIParser parser; + parser.readXUI(xmlNode, tab_params, "outfit_accordion_tab.xml"); + } + else + { + llwarns << "Failed to read xml of Outfit's Accordion Tab from outfit_accordion_tab.xml" << llendl; + } + } + + return tab_params; +} + + ////////////////////////////////////////////////////////////////////////// class LLOutfitListGearMenu @@ -90,7 +118,7 @@ public: registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this)); - enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitsList::isActionEnabled, mOutfitList, _2)); + enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2)); enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2)); mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>( @@ -160,29 +188,13 @@ private: void onTakeOff() { - // Take off selected items if there are any - if (mOutfitList->hasItemSelected()) - { - uuid_vec_t selected_uuids; - mOutfitList->getSelectedItemsUUIDs(selected_uuids); - - for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it) - { - if (get_is_item_worn(*it)) - { - LLAppearanceMgr::instance().removeItemFromAvatar(*it); - } - } - } - else // or take off the whole selected outfit if no items specified. - { + // Take off selected outfit. const LLUUID& selected_outfit_id = getSelectedOutfitID(); if (selected_outfit_id.notNull()) { LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id); } } - } void onRename() { @@ -214,6 +226,20 @@ private: LLAgentWearables::createWearable(type, true); } + bool onEnable(LLSD::String param) + { + // Handle the "Wear - Replace Current Outfit" menu option specially + // because LLOutfitList::isActionEnabled() checks whether it's allowed + // to wear selected outfit OR selected items, while we're only + // interested in the outfit (STORM-183). + if ("wear" == param) + { + return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID()); + } + + return mOutfitList->isActionEnabled(param); + } + bool onVisible(LLSD::String param) { const LLUUID& selected_outfit_id = getSelectedOutfitID(); @@ -275,11 +301,10 @@ protected: } else if ("wear_replace" == param) { - return !gAgentWearables.isCOFChangeInProgress(); + return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); } else if ("wear_add" == param) { - if (gAgentWearables.isCOFChangeInProgress()) return false; return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); } else if ("take_off" == param) @@ -404,6 +429,12 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/) mIsInitialized = true; } + + LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab(); + if (!selected_tab) return; + + // Pass focus to the selected outfit tab. + selected_tab->showAndFocusHeader(); } void LLOutfitsList::refreshList(const LLUUID& category_id) @@ -437,8 +468,12 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) std::string name = cat->getName(); - static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode(); - LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder<LLAccordionCtrlTab>(accordionXmlNode, NULL, NULL); + outfit_accordion_tab_params tab_params(get_accordion_tab_params()); + LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); + if (!tab) continue; + LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); + wearable_list->setShape(tab->getLocalRect()); + tab->addChild(wearable_list); tab->setName(name); tab->setTitle(name); @@ -455,10 +490,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) mAccordion->removeCollapsibleCtrl(tab); // kill removed tab - if (tab != NULL) - { tab->die(); - } continue; } @@ -676,7 +708,7 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata) } // outfit selected - return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID); + return LLAppearanceMgr::instance().getCanReplaceCOF(mSelectedOutfitUUID); } if (command_name == "take_off") { @@ -689,11 +721,6 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata) if (command_name == "wear_add") { // *TODO: do we ever get here? - if (gAgentWearables.isCOFChangeInProgress()) - { - return false; - } - return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID); } @@ -736,19 +763,6 @@ bool LLOutfitsList::hasItemSelected() ////////////////////////////////////////////////////////////////////////// // Private methods ////////////////////////////////////////////////////////////////////////// -LLXMLNodePtr LLOutfitsList::getAccordionTabXMLNode() -{ - LLXMLNodePtr xmlNode = NULL; - bool success = LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode); - if (!success) - { - llwarns << "Failed to read xml of Outfit's Accordion Tab from outfit_accordion_tab.xml" << llendl; - return NULL; - } - - return xmlNode; -} - void LLOutfitsList::computeDifference( const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, @@ -979,23 +993,6 @@ void LLOutfitsList::applyFilterToTab( } } -bool LLOutfitsList::canTakeOffSelected() -{ - uuid_vec_t selected_uuids; - getSelectedItemsUUIDs(selected_uuids); - - LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); - - for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if (!item) continue; - - if (is_worn(NULL, item)) return true; - } - return false; -} - bool LLOutfitsList::canWearSelected() { uuid_vec_t selected_items; @@ -1044,14 +1041,7 @@ void LLOutfitsList::wearSelectedItems() return; } - uuid_vec_t::const_iterator it; - // Wear items from all selected lists(if possible- add, else replace) - for (it = selected_uuids.begin(); it != selected_uuids.end()-1; ++it) - { - LLAppearanceMgr::getInstance()->wearItemOnAvatar(*it, false, false); - } - // call update only when wearing last item - LLAppearanceMgr::getInstance()->wearItemOnAvatar(*it, true, false); + wear_multiple(selected_uuids, false); } void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) @@ -1068,25 +1058,37 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) void LLOutfitsList::onCOFChanged() { - LLInventoryModel::changed_items_t changed_linked_items; + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; - const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); - for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin(); - iter != changed_items.end(); - ++iter) + // Collect current COF items + gInventory.collectDescendents( + LLAppearanceMgr::instance().getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + + uuid_vec_t vnew; + uuid_vec_t vadded; + uuid_vec_t vremoved; + + // From gInventory we get the UUIDs of links that are currently in COF. + // These links UUIDs are not the same UUIDs that we have in each wearable items list. + // So we collect base items' UUIDs to find them or links that point to them in wearable + // items lists and update their worn state there. + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + ++iter) { - LLViewerInventoryItem* item = gInventory.getItem(*iter); - if (item) - { - // From gInventory we get the UUIDs of new links added to COF - // or removed from COF. These links UUIDs are not the same UUIDs - // that we have in each wearable items list. So we collect base items - // UUIDs to find all items or links that point to same base items in wearable - // items lists and update their worn state there. - changed_linked_items.insert(item->getLinkedUUID()); - } + vnew.push_back((*iter)->getLinkedUUID()); } + // We need to update only items that were added or removed from COF. + LLCommonUtils::computeDifference(vnew, mCOFLinkedItems, vadded, vremoved); + + // Store the ids of items currently linked from COF. + mCOFLinkedItems = vnew; + for (outfits_map_t::iterator iter = mOutfitsMap.begin(); iter != mOutfitsMap.end(); ++iter) @@ -1097,9 +1099,13 @@ void LLOutfitsList::onCOFChanged() LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); if (!list) continue; + // Append removed ids to added ids because we should update all of them. + vadded.reserve(vadded.size() + vremoved.size()); + vadded.insert(vadded.end(), vremoved.begin(), vremoved.end()); + // Every list updates the labels of changed items or // the links that point to these items. - list->updateChangedItems(changed_linked_items); + list->updateChangedItems(vadded); } } |