/indra/llcharacter/llmultigesture.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 509 lines · 351 code · 65 blank · 93 comment · 21 complexity · 050f139b7e45e671d36f68724e7e0ad4 MD5 · raw file

  1. /**
  2. * @file llmultigesture.cpp
  3. * @brief Gestures that are asset-based and can have multiple steps.
  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 "linden_common.h"
  27. #include <algorithm>
  28. #include "stdio.h"
  29. #include "llmultigesture.h"
  30. #include "llerror.h"
  31. #include "lldatapacker.h"
  32. #include "llstl.h"
  33. const S32 GESTURE_VERSION = 2;
  34. //---------------------------------------------------------------------------
  35. // LLMultiGesture
  36. //---------------------------------------------------------------------------
  37. LLMultiGesture::LLMultiGesture()
  38. : mKey(),
  39. mMask(),
  40. mName(),
  41. mTrigger(),
  42. mReplaceText(),
  43. mSteps(),
  44. mPlaying(FALSE),
  45. mCurrentStep(0),
  46. mDoneCallback(NULL),
  47. mCallbackData(NULL)
  48. {
  49. reset();
  50. }
  51. LLMultiGesture::~LLMultiGesture()
  52. {
  53. std::for_each(mSteps.begin(), mSteps.end(), DeletePointer());
  54. }
  55. void LLMultiGesture::reset()
  56. {
  57. mPlaying = FALSE;
  58. mCurrentStep = 0;
  59. mWaitTimer.reset();
  60. mWaitingTimer = FALSE;
  61. mWaitingAnimations = FALSE;
  62. mWaitingAtEnd = FALSE;
  63. mRequestedAnimIDs.clear();
  64. mPlayingAnimIDs.clear();
  65. }
  66. S32 LLMultiGesture::getMaxSerialSize() const
  67. {
  68. S32 max_size = 0;
  69. // ascii format, being very conservative about possible
  70. // label lengths.
  71. max_size += 64; // version S32
  72. max_size += 64; // key U8
  73. max_size += 64; // mask U32
  74. max_size += 256; // trigger string
  75. max_size += 256; // replace string
  76. max_size += 64; // step count S32
  77. std::vector<LLGestureStep*>::const_iterator it;
  78. for (it = mSteps.begin(); it != mSteps.end(); ++it)
  79. {
  80. LLGestureStep* step = *it;
  81. max_size += 64; // type S32
  82. max_size += step->getMaxSerialSize();
  83. }
  84. /* binary format
  85. max_size += sizeof(S32); // version
  86. max_size += sizeof(mKey);
  87. max_size += sizeof(mMask);
  88. max_size += mTrigger.length() + 1; // for null
  89. max_size += sizeof(S32); // step count
  90. std::vector<LLGestureStep*>::const_iterator it;
  91. for (it = mSteps.begin(); it != mSteps.end(); ++it)
  92. {
  93. LLGestureStep* step = *it;
  94. max_size += sizeof(S32); // type
  95. max_size += step->getMaxSerialSize();
  96. }
  97. */
  98. return max_size;
  99. }
  100. BOOL LLMultiGesture::serialize(LLDataPacker& dp) const
  101. {
  102. dp.packS32(GESTURE_VERSION, "version");
  103. dp.packU8(mKey, "key");
  104. dp.packU32(mMask, "mask");
  105. dp.packString(mTrigger, "trigger");
  106. dp.packString(mReplaceText, "replace");
  107. S32 count = (S32)mSteps.size();
  108. dp.packS32(count, "step_count");
  109. S32 i;
  110. for (i = 0; i < count; ++i)
  111. {
  112. LLGestureStep* step = mSteps[i];
  113. dp.packS32(step->getType(), "step_type");
  114. BOOL ok = step->serialize(dp);
  115. if (!ok)
  116. {
  117. return FALSE;
  118. }
  119. }
  120. return TRUE;
  121. }
  122. BOOL LLMultiGesture::deserialize(LLDataPacker& dp)
  123. {
  124. S32 version;
  125. dp.unpackS32(version, "version");
  126. if (version != GESTURE_VERSION)
  127. {
  128. llwarns << "Bad LLMultiGesture version " << version
  129. << " should be " << GESTURE_VERSION
  130. << llendl;
  131. return FALSE;
  132. }
  133. dp.unpackU8(mKey, "key");
  134. dp.unpackU32(mMask, "mask");
  135. dp.unpackString(mTrigger, "trigger");
  136. dp.unpackString(mReplaceText, "replace");
  137. S32 count;
  138. dp.unpackS32(count, "step_count");
  139. if (count < 0)
  140. {
  141. llwarns << "Bad LLMultiGesture step count " << count << llendl;
  142. return FALSE;
  143. }
  144. S32 i;
  145. for (i = 0; i < count; ++i)
  146. {
  147. S32 type;
  148. dp.unpackS32(type, "step_type");
  149. EStepType step_type = (EStepType)type;
  150. switch(step_type)
  151. {
  152. case STEP_ANIMATION:
  153. {
  154. LLGestureStepAnimation* step = new LLGestureStepAnimation();
  155. BOOL ok = step->deserialize(dp);
  156. if (!ok) return FALSE;
  157. mSteps.push_back(step);
  158. break;
  159. }
  160. case STEP_SOUND:
  161. {
  162. LLGestureStepSound* step = new LLGestureStepSound();
  163. BOOL ok = step->deserialize(dp);
  164. if (!ok) return FALSE;
  165. mSteps.push_back(step);
  166. break;
  167. }
  168. case STEP_CHAT:
  169. {
  170. LLGestureStepChat* step = new LLGestureStepChat();
  171. BOOL ok = step->deserialize(dp);
  172. if (!ok) return FALSE;
  173. mSteps.push_back(step);
  174. break;
  175. }
  176. case STEP_WAIT:
  177. {
  178. LLGestureStepWait* step = new LLGestureStepWait();
  179. BOOL ok = step->deserialize(dp);
  180. if (!ok) return FALSE;
  181. mSteps.push_back(step);
  182. break;
  183. }
  184. default:
  185. {
  186. llwarns << "Bad LLMultiGesture step type " << type << llendl;
  187. return FALSE;
  188. }
  189. }
  190. }
  191. return TRUE;
  192. }
  193. void LLMultiGesture::dump()
  194. {
  195. llinfos << "key " << S32(mKey) << " mask " << U32(mMask)
  196. << " trigger " << mTrigger
  197. << " replace " << mReplaceText
  198. << llendl;
  199. U32 i;
  200. for (i = 0; i < mSteps.size(); ++i)
  201. {
  202. LLGestureStep* step = mSteps[i];
  203. step->dump();
  204. }
  205. }
  206. //---------------------------------------------------------------------------
  207. // LLGestureStepAnimation
  208. //---------------------------------------------------------------------------
  209. LLGestureStepAnimation::LLGestureStepAnimation()
  210. : LLGestureStep(),
  211. mAnimName("None"),
  212. mAnimAssetID(),
  213. mFlags(0x0)
  214. { }
  215. LLGestureStepAnimation::~LLGestureStepAnimation()
  216. { }
  217. S32 LLGestureStepAnimation::getMaxSerialSize() const
  218. {
  219. S32 max_size = 0;
  220. // ascii
  221. max_size += 256; // anim name
  222. max_size += 64; // anim asset id
  223. max_size += 64; // flags
  224. /* binary
  225. max_size += mAnimName.length() + 1;
  226. max_size += sizeof(mAnimAssetID);
  227. max_size += sizeof(mFlags);
  228. */
  229. return max_size;
  230. }
  231. BOOL LLGestureStepAnimation::serialize(LLDataPacker& dp) const
  232. {
  233. dp.packString(mAnimName, "anim_name");
  234. dp.packUUID(mAnimAssetID, "asset_id");
  235. dp.packU32(mFlags, "flags");
  236. return TRUE;
  237. }
  238. BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp)
  239. {
  240. dp.unpackString(mAnimName, "anim_name");
  241. // Apparently an earlier version of the gesture code added \r to the end
  242. // of the animation names. Get rid of it. JC
  243. if (!mAnimName.empty() && mAnimName[mAnimName.length() - 1] == '\r')
  244. {
  245. // chop the last character
  246. mAnimName.resize(mAnimName.length() - 1);
  247. }
  248. dp.unpackUUID(mAnimAssetID, "asset_id");
  249. dp.unpackU32(mFlags, "flags");
  250. return TRUE;
  251. }
  252. // *NOTE: result is translated in LLPreviewGesture::getLabel()
  253. std::vector<std::string> LLGestureStepAnimation::getLabel() const
  254. {
  255. std::vector<std::string> strings;
  256. // std::string label;
  257. if (mFlags & ANIM_FLAG_STOP)
  258. {
  259. strings.push_back( "AnimFlagStop");
  260. // label = "Stop Animation: ";
  261. }
  262. else
  263. {
  264. strings.push_back( "AnimFlagStart");
  265. // label = "Start Animation: ";
  266. }
  267. strings.push_back( mAnimName);
  268. // label += mAnimName;
  269. return strings;
  270. }
  271. void LLGestureStepAnimation::dump()
  272. {
  273. llinfos << "step animation " << mAnimName
  274. << " id " << mAnimAssetID
  275. << " flags " << mFlags
  276. << llendl;
  277. }
  278. //---------------------------------------------------------------------------
  279. // LLGestureStepSound
  280. //---------------------------------------------------------------------------
  281. LLGestureStepSound::LLGestureStepSound()
  282. : LLGestureStep(),
  283. mSoundName("None"),
  284. mSoundAssetID(),
  285. mFlags(0x0)
  286. { }
  287. LLGestureStepSound::~LLGestureStepSound()
  288. { }
  289. S32 LLGestureStepSound::getMaxSerialSize() const
  290. {
  291. S32 max_size = 0;
  292. max_size += 256; // sound name
  293. max_size += 64; // sound asset id
  294. max_size += 64; // flags
  295. /* binary
  296. max_size += mSoundName.length() + 1;
  297. max_size += sizeof(mSoundAssetID);
  298. max_size += sizeof(mFlags);
  299. */
  300. return max_size;
  301. }
  302. BOOL LLGestureStepSound::serialize(LLDataPacker& dp) const
  303. {
  304. dp.packString(mSoundName, "sound_name");
  305. dp.packUUID(mSoundAssetID, "asset_id");
  306. dp.packU32(mFlags, "flags");
  307. return TRUE;
  308. }
  309. BOOL LLGestureStepSound::deserialize(LLDataPacker& dp)
  310. {
  311. dp.unpackString(mSoundName, "sound_name");
  312. dp.unpackUUID(mSoundAssetID, "asset_id");
  313. dp.unpackU32(mFlags, "flags");
  314. return TRUE;
  315. }
  316. // *NOTE: result is translated in LLPreviewGesture::getLabel()
  317. std::vector<std::string> LLGestureStepSound::getLabel() const
  318. {
  319. std::vector<std::string> strings;
  320. strings.push_back( "Sound");
  321. strings.push_back( mSoundName);
  322. // std::string label("Sound: ");
  323. // label += mSoundName;
  324. return strings;
  325. }
  326. void LLGestureStepSound::dump()
  327. {
  328. llinfos << "step sound " << mSoundName
  329. << " id " << mSoundAssetID
  330. << " flags " << mFlags
  331. << llendl;
  332. }
  333. //---------------------------------------------------------------------------
  334. // LLGestureStepChat
  335. //---------------------------------------------------------------------------
  336. LLGestureStepChat::LLGestureStepChat()
  337. : LLGestureStep(),
  338. mChatText(),
  339. mFlags(0x0)
  340. { }
  341. LLGestureStepChat::~LLGestureStepChat()
  342. { }
  343. S32 LLGestureStepChat::getMaxSerialSize() const
  344. {
  345. S32 max_size = 0;
  346. max_size += 256; // chat text
  347. max_size += 64; // flags
  348. /* binary
  349. max_size += mChatText.length() + 1;
  350. max_size += sizeof(mFlags);
  351. */
  352. return max_size;
  353. }
  354. BOOL LLGestureStepChat::serialize(LLDataPacker& dp) const
  355. {
  356. dp.packString(mChatText, "chat_text");
  357. dp.packU32(mFlags, "flags");
  358. return TRUE;
  359. }
  360. BOOL LLGestureStepChat::deserialize(LLDataPacker& dp)
  361. {
  362. dp.unpackString(mChatText, "chat_text");
  363. dp.unpackU32(mFlags, "flags");
  364. return TRUE;
  365. }
  366. // *NOTE: result is translated in LLPreviewGesture::getLabel()
  367. std::vector<std::string> LLGestureStepChat::getLabel() const
  368. {
  369. std::vector<std::string> strings;
  370. strings.push_back("Chat");
  371. strings.push_back(mChatText);
  372. return strings;
  373. }
  374. void LLGestureStepChat::dump()
  375. {
  376. llinfos << "step chat " << mChatText
  377. << " flags " << mFlags
  378. << llendl;
  379. }
  380. //---------------------------------------------------------------------------
  381. // LLGestureStepWait
  382. //---------------------------------------------------------------------------
  383. LLGestureStepWait::LLGestureStepWait()
  384. : LLGestureStep(),
  385. mWaitSeconds(0.f),
  386. mFlags(0x0)
  387. { }
  388. LLGestureStepWait::~LLGestureStepWait()
  389. { }
  390. S32 LLGestureStepWait::getMaxSerialSize() const
  391. {
  392. S32 max_size = 0;
  393. max_size += 64; // wait seconds
  394. max_size += 64; // flags
  395. /* binary
  396. max_size += sizeof(mWaitSeconds);
  397. max_size += sizeof(mFlags);
  398. */
  399. return max_size;
  400. }
  401. BOOL LLGestureStepWait::serialize(LLDataPacker& dp) const
  402. {
  403. dp.packF32(mWaitSeconds, "wait_seconds");
  404. dp.packU32(mFlags, "flags");
  405. return TRUE;
  406. }
  407. BOOL LLGestureStepWait::deserialize(LLDataPacker& dp)
  408. {
  409. dp.unpackF32(mWaitSeconds, "wait_seconds");
  410. dp.unpackU32(mFlags, "flags");
  411. return TRUE;
  412. }
  413. // *NOTE: result is translated in LLPreviewGesture::getLabel()
  414. std::vector<std::string> LLGestureStepWait::getLabel() const
  415. {
  416. std::vector<std::string> strings;
  417. strings.push_back( "Wait" );
  418. // std::string label("--- Wait: ");
  419. if (mFlags & WAIT_FLAG_TIME)
  420. {
  421. char buffer[64]; /* Flawfinder: ignore */
  422. snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */
  423. strings.push_back(buffer);
  424. // label += buffer;
  425. }
  426. else if (mFlags & WAIT_FLAG_ALL_ANIM)
  427. {
  428. strings.push_back("until animations are done");
  429. // label += "until animations are done";
  430. }
  431. else
  432. {
  433. strings.push_back("");
  434. }
  435. return strings;
  436. }
  437. void LLGestureStepWait::dump()
  438. {
  439. llinfos << "step wait " << mWaitSeconds
  440. << " flags " << mFlags
  441. << llendl;
  442. }