PageRenderTime 64ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llgesturemgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1407 lines | 1026 code | 222 blank | 159 comment | 198 complexity | 5d12172915e1433c48742c946d68092b MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llgesturemgr.cpp
  3. * @brief Manager for playing gestures on the viewer
  4. *
  5. * $LicenseInfo:firstyear=2004&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 "llgesturemgr.h"
  28. // system
  29. #include <functional>
  30. #include <algorithm>
  31. // library
  32. #include "llaudioengine.h"
  33. #include "lldatapacker.h"
  34. #include "llinventory.h"
  35. #include "llkeyframemotion.h"
  36. #include "llmultigesture.h"
  37. #include "llnotificationsutil.h"
  38. #include "llstl.h"
  39. #include "llstring.h" // todo: remove
  40. #include "llvfile.h"
  41. #include "message.h"
  42. // newview
  43. #include "llagent.h"
  44. #include "lldelayedgestureerror.h"
  45. #include "llinventorymodel.h"
  46. #include "llviewermessage.h"
  47. #include "llvoavatarself.h"
  48. #include "llviewerstats.h"
  49. #include "llnearbychatbar.h"
  50. #include "llappearancemgr.h"
  51. #include "llgesturelistener.h"
  52. // Longest time, in seconds, to wait for all animations to stop playing
  53. const F32 MAX_WAIT_ANIM_SECS = 30.f;
  54. // If this gesture is a link, get the base gesture that this link points to,
  55. // otherwise just return this id.
  56. static const LLUUID& get_linked_uuid(const LLUUID& item_id);
  57. // Lightweight constructor.
  58. // init() does the heavy lifting.
  59. LLGestureMgr::LLGestureMgr()
  60. : mValid(FALSE),
  61. mPlaying(),
  62. mActive(),
  63. mLoadingCount(0)
  64. {
  65. gInventory.addObserver(this);
  66. mListener.reset(new LLGestureListener());
  67. }
  68. // We own the data for gestures, so clean them up.
  69. LLGestureMgr::~LLGestureMgr()
  70. {
  71. item_map_t::iterator it;
  72. for (it = mActive.begin(); it != mActive.end(); ++it)
  73. {
  74. LLMultiGesture* gesture = (*it).second;
  75. delete gesture;
  76. gesture = NULL;
  77. }
  78. gInventory.removeObserver(this);
  79. }
  80. void LLGestureMgr::init()
  81. {
  82. // TODO
  83. }
  84. void LLGestureMgr::changed(U32 mask)
  85. {
  86. LLInventoryFetchItemsObserver::changed(mask);
  87. if (mask & LLInventoryObserver::GESTURE)
  88. {
  89. // If there was a gesture label changed, update all the names in the
  90. // active gestures and then notify observers
  91. if (mask & LLInventoryObserver::LABEL)
  92. {
  93. for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
  94. {
  95. if(it->second)
  96. {
  97. LLViewerInventoryItem* item = gInventory.getItem(it->first);
  98. if(item)
  99. {
  100. it->second->mName = item->getName();
  101. }
  102. }
  103. }
  104. notifyObservers();
  105. }
  106. // If there was a gesture added or removed notify observers
  107. // STRUCTURE denotes that the inventory item has been moved
  108. // In the case of deleting gesture, it is moved to the trash
  109. else if(mask & LLInventoryObserver::ADD ||
  110. mask & LLInventoryObserver::REMOVE ||
  111. mask & LLInventoryObserver::STRUCTURE)
  112. {
  113. notifyObservers();
  114. }
  115. }
  116. }
  117. // Use this version when you have the item_id but not the asset_id,
  118. // and you KNOW the inventory is loaded.
  119. void LLGestureMgr::activateGesture(const LLUUID& item_id)
  120. {
  121. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  122. if (!item) return;
  123. if (item->getType() != LLAssetType::AT_GESTURE)
  124. return;
  125. LLUUID asset_id = item->getAssetUUID();
  126. mLoadingCount = 1;
  127. mDeactivateSimilarNames.clear();
  128. const BOOL inform_server = TRUE;
  129. const BOOL deactivate_similar = FALSE;
  130. activateGestureWithAsset(item_id, asset_id, inform_server, deactivate_similar);
  131. }
  132. void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items)
  133. {
  134. // Load up the assets
  135. S32 count = 0;
  136. LLViewerInventoryItem::item_array_t::const_iterator it;
  137. for (it = items.begin(); it != items.end(); ++it)
  138. {
  139. LLViewerInventoryItem* item = *it;
  140. if (isGestureActive(item->getUUID()))
  141. {
  142. continue;
  143. }
  144. else
  145. { // Make gesture active and persistent through login sessions. -spatters 07-12-06
  146. activateGesture(item->getUUID());
  147. }
  148. count++;
  149. }
  150. mLoadingCount = count;
  151. mDeactivateSimilarNames.clear();
  152. for (it = items.begin(); it != items.end(); ++it)
  153. {
  154. LLViewerInventoryItem* item = *it;
  155. if (isGestureActive(item->getUUID()))
  156. {
  157. continue;
  158. }
  159. // Don't inform server, we'll do that in bulk
  160. const BOOL no_inform_server = FALSE;
  161. const BOOL deactivate_similar = TRUE;
  162. activateGestureWithAsset(item->getUUID(), item->getAssetUUID(),
  163. no_inform_server,
  164. deactivate_similar);
  165. }
  166. // Inform the database of this change
  167. LLMessageSystem* msg = gMessageSystem;
  168. BOOL start_message = TRUE;
  169. for (it = items.begin(); it != items.end(); ++it)
  170. {
  171. LLViewerInventoryItem* item = *it;
  172. if (isGestureActive(item->getUUID()))
  173. {
  174. continue;
  175. }
  176. if (start_message)
  177. {
  178. msg->newMessage("ActivateGestures");
  179. msg->nextBlock("AgentData");
  180. msg->addUUID("AgentID", gAgent.getID());
  181. msg->addUUID("SessionID", gAgent.getSessionID());
  182. msg->addU32("Flags", 0x0);
  183. start_message = FALSE;
  184. }
  185. msg->nextBlock("Data");
  186. msg->addUUID("ItemID", item->getUUID());
  187. msg->addUUID("AssetID", item->getAssetUUID());
  188. msg->addU32("GestureFlags", 0x0);
  189. if (msg->getCurrentSendTotal() > MTUBYTES)
  190. {
  191. gAgent.sendReliableMessage();
  192. start_message = TRUE;
  193. }
  194. }
  195. if (!start_message)
  196. {
  197. gAgent.sendReliableMessage();
  198. }
  199. }
  200. struct LLLoadInfo
  201. {
  202. LLUUID mItemID;
  203. BOOL mInformServer;
  204. BOOL mDeactivateSimilar;
  205. };
  206. // If inform_server is true, will send a message upstream to update
  207. // the user_gesture_active table.
  208. /**
  209. * It will load a gesture from remote storage
  210. */
  211. void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,
  212. const LLUUID& asset_id,
  213. BOOL inform_server,
  214. BOOL deactivate_similar)
  215. {
  216. const LLUUID& base_item_id = get_linked_uuid(item_id);
  217. if( !gAssetStorage )
  218. {
  219. llwarns << "LLGestureMgr::activateGestureWithAsset without valid gAssetStorage" << llendl;
  220. return;
  221. }
  222. // If gesture is already active, nothing to do.
  223. if (isGestureActive(item_id))
  224. {
  225. llwarns << "Tried to loadGesture twice " << item_id << llendl;
  226. return;
  227. }
  228. // if (asset_id.isNull())
  229. // {
  230. // llwarns << "loadGesture() - gesture has no asset" << llendl;
  231. // return;
  232. // }
  233. // For now, put NULL into the item map. We'll build a gesture
  234. // class object when the asset data arrives.
  235. mActive[base_item_id] = NULL;
  236. // Copy the UUID
  237. if (asset_id.notNull())
  238. {
  239. LLLoadInfo* info = new LLLoadInfo;
  240. info->mItemID = base_item_id;
  241. info->mInformServer = inform_server;
  242. info->mDeactivateSimilar = deactivate_similar;
  243. const BOOL high_priority = TRUE;
  244. gAssetStorage->getAssetData(asset_id,
  245. LLAssetType::AT_GESTURE,
  246. onLoadComplete,
  247. (void*)info,
  248. high_priority);
  249. }
  250. else
  251. {
  252. notifyObservers();
  253. }
  254. }
  255. void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
  256. {
  257. const LLUUID& base_item_id = get_linked_uuid(item_id);
  258. item_map_t::iterator it = mActive.find(base_item_id);
  259. if (it == mActive.end())
  260. {
  261. llwarns << "deactivateGesture for inactive gesture " << item_id << llendl;
  262. return;
  263. }
  264. // mActive owns this gesture pointer, so clean up memory.
  265. LLMultiGesture* gesture = (*it).second;
  266. // Can be NULL gestures in the map
  267. if (gesture)
  268. {
  269. stopGesture(gesture);
  270. delete gesture;
  271. gesture = NULL;
  272. }
  273. mActive.erase(it);
  274. gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
  275. // Inform the database of this change
  276. LLMessageSystem* msg = gMessageSystem;
  277. msg->newMessage("DeactivateGestures");
  278. msg->nextBlock("AgentData");
  279. msg->addUUID("AgentID", gAgent.getID());
  280. msg->addUUID("SessionID", gAgent.getSessionID());
  281. msg->addU32("Flags", 0x0);
  282. msg->nextBlock("Data");
  283. msg->addUUID("ItemID", item_id);
  284. msg->addU32("GestureFlags", 0x0);
  285. gAgent.sendReliableMessage();
  286. LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, false);
  287. notifyObservers();
  288. }
  289. void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
  290. {
  291. const LLUUID& base_in_item_id = get_linked_uuid(in_item_id);
  292. uuid_vec_t gest_item_ids;
  293. // Deactivate all gestures that match
  294. item_map_t::iterator it;
  295. for (it = mActive.begin(); it != mActive.end(); )
  296. {
  297. const LLUUID& item_id = (*it).first;
  298. LLMultiGesture* gest = (*it).second;
  299. // Don't deactivate the gesture we are looking for duplicates of
  300. // (for replaceGesture)
  301. if (!gest || item_id == base_in_item_id)
  302. {
  303. // legal, can have null pointers in list
  304. ++it;
  305. }
  306. else if ((!gest->mTrigger.empty() && gest->mTrigger == in->mTrigger)
  307. || (gest->mKey != KEY_NONE && gest->mKey == in->mKey && gest->mMask == in->mMask))
  308. {
  309. gest_item_ids.push_back(item_id);
  310. stopGesture(gest);
  311. delete gest;
  312. gest = NULL;
  313. mActive.erase(it++);
  314. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
  315. }
  316. else
  317. {
  318. ++it;
  319. }
  320. }
  321. // Inform database of the change
  322. LLMessageSystem* msg = gMessageSystem;
  323. BOOL start_message = TRUE;
  324. uuid_vec_t::const_iterator vit = gest_item_ids.begin();
  325. while (vit != gest_item_ids.end())
  326. {
  327. if (start_message)
  328. {
  329. msg->newMessage("DeactivateGestures");
  330. msg->nextBlock("AgentData");
  331. msg->addUUID("AgentID", gAgent.getID());
  332. msg->addUUID("SessionID", gAgent.getSessionID());
  333. msg->addU32("Flags", 0x0);
  334. start_message = FALSE;
  335. }
  336. msg->nextBlock("Data");
  337. msg->addUUID("ItemID", *vit);
  338. msg->addU32("GestureFlags", 0x0);
  339. if (msg->getCurrentSendTotal() > MTUBYTES)
  340. {
  341. gAgent.sendReliableMessage();
  342. start_message = TRUE;
  343. }
  344. ++vit;
  345. }
  346. if (!start_message)
  347. {
  348. gAgent.sendReliableMessage();
  349. }
  350. // Add to the list of names for the user.
  351. for (vit = gest_item_ids.begin(); vit != gest_item_ids.end(); ++vit)
  352. {
  353. LLViewerInventoryItem* item = gInventory.getItem(*vit);
  354. if (!item) continue;
  355. mDeactivateSimilarNames.append(item->getName());
  356. mDeactivateSimilarNames.append("\n");
  357. }
  358. notifyObservers();
  359. }
  360. BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id)
  361. {
  362. const LLUUID& base_item_id = get_linked_uuid(item_id);
  363. item_map_t::iterator it = mActive.find(base_item_id);
  364. return (it != mActive.end());
  365. }
  366. BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id)
  367. {
  368. const LLUUID& base_item_id = get_linked_uuid(item_id);
  369. item_map_t::iterator it = mActive.find(base_item_id);
  370. if (it == mActive.end()) return FALSE;
  371. LLMultiGesture* gesture = (*it).second;
  372. if (!gesture) return FALSE;
  373. return gesture->mPlaying;
  374. }
  375. BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture)
  376. {
  377. if(!gesture)
  378. {
  379. return FALSE;
  380. }
  381. return gesture->mPlaying;
  382. }
  383. void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
  384. {
  385. const LLUUID& base_item_id = get_linked_uuid(item_id);
  386. item_map_t::iterator it = mActive.find(base_item_id);
  387. if (it == mActive.end())
  388. {
  389. llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl;
  390. return;
  391. }
  392. LLMultiGesture* old_gesture = (*it).second;
  393. stopGesture(old_gesture);
  394. mActive.erase(base_item_id);
  395. mActive[base_item_id] = new_gesture;
  396. delete old_gesture;
  397. old_gesture = NULL;
  398. if (asset_id.notNull())
  399. {
  400. mLoadingCount = 1;
  401. mDeactivateSimilarNames.clear();
  402. LLLoadInfo* info = new LLLoadInfo;
  403. info->mItemID = base_item_id;
  404. info->mInformServer = TRUE;
  405. info->mDeactivateSimilar = FALSE;
  406. const BOOL high_priority = TRUE;
  407. gAssetStorage->getAssetData(asset_id,
  408. LLAssetType::AT_GESTURE,
  409. onLoadComplete,
  410. (void*)info,
  411. high_priority);
  412. }
  413. notifyObservers();
  414. }
  415. void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
  416. {
  417. const LLUUID& base_item_id = get_linked_uuid(item_id);
  418. item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id);
  419. if (it == mActive.end())
  420. {
  421. llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl;
  422. return;
  423. }
  424. // mActive owns this gesture pointer, so clean up memory.
  425. LLMultiGesture* gesture = (*it).second;
  426. LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id);
  427. }
  428. void LLGestureMgr::playGesture(LLMultiGesture* gesture)
  429. {
  430. if (!gesture) return;
  431. // Reset gesture to first step
  432. gesture->mCurrentStep = 0;
  433. // Add to list of playing
  434. gesture->mPlaying = TRUE;
  435. mPlaying.push_back(gesture);
  436. // Load all needed assets to minimize the delays
  437. // when gesture is playing.
  438. for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin();
  439. steps_it != gesture->mSteps.end();
  440. ++steps_it)
  441. {
  442. LLGestureStep* step = *steps_it;
  443. switch(step->getType())
  444. {
  445. case STEP_ANIMATION:
  446. {
  447. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  448. const LLUUID& anim_id = anim_step->mAnimAssetID;
  449. // Don't request the animation if this step stops it or if it is already in Static VFS
  450. if (!(anim_id.isNull()
  451. || anim_step->mFlags & ANIM_FLAG_STOP
  452. || gAssetStorage->hasLocalAsset(anim_id, LLAssetType::AT_ANIMATION)))
  453. {
  454. mLoadingAssets.insert(anim_id);
  455. LLUUID* id = new LLUUID(gAgentID);
  456. gAssetStorage->getAssetData(anim_id,
  457. LLAssetType::AT_ANIMATION,
  458. onAssetLoadComplete,
  459. (void *)id,
  460. TRUE);
  461. }
  462. break;
  463. }
  464. case STEP_SOUND:
  465. {
  466. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  467. const LLUUID& sound_id = sound_step->mSoundAssetID;
  468. if (!(sound_id.isNull()
  469. || gAssetStorage->hasLocalAsset(sound_id, LLAssetType::AT_SOUND)))
  470. {
  471. mLoadingAssets.insert(sound_id);
  472. gAssetStorage->getAssetData(sound_id,
  473. LLAssetType::AT_SOUND,
  474. onAssetLoadComplete,
  475. NULL,
  476. TRUE);
  477. }
  478. break;
  479. }
  480. case STEP_CHAT:
  481. case STEP_WAIT:
  482. case STEP_EOF:
  483. {
  484. break;
  485. }
  486. default:
  487. {
  488. llwarns << "Unknown gesture step type: " << step->getType() << llendl;
  489. }
  490. }
  491. }
  492. // And get it going
  493. stepGesture(gesture);
  494. notifyObservers();
  495. }
  496. // Convenience function that looks up the item_id for you.
  497. void LLGestureMgr::playGesture(const LLUUID& item_id)
  498. {
  499. const LLUUID& base_item_id = get_linked_uuid(item_id);
  500. item_map_t::iterator it = mActive.find(base_item_id);
  501. if (it == mActive.end()) return;
  502. LLMultiGesture* gesture = (*it).second;
  503. if (!gesture) return;
  504. playGesture(gesture);
  505. }
  506. // Iterates through space delimited tokens in string, triggering any gestures found.
  507. // Generates a revised string that has the found tokens replaced by their replacement strings
  508. // and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
  509. BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
  510. {
  511. std::string tokenized = utf8str;
  512. BOOL found_gestures = FALSE;
  513. BOOL first_token = TRUE;
  514. typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  515. boost::char_separator<char> sep(" ");
  516. tokenizer tokens(tokenized, sep);
  517. tokenizer::iterator token_iter;
  518. for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
  519. {
  520. const char* cur_token = token_iter->c_str();
  521. LLMultiGesture* gesture = NULL;
  522. // Only pay attention to the first gesture in the string.
  523. if( !found_gestures )
  524. {
  525. // collect gestures that match
  526. std::vector <LLMultiGesture *> matching;
  527. item_map_t::iterator it;
  528. for (it = mActive.begin(); it != mActive.end(); ++it)
  529. {
  530. gesture = (*it).second;
  531. // Gesture asset data might not have arrived yet
  532. if (!gesture) continue;
  533. if (LLStringUtil::compareInsensitive(gesture->mTrigger, cur_token) == 0)
  534. {
  535. matching.push_back(gesture);
  536. }
  537. gesture = NULL;
  538. }
  539. if (matching.size() > 0)
  540. {
  541. // choose one at random
  542. {
  543. S32 random = ll_rand(matching.size());
  544. gesture = matching[random];
  545. playGesture(gesture);
  546. if (!gesture->mReplaceText.empty())
  547. {
  548. if( !first_token )
  549. {
  550. if (revised_string)
  551. revised_string->append( " " );
  552. }
  553. // Don't muck with the user's capitalization if we don't have to.
  554. if( LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0)
  555. {
  556. if (revised_string)
  557. revised_string->append( cur_token );
  558. }
  559. else
  560. {
  561. if (revised_string)
  562. revised_string->append( gesture->mReplaceText );
  563. }
  564. }
  565. found_gestures = TRUE;
  566. }
  567. }
  568. }
  569. if(!gesture)
  570. {
  571. // This token doesn't match a gesture. Pass it through to the output.
  572. if( !first_token )
  573. {
  574. if (revised_string)
  575. revised_string->append( " " );
  576. }
  577. if (revised_string)
  578. revised_string->append( cur_token );
  579. }
  580. first_token = FALSE;
  581. gesture = NULL;
  582. }
  583. return found_gestures;
  584. }
  585. BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask)
  586. {
  587. std::vector <LLMultiGesture *> matching;
  588. item_map_t::iterator it;
  589. // collect matching gestures
  590. for (it = mActive.begin(); it != mActive.end(); ++it)
  591. {
  592. LLMultiGesture* gesture = (*it).second;
  593. // asset data might not have arrived yet
  594. if (!gesture) continue;
  595. if (gesture->mKey == key
  596. && gesture->mMask == mask)
  597. {
  598. matching.push_back(gesture);
  599. }
  600. }
  601. // choose one and play it
  602. if (matching.size() > 0)
  603. {
  604. U32 random = ll_rand(matching.size());
  605. LLMultiGesture* gesture = matching[random];
  606. playGesture(gesture);
  607. return TRUE;
  608. }
  609. return FALSE;
  610. }
  611. S32 LLGestureMgr::getPlayingCount() const
  612. {
  613. return mPlaying.size();
  614. }
  615. struct IsGesturePlaying : public std::unary_function<LLMultiGesture*, bool>
  616. {
  617. bool operator()(const LLMultiGesture* gesture) const
  618. {
  619. return gesture->mPlaying ? true : false;
  620. }
  621. };
  622. void LLGestureMgr::update()
  623. {
  624. S32 i;
  625. for (i = 0; i < (S32)mPlaying.size(); ++i)
  626. {
  627. stepGesture(mPlaying[i]);
  628. }
  629. // Clear out gestures that are done, by moving all the
  630. // ones that are still playing to the front.
  631. std::vector<LLMultiGesture*>::iterator new_end;
  632. new_end = std::partition(mPlaying.begin(),
  633. mPlaying.end(),
  634. IsGesturePlaying());
  635. // Something finished playing
  636. if (new_end != mPlaying.end())
  637. {
  638. // Delete the completed gestures that want deletion
  639. std::vector<LLMultiGesture*>::iterator it;
  640. for (it = new_end; it != mPlaying.end(); ++it)
  641. {
  642. LLMultiGesture* gesture = *it;
  643. if (gesture->mDoneCallback)
  644. {
  645. gesture->mDoneCallback(gesture, gesture->mCallbackData);
  646. // callback might have deleted gesture, can't
  647. // rely on this pointer any more
  648. gesture = NULL;
  649. }
  650. }
  651. // And take done gestures out of the playing list
  652. mPlaying.erase(new_end, mPlaying.end());
  653. notifyObservers();
  654. }
  655. }
  656. // Run all steps until you're either done or hit a wait.
  657. void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
  658. {
  659. if (!gesture)
  660. {
  661. return;
  662. }
  663. if (!isAgentAvatarValid() || hasLoadingAssets(gesture)) return;
  664. // Of the ones that started playing, have any stopped?
  665. std::set<LLUUID>::iterator gest_it;
  666. for (gest_it = gesture->mPlayingAnimIDs.begin();
  667. gest_it != gesture->mPlayingAnimIDs.end();
  668. )
  669. {
  670. // look in signaled animations (simulator's view of what is
  671. // currently playing.
  672. LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it);
  673. if (play_it != gAgentAvatarp->mSignaledAnimations.end())
  674. {
  675. ++gest_it;
  676. }
  677. else
  678. {
  679. // not found, so not currently playing or scheduled to play
  680. // delete from the triggered set
  681. gesture->mPlayingAnimIDs.erase(gest_it++);
  682. }
  683. }
  684. // Of all the animations that we asked the sim to start for us,
  685. // pick up the ones that have actually started.
  686. for (gest_it = gesture->mRequestedAnimIDs.begin();
  687. gest_it != gesture->mRequestedAnimIDs.end();
  688. )
  689. {
  690. LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it);
  691. if (play_it != gAgentAvatarp->mSignaledAnimations.end())
  692. {
  693. // Hooray, this animation has started playing!
  694. // Copy into playing.
  695. gesture->mPlayingAnimIDs.insert(*gest_it);
  696. gesture->mRequestedAnimIDs.erase(gest_it++);
  697. }
  698. else
  699. {
  700. // nope, not playing yet
  701. ++gest_it;
  702. }
  703. }
  704. // Run the current steps
  705. BOOL waiting = FALSE;
  706. while (!waiting && gesture->mPlaying)
  707. {
  708. // Get the current step, if there is one.
  709. // Otherwise enter the waiting at end state.
  710. LLGestureStep* step = NULL;
  711. if (gesture->mCurrentStep < (S32)gesture->mSteps.size())
  712. {
  713. step = gesture->mSteps[gesture->mCurrentStep];
  714. llassert(step != NULL);
  715. }
  716. else
  717. {
  718. // step stays null, we're off the end
  719. gesture->mWaitingAtEnd = TRUE;
  720. }
  721. // If we're waiting at the end, wait for all gestures to stop
  722. // playing.
  723. // TODO: Wait for all sounds to complete as well.
  724. if (gesture->mWaitingAtEnd)
  725. {
  726. // Neither do we have any pending requests, nor are they
  727. // still playing.
  728. if ((gesture->mRequestedAnimIDs.empty()
  729. && gesture->mPlayingAnimIDs.empty()))
  730. {
  731. // all animations are done playing
  732. gesture->mWaitingAtEnd = FALSE;
  733. gesture->mPlaying = FALSE;
  734. }
  735. else
  736. {
  737. waiting = TRUE;
  738. }
  739. continue;
  740. }
  741. // If we're waiting on our animations to stop, poll for
  742. // completion.
  743. if (gesture->mWaitingAnimations)
  744. {
  745. // Neither do we have any pending requests, nor are they
  746. // still playing.
  747. if ((gesture->mRequestedAnimIDs.empty()
  748. && gesture->mPlayingAnimIDs.empty()))
  749. {
  750. // all animations are done playing
  751. gesture->mWaitingAnimations = FALSE;
  752. gesture->mCurrentStep++;
  753. }
  754. else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
  755. {
  756. // we've waited too long for an animation
  757. llinfos << "Waited too long for animations to stop, continuing gesture."
  758. << llendl;
  759. gesture->mWaitingAnimations = FALSE;
  760. gesture->mCurrentStep++;
  761. }
  762. else
  763. {
  764. waiting = TRUE;
  765. }
  766. continue;
  767. }
  768. // If we're waiting a fixed amount of time, check for timer
  769. // expiration.
  770. if (gesture->mWaitingTimer)
  771. {
  772. // We're waiting for a certain amount of time to pass
  773. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  774. F32 elapsed = gesture->mWaitTimer.getElapsedTimeF32();
  775. if (elapsed > wait_step->mWaitSeconds)
  776. {
  777. // wait is done, continue execution
  778. gesture->mWaitingTimer = FALSE;
  779. gesture->mCurrentStep++;
  780. }
  781. else
  782. {
  783. // we're waiting, so execution is done for now
  784. waiting = TRUE;
  785. }
  786. continue;
  787. }
  788. // Not waiting, do normal execution
  789. runStep(gesture, step);
  790. }
  791. }
  792. void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)
  793. {
  794. switch(step->getType())
  795. {
  796. case STEP_ANIMATION:
  797. {
  798. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  799. if (anim_step->mAnimAssetID.isNull())
  800. {
  801. gesture->mCurrentStep++;
  802. }
  803. if (anim_step->mFlags & ANIM_FLAG_STOP)
  804. {
  805. gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP);
  806. // remove it from our request set in case we just requested it
  807. std::set<LLUUID>::iterator set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID);
  808. if (set_it != gesture->mRequestedAnimIDs.end())
  809. {
  810. gesture->mRequestedAnimIDs.erase(set_it);
  811. }
  812. }
  813. else
  814. {
  815. gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_START);
  816. // Indicate that we've requested this animation to play as
  817. // part of this gesture (but it won't start playing for at
  818. // least one round-trip to simulator).
  819. gesture->mRequestedAnimIDs.insert(anim_step->mAnimAssetID);
  820. }
  821. gesture->mCurrentStep++;
  822. break;
  823. }
  824. case STEP_SOUND:
  825. {
  826. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  827. const LLUUID& sound_id = sound_step->mSoundAssetID;
  828. const F32 volume = 1.f;
  829. send_sound_trigger(sound_id, volume);
  830. gesture->mCurrentStep++;
  831. break;
  832. }
  833. case STEP_CHAT:
  834. {
  835. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  836. std::string chat_text = chat_step->mChatText;
  837. // Don't animate the nodding, as this might not blend with
  838. // other playing animations.
  839. const BOOL animate = FALSE;
  840. LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
  841. gesture->mCurrentStep++;
  842. break;
  843. }
  844. case STEP_WAIT:
  845. {
  846. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  847. if (wait_step->mFlags & WAIT_FLAG_TIME)
  848. {
  849. gesture->mWaitingTimer = TRUE;
  850. gesture->mWaitTimer.reset();
  851. }
  852. else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM)
  853. {
  854. gesture->mWaitingAnimations = TRUE;
  855. // Use the wait timer as a deadlock breaker for animation
  856. // waits.
  857. gesture->mWaitTimer.reset();
  858. }
  859. else
  860. {
  861. gesture->mCurrentStep++;
  862. }
  863. // Don't increment instruction pointer until wait is complete.
  864. break;
  865. }
  866. default:
  867. {
  868. break;
  869. }
  870. }
  871. }
  872. // static
  873. void LLGestureMgr::onLoadComplete(LLVFS *vfs,
  874. const LLUUID& asset_uuid,
  875. LLAssetType::EType type,
  876. void* user_data, S32 status, LLExtStat ext_status)
  877. {
  878. LLLoadInfo* info = (LLLoadInfo*)user_data;
  879. LLUUID item_id = info->mItemID;
  880. BOOL inform_server = info->mInformServer;
  881. BOOL deactivate_similar = info->mDeactivateSimilar;
  882. delete info;
  883. info = NULL;
  884. LLGestureMgr& self = LLGestureMgr::instance();
  885. self.mLoadingCount--;
  886. if (0 == status)
  887. {
  888. LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
  889. S32 size = file.getSize();
  890. std::vector<char> buffer(size+1);
  891. file.read((U8*)&buffer[0], size);
  892. // ensure there's a trailing NULL so strlen will work.
  893. buffer[size] = '\0';
  894. LLMultiGesture* gesture = new LLMultiGesture();
  895. LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
  896. BOOL ok = gesture->deserialize(dp);
  897. if (ok)
  898. {
  899. if (deactivate_similar)
  900. {
  901. self.deactivateSimilarGestures(gesture, item_id);
  902. // Display deactivation message if this was the last of the bunch.
  903. if (self.mLoadingCount == 0
  904. && self.mDeactivateSimilarNames.length() > 0)
  905. {
  906. // we're done with this set of deactivations
  907. LLSD args;
  908. args["NAMES"] = self.mDeactivateSimilarNames;
  909. LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
  910. }
  911. }
  912. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  913. if(item)
  914. {
  915. gesture->mName = item->getName();
  916. }
  917. else
  918. {
  919. // Watch this item and set gesture name when item exists in inventory
  920. self.setFetchID(item_id);
  921. self.startFetch();
  922. }
  923. self.mActive[item_id] = gesture;
  924. // Everything has been successful. Add to the active list.
  925. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
  926. if (inform_server)
  927. {
  928. // Inform the database of this change
  929. LLMessageSystem* msg = gMessageSystem;
  930. msg->newMessage("ActivateGestures");
  931. msg->nextBlock("AgentData");
  932. msg->addUUID("AgentID", gAgent.getID());
  933. msg->addUUID("SessionID", gAgent.getSessionID());
  934. msg->addU32("Flags", 0x0);
  935. msg->nextBlock("Data");
  936. msg->addUUID("ItemID", item_id);
  937. msg->addUUID("AssetID", asset_uuid);
  938. msg->addU32("GestureFlags", 0x0);
  939. gAgent.sendReliableMessage();
  940. }
  941. callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
  942. if(i_cb != self.mCallbackMap.end())
  943. {
  944. i_cb->second(gesture);
  945. self.mCallbackMap.erase(i_cb);
  946. }
  947. self.notifyObservers();
  948. }
  949. else
  950. {
  951. llwarns << "Unable to load gesture" << llendl;
  952. self.mActive.erase(item_id);
  953. delete gesture;
  954. gesture = NULL;
  955. }
  956. }
  957. else
  958. {
  959. LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
  960. if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
  961. LL_ERR_FILE_EMPTY == status)
  962. {
  963. LLDelayedGestureError::gestureMissing( item_id );
  964. }
  965. else
  966. {
  967. LLDelayedGestureError::gestureFailedToLoad( item_id );
  968. }
  969. llwarns << "Problem loading gesture: " << status << llendl;
  970. LLGestureMgr::instance().mActive.erase(item_id);
  971. }
  972. }
  973. // static
  974. void LLGestureMgr::onAssetLoadComplete(LLVFS *vfs,
  975. const LLUUID& asset_uuid,
  976. LLAssetType::EType type,
  977. void* user_data, S32 status, LLExtStat ext_status)
  978. {
  979. LLGestureMgr& self = LLGestureMgr::instance();
  980. // Complete the asset loading process depending on the type and
  981. // remove the asset id from pending downloads list.
  982. switch(type)
  983. {
  984. case LLAssetType::AT_ANIMATION:
  985. {
  986. LLKeyframeMotion::onLoadComplete(vfs, asset_uuid, type, user_data, status, ext_status);
  987. self.mLoadingAssets.erase(asset_uuid);
  988. break;
  989. }
  990. case LLAssetType::AT_SOUND:
  991. {
  992. LLAudioEngine::assetCallback(vfs, asset_uuid, type, user_data, status, ext_status);
  993. self.mLoadingAssets.erase(asset_uuid);
  994. break;
  995. }
  996. default:
  997. {
  998. llwarns << "Unexpected asset type: " << type << llendl;
  999. // We don't want to return from this callback without
  1000. // an animation or sound callback being fired
  1001. // and *user_data handled to avoid memory leaks.
  1002. llassert(type == LLAssetType::AT_ANIMATION || type == LLAssetType::AT_SOUND);
  1003. }
  1004. }
  1005. }
  1006. // static
  1007. bool LLGestureMgr::hasLoadingAssets(LLMultiGesture* gesture)
  1008. {
  1009. LLGestureMgr& self = LLGestureMgr::instance();
  1010. for (std::vector<LLGestureStep*>::iterator steps_it = gesture->mSteps.begin();
  1011. steps_it != gesture->mSteps.end();
  1012. ++steps_it)
  1013. {
  1014. LLGestureStep* step = *steps_it;
  1015. switch(step->getType())
  1016. {
  1017. case STEP_ANIMATION:
  1018. {
  1019. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  1020. const LLUUID& anim_id = anim_step->mAnimAssetID;
  1021. if (!(anim_id.isNull()
  1022. || anim_step->mFlags & ANIM_FLAG_STOP
  1023. || self.mLoadingAssets.find(anim_id) == self.mLoadingAssets.end()))
  1024. {
  1025. return true;
  1026. }
  1027. break;
  1028. }
  1029. case STEP_SOUND:
  1030. {
  1031. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  1032. const LLUUID& sound_id = sound_step->mSoundAssetID;
  1033. if (!(sound_id.isNull()
  1034. || self.mLoadingAssets.find(sound_id) == self.mLoadingAssets.end()))
  1035. {
  1036. return true;
  1037. }
  1038. break;
  1039. }
  1040. case STEP_CHAT:
  1041. case STEP_WAIT:
  1042. case STEP_EOF:
  1043. {
  1044. break;
  1045. }
  1046. default:
  1047. {
  1048. llwarns << "Unknown gesture step type: " << step->getType() << llendl;
  1049. }
  1050. }
  1051. }
  1052. return false;
  1053. }
  1054. void LLGestureMgr::stopGesture(LLMultiGesture* gesture)
  1055. {
  1056. if (!gesture) return;
  1057. // Stop any animations that this gesture is currently playing
  1058. std::set<LLUUID>::const_iterator set_it;
  1059. for (set_it = gesture->mRequestedAnimIDs.begin(); set_it != gesture->mRequestedAnimIDs.end(); ++set_it)
  1060. {
  1061. const LLUUID& anim_id = *set_it;
  1062. gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
  1063. }
  1064. for (set_it = gesture->mPlayingAnimIDs.begin(); set_it != gesture->mPlayingAnimIDs.end(); ++set_it)
  1065. {
  1066. const LLUUID& anim_id = *set_it;
  1067. gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
  1068. }
  1069. std::vector<LLMultiGesture*>::iterator it;
  1070. it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
  1071. while (it != mPlaying.end())
  1072. {
  1073. mPlaying.erase(it);
  1074. it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
  1075. }
  1076. gesture->reset();
  1077. if (gesture->mDoneCallback)
  1078. {
  1079. gesture->mDoneCallback(gesture, gesture->mCallbackData);
  1080. // callback might have deleted gesture, can't
  1081. // rely on this pointer any more
  1082. gesture = NULL;
  1083. }
  1084. notifyObservers();
  1085. }
  1086. void LLGestureMgr::stopGesture(const LLUUID& item_id)
  1087. {
  1088. const LLUUID& base_item_id = get_linked_uuid(item_id);
  1089. item_map_t::iterator it = mActive.find(base_item_id);
  1090. if (it == mActive.end()) return;
  1091. LLMultiGesture* gesture = (*it).second;
  1092. if (!gesture) return;
  1093. stopGesture(gesture);
  1094. }
  1095. void LLGestureMgr::addObserver(LLGestureManagerObserver* observer)
  1096. {
  1097. mObservers.push_back(observer);
  1098. }
  1099. void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer)
  1100. {
  1101. std::vector<LLGestureManagerObserver*>::iterator it;
  1102. it = std::find(mObservers.begin(), mObservers.end(), observer);
  1103. if (it != mObservers.end())
  1104. {
  1105. mObservers.erase(it);
  1106. }
  1107. }
  1108. // Call this method when it's time to update everyone on a new state.
  1109. // Copy the list because an observer could respond by removing itself
  1110. // from the list.
  1111. void LLGestureMgr::notifyObservers()
  1112. {
  1113. lldebugs << "LLGestureMgr::notifyObservers" << llendl;
  1114. for(std::vector<LLGestureManagerObserver*>::iterator iter = mObservers.begin();
  1115. iter != mObservers.end();
  1116. ++iter)
  1117. {
  1118. LLGestureManagerObserver* observer = (*iter);
  1119. observer->changed();
  1120. }
  1121. }
  1122. BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str)
  1123. {
  1124. S32 in_len = in_str.length();
  1125. item_map_t::iterator it;
  1126. for (it = mActive.begin(); it != mActive.end(); ++it)
  1127. {
  1128. LLMultiGesture* gesture = (*it).second;
  1129. if (gesture)
  1130. {
  1131. const std::string& trigger = gesture->getTrigger();
  1132. if (in_len > (S32)trigger.length())
  1133. {
  1134. // too short, bail out
  1135. continue;
  1136. }
  1137. std::string trigger_trunc = trigger;
  1138. LLStringUtil::truncate(trigger_trunc, in_len);
  1139. if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
  1140. {
  1141. *out_str = trigger;
  1142. return TRUE;
  1143. }
  1144. }
  1145. }
  1146. return FALSE;
  1147. }
  1148. void LLGestureMgr::getItemIDs(uuid_vec_t* ids)
  1149. {
  1150. item_map_t::const_iterator it;
  1151. for (it = mActive.begin(); it != mActive.end(); ++it)
  1152. {
  1153. ids->push_back(it->first);
  1154. }
  1155. }
  1156. void LLGestureMgr::done()
  1157. {
  1158. bool notify = false;
  1159. for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
  1160. {
  1161. if(it->second && it->second->mName.empty())
  1162. {
  1163. LLViewerInventoryItem* item = gInventory.getItem(it->first);
  1164. if(item)
  1165. {
  1166. it->second->mName = item->getName();
  1167. notify = true;
  1168. }
  1169. }
  1170. }
  1171. if(notify)
  1172. {
  1173. notifyObservers();
  1174. }
  1175. }
  1176. // static
  1177. const LLUUID& get_linked_uuid(const LLUUID &item_id)
  1178. {
  1179. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  1180. if (item && item->getIsLinkType())
  1181. {
  1182. return item->getLinkedUUID();
  1183. }
  1184. return item_id;
  1185. }