summaryrefslogtreecommitdiff
path: root/indra/newview/llcofwearables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llcofwearables.cpp')
-rw-r--r--indra/newview/llcofwearables.cpp322
1 files changed, 66 insertions, 256 deletions
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 04623c03be..916d53da3c 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -2,25 +2,31 @@
* @file llcofwearables.cpp
* @brief LLCOFWearables displayes wearables from the current outfit split into three lists (attachments, clothing and body parts)
*
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * 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.
+ * 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
*
- * 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.
+ * 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
*
- * 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
+ * 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.
*
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * 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$
*/
@@ -28,8 +34,6 @@
#include "llcofwearables.h"
-#include "llaccordionctrl.h"
-#include "llaccordionctrltab.h"
#include "llagentdata.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
@@ -54,85 +58,39 @@ static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;
class CofContextMenu : public LLListContextMenu
{
protected:
- CofContextMenu(LLCOFWearables* cof_wearables)
- : mCOFWearables(cof_wearables)
- {
- llassert(mCOFWearables);
- }
-
- void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
+ static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
{
LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");
- LLWearableType::EType w_type = getWearableType(item_id);
// Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant.
- if (w_type == LLWearableType::WT_NONE)
+ LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
+ if (!item || !item->isWearableType())
{
menu_item->setVisible(FALSE);
return;
}
// Set proper label for the "Create new <WEARABLE_TYPE>" menu item.
- std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type));
+ LLStringUtil::format_map_t args;
+ LLWearableType::EType w_type = item->getWearableType();
+ args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type);
+ std::string new_label = LLTrans::getString("CreateNewWearable", args);
menu_item->setLabel(new_label);
}
- void createNew(const LLUUID& item_id)
+ static void createNew(const LLUUID& item_id)
{
- LLAgentWearables::createWearable(getWearableType(item_id), true);
- }
-
- // Get wearable type of the given item.
- //
- // There is a special case: so-called "dummy items"
- // (i.e. the ones that are there just to indicate that you're not wearing
- // any wearables of the corresponding type. They are currently grayed out
- // and suffixed with "not worn").
- // Those items don't have an UUID, but they do have an associated wearable type.
- // If the user has invoked context menu for such item,
- // we ignore the passed item_id and retrieve wearable type from the item.
- LLWearableType::EType getWearableType(const LLUUID& item_id)
- {
- if (!isDummyItem(item_id))
- {
- LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
- if (item && item->isWearableType())
- {
- return item->getWearableType();
- }
- }
- else if (mCOFWearables) // dummy item selected
- {
- LLPanelDummyClothingListItem* item;
+ LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
+ if (!item || !item->isWearableType()) return;
- item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem());
- if (item)
- {
- return item->getWearableType();
- }
- }
-
- return LLWearableType::WT_NONE;
- }
-
- static bool isDummyItem(const LLUUID& item_id)
- {
- return item_id.isNull();
+ LLAgentWearables::createWearable(item->getWearableType(), true);
}
-
- LLCOFWearables* mCOFWearables;
};
//////////////////////////////////////////////////////////////////////////
-class CofAttachmentContextMenu : public CofContextMenu
+class CofAttachmentContextMenu : public LLListContextMenu
{
-public:
- CofAttachmentContextMenu(LLCOFWearables* cof_wearables)
- : CofContextMenu(cof_wearables)
- {
- }
-
protected:
/*virtual*/ LLContextMenu* createMenu()
@@ -150,28 +108,7 @@ protected:
class CofClothingContextMenu : public CofContextMenu
{
-public:
- CofClothingContextMenu(LLCOFWearables* cof_wearables)
- : CofContextMenu(cof_wearables)
- {
- }
-
protected:
- static void replaceWearable(const LLUUID& item_id)
- {
- // *TODO: Most probable that accessing to LLPanelOutfitEdit instance should be:
- // LLSideTray::getInstance()->getSidepanelAppearance()->getPanelOutfitEdit()
- // without casting. Getter methods provides possibility to check and construct
- // absent instance. Explicit relations between components avoids situations
- // when we tries to construct instance with unsatisfied implicit input conditions.
- LLPanelOutfitEdit * panel_outfit_edit =
- dynamic_cast<LLPanelOutfitEdit*> (LLSideTray::getInstance()->getPanel(
- "panel_outfit_edit"));
- if (panel_outfit_edit != NULL)
- {
- panel_outfit_edit->onReplaceMenuItemClicked(item_id);
- }
- }
/*virtual*/ LLContextMenu* createMenu()
{
@@ -181,9 +118,10 @@ protected:
functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs));
- registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id));
+ registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false));
+ registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true));
registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
- registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));
+ registrar.add("Clothing.Create", boost::bind(createNew, selected_id));
enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2));
@@ -201,34 +139,40 @@ protected:
std::string param = data.asString();
LLUUID selected_id = mUUIDs.back();
- if ("take_off" == param)
+ if ("move_up" == param)
{
- return get_is_item_worn(selected_id);
+ return gAgentWearables.canMoveWearable(selected_id, false);
}
- else if ("edit" == param)
+ else if ("move_down" == param)
{
- return mUUIDs.size() == 1 && gAgentWearables.isWearableModifiable(selected_id);
+ return gAgentWearables.canMoveWearable(selected_id, true);
}
- else if ("replace" == param)
+ else if ("take_off" == param)
{
- return get_is_item_worn(selected_id) && mUUIDs.size() == 1;
+ return get_is_item_worn(selected_id);
+ }
+ else if ("edit" == param)
+ {
+ return gAgentWearables.isWearableModifiable(selected_id);
}
-
return true;
}
+
+ // We don't use LLAppearanceMgr::moveWearable() directly because
+ // the item may be invalidated between setting the callback and calling it.
+ static bool moveWearable(const LLUUID& item_id, bool closer_to_body)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ return LLAppearanceMgr::instance().moveWearable(item, closer_to_body);
+ }
};
//////////////////////////////////////////////////////////////////////////
class CofBodyPartContextMenu : public CofContextMenu
{
-public:
- CofBodyPartContextMenu(LLCOFWearables* cof_wearables)
- : CofContextMenu(cof_wearables)
- {
- }
-
protected:
+
/*virtual*/ LLContextMenu* createMenu()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -238,9 +182,9 @@ protected:
// *HACK* need to pass pointer to LLPanelOutfitEdit instead of LLSideTray::getInstance()->getPanel().
// LLSideTray::getInstance()->getPanel() is rather slow variant
LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
- registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceMenuItemClicked, panel_oe, selected_id));
+ registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
- registrar.add("BodyPart.Create", boost::bind(&CofBodyPartContextMenu::createNew, this, selected_id));
+ registrar.add("BodyPart.Create", boost::bind(createNew, selected_id));
enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
@@ -260,7 +204,7 @@ protected:
if ("edit" == param)
{
- return mUUIDs.size() == 1 && gAgentWearables.isWearableModifiable(selected_id);
+ return gAgentWearables.isWearableModifiable(selected_id);
}
return true;
@@ -273,17 +217,11 @@ LLCOFWearables::LLCOFWearables() : LLPanel(),
mAttachments(NULL),
mClothing(NULL),
mBodyParts(NULL),
- mLastSelectedList(NULL),
- mClothingTab(NULL),
- mAttachmentsTab(NULL),
- mBodyPartsTab(NULL),
- mLastSelectedTab(NULL),
- mAccordionCtrl(NULL),
- mCOFVersion(-1)
+ mLastSelectedList(NULL)
{
- mClothingMenu = new CofClothingContextMenu(this);
- mAttachmentMenu = new CofAttachmentContextMenu(this);
- mBodyPartMenu = new CofBodyPartContextMenu(this);
+ mClothingMenu = new CofClothingContextMenu();
+ mAttachmentMenu = new CofAttachmentContextMenu();
+ mBodyPartMenu = new CofBodyPartContextMenu();
};
LLCOFWearables::~LLCOFWearables()
@@ -317,22 +255,6 @@ BOOL LLCOFWearables::postBuild()
mAttachments->setComparator(&WEARABLE_NAME_COMPARATOR);
mBodyParts->setComparator(&WEARABLE_NAME_COMPARATOR);
-
- mClothingTab = getChild<LLAccordionCtrlTab>("tab_clothing");
- mClothingTab->setDropDownStateChangedCallback(boost::bind(&LLCOFWearables::onAccordionTabStateChanged, this, _1, _2));
-
- mAttachmentsTab = getChild<LLAccordionCtrlTab>("tab_attachments");
- mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLCOFWearables::onAccordionTabStateChanged, this, _1, _2));
-
- mBodyPartsTab = getChild<LLAccordionCtrlTab>("tab_body_parts");
- mBodyPartsTab->setDropDownStateChangedCallback(boost::bind(&LLCOFWearables::onAccordionTabStateChanged, this, _1, _2));
-
- mTab2AssetType[mClothingTab] = LLAssetType::AT_CLOTHING;
- mTab2AssetType[mAttachmentsTab] = LLAssetType::AT_OBJECT;
- mTab2AssetType[mBodyPartsTab] = LLAssetType::AT_BODYPART;
-
- mAccordionCtrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
-
return LLPanel::postBuild();
}
@@ -352,51 +274,8 @@ void LLCOFWearables::onSelectionChange(LLFlatListView* selected_list)
onCommit();
}
-void LLCOFWearables::onAccordionTabStateChanged(LLUICtrl* ctrl, const LLSD& expanded)
-{
- bool had_selected_items = mClothing->numSelected() || mAttachments->numSelected() || mBodyParts->numSelected();
- mClothing->resetSelection(true);
- mAttachments->resetSelection(true);
- mBodyParts->resetSelection(true);
-
- bool tab_selection_changed = false;
- LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
- if (tab && tab != mLastSelectedTab)
- {
- mLastSelectedTab = tab;
- tab_selection_changed = true;
- }
-
- if (had_selected_items || tab_selection_changed)
- {
- //sending commit signal to indicate selection changes
- onCommit();
- }
-}
-
void LLCOFWearables::refresh()
{
- const LLUUID cof_id = LLAppearanceMgr::instance().getCOF();
- if (cof_id.isNull())
- {
- llwarns << "COF ID cannot be NULL" << llendl;
- return;
- }
-
- LLViewerInventoryCategory* catp = gInventory.getCategory(cof_id);
- if (!catp)
- {
- llwarns << "COF category cannot be NULL" << llendl;
- return;
- }
-
- // BAP - this check has to be removed because an item name change does not
- // change cat version - ie, checking version is not a complete way
- // of finding out whether anything has changed in this category.
- //if (mCOFVersion == catp->getVersion()) return;
-
- mCOFVersion = catp->getVersion();
-
typedef std::vector<LLSD> values_vector_t;
typedef std::map<LLFlatListView*, values_vector_t> selection_map_t;
@@ -412,7 +291,7 @@ void LLCOFWearables::refresh()
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t cof_items;
- gInventory.collectDescendents(cof_id, cats, cof_items, LLInventoryModel::EXCLUDE_TRASH);
+ gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, cof_items, LLInventoryModel::EXCLUDE_TRASH);
populateAttachmentsAndBodypartsLists(cof_items);
@@ -429,26 +308,14 @@ void LLCOFWearables::refresh()
iter != iter_end; ++iter)
{
LLFlatListView* list = iter->first;
- if (!list) continue;
-
- //restoring selection should not fire commit callbacks
- list->setCommitOnSelectionChange(false);
-
const values_vector_t& values = iter->second;
for (values_vector_t::const_iterator
value_it = values.begin(),
value_it_end = values.end();
value_it != value_it_end; ++value_it)
{
- // value_it may be null because of dummy items
- // Dummy items have no ID
- if(value_it->asUUID().notNull())
- {
- list->selectItemByValue(*value_it);
- }
+ list->selectItemByValue(*value_it);
}
-
- list->setCommitOnSelectionChange(true);
}
}
@@ -520,7 +387,7 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory
item_panel->childSetAction("btn_edit", mCOFCallbacks.mEditWearable);
//turning on gray separator line for the last item in the items group of the same wearable type
- item_panel->setSeparatorVisible(last);
+ item_panel->childSetVisible("wearable_type_separator_icon", last);
return item_panel;
}
@@ -632,14 +499,6 @@ LLPanel* LLCOFWearables::getSelectedItem()
return mLastSelectedList->getSelectedItem();
}
-void LLCOFWearables::getSelectedItems(std::vector<LLPanel*>& selected_items) const
-{
- if (mLastSelectedList)
- {
- mLastSelectedList->getSelectedItems(selected_items);
- }
-}
-
void LLCOFWearables::clear()
{
mAttachments->clear();
@@ -647,42 +506,6 @@ void LLCOFWearables::clear()
mBodyParts->clear();
}
-LLAssetType::EType LLCOFWearables::getExpandedAccordionAssetType()
-{
- typedef std::map<std::string, LLAssetType::EType> type_map_t;
-
- static type_map_t type_map;
-
- if (mAccordionCtrl != NULL)
- {
- const LLAccordionCtrlTab* expanded_tab = mAccordionCtrl->getExpandedTab();
-
- return get_if_there(mTab2AssetType, expanded_tab, LLAssetType::AT_NONE);
- }
-
- return LLAssetType::AT_NONE;
-}
-
-LLAssetType::EType LLCOFWearables::getSelectedAccordionAssetType()
-{
- if (mAccordionCtrl != NULL)
- {
- const LLAccordionCtrlTab* selected_tab = mAccordionCtrl->getSelectedTab();
-
- return get_if_there(mTab2AssetType, selected_tab, LLAssetType::AT_NONE);
- }
-
- return LLAssetType::AT_NONE;
-}
-
-void LLCOFWearables::expandDefaultAccordionTab()
-{
- if (mAccordionCtrl != NULL)
- {
- mAccordionCtrl->expandDefaultTab();
- }
-}
-
void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContextMenu* menu)
{
if(menu)
@@ -690,20 +513,7 @@ void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContex
uuid_vec_t selected_uuids;
if(getSelectedUUIDs(selected_uuids))
{
- bool show_menu = false;
- for(uuid_vec_t::iterator it = selected_uuids.begin();it!=selected_uuids.end();++it)
- {
- if ((*it).notNull())
- {
- show_menu = true;
- break;
- }
- }
-
- if(show_menu)
- {
- menu->show(ctrl, selected_uuids, x, y);
- }
+ menu->show(ctrl, selected_uuids, x, y);
}
}
}