/indra/newview/llfloatergesture.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 633 lines · 510 code · 71 blank · 52 comment · 89 complexity · 89e8585e135e1deb18d820089847d686 MD5 · raw file

  1. /**
  2. * @file llfloatergesture.cpp
  3. * @brief Read-only list of gestures from your inventory.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llfloatergesture.h"
  28. #include "llinventory.h"
  29. #include "llinventorybridge.h"
  30. #include "llinventoryfunctions.h"
  31. #include "llinventorymodel.h"
  32. #include "llinventoryclipboard.h"
  33. #include "llagent.h"
  34. #include "llappearancemgr.h"
  35. #include "llclipboard.h"
  36. #include "llgesturemgr.h"
  37. #include "llkeyboard.h"
  38. #include "llmenugl.h"
  39. #include "llmultigesture.h"
  40. #include "llpreviewgesture.h"
  41. #include "llscrolllistctrl.h"
  42. #include "lltrans.h"
  43. #include "llviewergesture.h"
  44. #include "llviewermenu.h"
  45. #include "llviewerinventory.h"
  46. #include "llviewercontrol.h"
  47. BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b )
  48. {
  49. return LLStringUtil::precedesDict( a->getName(), b->getName() );
  50. }
  51. class LLFloaterGestureObserver : public LLGestureManagerObserver
  52. {
  53. public:
  54. LLFloaterGestureObserver(LLFloaterGesture* floater) : mFloater(floater) {}
  55. virtual ~LLFloaterGestureObserver() {}
  56. virtual void changed() { mFloater->refreshAll(); }
  57. private:
  58. LLFloaterGesture* mFloater;
  59. };
  60. //-----------------------------
  61. // GestureCallback
  62. //-----------------------------
  63. class GestureShowCallback : public LLInventoryCallback
  64. {
  65. public:
  66. void fire(const LLUUID &inv_item)
  67. {
  68. LLPreviewGesture::show(inv_item, LLUUID::null);
  69. }
  70. };
  71. class GestureCopiedCallback : public LLInventoryCallback
  72. {
  73. private:
  74. LLFloaterGesture* mFloater;
  75. public:
  76. GestureCopiedCallback(LLFloaterGesture* floater): mFloater(floater)
  77. {}
  78. void fire(const LLUUID &inv_item)
  79. {
  80. if(mFloater)
  81. {
  82. mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list"));
  83. }
  84. }
  85. };
  86. //---------------------------------------------------------------------------
  87. // LLFloaterGesture
  88. //---------------------------------------------------------------------------
  89. LLFloaterGesture::LLFloaterGesture(const LLSD& key)
  90. : LLFloater(key)
  91. {
  92. mObserver = new LLFloaterGestureObserver(this);
  93. LLGestureMgr::instance().addObserver(mObserver);
  94. mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
  95. mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
  96. mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
  97. mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
  98. mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
  99. }
  100. void LLFloaterGesture::done()
  101. {
  102. //this method can be called twice: for GestureFolder and once after loading all sudir of GestureFolder
  103. if (gInventory.isCategoryComplete(mGestureFolderID))
  104. {
  105. LL_DEBUGS("Gesture")<< "mGestureFolderID loaded" << LL_ENDL;
  106. // we load only gesture folder without childred.
  107. LLInventoryModel::cat_array_t* categories;
  108. LLInventoryModel::item_array_t* items;
  109. uuid_vec_t unloaded_folders;
  110. LL_DEBUGS("Gesture")<< "Get subdirs of Gesture Folder...." << LL_ENDL;
  111. gInventory.getDirectDescendentsOf(mGestureFolderID, categories, items);
  112. if (categories->empty())
  113. {
  114. gInventory.removeObserver(this);
  115. LL_INFOS("Gesture")<< "Gesture dos NOT contains sub-directories."<< LL_ENDL;
  116. return;
  117. }
  118. LL_DEBUGS("Gesture")<< "There are " << categories->size() << " Folders "<< LL_ENDL;
  119. for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); it++)
  120. {
  121. if (!gInventory.isCategoryComplete(it->get()->getUUID()))
  122. {
  123. unloaded_folders.push_back(it->get()->getUUID());
  124. LL_DEBUGS("Gesture")<< it->get()->getName()<< " Folder added to fetchlist"<< LL_ENDL;
  125. }
  126. }
  127. if (!unloaded_folders.empty())
  128. {
  129. LL_DEBUGS("Gesture")<< "Fetching subdirectories....." << LL_ENDL;
  130. setFetchIDs(unloaded_folders);
  131. startFetch();
  132. }
  133. else
  134. {
  135. LL_DEBUGS("Gesture")<< "All Gesture subdirectories have been loaded."<< LL_ENDL;
  136. gInventory.removeObserver(this);
  137. buildGestureList();
  138. }
  139. }
  140. else
  141. {
  142. LL_WARNS("Gesture")<< "Gesture list was NOT loaded"<< LL_ENDL;
  143. }
  144. }
  145. // virtual
  146. LLFloaterGesture::~LLFloaterGesture()
  147. {
  148. LLGestureMgr::instance().removeObserver(mObserver);
  149. delete mObserver;
  150. mObserver = NULL;
  151. gInventory.removeObserver(this);
  152. }
  153. // virtual
  154. BOOL LLFloaterGesture::postBuild()
  155. {
  156. std::string label;
  157. label = getTitle();
  158. setTitle(label);
  159. mGestureList = getChild<LLScrollListCtrl>("gesture_list");
  160. mGestureList->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList, this));
  161. mGestureList->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
  162. getChild<LLUICtrl>("edit_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickEdit, this));
  163. getChild<LLUICtrl>("play_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
  164. getChild<LLUICtrl>("stop_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
  165. getChild<LLButton>("activate_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
  166. getChild<LLUICtrl>("new_gesture_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickNew, this));
  167. getChild<LLButton>("del_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onDeleteSelected, this));
  168. getChildView("play_btn")->setVisible( true);
  169. getChildView("stop_btn")->setVisible( false);
  170. setDefaultBtn("play_btn");
  171. mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
  172. uuid_vec_t folders;
  173. folders.push_back(mGestureFolderID);
  174. //perform loading Gesture directory anyway to make sure that all subdirectory are loaded too. See method done() for details.
  175. gInventory.addObserver(this);
  176. setFetchIDs(folders);
  177. startFetch();
  178. if (mGestureList)
  179. {
  180. buildGestureList();
  181. mGestureList->setFocus(TRUE);
  182. const BOOL ascending = TRUE;
  183. mGestureList->sortByColumn(std::string("name"), ascending);
  184. mGestureList->selectFirstItem();
  185. }
  186. // Update button labels
  187. onCommitList();
  188. return TRUE;
  189. }
  190. void LLFloaterGesture::refreshAll()
  191. {
  192. if (!mGestureList) return;
  193. buildGestureList();
  194. if (mSelectedID.isNull())
  195. {
  196. mGestureList->selectFirstItem();
  197. }
  198. else
  199. {
  200. if (! mGestureList->setCurrentByID(mSelectedID))
  201. {
  202. mGestureList->selectFirstItem();
  203. }
  204. }
  205. // Update button labels
  206. onCommitList();
  207. }
  208. void LLFloaterGesture::buildGestureList()
  209. {
  210. S32 scroll_pos = mGestureList->getScrollPos();
  211. uuid_vec_t selected_items;
  212. getSelectedIds(selected_items);
  213. LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL;
  214. mGestureList->deleteAllItems();
  215. LLGestureMgr::item_map_t::const_iterator it;
  216. const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures();
  217. for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
  218. {
  219. addGesture(it->first,it->second, mGestureList);
  220. }
  221. if (gInventory.isCategoryComplete(mGestureFolderID))
  222. {
  223. LLIsType is_gesture(LLAssetType::AT_GESTURE);
  224. LLInventoryModel::cat_array_t categories;
  225. LLInventoryModel::item_array_t items;
  226. gInventory.collectDescendentsIf(mGestureFolderID, categories, items,
  227. LLInventoryModel::EXCLUDE_TRASH, is_gesture);
  228. for (LLInventoryModel::item_array_t::iterator it = items.begin(); it!= items.end(); ++it)
  229. {
  230. LLInventoryItem* item = it->get();
  231. if (active_gestures.find(item->getUUID()) == active_gestures.end())
  232. {
  233. // if gesture wasn't loaded yet, we can display only name
  234. addGesture(item->getUUID(), NULL, mGestureList);
  235. }
  236. }
  237. }
  238. // attempt to preserve scroll position through re-builds
  239. // since we do re-build whenever something gets dirty
  240. for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++)
  241. {
  242. mGestureList->selectByID(*it);
  243. }
  244. mGestureList->setScrollPos(scroll_pos);
  245. }
  246. void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list )
  247. {
  248. // Note: Can have NULL item if inventory hasn't arrived yet.
  249. static std::string item_name = getString("loading");
  250. LLInventoryItem* item = gInventory.getItem(item_id);
  251. if (item)
  252. {
  253. item_name = item->getName();
  254. }
  255. static std::string font_style = "NORMAL";
  256. // If gesture is playing, bold it
  257. LLSD element;
  258. element["id"] = item_id;
  259. if (gesture)
  260. {
  261. if (gesture->mPlaying)
  262. {
  263. font_style = "BOLD";
  264. }
  265. item_name = gesture->mName;
  266. element["columns"][0]["column"] = "trigger";
  267. element["columns"][0]["value"] = gesture->mTrigger;
  268. element["columns"][0]["font"]["name"] = "SANSSERIF";
  269. element["columns"][0]["font"]["style"] = font_style;
  270. std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
  271. std::string buffer;
  272. if (gesture->mKey == KEY_NONE)
  273. {
  274. buffer = "---";
  275. key_string = "~~~"; // alphabetize to end
  276. }
  277. else
  278. {
  279. buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
  280. gesture->mKey);
  281. }
  282. element["columns"][1]["column"] = "shortcut";
  283. element["columns"][1]["value"] = buffer;
  284. element["columns"][1]["font"]["name"] = "SANSSERIF";
  285. element["columns"][1]["font"]["style"] = font_style;
  286. // hidden column for sorting
  287. element["columns"][2]["column"] = "key";
  288. element["columns"][2]["value"] = key_string;
  289. element["columns"][2]["font"]["name"] = "SANSSERIF";
  290. element["columns"][2]["font"]["style"] = font_style;
  291. // Only add "playing" if we've got the name, less confusing. JC
  292. if (item && gesture->mPlaying)
  293. {
  294. item_name += " " + getString("playing");
  295. }
  296. element["columns"][3]["column"] = "name";
  297. element["columns"][3]["value"] = item_name;
  298. element["columns"][3]["font"]["name"] = "SANSSERIF";
  299. element["columns"][3]["font"]["style"] = font_style;
  300. }
  301. else
  302. {
  303. element["columns"][0]["column"] = "trigger";
  304. element["columns"][0]["value"] = "";
  305. element["columns"][0]["font"]["name"] = "SANSSERIF";
  306. element["columns"][0]["font"]["style"] = font_style;
  307. element["columns"][1]["column"] = "shortcut";
  308. element["columns"][1]["value"] = "---";
  309. element["columns"][1]["font"]["name"] = "SANSSERIF";
  310. element["columns"][1]["font"]["style"] = font_style;
  311. element["columns"][2]["column"] = "key";
  312. element["columns"][2]["value"] = "~~~";
  313. element["columns"][2]["font"]["name"] = "SANSSERIF";
  314. element["columns"][2]["font"]["style"] = font_style;
  315. element["columns"][3]["column"] = "name";
  316. element["columns"][3]["value"] = item_name;
  317. element["columns"][3]["font"]["name"] = "SANSSERIF";
  318. element["columns"][3]["font"]["style"] = font_style;
  319. }
  320. LL_DEBUGS("Gesture") << "Added gesture [" << item_name << "]" << LL_ENDL;
  321. LLScrollListItem* sl_item = list->addElement(element, ADD_BOTTOM);
  322. if(sl_item)
  323. {
  324. LLFontGL::StyleFlags style = LLGestureMgr::getInstance()->isGestureActive(item_id) ? LLFontGL::BOLD : LLFontGL::NORMAL;
  325. // *TODO find out why ["font"]["style"] does not affect font style
  326. ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(style);
  327. }
  328. }
  329. void LLFloaterGesture::getSelectedIds(uuid_vec_t& ids)
  330. {
  331. std::vector<LLScrollListItem*> items = mGestureList->getAllSelected();
  332. for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++)
  333. {
  334. ids.push_back((*it)->getUUID());
  335. }
  336. }
  337. bool LLFloaterGesture::isActionEnabled(const LLSD& command)
  338. {
  339. // paste copy_uuid edit_gesture
  340. std::string command_name = command.asString();
  341. if("paste" == command_name)
  342. {
  343. if(!LLInventoryClipboard::instance().hasContents())
  344. return false;
  345. LLDynamicArray<LLUUID> ids;
  346. LLInventoryClipboard::instance().retrieve(ids);
  347. for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
  348. {
  349. LLInventoryItem* item = gInventory.getItem(*it);
  350. if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
  351. {
  352. return true;
  353. }
  354. }
  355. return false;
  356. }
  357. else if("copy_uuid" == command_name || "edit_gesture" == command_name)
  358. {
  359. return mGestureList->getAllSelected().size() == 1;
  360. }
  361. return true;
  362. }
  363. void LLFloaterGesture::onClickPlay()
  364. {
  365. const LLUUID& item_id = mGestureList->getCurrentID();
  366. if(item_id.isNull()) return;
  367. LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;
  368. if(!LLGestureMgr::instance().isGestureActive(item_id))
  369. {
  370. // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList.
  371. BOOL inform_server = TRUE;
  372. BOOL deactivate_similar = FALSE;
  373. LLGestureMgr::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));
  374. LLViewerInventoryItem *item = gInventory.getItem(item_id);
  375. llassert(item);
  376. if (item)
  377. {
  378. LLGestureMgr::instance().activateGestureWithAsset(item_id, item->getAssetUUID(), inform_server, deactivate_similar);
  379. LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL;
  380. }
  381. }
  382. else
  383. {
  384. playGesture(item_id);
  385. }
  386. }
  387. void LLFloaterGesture::onClickNew()
  388. {
  389. LLPointer<LLInventoryCallback> cb = new GestureShowCallback();
  390. create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
  391. LLUUID::null, LLTransactionID::tnull, "New Gesture", "", LLAssetType::AT_GESTURE,
  392. LLInventoryType::IT_GESTURE, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
  393. }
  394. void LLFloaterGesture::onActivateBtnClick()
  395. {
  396. uuid_vec_t ids;
  397. getSelectedIds(ids);
  398. if(ids.empty())
  399. return;
  400. LLGestureMgr* gm = LLGestureMgr::getInstance();
  401. uuid_vec_t::const_iterator it = ids.begin();
  402. BOOL first_gesture_state = gm->isGestureActive(*it);
  403. BOOL is_mixed = FALSE;
  404. while( ++it != ids.end() )
  405. {
  406. if(first_gesture_state != gm->isGestureActive(*it))
  407. {
  408. is_mixed = TRUE;
  409. break;
  410. }
  411. }
  412. for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
  413. {
  414. if(is_mixed)
  415. {
  416. gm->activateGesture(*it);
  417. }
  418. else
  419. {
  420. if(first_gesture_state)
  421. {
  422. gm->deactivateGesture(*it);
  423. }
  424. else
  425. {
  426. gm->activateGesture(*it);
  427. }
  428. }
  429. }
  430. }
  431. void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
  432. {
  433. std::string command_name = command.asString();
  434. // since we select this comman inventory item had already arrived .
  435. if("copy_gesture" == command_name)
  436. {
  437. uuid_vec_t ids;
  438. getSelectedIds(ids);
  439. // make sure that clopboard is empty
  440. LLInventoryClipboard::instance().reset();
  441. for(uuid_vec_t::iterator it = ids.begin(); it != ids.end(); it++)
  442. {
  443. LLInventoryItem* item = gInventory.getItem(*it);
  444. if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
  445. {
  446. LLInventoryClipboard::instance().add(item->getUUID());
  447. }
  448. }
  449. }
  450. else if ("paste" == command_name)
  451. {
  452. LLInventoryClipboard& clipbord = LLInventoryClipboard::instance();
  453. LLDynamicArray<LLUUID> ids;
  454. clipbord.retrieve(ids);
  455. if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID))
  456. return;
  457. LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID);
  458. llassert(gesture_dir);
  459. LLPointer<GestureCopiedCallback> cb = new GestureCopiedCallback(this);
  460. for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
  461. {
  462. LLInventoryItem* item = gInventory.getItem(*it);
  463. if(gesture_dir && item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
  464. {
  465. LLStringUtil::format_map_t string_args;
  466. string_args["[COPY_NAME]"] = item->getName();
  467. LL_DEBUGS("Gesture")<< "Copying gesture " << item->getName() << " "<< item->getUUID() << " into "
  468. << gesture_dir->getName() << " "<< gesture_dir->getUUID() << LL_ENDL;
  469. copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(),
  470. gesture_dir->getUUID(), getString("copy_name", string_args), cb);
  471. }
  472. }
  473. clipbord.reset();
  474. }
  475. else if ("copy_uuid" == command_name)
  476. {
  477. gClipboard.copyFromString(utf8str_to_wstring(mGestureList->getCurrentID().asString()), mGestureList->getCurrentID());
  478. }
  479. }
  480. void LLFloaterGesture::onClickEdit()
  481. {
  482. const LLUUID& item_id = mGestureList->getCurrentID();
  483. LLInventoryItem* item = gInventory.getItem(item_id);
  484. if (!item) return;
  485. LLPreviewGesture* previewp = LLPreviewGesture::show(item_id, LLUUID::null);
  486. if (!previewp->getHost())
  487. {
  488. previewp->setRect(gFloaterView->findNeighboringPosition(this, previewp));
  489. }
  490. }
  491. void LLFloaterGesture::onCommitList()
  492. {
  493. const LLUUID& item_id = mGestureList->getCurrentID();
  494. mSelectedID = item_id;
  495. if (LLGestureMgr::instance().isGesturePlaying(item_id))
  496. {
  497. getChildView("play_btn")->setVisible( false);
  498. getChildView("stop_btn")->setVisible( true);
  499. }
  500. else
  501. {
  502. getChildView("play_btn")->setVisible( true);
  503. getChildView("stop_btn")->setVisible( false);
  504. }
  505. }
  506. void LLFloaterGesture::onDeleteSelected()
  507. {
  508. uuid_vec_t ids;
  509. getSelectedIds(ids);
  510. if(ids.empty())
  511. return;
  512. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  513. LLGestureMgr* gm = LLGestureMgr::getInstance();
  514. for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
  515. {
  516. const LLUUID& selected_item = *it;
  517. LLInventoryItem* inv_item = gInventory.getItem(selected_item);
  518. if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_GESTURE)
  519. {
  520. if(gm->isGestureActive(selected_item))
  521. {
  522. gm->deactivateGesture(selected_item);
  523. }
  524. LLInventoryModel::update_list_t update;
  525. LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
  526. update.push_back(old_folder);
  527. LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
  528. update.push_back(new_folder);
  529. gInventory.accountForUpdate(update);
  530. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
  531. new_item->setParent(trash_id);
  532. // no need to restamp it though it's a move into trash because
  533. // it's a brand new item already.
  534. new_item->updateParentOnServer(FALSE);
  535. gInventory.updateItem(new_item);
  536. }
  537. }
  538. gInventory.notifyObservers();
  539. buildGestureList();
  540. }
  541. void LLFloaterGesture::addToCurrentOutFit()
  542. {
  543. uuid_vec_t ids;
  544. getSelectedIds(ids);
  545. LLAppearanceMgr* am = LLAppearanceMgr::getInstance();
  546. for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++)
  547. {
  548. am->addCOFItemLink(*it);
  549. }
  550. }
  551. void LLFloaterGesture::playGesture(LLUUID item_id)
  552. {
  553. LL_DEBUGS("Gesture")<<"Playing gesture "<< item_id<<LL_ENDL;
  554. if (LLGestureMgr::instance().isGesturePlaying(item_id))
  555. {
  556. LLGestureMgr::instance().stopGesture(item_id);
  557. }
  558. else
  559. {
  560. LLGestureMgr::instance().playGesture(item_id);
  561. }
  562. }