From cfc2d2890e02898199337f46f364edc2fd3efcf8 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko <118780484+maxim-productengine@users.noreply.github.com> Date: Thu, 1 Dec 2022 02:04:04 +0200 Subject: [PATCH] SL-18243 Add wear and unwear buttons on line items in Outfits floater --- indra/newview/llinventorylistitem.h | 2 +- indra/newview/llwearableitemslist.cpp | 101 ++++++++++++++++-- indra/newview/llwearableitemslist.h | 23 +++- .../skins/default/textures/icons/add_icon.png | Bin 0 -> 3386 bytes .../default/textures/icons/remove_icon.png | Bin 0 -> 3446 bytes .../skins/default/textures/textures.xml | 3 + .../default/xui/en/outfit_accordion_tab.xml | 1 + .../default/xui/en/panel_outfits_wearing.xml | 1 + .../en/widgets/wearable_outfit_list_item.xml | 64 +++++++++++ 9 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/add_icon.png create mode 100644 indra/newview/skins/default/textures/icons/remove_icon.png create mode 100644 indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h index d4dd212cc3..cf713a6930 100644 --- a/indra/newview/llinventorylistitem.h +++ b/indra/newview/llinventorylistitem.h @@ -197,6 +197,7 @@ protected: virtual BOOL handleToolTip( S32 x, S32 y, MASK mask); const LLUUID mInventoryItemUUID; + bool mHovered; private: @@ -221,7 +222,6 @@ private: LLUIImagePtr mSelectedImage; LLUIImagePtr mSeparatorImage; - bool mHovered; bool mSelected; bool mSeparatorVisible; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index bf4db81475..89b74ae962 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -92,17 +92,77 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); + +LLPanelWearableOutfitItem::Params::Params() +: add_btn("add_btn"), + remove_btn("remove_btn") +{ +} + +BOOL LLPanelWearableOutfitItem::postBuild() +{ + LLPanelWearableListItem::postBuild(); + + LLViewerInventoryItem* inv_item = getItem(); + mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART); + if(mShowWidgets) + { + addWidgetToRightSide("add_wearable"); + addWidgetToRightSide("remove_wearable"); + + childSetAction("add_wearable", boost::bind(&LLPanelWearableOutfitItem::onAddWearable, this)); + childSetAction("remove_wearable", boost::bind(&LLPanelWearableOutfitItem::onRemoveWearable, this)); + + setWidgetsVisible(false); + reshapeWidgets(); + } + return TRUE; +} + +BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if(!mShowWidgets) + { + return LLPanelWearableListItem::handleDoubleClick(x, y, mask); + } + + if(LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + { + onRemoveWearable(); + } + else + { + onAddWearable(); + } + return TRUE; +} + +void LLPanelWearableOutfitItem::onAddWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().wearItemOnAvatar(mInventoryItemUUID, true, false); +} + +void LLPanelWearableOutfitItem::onRemoveWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().removeItemFromAvatar(mInventoryItemUUID); +} // static LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item, - bool worn_indication_enabled) + bool worn_indication_enabled, + bool show_widgets) { LLPanelWearableOutfitItem* list_item = NULL; if (item) { - const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams(); + const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams(); - list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params); + list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets); list_item->initFromParams(params); list_item->postBuild(); } @@ -110,11 +170,23 @@ LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryIt } LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, - const LLPanelWearableOutfitItem::Params& params) -: LLPanelInventoryListItemBase(item, params) + bool worn_indication_enabled, + const LLPanelWearableOutfitItem::Params& params, + bool show_widgets) +: LLPanelWearableListItem(item, params) , mWornIndicationEnabled(worn_indication_enabled) +, mShowWidgets(show_widgets) { + if(mShowWidgets) + { + LLButton::Params button_params = params.add_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create(button_params)); + + button_params = params.remove_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create(button_params)); + } } // virtual @@ -127,11 +199,22 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, // We don't use get_is_item_worn() here because this update is triggered by // an inventory observer upon link in COF beind added or removed so actual // worn status of a linked item may still remain unchanged. - if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID); + if (mWornIndicationEnabled && is_worn) { search_label += LLTrans::getString("worn"); item_state = IS_WORN; } + if(mShowWidgets) + { + setShowWidget("add_wearable", !is_worn); + setShowWidget("remove_wearable", is_worn); + if(mHovered) + { + setWidgetsVisible(true); + reshapeWidgets(); + } + } LLPanelInventoryListItemBase::updateItem(search_label, item_state); } @@ -634,6 +717,7 @@ static const LLDefaultChildRegistry::Register r("wearable_i LLWearableItemsList::Params::Params() : standalone("standalone", true) , worn_indication_enabled("worn_indication_enabled", true) +, show_item_widgets("show_item_widgets", false) {} LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) @@ -649,6 +733,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) } mWornIndicationEnabled = p.worn_indication_enabled; setNoItemsCommentText(LLTrans::getString("LoadingData")); + mShowItemWidgets = p.show_item_widgets; } // virtual @@ -665,7 +750,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item) return NULL; } - return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); + return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets); } void LLWearableItemsList::updateList(const LLUUID& category_id) diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index ba8488b237..f7774a7086 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -72,12 +72,23 @@ protected: * Extends LLPanelInventoryListItemBase with handling * double click to wear the item. */ -class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase +class LLPanelWearableOutfitItem : public LLPanelWearableListItem { LOG_CLASS(LLPanelWearableOutfitItem); public: + struct Params : public LLInitParam::Block + { + Optional add_btn, remove_btn; + + Params(); + }; + + BOOL postBuild(); + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item, - bool worn_indication_enabled); + bool worn_indication_enabled, + bool show_widgets); /** * Updates item name and (worn) suffix. @@ -85,12 +96,16 @@ public: /*virtual*/ void updateItem(const std::string& name, EItemState item_state = IS_DEFAULT); + void onAddWearable(); + void onRemoveWearable(); + protected: LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, const Params& params); + bool worn_indication_enabled, const Params& params, bool show_widgets = false); private: bool mWornIndicationEnabled; + bool mShowWidgets; }; class LLPanelDeletableWearableListItem : public LLPanelWearableListItem @@ -442,6 +457,7 @@ public: { Optional standalone; Optional worn_indication_enabled; + Optional show_item_widgets; Params(); }; @@ -482,6 +498,7 @@ protected: bool mIsStandalone; bool mWornIndicationEnabled; + bool mShowItemWidgets; ESortOrder mSortOrder; diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cb68ee8e16d59fc379949164be128432622f8cdf GIT binary patch literal 3386 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 Qt^fc407*qoM6N<$f=y$5JOBUy literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6e62ee33f49f64c703bf0557cfc683ee5612219f GIT binary patch literal 3446 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 Y0IB9Z%q^`s8vp + + + diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 2a24c74feb..d74dca8b95 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -18,6 +18,7 @@ follows="all" keep_one_selected="true" multi_select="true" + show_item_widgets="true" name="wearable_items_list" translate="false" standalone="false" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index 42a7974316..b2dc975c6e 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -36,6 +36,7 @@ left="3" multi_select="true" name="cof_items_list" + show_item_widgets="true" standalone="false" top="0" width="309" diff --git a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml new file mode 100644 index 0000000000..cd84b91b1f --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + +