diff options
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llcommon/llcommonutils.cpp | 61 | ||||
-rw-r--r-- | indra/llcommon/llcommonutils.h | 51 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llfilteredwearablelist.cpp | 113 | ||||
-rw-r--r-- | indra/newview/llfilteredwearablelist.h | 70 | ||||
-rw-r--r-- | indra/newview/llinventoryitemslist.cpp | 96 | ||||
-rw-r--r-- | indra/newview/llinventoryitemslist.h | 34 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 14 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitedit.h | 6 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_outfit_edit.xml | 24 |
11 files changed, 458 insertions, 15 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 4481d334b2..3c689930b8 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -35,6 +35,7 @@ set(llcommon_SOURCE_FILES llbase32.cpp llbase64.cpp llcommon.cpp + llcommonutils.cpp llcoros.cpp llcrc.cpp llcriticaldamp.cpp @@ -124,6 +125,7 @@ set(llcommon_HEADER_FILES llchat.h llclickaction.h llcommon.h + llcommonutils.h llcoros.h llcrc.h llcriticaldamp.h diff --git a/indra/llcommon/llcommonutils.cpp b/indra/llcommon/llcommonutils.cpp new file mode 100644 index 0000000000..0022dc6915 --- /dev/null +++ b/indra/llcommon/llcommonutils.cpp @@ -0,0 +1,61 @@ +/** + * @file llcommonutils.h + * @brief Commin utils + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llcommonutils.h" + +void LLCommonUtils::computeDifference( + const uuid_vec_t& vnew, + const uuid_vec_t& vcur, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vnew_copy(vnew); + uuid_vec_t vcur_copy(vcur); + + std::sort(vnew_copy.begin(), vnew_copy.end()); + std::sort(vcur_copy.begin(), vcur_copy.end()); + + size_t maxsize = llmax(vnew_copy.size(), vcur_copy.size()); + vadded.resize(maxsize); + vremoved.resize(maxsize); + + uuid_vec_t::iterator it; + // what was removed + it = set_difference(vcur_copy.begin(), vcur_copy.end(), vnew_copy.begin(), vnew_copy.end(), vremoved.begin()); + vremoved.erase(it, vremoved.end()); + + // what was added + it = set_difference(vnew_copy.begin(), vnew_copy.end(), vcur_copy.begin(), vcur_copy.end(), vadded.begin()); + vadded.erase(it, vadded.end()); +} + +// EOF diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h new file mode 100644 index 0000000000..f769ab87d3 --- /dev/null +++ b/indra/llcommon/llcommonutils.h @@ -0,0 +1,51 @@ +/** + * @file llcommonutils.h + * @brief Common utils + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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. + * $/LicenseInfo$ + */ + +#ifndef LL_LLCOMMONUTILS_H +#define LL_LLCOMMONUTILS_H + +namespace LLCommonUtils +{ + /** + * Computes difference between 'vnew' and 'vcur' vectors. + * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded' + * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved' + */ + LL_COMMON_API void computeDifference( + const uuid_vec_t& vnew, + const uuid_vec_t& vcur, + uuid_vec_t& vadded, + uuid_vec_t& vremoved); +}; + +#endif //LL_LLCOMMONUTILS_H + +// EOF diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c372edbea1..bfb5798909 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -142,6 +142,7 @@ set(viewer_SOURCE_FILES llfavoritesbar.cpp llfeaturemanager.cpp llfilepicker.cpp + llfilteredwearablelist.cpp llfirstuse.cpp llflexibleobject.cpp llfloaterabout.cpp @@ -651,6 +652,7 @@ set(viewer_HEADER_FILES llfavoritesbar.h llfeaturemanager.h llfilepicker.h + llfilteredwearablelist.h llfirstuse.h llflexibleobject.h llfloaterabout.h diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp new file mode 100644 index 0000000000..01d3c3f22e --- /dev/null +++ b/indra/newview/llfilteredwearablelist.cpp @@ -0,0 +1,113 @@ +/** + * @file llfilteredwearablelist.cpp + * @brief Functionality for showing filtered wearable flat list + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfilteredwearablelist.h" + +// newview +#include "llinventoryfunctions.h" +#include "llinventoryitemslist.h" +#include "llinventorymodel.h" + +class LLFindItemsByMask : public LLInventoryCollectFunctor +{ +public: + LLFindItemsByMask(U64 mask) + : mFilterMask(mask) + {} + + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if(item) + { + if( mFilterMask & (1LL << item->getInventoryType()) ) + { + return TRUE; + } + } + return FALSE; + } + +private: + U64 mFilterMask; +}; + +////////////////////////////////////////////////////////////////////////// + +LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask) +: mWearableList(list) +, mFilterMask(filter_mask) +{ + llassert(mWearableList); + gInventory.addObserver(this); + gInventory.fetchDescendentsOf(gInventory.getRootFolderID()); +} + +LLFilteredWearableListManager::~LLFilteredWearableListManager() +{ + gInventory.removeObserver(this); +} + +void LLFilteredWearableListManager::changed(U32 mask) +{ + if(!gInventory.isInventoryUsable()) + { + return; + } + + populateList(); +} + +void LLFilteredWearableListManager::setFilterMask(U64 mask) +{ + mFilterMask = mask; + populateList(); +} + +void LLFilteredWearableListManager::populateList() +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLFindItemsByMask collector(mFilterMask); + + gInventory.collectDescendentsIf( + gInventory.getRootFolderID(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + collector); + + // Probably will also need to get items from Library (waiting for reply in EXT-6724). + + mWearableList->refreshList(item_array); +} + +// EOF diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h new file mode 100644 index 0000000000..3f42833bb4 --- /dev/null +++ b/indra/newview/llfilteredwearablelist.h @@ -0,0 +1,70 @@ +/** + * @file llfilteredwearablelist.h + * @brief Functionality for showing filtered wearable flat list + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFILTEREDWEARABLELIST_H +#define LL_LLFILTEREDWEARABLELIST_H + +#include "llinventoryobserver.h" + +class LLInventoryItemsList; + +// Class that fills LLInventoryItemsList with filtered data. +class LLFilteredWearableListManager : public LLInventoryObserver +{ + LOG_CLASS(LLFilteredWearableListManager); +public: + + LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask); + ~LLFilteredWearableListManager(); + + /** LLInventoryObserver implementation + * + */ + /*virtual*/ void changed(U32 mask); + + /** + * Sets new filter and applies it immediately + */ + void setFilterMask(U64 mask); + + /** + * Populates wearable list with filtered data. + */ + void populateList(); + +private: + LLInventoryItemsList* mWearableList; + U64 mFilterMask; +}; + +#endif //LL_LLFILTEREDWEARABLELIST_H + +// EOF diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 9489e0f2e4..9f54b86607 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -33,6 +33,9 @@ #include "llinventoryitemslist.h" +// llcommon +#include "llcommonutils.h" + #include "lliconctrl.h" #include "llinventoryfunctions.h" @@ -112,6 +115,7 @@ void LLPanelInventoryItem::onMouseLeave(S32 x, S32 y, MASK mask) LLInventoryItemsList::LLInventoryItemsList(const LLFlatListView::Params& p) : LLFlatListView(p) +, mNeedsRefresh(false) {} // virtual @@ -120,22 +124,88 @@ LLInventoryItemsList::~LLInventoryItemsList() void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array) { - clear(); + getIDs().clear(); + LLInventoryModel::item_array_t::const_iterator it = item_array.begin(); + for( ; item_array.end() != it; ++it) + { + getIDs().push_back((*it)->getUUID()); + } + mNeedsRefresh = true; +} - for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) +void LLInventoryItemsList::draw() +{ + LLFlatListView::draw(); + if(mNeedsRefresh) { - LLViewerInventoryItem *item = (*iter); - - LLPanelInventoryItem *list_item = new LLPanelInventoryItem(item->getType(), - item->getInventoryType(), - item->getFlags(), - item->getName(), - LLStringUtil::null); - if (!addItem(list_item, item->getUUID())) + refresh(); + } +} + +void LLInventoryItemsList::refresh() +{ + static const unsigned ADD_LIMIT = 50; + + uuid_vec_t added_items; + uuid_vec_t removed_items; + + computeDifference(getIDs(), added_items, removed_items); + + bool add_limit_exceeded = false; + unsigned nadded = 0; + + uuid_vec_t::const_iterator it = added_items.begin(); + for( ; added_items.end() != it; ++it) + { + if(nadded >= ADD_LIMIT) { - llerrs << "Couldn't add flat item." << llendl; + add_limit_exceeded = true; + break; } + LLViewerInventoryItem* item = gInventory.getItem(*it); + addNewItem(item); + ++nadded; + } + + it = removed_items.begin(); + for( ; removed_items.end() != it; ++it) + { + removeItemByUUID(*it); } + + bool needs_refresh = add_limit_exceeded; + setNeedsRefresh(needs_refresh); +} + +void LLInventoryItemsList::computeDifference( + const uuid_vec_t& vnew, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vcur; + { + std::vector<LLSD> vcur_values; + getValues(vcur_values); + + for (size_t i=0; i<vcur_values.size(); i++) + vcur.push_back(vcur_values[i].asUUID()); + } + + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); } + +void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item) +{ + llassert(item); + + LLPanelInventoryItem *list_item = new LLPanelInventoryItem(item->getType(), + item->getInventoryType(), item->getFlags(), item->getName(), LLStringUtil::null); + + if (!addItem(list_item, item->getUUID())) + { + llwarns << "Couldn't add flat list item." << llendl; + llassert(!"Couldn't add flat list item."); + } +} + +// EOF diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index bba739dbbf..0ca4146867 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -80,9 +80,43 @@ public: void refreshList(const LLInventoryModel::item_array_t item_array); + /** + * Let list know items need to be refreshed in next draw() + */ + void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; } + + bool getNeedsRefresh(){ return mNeedsRefresh; } + + /*virtual*/ void draw(); + protected: friend class LLUICtrlFactory; LLInventoryItemsList(const LLFlatListView::Params& p); + + uuid_vec_t& getIDs() { return mIDs; } + + /** + * Refreshes list items, adds new items and removes deleted items. + * Called from draw() until all new items are added, , + * maximum 50 items can be added during single call. + */ + void refresh(); + + /** + * Compute difference between new items and current items, fills 'vadded' with added items, + * 'vremoved' with removed items. See LLCommonUtils::computeDifference + */ + void computeDifference(const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); + + /** + * Add an item to the list + */ + void addNewItem(LLViewerInventoryItem* item); + +private: + uuid_vec_t mIDs; // IDs of items that were added in refreshList(). + // Will be used in refresh() to determine added and removed ids + bool mNeedsRefresh; }; #endif //LL_LLINVENTORYITEMSLIST_H diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index ce17e1d624..e139cb31d6 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -38,7 +38,9 @@ #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" +#include "llfilteredwearablelist.h" #include "llinventory.h" +#include "llinventoryitemslist.h" #include "llviewercontrol.h" #include "llui.h" #include "llfloater.h" @@ -164,6 +166,7 @@ BOOL LLPanelOutfitEdit::postBuild() childSetCommitCallback("add_btn", boost::bind(&LLPanelOutfitEdit::showAddWearablesPanel, this), NULL); childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL); + childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL); mLookContents = getChild<LLScrollListCtrl>("look_items_list"); mLookContents->sortByColumn("look_item_sort", TRUE); @@ -229,6 +232,9 @@ BOOL LLPanelOutfitEdit::postBuild() save_registar.add("Outfit.SaveAsNew.Action", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true)); mSaveMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_save_outfit.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mWearableListManager = new LLFilteredWearableListManager( + getChild<LLInventoryItemsList>("filtered_wearables_list"), ALL_ITEMS_MASK); + return TRUE; } @@ -242,6 +248,11 @@ void LLPanelOutfitEdit::showWearablesFilter() childSetVisible("filter_combobox_panel", childGetValue("filter_button")); } +void LLPanelOutfitEdit::showFilteredWearablesPanel() +{ + childSetVisible("filtered_wearables_panel", !childIsVisible("filtered_wearables_panel")); +} + void LLPanelOutfitEdit::saveOutfit(bool as_new) { if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit()) @@ -275,6 +286,7 @@ void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) { U32 curr_filter_type = type_filter->getCurrentIndex(); mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); + mWearableListManager->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask); } mSavedFolderState->setApply(TRUE); @@ -577,4 +589,4 @@ void LLPanelOutfitEdit::displayCurrentOutfit() updateLookInfo(); } - +// EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 69e8016534..308ee23115 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -55,6 +55,7 @@ class LLScrollListCtrl; class LLToggleableMenu; class LLLookFetchObserver; class LLFilterEditor; +class LLFilteredWearableListManager; class LLPanelOutfitEdit : public LLPanel { @@ -88,6 +89,7 @@ public: void showAddWearablesPanel(); void showWearablesFilter(); + void showFilteredWearablesPanel(); void saveOutfit(bool as_new = false); void showSaveMenu(); @@ -122,7 +124,9 @@ private: LLButton* mUpBtn; LLButton* mEditWearableBtn; LLToggleableMenu* mSaveMenu; - + + LLFilteredWearableListManager* mWearableListManager; + LLLookFetchObserver* mFetchLook; LLInventoryLookObserver* mLookObserver; std::vector<LLLookItemType> mLookItemTypes; diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index c77e4e8d5e..b1f0ff15cb 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -342,6 +342,30 @@ width="300"/> <panel + name="filtered_wearables_panel" + background_opaque="true" + background_visible="true" + layout="topleft" + follows="left|top|right|bottom" + border="false" + height="155" + left="0" + mouse_opaque="false" + width="300" + top_delta="0" + visible="false"> + <wearable_items_list + name="filtered_wearables_list" + allow_select="true" + layout="topleft" + follows="all" + width="300" + height="155" + left="0" + top="0" /> + </panel> + + <panel background_visible="true" bevel_style="none" follows="left|right|bottom" |