llpaneloutfitsinventory.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:18k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file llpaneloutfitsinventory.cpp
  3.  * @brief Outfits inventory panel
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpaneloutfitsinventory.h"
  34. #include "llagent.h"
  35. #include "llagentwearables.h"
  36. #include "llappearancemgr.h"
  37. #include "llbutton.h"
  38. #include "llfloaterreg.h"
  39. #include "llfloaterworldmap.h"
  40. #include "llfloaterinventory.h"
  41. #include "llfoldervieweventlistener.h"
  42. #include "llinventoryfunctions.h"
  43. #include "llinventorypanel.h"
  44. #include "lllandmark.h"
  45. #include "lllineeditor.h"
  46. #include "llmodaldialog.h"
  47. #include "llsidepanelappearance.h"
  48. #include "llsidetray.h"
  49. #include "lltabcontainer.h"
  50. #include "llviewerfoldertype.h"
  51. #include "llviewerjointattachment.h"
  52. #include "llvoavatarself.h"
  53. // List Commands
  54. #include "lldndbutton.h"
  55. #include "llmenugl.h"
  56. #include "llviewermenu.h"
  57. #include "llviewercontrol.h"
  58. static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
  59. static const std::string COF_TAB_NAME = "cof_tab";
  60. static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
  61. bool LLPanelOutfitsInventory::sShowDebugEditor = false;
  62. class LLOutfitSaveAsDialog : public LLModalDialog
  63. {
  64. private:
  65. std::string mItemName;
  66. std::string mTempItemName;
  67. boost::signals2::signal<void (const std::string&)> mSaveAsSignal;
  68. public:
  69. LLOutfitSaveAsDialog( const LLSD& key )
  70. : LLModalDialog( key ),
  71.   mTempItemName(key.asString())
  72. {
  73. }
  74. BOOL postBuild()
  75. {
  76. getChild<LLUICtrl>("Save")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onSave, this ));
  77. getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onCancel, this ));
  78. childSetTextArg("name ed", "[DESC]", mTempItemName);
  79. return TRUE;
  80. }
  81. void setSaveAsCommit( const boost::signals2::signal<void (const std::string&)>::slot_type& cb )
  82. {
  83. mSaveAsSignal.connect(cb);
  84. }
  85. virtual void onOpen(const LLSD& key)
  86. {
  87. LLLineEditor* edit = getChild<LLLineEditor>("name ed");
  88. if (edit)
  89. {
  90. edit->setFocus(TRUE);
  91. edit->selectAll();
  92. }
  93. }
  94. void onSave()
  95. {
  96. mItemName = childGetValue("name ed").asString();
  97. LLStringUtil::trim(mItemName);
  98. if( !mItemName.empty() )
  99. {
  100. mSaveAsSignal(mItemName);
  101. closeFloater(); // destroys this object
  102. }
  103. }
  104. void onCancel()
  105. {
  106. closeFloater(); // destroys this object
  107. }
  108. };
  109. LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
  110. mActivePanel(NULL),
  111. mParent(NULL)
  112. {
  113. mSavedFolderState = new LLSaveFolderState();
  114. mSavedFolderState->setApply(FALSE);
  115. static bool registered_dialog = false;
  116. if (!registered_dialog)
  117. {
  118. LLFloaterReg::add("outfit_save_as", "floater_outfit_save_as.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutfitSaveAsDialog>);
  119. registered_dialog = true;
  120. }
  121. }
  122. LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
  123. {
  124. delete mSavedFolderState;
  125. }
  126. // virtual
  127. BOOL LLPanelOutfitsInventory::postBuild()
  128. {
  129. sShowDebugEditor = gSavedSettings.getBOOL("ShowDebugAppearanceEditor");
  130. initTabPanels();
  131. initListCommandsHandlers();
  132. return TRUE;
  133. }
  134. // virtual
  135. void LLPanelOutfitsInventory::onOpen(const LLSD& key)
  136. {
  137. // Make sure we know which tab is selected, update the filter,
  138. // and update verbs.
  139. onTabChange();
  140. // Auto open the first outfit newly created so new users can see sample outfit contents
  141. static bool should_open_outfit = true;
  142. if (should_open_outfit && gAgent.isFirstLogin())
  143. {
  144. LLInventoryPanel* outfits_panel = getChild<LLInventoryPanel>(OUTFITS_TAB_NAME);
  145. if (outfits_panel)
  146. {
  147. LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
  148. LLFolderViewFolder* my_outfits_folder = outfits_panel->getRootFolder()->getFolderByID(my_outfits_id);
  149. if (my_outfits_folder)
  150. {
  151. LLFolderViewFolder* first_outfit = dynamic_cast<LLFolderViewFolder*>(my_outfits_folder->getFirstChild());
  152. if (first_outfit)
  153. {
  154. first_outfit->setOpen(TRUE);
  155. }
  156. }
  157. }
  158. }
  159. should_open_outfit = false;
  160. }
  161. void LLPanelOutfitsInventory::updateVerbs()
  162. {
  163. if (mParent)
  164. {
  165. mParent->updateVerbs();
  166. }
  167. if (mListCommands)
  168. {
  169. mListCommands->childSetVisible("look_edit_btn",sShowDebugEditor);
  170. updateListCommands();
  171. }
  172. }
  173. void LLPanelOutfitsInventory::setParent(LLSidepanelAppearance* parent)
  174. {
  175. mParent = parent;
  176. }
  177. // virtual
  178. void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
  179. {
  180. mFilterSubString = string;
  181. if (string == "")
  182. {
  183. mActivePanel->setFilterSubString(LLStringUtil::null);
  184. // re-open folders that were initially open
  185. mSavedFolderState->setApply(TRUE);
  186. getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
  187. LLOpenFoldersWithSelection opener;
  188. getRootFolder()->applyFunctorRecursively(opener);
  189. getRootFolder()->scrollToShowSelection();
  190. }
  191. gInventory.startBackgroundFetch();
  192. if (mActivePanel->getFilterSubString().empty() && string.empty())
  193. {
  194. // current filter and new filter empty, do nothing
  195. return;
  196. }
  197. // save current folder open state if no filter currently applied
  198. if (getRootFolder()->getFilterSubString().empty())
  199. {
  200. mSavedFolderState->setApply(FALSE);
  201. getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
  202. }
  203. // set new filter string
  204. mActivePanel->setFilterSubString(string);
  205. }
  206. void LLPanelOutfitsInventory::onWearButtonClick()
  207. {
  208. LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
  209. if (listenerp)
  210. {
  211. listenerp->performAction(NULL, NULL,"replaceoutfit");
  212. }
  213. }
  214. void LLPanelOutfitsInventory::onAdd()
  215. {
  216. LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
  217. if (listenerp)
  218. {
  219. listenerp->performAction(NULL, NULL,"addtooutfit");
  220. }
  221. }
  222. void LLPanelOutfitsInventory::onRemove()
  223. {
  224. LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
  225. if (listenerp)
  226. {
  227. listenerp->performAction(NULL, NULL,"removefromoutfit");
  228. }
  229. }
  230. void LLPanelOutfitsInventory::onEdit()
  231. {
  232. }
  233. void LLPanelOutfitsInventory::onSave()
  234. {
  235. std::string outfit_name;
  236. if (!LLAppearanceManager::getInstance()->getBaseOutfitName(outfit_name))
  237. {
  238. outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
  239. }
  240. LLOutfitSaveAsDialog* save_as_dialog = LLFloaterReg::showTypedInstance<LLOutfitSaveAsDialog>("outfit_save_as", LLSD(outfit_name), TRUE);
  241. if (save_as_dialog)
  242. {
  243. save_as_dialog->setSaveAsCommit(boost::bind(&LLPanelOutfitsInventory::onSaveCommit, this, _1 ));
  244. }
  245. }
  246. void LLPanelOutfitsInventory::onSaveCommit(const std::string& outfit_name)
  247. {
  248. LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name);
  249. LLSD key;
  250. LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key);
  251. if (mAppearanceTabs)
  252. {
  253. mAppearanceTabs->selectTabByName(OUTFITS_TAB_NAME);
  254. }
  255. }
  256. void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
  257. {
  258. updateVerbs();
  259. if (getRootFolder()->needsAutoRename() && items.size())
  260. {
  261. getRootFolder()->startRenamingSelectedItem();
  262. getRootFolder()->setNeedsAutoRename(FALSE);
  263. }
  264. }
  265. void LLPanelOutfitsInventory::onSelectorButtonClicked()
  266. {
  267.   LLFolderViewItem* cur_item = getRootFolder()->getCurSelectedItem();
  268.   LLFolderViewEventListener* listenerp = cur_item->getListener();
  269.   if (getIsCorrectType(listenerp))
  270.   {
  271.   LLSD key;
  272.   key["type"] = "look";
  273.   key["id"] = listenerp->getUUID();
  274.   LLSideTray::getInstance()->showPanel("sidepanel_appearance", key);
  275.   } 
  276. }
  277. LLFolderViewEventListener *LLPanelOutfitsInventory::getCorrectListenerForAction()
  278. {
  279. LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem();
  280. if (!current_item)
  281. return NULL;
  282. LLFolderViewEventListener* listenerp = current_item->getListener();
  283. if (getIsCorrectType(listenerp))
  284. {
  285. return listenerp;
  286. }
  287. return NULL;
  288. }
  289. bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *listenerp) const
  290. {
  291. if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
  292. {
  293. LLViewerInventoryCategory *cat = gInventory.getCategory(listenerp->getUUID());
  294. if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
  295. {
  296. return true;
  297. }
  298. }
  299. return false;
  300. }
  301. LLFolderView *LLPanelOutfitsInventory::getRootFolder()
  302. {
  303. return mActivePanel->getRootFolder();
  304. }
  305. //////////////////////////////////////////////////////////////////////////////////
  306. // List Commands                                                                //
  307. void LLPanelOutfitsInventory::initListCommandsHandlers()
  308. {
  309. mListCommands = getChild<LLPanel>("bottom_panel");
  310. mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
  311. mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
  312. mListCommands->childSetAction("make_outfit_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this));
  313. mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
  314. mListCommands->childSetAction("look_edit_btn", boost::bind(&LLPanelOutfitsInventory::onSelectorButtonClicked, this));
  315. LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
  316. trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this
  317.    ,       _4 // BOOL drop
  318.    ,       _5 // EDragAndDropType cargo_type
  319.    ,       _7 // EAcceptance* accept
  320.    ));
  321. mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action",
  322.  boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2));
  323. mEnableCallbackRegistrar.add("panel_outfits_inventory_gear_default.Enable",
  324.  boost::bind(&LLPanelOutfitsInventory::isActionEnabled, this, _2));
  325. mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("panel_outfits_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  326. }
  327. void LLPanelOutfitsInventory::updateListCommands()
  328. {
  329. bool trash_enabled = isActionEnabled("delete");
  330. bool wear_enabled = isActionEnabled("wear");
  331. bool make_outfit_enabled = isActionEnabled("make_outfit");
  332. mListCommands->childSetEnabled("trash_btn", trash_enabled);
  333. mListCommands->childSetEnabled("wear_btn", wear_enabled);
  334. mListCommands->childSetVisible("wear_btn", wear_enabled);
  335. mListCommands->childSetEnabled("make_outfit_btn", make_outfit_enabled);
  336. }
  337. void LLPanelOutfitsInventory::onGearButtonClick()
  338. {
  339. showActionMenu(mMenuGearDefault,"options_gear_btn");
  340. }
  341. void LLPanelOutfitsInventory::onAddButtonClick()
  342. {
  343. onSave();
  344. }
  345. void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
  346. {
  347. if (menu)
  348. {
  349. menu->buildDrawLabels();
  350. menu->updateParent(LLMenuGL::sMenuContainer);
  351. LLView* spawning_view = getChild<LLView> (spawning_view_name);
  352. S32 menu_x, menu_y;
  353. //show menu in co-ordinates of panel
  354. spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
  355. menu_y += menu->getRect().getHeight();
  356. LLMenuGL::showPopup(this, menu, menu_x, menu_y);
  357. }
  358. }
  359. void LLPanelOutfitsInventory::onTrashButtonClick()
  360. {
  361. onClipboardAction("delete");
  362. }
  363. void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata)
  364. {
  365. std::string command_name = userdata.asString();
  366. getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
  367. updateListCommands();
  368. updateVerbs();
  369. }
  370. void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata)
  371. {
  372. if (!isActionEnabled(userdata))
  373. return;
  374. const std::string command_name = userdata.asString();
  375. if (command_name == "new")
  376. {
  377. onSave();
  378. }
  379. if (command_name == "edit")
  380. {
  381. onEdit();
  382. }
  383. if (command_name == "wear")
  384. {
  385. onWearButtonClick();
  386. }
  387. // Note: This option has been removed from the gear menu.
  388. if (command_name == "add")
  389. {
  390. onAdd();
  391. }
  392. if (command_name == "remove")
  393. {
  394. onRemove();
  395. }
  396. if (command_name == "rename")
  397. {
  398. onClipboardAction("rename");
  399. }
  400. if (command_name == "remove_link")
  401. {
  402. onClipboardAction("delete");
  403. }
  404. if (command_name == "delete")
  405. {
  406. onClipboardAction("delete");
  407. }
  408. updateListCommands();
  409. updateVerbs();
  410. }
  411. BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
  412. {
  413. const std::string command_name = userdata.asString();
  414. if (command_name == "delete" || command_name == "remove")
  415. {
  416. BOOL can_delete = FALSE;
  417. LLFolderView *folder = getActivePanel()->getRootFolder();
  418. if (folder)
  419. {
  420. std::set<LLUUID> selection_set;
  421. folder->getSelectionList(selection_set);
  422. can_delete = (selection_set.size() > 0);
  423. for (std::set<LLUUID>::iterator iter = selection_set.begin();
  424.  iter != selection_set.end();
  425.  ++iter)
  426. {
  427. const LLUUID &item_id = (*iter);
  428. LLFolderViewItem *item = folder->getItemByID(item_id);
  429. can_delete &= item->getListener()->isItemRemovable();
  430. }
  431. return can_delete;
  432. }
  433. return FALSE;
  434. }
  435. if (command_name == "remove_link")
  436. {
  437. BOOL can_delete = FALSE;
  438. LLFolderView *folder = getActivePanel()->getRootFolder();
  439. if (folder)
  440. {
  441. std::set<LLUUID> selection_set;
  442. folder->getSelectionList(selection_set);
  443. can_delete = (selection_set.size() > 0);
  444. for (std::set<LLUUID>::iterator iter = selection_set.begin();
  445.  iter != selection_set.end();
  446.  ++iter)
  447. {
  448. const LLUUID &item_id = (*iter);
  449. LLViewerInventoryItem *item = gInventory.getItem(item_id);
  450. if (!item || !item->getIsLinkType())
  451. return FALSE;
  452. }
  453. return can_delete;
  454. }
  455. return FALSE;
  456. }
  457. if (command_name == "rename" ||
  458. command_name == "delete_outfit")
  459. {
  460. return (getCorrectListenerForAction() != NULL) && hasItemsSelected();
  461. }
  462. if (command_name == "wear")
  463. {
  464. if (isCOFPanelActive())
  465. {
  466. return FALSE;
  467. }
  468. }
  469. if (command_name == "make_outfit")
  470. {
  471. return TRUE;
  472. }
  473.    
  474. if (command_name == "edit" || 
  475. command_name == "add"
  476. )
  477. {
  478. return (getCorrectListenerForAction() != NULL);
  479. }
  480. return TRUE;
  481. }
  482. bool LLPanelOutfitsInventory::hasItemsSelected()
  483. {
  484. bool has_items_selected = false;
  485. LLFolderView *folder = getActivePanel()->getRootFolder();
  486. if (folder)
  487. {
  488. std::set<LLUUID> selection_set;
  489. folder->getSelectionList(selection_set);
  490. has_items_selected = (selection_set.size() > 0);
  491. }
  492. return has_items_selected;
  493. }
  494. bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
  495. {
  496. *accept = ACCEPT_NO;
  497. const bool is_enabled = isActionEnabled("delete");
  498. if (is_enabled) *accept = ACCEPT_YES_MULTI;
  499. if (is_enabled && drop)
  500. {
  501. onClipboardAction("delete");
  502. }
  503. return true;
  504. }
  505. // List Commands                                                              //
  506. ////////////////////////////////////////////////////////////////////////////////
  507. //////////////////////////////////////////////////////////////////////////////////
  508. // Tab panels                                                                    //
  509. void LLPanelOutfitsInventory::initTabPanels()
  510. {
  511. LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>(COF_TAB_NAME);
  512. cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  513. mTabPanels.push_back(cof_panel);
  514. LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>(OUTFITS_TAB_NAME);
  515. myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY);
  516. myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  517. mTabPanels.push_back(myoutfits_panel);
  518. for (tabpanels_vec_t::iterator iter = mTabPanels.begin();
  519.  iter != mTabPanels.end();
  520.  ++iter)
  521. {
  522. LLInventoryPanel *panel = (*iter);
  523. panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, panel, _1, _2));
  524. }
  525. mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");
  526. mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));
  527. mActivePanel = (LLInventoryPanel*)mAppearanceTabs->getCurrentPanel();
  528. }
  529. void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
  530. {
  531. if (user_action && items.size() > 0)
  532. {
  533. for (tabpanels_vec_t::iterator iter = mTabPanels.begin();
  534.  iter != mTabPanels.end();
  535.  ++iter)
  536. {
  537. LLInventoryPanel *panel = (*iter);
  538. if (panel == tab_panel)
  539. {
  540. mActivePanel = panel;
  541. }
  542. else
  543. {
  544. panel->getRootFolder()->clearSelection();
  545. }
  546. }
  547. }
  548. onSelectionChange(items, user_action);
  549. }
  550. void LLPanelOutfitsInventory::onTabChange()
  551. {
  552. mActivePanel = (LLInventoryPanel*)childGetVisibleTab("appearance_tabs");
  553. if (!mActivePanel)
  554. {
  555. return;
  556. }
  557. mActivePanel->setFilterSubString(mFilterSubString);
  558. updateVerbs();
  559. }
  560. BOOL LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) const
  561. {
  562. for(tabpanels_vec_t::const_iterator it = mTabPanels.begin();
  563. it != mTabPanels.end();
  564. ++it)
  565. {
  566. if (*it == panel)
  567. return TRUE;
  568. }
  569. return FALSE;
  570. }
  571. BOOL LLPanelOutfitsInventory::isCOFPanelActive() const
  572. {
  573. return (getActivePanel()->getName() == COF_TAB_NAME);
  574. }