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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llgesturemgr.cpp
  3.  * @brief Manager for playing gestures on the viewer
  4.  *
  5.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2004-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 "llgesturemgr.h"
  34. // system
  35. #include <functional>
  36. #include <algorithm>
  37. // library
  38. #include "lldatapacker.h"
  39. #include "llinventory.h"
  40. #include "llmultigesture.h"
  41. #include "llnotificationsutil.h"
  42. #include "llstl.h"
  43. #include "llstring.h" // todo: remove
  44. #include "llvfile.h"
  45. #include "message.h"
  46. // newview
  47. #include "llagent.h"
  48. #include "lldelayedgestureerror.h"
  49. #include "llinventorymodel.h"
  50. #include "llviewermessage.h"
  51. #include "llvoavatarself.h"
  52. #include "llviewerstats.h"
  53. #include "llnearbychatbar.h"
  54. #include "llappearancemgr.h"
  55. // Longest time, in seconds, to wait for all animations to stop playing
  56. const F32 MAX_WAIT_ANIM_SECS = 30.f;
  57. // If this gesture is a link, get the base gesture that this link points to,
  58. // otherwise just return this id.
  59. static const LLUUID& get_linked_uuid(const LLUUID& item_id);
  60. // Lightweight constructor.
  61. // init() does the heavy lifting.
  62. LLGestureManager::LLGestureManager()
  63. : mValid(FALSE),
  64. mPlaying(),
  65. mActive(),
  66. mLoadingCount(0)
  67. {
  68. mRetryIfMissing = true;
  69. gInventory.addObserver(this);
  70. }
  71. // We own the data for gestures, so clean them up.
  72. LLGestureManager::~LLGestureManager()
  73. {
  74. item_map_t::iterator it;
  75. for (it = mActive.begin(); it != mActive.end(); ++it)
  76. {
  77. LLMultiGesture* gesture = (*it).second;
  78. delete gesture;
  79. gesture = NULL;
  80. }
  81. gInventory.removeObserver(this);
  82. }
  83. void LLGestureManager::init()
  84. {
  85. // TODO
  86. }
  87. void LLGestureManager::changed(U32 mask) 
  88. LLInventoryFetchObserver::changed(mask);
  89. if (mask & LLInventoryObserver::GESTURE)
  90. {
  91. // If there was a gesture label changed, update all the names in the 
  92. // active gestures and then notify observers
  93. if (mask & LLInventoryObserver::LABEL)
  94. {
  95. for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
  96. {
  97. if(it->second)
  98. {
  99. LLViewerInventoryItem* item = gInventory.getItem(it->first);
  100. if(item)
  101. {
  102. it->second->mName = item->getName();
  103. }
  104. }
  105. }
  106. notifyObservers();
  107. }
  108. // If there was a gesture added or removed notify observers
  109. // STRUCTURE denotes that the inventory item has been moved
  110. // In the case of deleting gesture, it is moved to the trash
  111. else if(mask & LLInventoryObserver::ADD ||
  112. mask & LLInventoryObserver::REMOVE ||
  113. mask & LLInventoryObserver::STRUCTURE)
  114. {
  115. notifyObservers();
  116. }
  117. }
  118. }
  119. // Use this version when you have the item_id but not the asset_id,
  120. // and you KNOW the inventory is loaded.
  121. void LLGestureManager::activateGesture(const LLUUID& item_id)
  122. {
  123. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  124. if (!item) 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 LLGestureManager::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 LLGestureManager::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 << "LLGestureManager::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 LLGestureManager::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. LLAppearanceManager::instance().removeCOFItemLinks(base_item_id, false);
  287. notifyObservers();
  288. }
  289. void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
  290. {
  291. const LLUUID& base_in_item_id = get_linked_uuid(in_item_id);
  292. std::vector<LLUUID> 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. std::vector<LLUUID>::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 LLGestureManager::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 LLGestureManager::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 LLGestureManager::isGesturePlaying(LLMultiGesture* gesture)
  376. {
  377. if(!gesture)
  378. {
  379. return FALSE;
  380. }
  381. return gesture->mPlaying;
  382. }
  383. void LLGestureManager::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 LLGestureManager::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 = LLGestureManager::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. LLGestureManager::instance().replaceGesture(base_item_id, gesture, new_asset_id);
  427. }
  428. void LLGestureManager::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. // And get it going
  437. stepGesture(gesture);
  438. notifyObservers();
  439. }
  440. // Convenience function that looks up the item_id for you.
  441. void LLGestureManager::playGesture(const LLUUID& item_id)
  442. {
  443. const LLUUID& base_item_id = get_linked_uuid(item_id);
  444. item_map_t::iterator it = mActive.find(base_item_id);
  445. if (it == mActive.end()) return;
  446. LLMultiGesture* gesture = (*it).second;
  447. if (!gesture) return;
  448. playGesture(gesture);
  449. }
  450. // Iterates through space delimited tokens in string, triggering any gestures found.
  451. // Generates a revised string that has the found tokens replaced by their replacement strings
  452. // and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
  453. BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
  454. {
  455. std::string tokenized = utf8str;
  456. BOOL found_gestures = FALSE;
  457. BOOL first_token = TRUE;
  458. typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  459. boost::char_separator<char> sep(" ");
  460. tokenizer tokens(tokenized, sep);
  461. tokenizer::iterator token_iter;
  462. for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
  463. {
  464. const char* cur_token = token_iter->c_str();
  465. LLMultiGesture* gesture = NULL;
  466. // Only pay attention to the first gesture in the string.
  467. if( !found_gestures )
  468. {
  469. // collect gestures that match
  470. std::vector <LLMultiGesture *> matching;
  471. item_map_t::iterator it;
  472. for (it = mActive.begin(); it != mActive.end(); ++it)
  473. {
  474. gesture = (*it).second;
  475. // Gesture asset data might not have arrived yet
  476. if (!gesture) continue;
  477. if (LLStringUtil::compareInsensitive(gesture->mTrigger, cur_token) == 0)
  478. {
  479. matching.push_back(gesture);
  480. }
  481. gesture = NULL;
  482. }
  483. if (matching.size() > 0)
  484. {
  485. // choose one at random
  486. {
  487. S32 random = ll_rand(matching.size());
  488. gesture = matching[random];
  489. playGesture(gesture);
  490. if (!gesture->mReplaceText.empty())
  491. {
  492. if( !first_token )
  493. {
  494. if (revised_string)
  495. revised_string->append( " " );
  496. }
  497. // Don't muck with the user's capitalization if we don't have to.
  498. if( LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0)
  499. {
  500. if (revised_string)
  501. revised_string->append( cur_token );
  502. }
  503. else
  504. {
  505. if (revised_string)
  506. revised_string->append( gesture->mReplaceText );
  507. }
  508. }
  509. found_gestures = TRUE;
  510. }
  511. }
  512. }
  513. if(!gesture)
  514. {
  515. // This token doesn't match a gesture.  Pass it through to the output.
  516. if( !first_token )
  517. {
  518. if (revised_string)
  519. revised_string->append( " " );
  520. }
  521. if (revised_string)
  522. revised_string->append( cur_token );
  523. }
  524. first_token = FALSE;
  525. gesture = NULL;
  526. }
  527. return found_gestures;
  528. }
  529. BOOL LLGestureManager::triggerGesture(KEY key, MASK mask)
  530. {
  531. std::vector <LLMultiGesture *> matching;
  532. item_map_t::iterator it;
  533. // collect matching gestures
  534. for (it = mActive.begin(); it != mActive.end(); ++it)
  535. {
  536. LLMultiGesture* gesture = (*it).second;
  537. // asset data might not have arrived yet
  538. if (!gesture) continue;
  539. if (gesture->mKey == key
  540. && gesture->mMask == mask)
  541. {
  542. matching.push_back(gesture);
  543. }
  544. }
  545. // choose one and play it
  546. if (matching.size() > 0)
  547. {
  548. U32 random = ll_rand(matching.size());
  549. LLMultiGesture* gesture = matching[random];
  550. playGesture(gesture);
  551. return TRUE;
  552. }
  553. return FALSE;
  554. }
  555. S32 LLGestureManager::getPlayingCount() const
  556. {
  557. return mPlaying.size();
  558. }
  559. struct IsGesturePlaying : public std::unary_function<LLMultiGesture*, bool>
  560. {
  561. bool operator()(const LLMultiGesture* gesture) const
  562. {
  563. return gesture->mPlaying ? true : false;
  564. }
  565. };
  566. void LLGestureManager::update()
  567. {
  568. S32 i;
  569. for (i = 0; i < (S32)mPlaying.size(); ++i)
  570. {
  571. stepGesture(mPlaying[i]);
  572. }
  573. // Clear out gestures that are done, by moving all the
  574. // ones that are still playing to the front.
  575. std::vector<LLMultiGesture*>::iterator new_end;
  576. new_end = std::partition(mPlaying.begin(),
  577.  mPlaying.end(),
  578.  IsGesturePlaying());
  579. // Something finished playing
  580. if (new_end != mPlaying.end())
  581. {
  582. // Delete the completed gestures that want deletion
  583. std::vector<LLMultiGesture*>::iterator it;
  584. for (it = new_end; it != mPlaying.end(); ++it)
  585. {
  586. LLMultiGesture* gesture = *it;
  587. if (gesture->mDoneCallback)
  588. {
  589. gesture->mDoneCallback(gesture, gesture->mCallbackData);
  590. // callback might have deleted gesture, can't
  591. // rely on this pointer any more
  592. gesture = NULL;
  593. }
  594. }
  595. // And take done gestures out of the playing list
  596. mPlaying.erase(new_end, mPlaying.end());
  597. notifyObservers();
  598. }
  599. }
  600. // Run all steps until you're either done or hit a wait.
  601. void LLGestureManager::stepGesture(LLMultiGesture* gesture)
  602. {
  603. if (!gesture)
  604. {
  605. return;
  606. }
  607. LLVOAvatar* avatar = gAgent.getAvatarObject();
  608. if (!avatar) return;
  609. // Of the ones that started playing, have any stopped?
  610. std::set<LLUUID>::iterator gest_it;
  611. for (gest_it = gesture->mPlayingAnimIDs.begin(); 
  612.  gest_it != gesture->mPlayingAnimIDs.end(); 
  613.  )
  614. {
  615. // look in signaled animations (simulator's view of what is
  616. // currently playing.
  617. LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
  618. if (play_it != avatar->mSignaledAnimations.end())
  619. {
  620. ++gest_it;
  621. }
  622. else
  623. {
  624. // not found, so not currently playing or scheduled to play
  625. // delete from the triggered set
  626. gesture->mPlayingAnimIDs.erase(gest_it++);
  627. }
  628. }
  629. // Of all the animations that we asked the sim to start for us,
  630. // pick up the ones that have actually started.
  631. for (gest_it = gesture->mRequestedAnimIDs.begin();
  632.  gest_it != gesture->mRequestedAnimIDs.end();
  633.  )
  634. {
  635.  LLVOAvatar::AnimIterator play_it = avatar->mSignaledAnimations.find(*gest_it);
  636. if (play_it != avatar->mSignaledAnimations.end())
  637. {
  638. // Hooray, this animation has started playing!
  639. // Copy into playing.
  640. gesture->mPlayingAnimIDs.insert(*gest_it);
  641. gesture->mRequestedAnimIDs.erase(gest_it++);
  642. }
  643. else
  644. {
  645. // nope, not playing yet
  646. ++gest_it;
  647. }
  648. }
  649. // Run the current steps
  650. BOOL waiting = FALSE;
  651. while (!waiting && gesture->mPlaying)
  652. {
  653. // Get the current step, if there is one.
  654. // Otherwise enter the waiting at end state.
  655. LLGestureStep* step = NULL;
  656. if (gesture->mCurrentStep < (S32)gesture->mSteps.size())
  657. {
  658. step = gesture->mSteps[gesture->mCurrentStep];
  659. llassert(step != NULL);
  660. }
  661. else
  662. {
  663. // step stays null, we're off the end
  664. gesture->mWaitingAtEnd = TRUE;
  665. }
  666. // If we're waiting at the end, wait for all gestures to stop
  667. // playing.
  668. // TODO: Wait for all sounds to complete as well.
  669. if (gesture->mWaitingAtEnd)
  670. {
  671. // Neither do we have any pending requests, nor are they
  672. // still playing.
  673. if ((gesture->mRequestedAnimIDs.empty()
  674. && gesture->mPlayingAnimIDs.empty()))
  675. {
  676. // all animations are done playing
  677. gesture->mWaitingAtEnd = FALSE;
  678. gesture->mPlaying = FALSE;
  679. }
  680. else
  681. {
  682. waiting = TRUE;
  683. }
  684. continue;
  685. }
  686. // If we're waiting on our animations to stop, poll for
  687. // completion.
  688. if (gesture->mWaitingAnimations)
  689. {
  690. // Neither do we have any pending requests, nor are they
  691. // still playing.
  692. if ((gesture->mRequestedAnimIDs.empty()
  693. && gesture->mPlayingAnimIDs.empty()))
  694. {
  695. // all animations are done playing
  696. gesture->mWaitingAnimations = FALSE;
  697. gesture->mCurrentStep++;
  698. }
  699. else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
  700. {
  701. // we've waited too long for an animation
  702. llinfos << "Waited too long for animations to stop, continuing gesture."
  703. << llendl;
  704. gesture->mWaitingAnimations = FALSE;
  705. gesture->mCurrentStep++;
  706. }
  707. else
  708. {
  709. waiting = TRUE;
  710. }
  711. continue;
  712. }
  713. // If we're waiting a fixed amount of time, check for timer
  714. // expiration.
  715. if (gesture->mWaitingTimer)
  716. {
  717. // We're waiting for a certain amount of time to pass
  718. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  719. F32 elapsed = gesture->mWaitTimer.getElapsedTimeF32();
  720. if (elapsed > wait_step->mWaitSeconds)
  721. {
  722. // wait is done, continue execution
  723. gesture->mWaitingTimer = FALSE;
  724. gesture->mCurrentStep++;
  725. }
  726. else
  727. {
  728. // we're waiting, so execution is done for now
  729. waiting = TRUE;
  730. }
  731. continue;
  732. }
  733. // Not waiting, do normal execution
  734. runStep(gesture, step);
  735. }
  736. }
  737. void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
  738. {
  739. switch(step->getType())
  740. {
  741. case STEP_ANIMATION:
  742. {
  743. LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step;
  744. if (anim_step->mAnimAssetID.isNull())
  745. {
  746. gesture->mCurrentStep++;
  747. }
  748. if (anim_step->mFlags & ANIM_FLAG_STOP)
  749. {
  750. gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_STOP);
  751. // remove it from our request set in case we just requested it
  752. std::set<LLUUID>::iterator set_it = gesture->mRequestedAnimIDs.find(anim_step->mAnimAssetID);
  753. if (set_it != gesture->mRequestedAnimIDs.end())
  754. {
  755. gesture->mRequestedAnimIDs.erase(set_it);
  756. }
  757. }
  758. else
  759. {
  760. gAgent.sendAnimationRequest(anim_step->mAnimAssetID, ANIM_REQUEST_START);
  761. // Indicate that we've requested this animation to play as
  762. // part of this gesture (but it won't start playing for at
  763. // least one round-trip to simulator).
  764. gesture->mRequestedAnimIDs.insert(anim_step->mAnimAssetID);
  765. }
  766. gesture->mCurrentStep++;
  767. break;
  768. }
  769. case STEP_SOUND:
  770. {
  771. LLGestureStepSound* sound_step = (LLGestureStepSound*)step;
  772. const LLUUID& sound_id = sound_step->mSoundAssetID;
  773. const F32 volume = 1.f;
  774. send_sound_trigger(sound_id, volume);
  775. gesture->mCurrentStep++;
  776. break;
  777. }
  778. case STEP_CHAT:
  779. {
  780. LLGestureStepChat* chat_step = (LLGestureStepChat*)step;
  781. std::string chat_text = chat_step->mChatText;
  782. // Don't animate the nodding, as this might not blend with
  783. // other playing animations.
  784. const BOOL animate = FALSE;
  785. LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
  786. gesture->mCurrentStep++;
  787. break;
  788. }
  789. case STEP_WAIT:
  790. {
  791. LLGestureStepWait* wait_step = (LLGestureStepWait*)step;
  792. if (wait_step->mFlags & WAIT_FLAG_TIME)
  793. {
  794. gesture->mWaitingTimer = TRUE;
  795. gesture->mWaitTimer.reset();
  796. }
  797. else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM)
  798. {
  799. gesture->mWaitingAnimations = TRUE;
  800. // Use the wait timer as a deadlock breaker for animation
  801. // waits.
  802. gesture->mWaitTimer.reset();
  803. }
  804. else
  805. {
  806. gesture->mCurrentStep++;
  807. }
  808. // Don't increment instruction pointer until wait is complete.
  809. break;
  810. }
  811. default:
  812. {
  813. break;
  814. }
  815. }
  816. }
  817. // static
  818. void LLGestureManager::onLoadComplete(LLVFS *vfs,
  819.    const LLUUID& asset_uuid,
  820.    LLAssetType::EType type,
  821.    void* user_data, S32 status, LLExtStat ext_status)
  822. {
  823. LLLoadInfo* info = (LLLoadInfo*)user_data;
  824. LLUUID item_id = info->mItemID;
  825. BOOL inform_server = info->mInformServer;
  826. BOOL deactivate_similar = info->mDeactivateSimilar;
  827. delete info;
  828. info = NULL;
  829. LLGestureManager& self = LLGestureManager::instance();
  830. self.mLoadingCount--;
  831. if (0 == status)
  832. {
  833. LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
  834. S32 size = file.getSize();
  835. std::vector<char> buffer(size+1);
  836. file.read((U8*)&buffer[0], size);
  837. // ensure there's a trailing NULL so strlen will work.
  838. buffer[size] = '';
  839. LLMultiGesture* gesture = new LLMultiGesture();
  840. LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
  841. BOOL ok = gesture->deserialize(dp);
  842. if (ok)
  843. {
  844. if (deactivate_similar)
  845. {
  846. self.deactivateSimilarGestures(gesture, item_id);
  847. // Display deactivation message if this was the last of the bunch.
  848. if (self.mLoadingCount == 0
  849. && self.mDeactivateSimilarNames.length() > 0)
  850. {
  851. // we're done with this set of deactivations
  852. LLSD args;
  853. args["NAMES"] = self.mDeactivateSimilarNames;
  854. LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
  855. }
  856. }
  857. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  858. if(item)
  859. {
  860. gesture->mName = item->getName();
  861. }
  862. else
  863. {
  864. // Watch this item and set gesture name when item exists in inventory
  865. item_ref_t ids;
  866. ids.push_back(item_id);
  867. self.fetchItems(ids);
  868. }
  869. self.mActive[item_id] = gesture;
  870. // Everything has been successful.  Add to the active list.
  871. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
  872. if (inform_server)
  873. {
  874. // Inform the database of this change
  875. LLMessageSystem* msg = gMessageSystem;
  876. msg->newMessage("ActivateGestures");
  877. msg->nextBlock("AgentData");
  878. msg->addUUID("AgentID", gAgent.getID());
  879. msg->addUUID("SessionID", gAgent.getSessionID());
  880. msg->addU32("Flags", 0x0);
  881. msg->nextBlock("Data");
  882. msg->addUUID("ItemID", item_id);
  883. msg->addUUID("AssetID", asset_uuid);
  884. msg->addU32("GestureFlags", 0x0);
  885. gAgent.sendReliableMessage();
  886. }
  887. callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
  888. if(i_cb != self.mCallbackMap.end())
  889. {
  890. i_cb->second(gesture);
  891. self.mCallbackMap.erase(i_cb);
  892. }
  893. self.notifyObservers();
  894. }
  895. else
  896. {
  897. llwarns << "Unable to load gesture" << llendl;
  898. self.mActive.erase(item_id);
  899. delete gesture;
  900. gesture = NULL;
  901. }
  902. }
  903. else
  904. {
  905. LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
  906. if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
  907. LL_ERR_FILE_EMPTY == status)
  908. {
  909. LLDelayedGestureError::gestureMissing( item_id );
  910. }
  911. else
  912. {
  913. LLDelayedGestureError::gestureFailedToLoad( item_id );
  914. }
  915. llwarns << "Problem loading gesture: " << status << llendl;
  916. LLGestureManager::instance().mActive.erase(item_id);
  917. }
  918. }
  919. void LLGestureManager::stopGesture(LLMultiGesture* gesture)
  920. {
  921. if (!gesture) return;
  922. // Stop any animations that this gesture is currently playing
  923. std::set<LLUUID>::const_iterator set_it;
  924. for (set_it = gesture->mRequestedAnimIDs.begin(); set_it != gesture->mRequestedAnimIDs.end(); ++set_it)
  925. {
  926. const LLUUID& anim_id = *set_it;
  927. gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
  928. }
  929. for (set_it = gesture->mPlayingAnimIDs.begin(); set_it != gesture->mPlayingAnimIDs.end(); ++set_it)
  930. {
  931. const LLUUID& anim_id = *set_it;
  932. gAgent.sendAnimationRequest(anim_id, ANIM_REQUEST_STOP);
  933. }
  934. std::vector<LLMultiGesture*>::iterator it;
  935. it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
  936. while (it != mPlaying.end())
  937. {
  938. mPlaying.erase(it);
  939. it = std::find(mPlaying.begin(), mPlaying.end(), gesture);
  940. }
  941. gesture->reset();
  942. if (gesture->mDoneCallback)
  943. {
  944. gesture->mDoneCallback(gesture, gesture->mCallbackData);
  945. // callback might have deleted gesture, can't
  946. // rely on this pointer any more
  947. gesture = NULL;
  948. }
  949. notifyObservers();
  950. }
  951. void LLGestureManager::stopGesture(const LLUUID& item_id)
  952. {
  953. const LLUUID& base_item_id = get_linked_uuid(item_id);
  954. item_map_t::iterator it = mActive.find(base_item_id);
  955. if (it == mActive.end()) return;
  956. LLMultiGesture* gesture = (*it).second;
  957. if (!gesture) return;
  958. stopGesture(gesture);
  959. }
  960. void LLGestureManager::addObserver(LLGestureManagerObserver* observer)
  961. {
  962. mObservers.push_back(observer);
  963. }
  964. void LLGestureManager::removeObserver(LLGestureManagerObserver* observer)
  965. {
  966. std::vector<LLGestureManagerObserver*>::iterator it;
  967. it = std::find(mObservers.begin(), mObservers.end(), observer);
  968. if (it != mObservers.end())
  969. {
  970. mObservers.erase(it);
  971. }
  972. }
  973. // Call this method when it's time to update everyone on a new state.
  974. // Copy the list because an observer could respond by removing itself
  975. // from the list.
  976. void LLGestureManager::notifyObservers()
  977. {
  978. lldebugs << "LLGestureManager::notifyObservers" << llendl;
  979. std::vector<LLGestureManagerObserver*> observers = mObservers;
  980. std::vector<LLGestureManagerObserver*>::iterator it;
  981. for (it = observers.begin(); it != observers.end(); ++it)
  982. {
  983. LLGestureManagerObserver* observer = *it;
  984. observer->changed();
  985. }
  986. }
  987. BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_str)
  988. {
  989. S32 in_len = in_str.length();
  990. item_map_t::iterator it;
  991. for (it = mActive.begin(); it != mActive.end(); ++it)
  992. {
  993. LLMultiGesture* gesture = (*it).second;
  994. if (gesture)
  995. {
  996. const std::string& trigger = gesture->getTrigger();
  997. if (in_len > (S32)trigger.length())
  998. {
  999. // too short, bail out
  1000. continue;
  1001. }
  1002. std::string trigger_trunc = trigger;
  1003. LLStringUtil::truncate(trigger_trunc, in_len);
  1004. if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
  1005. {
  1006. *out_str = trigger;
  1007. return TRUE;
  1008. }
  1009. }
  1010. }
  1011. return FALSE;
  1012. }
  1013. void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
  1014. {
  1015. item_map_t::const_iterator it;
  1016. for (it = mActive.begin(); it != mActive.end(); ++it)
  1017. {
  1018. ids->push_back(it->first);
  1019. }
  1020. }
  1021. void LLGestureManager::done()
  1022. {
  1023. bool notify = false;
  1024. for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
  1025. {
  1026. if(it->second && it->second->mName.empty())
  1027. {
  1028. LLViewerInventoryItem* item = gInventory.getItem(it->first);
  1029. if(item)
  1030. {
  1031. it->second->mName = item->getName();
  1032. notify = true;
  1033. }
  1034. }
  1035. }
  1036. if(notify)
  1037. {
  1038. notifyObservers();
  1039. }
  1040. }
  1041. // static
  1042. const LLUUID& get_linked_uuid(const LLUUID &item_id)
  1043. {
  1044. LLViewerInventoryItem* item = gInventory.getItem(item_id);
  1045. if (item && item->getIsLinkType())
  1046. {
  1047. return item->getLinkedUUID();
  1048. }
  1049. return item_id;
  1050. }