diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/CMakeLists.txt | 10 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 6 | ||||
-rw-r--r-- | indra/newview/llinventoryfilter.cpp | 17 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.cpp | 35 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.h | 4 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitsinventory.cpp | 245 | ||||
-rw-r--r-- | indra/newview/llpaneloutfitsinventory.h | 76 | ||||
-rw-r--r-- | indra/newview/llsidepanelappearance.cpp | 373 | ||||
-rw-r--r-- | indra/newview/llsidepanelappearance.h | 102 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_inventory.xml | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_outfits_inventory.xml | 81 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_side_tray.xml | 6 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/sidepanel_appearance.xml | 104 |
14 files changed, 1026 insertions, 37 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4adef84cd3..e7458529be 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -297,8 +297,6 @@ set(viewer_SOURCE_FILES llnotify.cpp lloutputmonitorctrl.cpp lloverlaybar.cpp - llpanelappearance.cpp - llpanelappearancetab.cpp llpanelavatar.cpp llpanelavatarrow.cpp llpanelavatartag.cpp @@ -322,7 +320,6 @@ set(viewer_SOURCE_FILES llpanellandmedia.cpp llpanellogin.cpp llpanellookinfo.cpp - llpanellooks.cpp llpanelmaininventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp @@ -330,6 +327,7 @@ set(viewer_SOURCE_FILES llpanelmeprofile.cpp llpanelobject.cpp llpanelobjectinventory.cpp + llpaneloutfitsinventory.cpp llpanelpeople.cpp llpanelpeoplemenus.cpp llpanelpermissions.cpp @@ -370,6 +368,7 @@ set(viewer_SOURCE_FILES llsearchcombobox.cpp llsearchhistory.cpp llselectmgr.cpp + llsidepanelappearance.cpp llsidepanelinventory.cpp llsidepanelinventorysubpanel.cpp llsidepaneliteminfo.cpp @@ -792,8 +791,6 @@ set(viewer_HEADER_FILES llnotify.h lloutputmonitorctrl.h lloverlaybar.h - llpanelappearance.h - llpanelappearancetab.h llpanelavatar.h llpanelavatarrow.h llpanelavatartag.h @@ -817,7 +814,6 @@ set(viewer_HEADER_FILES llpanellandmedia.h llpanellogin.h llpanellookinfo.h - llpanellooks.h llpanelmaininventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h @@ -825,6 +821,7 @@ set(viewer_HEADER_FILES llpanelmeprofile.h llpanelobject.h llpanelobjectinventory.h + llpaneloutfitsinventory.h llpanelpeople.h llpanelpeoplemenus.h llpanelpermissions.h @@ -867,6 +864,7 @@ set(viewer_HEADER_FILES llsearchcombobox.h llsearchhistory.h llselectmgr.h + llsidepanelappearance.h llsidepanelinventory.h llsidepanelinventorysubpanel.h llsidepaneliteminfo.h diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 80ac9e4085..554f270c02 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -40,7 +40,7 @@ #include "llinventorybridge.h" #include "llinventoryobserver.h" #include "llnotifications.h" -#include "llpanelappearance.h" +#include "llsidepanelappearance.h" #include "llsidetray.h" #include "llvoavatar.h" #include "llvoavatarself.h" @@ -530,10 +530,10 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) LLAssetType::AT_LINK_FOLDER, link_waiter); // Update the current outfit name of the appearance sidepanel. - LLPanelAppearance* panel_appearance = dynamic_cast<LLPanelAppearance *>(LLSideTray::getInstance()->getPanel("panel_appearance")); + LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance *>(LLSideTray::getInstance()->getPanel("sidepanel_appearance")); if (panel_appearance) { - panel_appearance->refreshCurrentLookName(catp->getName()); + panel_appearance->refreshCurrentOutfitName(catp->getName()); } } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3e4b3327db..085c96c93d 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -100,17 +100,18 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item) bool passed_type = false; if (mFilterOps.mFilterForCategories) { - if (listener->getInventoryType() == LLInventoryType::IT_CATEGORY) + // Pass if this item is a category of the filter type, or + // if its parent is a category of the filter type. + LLUUID uuid = listener->getUUID(); + if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) { - LLViewerInventoryCategory *cat = gInventory.getCategory(listener->getUUID()); - if (cat) - { - passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0)); - } + const LLInventoryObject *obj = gInventory.getObject(uuid); + uuid = obj->getParentUUID(); } - else + LLViewerInventoryCategory *cat = gInventory.getCategory(uuid); + if (cat) { - passed_type = TRUE; + passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0)); } } else diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 7b7090d10d..450ce92412 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -145,23 +145,10 @@ BOOL LLInventoryPanel::postBuild() mInventoryObserver = new LLInventoryPanelObserver(this);
mInventory->addObserver(mInventoryObserver);
- // determine the root folder, if any, so inventory contents show just the children
- // of that folder (i.e. not including the folder itself).
- const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
-
- if ("LIBRARY" == mStartFolderString)
- {
- mStartFolderID = gInventory.getLibraryRootFolderID();
- }
- else
- {
- mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
- }
-
// build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
{
- rebuildViewsFor(mStartFolderID);
+ rebuildViews();
mHasInventoryConnection = true;
defaultOpenInventory();
}
@@ -268,7 +255,7 @@ void LLInventoryPanel::modelChanged(U32 mask) // inventory just initialized, do complete build
if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
{
- rebuildViewsFor(mStartFolderID);
+ rebuildViews();
mHasInventoryConnection = true;
defaultOpenInventory();
return;
@@ -388,6 +375,24 @@ void LLInventoryPanel::modelChanged(U32 mask) }
+void LLInventoryPanel::rebuildViews()
+{
+ // Determine the root folder and rebuild the views starting
+ // at that folder.
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+
+ rebuildViewsFor(mStartFolderID);
+}
+
void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
LLFolderViewItem* old_view = NULL;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index e398c44105..0ccee337c9 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -162,6 +162,10 @@ public: void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); } protected: + // Destroys the old views, and regenerates them based on the + // start folder ID. + void rebuildViews(); + // Given the id and the parent, build all of the folder views. void rebuildViewsFor(const LLUUID& id); virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e3b2ab77aa..6c7d434eeb 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -49,7 +49,7 @@ #include "llviewermenu.h"
#include "llviewertexturelist.h"
-static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory");
void on_file_loaded_for_save(BOOL success,
LLViewerFetchedTexture *src_vi,
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp new file mode 100644 index 0000000000..2964bbe792 --- /dev/null +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -0,0 +1,245 @@ +/** + * @file llpaneloutfitsinventory.cpp + * @brief Outfits inventory panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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 "llpaneloutfitsinventory.h" + +#include "llagent.h" +#include "llbutton.h" +#include "llfloaterreg.h" +#include "lllandmark.h" + +#include "llfloaterworldmap.h" +#include "llfloaterinventory.h" +#include "llfoldervieweventlistener.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" +#include "llsidetray.h" +#include "lltabcontainer.h" +#include "llagentwearables.h" +#include "llviewerjointattachment.h" +#include "llviewerfoldertype.h" +#include "llvoavatarself.h" + +static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory"); + +LLPanelOutfitsInventory::LLPanelOutfitsInventory() : + mInventoryPanel(NULL), + mActionBtn(NULL), + mWearBtn(NULL), + mEditBtn(NULL) +{ + mSavedFolderState = new LLSaveFolderState(); + mSavedFolderState->setApply(FALSE); + + // LLUICtrlFactory::getInstance()->buildPanel(this, "panel_outfits_inventory.xml"); +} + +LLPanelOutfitsInventory::~LLPanelOutfitsInventory() +{ + delete mSavedFolderState; +} + +// virtual +BOOL LLPanelOutfitsInventory::postBuild() +{ + mInventoryPanel = getChild<LLInventoryPanel>("outfits_list"); + mInventoryPanel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, TRUE); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_MY_OUTFITS); + mInventoryPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onSelectionChange, this, _1, _2)); + + LLFolderView* root_folder = getRootFolder(); + root_folder->setReshapeCallback(boost::bind(&LLPanelOutfitsInventory::onSelectionChange, this, _1, _2)); + + mWearBtn = getChild<LLButton>("wear_btn"); + mEditBtn = getChild<LLButton>("edit_btn"); + mActionBtn = getChild<LLButton>("action_btn"); + + return TRUE; +} + +// virtual +void LLPanelOutfitsInventory::onSearchEdit(const std::string& string) +{ + if (string == "") + { + mInventoryPanel->setFilterSubString(LLStringUtil::null); + + // re-open folders that were initially open + mSavedFolderState->setApply(TRUE); + getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + LLOpenFoldersWithSelection opener; + getRootFolder()->applyFunctorRecursively(opener); + getRootFolder()->scrollToShowSelection(); + } + + gInventory.startBackgroundFetch(); + + if (mInventoryPanel->getFilterSubString().empty() && string.empty()) + { + // current filter and new filter empty, do nothing + return; + } + + // save current folder open state if no filter currently applied + if (getRootFolder()->getFilterSubString().empty()) + { + mSavedFolderState->setApply(FALSE); + getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + } + + // set new filter string + mInventoryPanel->setFilterSubString(string); +} + +void LLPanelOutfitsInventory::onWear() +{ + LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem(); + if (!current_item) + return; + + LLFolderViewEventListener* listenerp = current_item->getListener(); + if (getIsCorrectType(listenerp)) + { + listenerp->performAction(NULL, NULL,"replaceoutfit"); + } +} + +void LLPanelOutfitsInventory::onEdit() +{ +} + +void LLPanelOutfitsInventory::onNew() +{ + const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); + LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); + getRootFolder()->setSelectionByID(outfit_folder, TRUE); + getRootFolder()->setNeedsAutoRename(TRUE); +} + +void LLPanelOutfitsInventory::updateVerbs() +{ + BOOL enabled = FALSE; + + LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem(); + if (current_item) + { + LLFolderViewEventListener* listenerp = current_item->getListener(); + if (getIsCorrectType(listenerp)) + { + enabled = TRUE; + } + } + + if (mWearBtn) + { + mWearBtn->setEnabled(enabled); + } + // mEditBtn->setEnabled(enabled); +} + +void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) +{ + LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem(); + if (!current_item) + return; + + /* + LLFolderViewEventListener* listenerp = current_item->getListener(); + if (getIsCorrectType(listenerp)) + { + S32 bottom = 0; + LLFolderViewItem* folder = current_item->getParentFolder(); + + while ( folder->getParentFolder() != NULL ) + { + bottom += folder->getRect().mBottom; + folder = folder->getParentFolder(); + } + + LLRect rect = current_item->getRect(); + LLRect btn_rect( + rect.mRight - mActionBtn->getRect().getWidth(), + bottom + rect.mTop, + rect.mRight, + bottom + rect.mBottom); + + mActionBtn->setRect(btn_rect); + + if (!mActionBtn->getVisible()) + mActionBtn->setVisible(TRUE); + } + else + { + if (mActionBtn->getVisible()) + mActionBtn->setVisible(FALSE); + } + */ + + updateVerbs(); +} + +void LLPanelOutfitsInventory::onSelectorButtonClicked() +{ + /* + LLFolderViewItem* cur_item = getRootFolder()->getCurSelectedItem(); + + LLFolderViewEventListener* listenerp = cur_item->getListener(); + if (getIsCorrectType(listenerp)) + { + LLSD key; + key["type"] = "look"; + key["id"] = listenerp->getUUID(); + + LLSideTray::getInstance()->showPanel("sidepanel_appearance", key); + } + */ +} + +bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *listenerp) const +{ + if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY) + { + LLViewerInventoryCategory *cat = gInventory.getCategory(listenerp->getUUID()); + if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return true; + } + } + return false; +} + +LLFolderView *LLPanelOutfitsInventory::getRootFolder() +{ + return mInventoryPanel->getRootFolder(); +} diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h new file mode 100644 index 0000000000..3f837d3635 --- /dev/null +++ b/indra/newview/llpaneloutfitsinventory.h @@ -0,0 +1,76 @@ +/** + * @file llpaneloutfitsinventory.h + * @brief Outfits inventory panel + * class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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_LLPANELOUTFITSINVENTORY_H +#define LL_LLPANELOUTFITSINVENTORY_H + +#include "llpanel.h" +#include "llinventoryobserver.h" + +class LLFolderView; +class LLFolderViewItem; +class LLFolderViewEventListener; +class LLInventoryPanel; +class LLSaveFolderState; +class LLButton; + +class LLPanelOutfitsInventory : public LLPanel +{ +public: + LLPanelOutfitsInventory(); + virtual ~LLPanelOutfitsInventory(); + + /*virtual*/ BOOL postBuild(); + + void onSearchEdit(const std::string& string); + void onWear(); + void onEdit(); + void onNew(); + void updateVerbs(); + + void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + void onSelectorButtonClicked(); + + LLFolderView* getRootFolder(); + +private: + bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const; + LLInventoryPanel* mInventoryPanel; + LLSaveFolderState* mSavedFolderState; + + LLButton* mActionBtn; + LLButton* mWearBtn; + LLButton* mEditBtn; + +}; + +#endif //LL_LLPANELOUTFITSINVENTORY_H diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp new file mode 100644 index 0000000000..d92e404c2c --- /dev/null +++ b/indra/newview/llsidepanelappearance.cpp @@ -0,0 +1,373 @@ +/** + * @file llsidepanelappearance.cpp + * @brief Side Bar "Appearance" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2004-2009, 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 "llsidepanelappearance.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llfiltereditor.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llpaneleditwearable.h" +#include "llpaneloutfitsinventory.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "llwearable.h" + +static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance"); + +class LLCurrentlyWornFetchObserver : public LLInventoryFetchObserver +{ +public: + LLCurrentlyWornFetchObserver(LLSidepanelAppearance *panel) : + mPanel(panel) + {} + ~LLCurrentlyWornFetchObserver() {} + virtual void done() + { + mPanel->inventoryFetched(); + gInventory.removeObserver(this); + } +private: + LLSidepanelAppearance *mPanel; +}; + +LLSidepanelAppearance::LLSidepanelAppearance() : + LLPanel(), + mFilterSubString(LLStringUtil::null), + mFilterEditor(NULL), + mLookInfo(NULL), + mCurrLookPanel(NULL) +{ + //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_appearance.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() + mFetchWorn = new LLCurrentlyWornFetchObserver(this); +} + +LLSidepanelAppearance::~LLSidepanelAppearance() +{ +} + +// virtual +BOOL LLSidepanelAppearance::postBuild() +{ + mEditAppearanceBtn = getChild<LLButton>("editappearance_btn"); + mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); + + mWearBtn = getChild<LLButton>("wear_btn"); + mWearBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onWearButtonClicked, this)); + + mEditBtn = getChild<LLButton>("edit_btn"); + mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this)); + + mNewLookBtn = getChild<LLButton>("newlook_btn"); + mNewLookBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); + mNewLookBtn->setEnabled(false); + + mOverflowBtn = getChild<LLButton>("overflow_btn"); + + mFilterEditor = getChild<LLFilterEditor>("Filter"); + if (mFilterEditor) + { + mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); + } + + mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory")); + + mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info")); + if (mLookInfo) + { + LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn"); + if (back_btn) + { + back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this)); + } + + // *TODO: Assign the action to an appropriate event. + // mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::toggleMediaPanel, this)); + } + + mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable")); + if (mEditWearable) + { + LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn"); + if (edit_wearable_back_btn) + { + edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditWearBackClicked, this)); + } + } + + mCurrentLookName = getChild<LLTextBox>("currentlook_name"); + + mCurrLookPanel = getChild<LLPanel>("panel_currentlook"); + + return TRUE; +} + +// virtual +void LLSidepanelAppearance::onOpen(const LLSD& key) +{ + fetchInventory(); + refreshCurrentOutfitName(); + + if(key.size() == 0) + return; + + toggleLookInfoPanel(TRUE); + updateVerbs(); + + mLookInfoType = key["type"].asString(); + + if (mLookInfoType == "look") + { + LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID()); + if (pLook) + mLookInfo->displayLookInfo(pLook); + } +} + +void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) +{ + if (mFilterSubString != search_string) + { + mFilterSubString = search_string; + + // Searches are case-insensitive + LLStringUtil::toUpper(mFilterSubString); + LLStringUtil::trimHead(mFilterSubString); + + mPanelOutfitsInventory->onSearchEdit(mFilterSubString); + } +} + +void LLSidepanelAppearance::onWearButtonClicked() +{ + if (mLookInfo->getVisible()) + { + } + else + { + mPanelOutfitsInventory->onWear(); + } +} + +void LLSidepanelAppearance::onEditAppearanceButtonClicked() +{ + if (gAgentWearables.areWearablesLoaded()) + { + gAgent.changeCameraToCustomizeAvatar(); + } +} + +void LLSidepanelAppearance::onEditButtonClicked() +{ + toggleLookInfoPanel(FALSE); + toggleWearableEditPanel(TRUE, NULL); + /*if (mLookInfo->getVisible()) + { + } + else + { + mPanelOutfitsInventory->onEdit(); + }*/ +} + +void LLSidepanelAppearance::onNewOutfitButtonClicked() +{ + if (mLookInfo->getVisible()) + { + } + else + { + mPanelOutfitsInventory->onNew(); + } +} + + +void LLSidepanelAppearance::onBackButtonClicked() +{ + toggleLookInfoPanel(FALSE); +} + +void LLSidepanelAppearance::onEditWearBackClicked() +{ + mEditWearable->saveChanges(); + toggleWearableEditPanel(FALSE, NULL); + toggleLookInfoPanel(TRUE); +} + +void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible) +{ + if (!mLookInfo) + return; + + mLookInfo->setVisible(visible); + mPanelOutfitsInventory->setVisible(!visible); + mFilterEditor->setVisible(!visible); + mWearBtn->setVisible(!visible); + mEditBtn->setVisible(!visible); + mNewLookBtn->setVisible(!visible); + mOverflowBtn->setVisible(!visible); + mCurrLookPanel->setVisible(!visible); +} + +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable) +{ + if (!wearable) + { + wearable = gAgentWearables.getWearable(WT_SHAPE, 0); + } + if (!mEditWearable || !wearable) + { + return; + } + + mEditWearable->setVisible(visible); + mFilterEditor->setVisible(!visible); + mPanelOutfitsInventory->setVisible(!visible); +} + +void LLSidepanelAppearance::updateVerbs() +{ + bool is_look_info_visible = mLookInfo->getVisible(); + mOverflowBtn->setEnabled(false); + + if (is_look_info_visible) + { + } + else + { + mPanelOutfitsInventory->updateVerbs(); + } +} + +void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string name) +{ + if (name == "") + { + const LLUUID current_outfit_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + // Can't search on AT_OUTFIT since links to categories return AT_CATEGORY for type since they don't + // return preferred type. + LLIsType is_category( LLAssetType::AT_CATEGORY ); + gInventory.collectDescendentsIf(current_outfit_cat, + cat_array, + item_array, + false, + is_category, + false); + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + iter++) + { + const LLViewerInventoryItem *item = (*iter); + const LLViewerInventoryCategory *cat = item->getLinkedCategory(); + if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + mCurrentLookName->setText(cat->getName()); + return; + } + } + mCurrentLookName->setText(std::string("")); + } + else + { + mCurrentLookName->setText(name); + } +} + +//static +void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data) +{ + LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data; + panel->toggleLookInfoPanel(FALSE); + panel->toggleWearableEditPanel(TRUE, wearable); +} + +// Fetch currently worn items and only enable the New Look button after everything's been +// fetched. Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks. +void LLSidepanelAppearance::fetchInventory() +{ + + mNewLookBtn->setEnabled(false); + LLInventoryFetchObserver::item_ref_t ids; + LLUUID item_id; + for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type) + { + // MULTI_WEARABLE: + item_id = gAgentWearables.getWearableItemID((EWearableType)type,0); + if(item_id.notNull()) + { + ids.push_back(item_id); + } + } + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar ) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment) continue; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + if (!attached_object) continue; + const LLUUID& item_id = attached_object->getItemID(); + if (item_id.isNull()) continue; + ids.push_back(item_id); + } + } + } + + mFetchWorn->fetchItems(ids); + // If no items to be fetched, done will never be triggered. + // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. + if (mFetchWorn->isEverythingComplete()) + { + mFetchWorn->done(); + } + else + { + gInventory.addObserver(mFetchWorn); + } +} + +void LLSidepanelAppearance::inventoryFetched() +{ + mNewLookBtn->setEnabled(true); +} diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h new file mode 100644 index 0000000000..7be6d2d432 --- /dev/null +++ b/indra/newview/llsidepanelappearance.h @@ -0,0 +1,102 @@ +/** + * @file llsidepanelappearance.h + * @brief Side Bar "Appearance" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2004-2009, 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_LLSIDEPANELAPPEARANCE_H +#define LL_LLSIDEPANELAPPEARANCE_H + +#include "llpanel.h" +#include "llinventoryobserver.h" + +#include "llinventory.h" +#include "llpanellookinfo.h" + +class LLFilterEditor; +class LLCurrentlyWornFetchObserver; +class LLPanelEditWearable; +class LLWearable; +class LLPanelOutfitsInventory; + +class LLSidepanelAppearance : public LLPanel +{ +public: + LLSidepanelAppearance(); + virtual ~LLSidepanelAppearance(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + void refreshCurrentOutfitName(const std::string name = ""); + + static void editWearable(LLWearable *wearable, void *data); + + void fetchInventory(); + void inventoryFetched(); +private: + void onFilterEdit(const std::string& search_string); + + void onEditAppearanceButtonClicked(); + void onWearButtonClicked(); + void onEditButtonClicked(); + void onNewOutfitButtonClicked(); + void onBackButtonClicked(); + void onEditWearBackClicked(); + void toggleLookInfoPanel(BOOL visible); + void toggleWearableEditPanel(BOOL visible, LLWearable* wearable); + + void updateVerbs(); + + LLFilterEditor* mFilterEditor; + LLPanelOutfitsInventory* mPanelOutfitsInventory; + LLPanelLookInfo* mLookInfo; + LLPanelEditWearable* mEditWearable; + + LLButton* mEditAppearanceBtn; + LLButton* mWearBtn; + LLButton* mEditBtn; + LLButton* mNewLookBtn; + LLButton* mOverflowBtn; + LLPanel* mCurrLookPanel; + + LLTextBox* mCurrentLookName; + + // Used to make sure the user's inventory is in memory. + LLCurrentlyWornFetchObserver* mFetchWorn; + + // Search string for filtering landmarks and teleport + // history locations + std::string mFilterSubString; + + // Information type currently shown in Look Information panel + std::string mLookInfoType; + +}; + +#endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index b48c962413..7cfcac8a9a 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -30,7 +30,7 @@ name="Fetched"> Fetched </floater.string> -<panel + <panel bottom="560" class="panel_main_inventory" filename="panel_main_inventory.xml" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml new file mode 100644 index 0000000000..f511ec0d6f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="Outfits" + bottom="0" + height="326" + left="0" + width="310" + border="true" + follows="left|top|right|bottom"> + <inventory_panel + allow_multi_select="true" + border="true" + bottom="0" + follows="left|top|right|bottom" + height="326" + left="0" + mouse_opaque="true" + name="outfits_list" + width="310" + start_folder="My Outfits"/> + <button bottom="0" + halign="center" + height="16" + label=">" + enabled="false" + mouse_opaque="false" + name="selector" + width="20" + left="0" + visible="false" + follows="right|bottom" + tool_tip="View outfit properties"/> + <panel + background_visible="true" + bevel_style="none" + bottom="0" + follows="left|right|bottom" + height="30" + layout="bottomleft" + left="0" + visible="true" + name="bottom_panel" + width="310"> + <button + follows="bottom|left" + tool_tip="Show additional options" + height="18" + image_disabled="OptionsMenu_Disabled" + image_selected="OptionsMenu_Press" + image_unselected="OptionsMenu_Off" + layout="topleft" + left="10" + name="options_gear_btn" + picture_style="true" + top="6" + width="18" /> + <button + follows="bottom|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + left_pad="5" + name="add_btn" + picture_style="true" + tool_tip="Add new item" + width="18" /> + <dnd_button + follows="bottom|right" + height="18" + image_selected="TrashItem_Press" + image_unselected="TrashItem_Off" + layout="topleft" + right="-5" + name="trash_btn" + picture_style="true" + tool_tip="Remove selected item" + top="6" + width="18" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index a419a02d75..d02354a647 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -120,9 +120,9 @@ background_visible="true" > <panel - class="panel_appearance" - name="panel_appearance" - filename="panel_appearance.xml" + class="sidepanel_appearance" + name="sidepanel_appearance" + filename="sidepanel_appearance.xml" label="Edit Appearance" font="SansSerifBold" /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml new file mode 100644 index 0000000000..d87211d432 --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + follows="all" + height="400" + label="Appearance" + layout="topleft" + min_height="350" + min_width="240" + name="appearance panel" + width="333"> + <string + name="looks_tab_title" + value="Looks" /> + <panel + left="5" width="320" height="55" + background_visible="true" + background_opaque="false" + bg_alpha_color="0.2 0.2 0.2 1.0" + name="panel_currentlook" + follows="left|top|right"> + <text + top="-5" width="200" left="5" height="10" follows="left|right|top" + font="SansSerif" text_color="LtGray" word_wrap="true" + mouse_opaque="false" name="currentlook_title"> + Current Look + </text> + <text + top="-30" left="8" height="10" follows="left|right|top" + font="SansSerifBold" text_color="white" word_wrap="true" + mouse_opaque="false" name="currentlook_name" > + MyLook + </text> + <button + follows="left|right|top" + font="SansSerif" + top="28" right="-105" width="60" height="20" + layout="topleft" + label="Edit" + name="editappearance_btn"/> + </panel> + + <filter_editor + follows="left|top|right" + font="SansSerif" + label="Filter" + layout="topleft" + left="15" + width="313" + height="20" + name="Filter" /> + <panel + class="panel_outfits_inventory" + filename="panel_outfits_inventory.xml" + name="panel_outfits_inventory" + follows="all" + height="271" + halign="center" + layout="topleft" + left="10" + top_pad="19" + width="313" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="Wear" + layout="topleft" + left="10" + name="wear_btn" + top_pad="0" + width="80" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="New Look" + layout="topleft" + left_pad="0" + name="newlook_btn" + top_delta="0" + width="90" /> + + <panel + class="panel_look_info" + filename="panel_look_info.xml" + follows="all" + layout="topleft" + left="0" + name="panel_look_info" + top="-200" + visible="false" /> + + <panel + class="panel_edit_wearable" + filename="panel_edit_wearable.xml" + follows="all" + layout="topleft" + left="0" + name="panel_edit_wearable" + top="-200" + visible="false" + width="333" /> +</panel> |