tsThread.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "ts/tsShapeInstance.h"
  24. //-------------------------------------------------------------------------------------
  25. // This file contains the shape instance thread class (defined in tsShapeInstance.h)
  26. // and the tsShapeInstance functions to interface with the thread class.
  27. //-------------------------------------------------------------------------------------
  28. //-------------------------------------------------------------------------------------
  29. // Thread class
  30. //-------------------------------------------------------------------------------------
  31. // given a position on the thread, choose correct keyframes
  32. // slight difference between one-shot and cyclic sequences -- see comments below for details
  33. void TSThread::selectKeyframes(F32 pos, const TSSequence * seq, S32 * k1, S32 * k2, F32 * kpos)
  34. {
  35. S32 numKF = seq->numKeyframes;
  36. F32 kf;
  37. if (seq->isCyclic())
  38. {
  39. // cyclic sequence:
  40. // pos=0 and pos=1 are equivalent, so we don't have a keyframe at pos=1
  41. // last keyframe corresponds to pos=n/(n-1) up to (not including) pos=1
  42. // (where n == num keyframes)
  43. AssertFatal(pos>=0.0f && pos<1.0f,"TSThread::selectKeyframes");
  44. kf = pos * (F32) (numKF);
  45. // set keyPos
  46. if (kpos)
  47. *kpos = kf - (S32) kf;
  48. // make sure compiler doing what we want...
  49. AssertFatal(*kpos>=0.0f && *kpos<1.0f,"TSThread::selectKeyframes");
  50. S32 kfIdx1 = (S32) kf;
  51. // following assert could happen if pos1<1 && pos1==1...paradoxically...
  52. AssertFatal(kfIdx1<=seq->numKeyframes,"TSThread::selectKeyframes");
  53. S32 kfIdx2 = (kfIdx1==seq->numKeyframes-1) ? 0 : kfIdx1+1;
  54. if (k1)
  55. *k1 = kfIdx1;
  56. if (k2)
  57. *k2 = kfIdx2;
  58. }
  59. else
  60. {
  61. // one-shot sequence:
  62. // pos=0 and pos=1 are now different, so we have a keyframe at pos=1
  63. // last keyframe corresponds to pos=1
  64. // rest of the keyframes are equally spaced (so 1/(n-1) pos units long)
  65. // (where n == num keyframes)
  66. AssertFatal(pos>=0.0f && pos<=1.0f,"TSThread::selectKeyframes");
  67. if (pos==1.0f)
  68. {
  69. if (kpos)
  70. *kpos = 0.0f;
  71. if (k1)
  72. *k1 = seq->numKeyframes-1;
  73. if (k2)
  74. *k2 = seq->numKeyframes-1;
  75. }
  76. else
  77. {
  78. kf = pos * (F32) (numKF-1);
  79. // set keyPos
  80. if (kpos)
  81. *kpos = kf - (S32) kf;
  82. S32 kfIdx1 = (S32) kf;
  83. // following assert could happen if pos1<1 && pos1==1...paradoxically...
  84. AssertFatal(kfIdx1<seq->numKeyframes,"TSThread::selectKeyFrames: invalid keyframe!");
  85. S32 kfIdx2 = kfIdx1+1;
  86. if (k1)
  87. *k1 = kfIdx1;
  88. if (k2)
  89. *k2 = kfIdx2;
  90. }
  91. }
  92. }
  93. void TSThread::getGround(F32 t, MatrixF * pMat)
  94. {
  95. static const QuatF unitRotation(0,0,0,1);
  96. static const Point3F unitTranslation = Point3F::Zero;
  97. const QuatF * q1, * q2;
  98. QuatF rot1,rot2;
  99. const Point3F * p1, * p2;
  100. // if N = sequence->numGroundFrames, then there are N+1 positions we
  101. // interpolate betweeen: 0/N, 1/N ... N/N
  102. // we need to convert the p passed to us into 2 ground keyframes:
  103. // the 0.99999f is in case 'p' is exactly 1.0f, which is legal but 'kf'
  104. // needs to be strictly less than 'sequence->numGroundFrames'
  105. F32 kf = 0.999999f * t * (F32) getSequence()->numGroundFrames;
  106. // get frame number and interp param (kpos)
  107. S32 frame = (S32)kf;
  108. F32 kpos = kf - (F32)frame;
  109. // now point pT1 and pT2 at transforms for keyframes 'frame' and 'frame+1'
  110. // following a little strange: first ground keyframe (0/N in comment above) is
  111. // assumed to be ident. and not found in the list.
  112. if (frame)
  113. {
  114. p1 = &mShapeInstance->mShape->groundTranslations[getSequence()->firstGroundFrame + frame - 1];
  115. q1 = &mShapeInstance->mShape->groundRotations[getSequence()->firstGroundFrame + frame - 1].getQuatF(&rot1);
  116. }
  117. else
  118. {
  119. p1 = &unitTranslation;
  120. q1 = &unitRotation;
  121. }
  122. // similar to above, ground keyframe number 'frame+1' is actually offset by 'frame'
  123. p2 = &mShapeInstance->mShape->groundTranslations[getSequence()->firstGroundFrame + frame];
  124. q2 = &mShapeInstance->mShape->groundRotations[getSequence()->firstGroundFrame + frame].getQuatF(&rot2);
  125. QuatF q;
  126. Point3F p;
  127. TSTransform::interpolate(*q1,*q2,kpos,&q);
  128. TSTransform::interpolate(*p1,*p2,kpos,&p);
  129. TSTransform::setMatrix(q,p,pMat);
  130. }
  131. void TSThread::setSequence(S32 seq, F32 toPos)
  132. {
  133. const TSShape * shape = mShapeInstance->mShape;
  134. AssertFatal(shape && shape->sequences.size()>seq && toPos>=0.0f && toPos<=1.0f,
  135. "TSThread::setSequence: invalid shape handle, sequence number, or position.");
  136. mShapeInstance->clearTransition(this);
  137. sequence = seq;
  138. priority = getSequence()->priority;
  139. pos = toPos;
  140. makePath = getSequence()->makePath();
  141. path.start = path.end = 0;
  142. path.loop = 0;
  143. // 1.0f doesn't exist on cyclic sequences
  144. if (pos>0.9999f && getSequence()->isCyclic())
  145. pos = 0.9999f;
  146. // select keyframes
  147. selectKeyframes(pos,getSequence(),&keyNum1,&keyNum2,&keyPos);
  148. }
  149. void TSThread::transitionToSequence(S32 seq, F32 toPos, F32 duration, bool continuePlay)
  150. {
  151. AssertFatal(duration>=0.0f,"TSThread::transitionToSequence: negative duration not allowed");
  152. // make sure these nodes are smoothly interpolated to new positions...
  153. // basically, any node we controlled just prior to transition, or at any stage
  154. // of the transition is interpolated. If we start to transtion from A to B,
  155. // but before reaching B we transtion to C, we interpolate all nodes controlled
  156. // by A, B, or C to their new position.
  157. if (transitionData.inTransition)
  158. {
  159. transitionData.oldRotationNodes.overlap(getSequence()->rotationMatters);
  160. transitionData.oldTranslationNodes.overlap(getSequence()->translationMatters);
  161. transitionData.oldScaleNodes.overlap(getSequence()->scaleMatters);
  162. }
  163. else
  164. {
  165. transitionData.oldRotationNodes = getSequence()->rotationMatters;
  166. transitionData.oldTranslationNodes = getSequence()->translationMatters;
  167. transitionData.oldScaleNodes = getSequence()->scaleMatters;
  168. }
  169. // set time characteristics of transition
  170. transitionData.oldSequence = sequence;
  171. transitionData.oldPos = pos;
  172. transitionData.duration = duration;
  173. transitionData.pos = 0.0f;
  174. transitionData.direction = timeScale>0.0f ? 1.0f : -1.0f;
  175. transitionData.targetScale = continuePlay ? 1.0f : 0.0f;
  176. // in transition...
  177. transitionData.inTransition = true;
  178. // set target sequence data
  179. sequence = seq;
  180. priority = getSequence()->priority;
  181. pos = toPos;
  182. makePath = getSequence()->makePath();
  183. path.start = path.end = 0;
  184. path.loop = 0;
  185. // 1.0f doesn't exist on cyclic sequences
  186. if (pos>0.9999f && getSequence()->isCyclic())
  187. pos = 0.9999f;
  188. // select keyframes
  189. selectKeyframes(pos,getSequence(),&keyNum1,&keyNum2,&keyPos);
  190. }
  191. bool TSThread::isInTransition()
  192. {
  193. return transitionData.inTransition;
  194. }
  195. void TSThread::animateTriggers()
  196. {
  197. if (!getSequence()->numTriggers)
  198. return;
  199. switch (path.loop)
  200. {
  201. case -1 :
  202. activateTriggers(path.start,0);
  203. activateTriggers(1,path.end);
  204. break;
  205. case 0 :
  206. activateTriggers(path.start,path.end);
  207. break;
  208. case 1 :
  209. activateTriggers(path.start,1);
  210. activateTriggers(0,path.end);
  211. break;
  212. default:
  213. {
  214. if (path.loop>0)
  215. {
  216. activateTriggers(path.end,1);
  217. activateTriggers(0,path.end);
  218. }
  219. else
  220. {
  221. activateTriggers(path.end,0);
  222. activateTriggers(1,path.end);
  223. }
  224. }
  225. }
  226. }
  227. void TSThread::activateTriggers(F32 a, F32 b)
  228. {
  229. S32 i;
  230. const TSShape * shape = mShapeInstance->mShape;
  231. S32 firstTrigger = getSequence()->firstTrigger;
  232. S32 numTriggers = getSequence()->numTriggers;
  233. // first find triggers at position a and b
  234. // we assume there aren't many triggers, so
  235. // search is linear
  236. F32 lastPos = -1.0f;
  237. S32 aIndex = numTriggers+firstTrigger; // initialized to handle case where pos past all triggers
  238. S32 bIndex = numTriggers+firstTrigger; // initialized to handle case where pos past all triggers
  239. for (i=firstTrigger; i<numTriggers+firstTrigger; i++)
  240. {
  241. // is a between this trigger and previous one...
  242. if (a>lastPos && a<=shape->triggers[i].pos)
  243. aIndex = i;
  244. // is b between this trigger and previous one...
  245. if (b>lastPos && b<=shape->triggers[i].pos)
  246. bIndex = i;
  247. lastPos = shape->triggers[i].pos;
  248. }
  249. // activate triggers between aIndex and bIndex (depends on direction)
  250. if (aIndex<=bIndex)
  251. {
  252. for (i=aIndex; i<bIndex; i++)
  253. {
  254. U32 state = shape->triggers[i].state;
  255. bool on = (state & TSShape::Trigger::StateOn)!=0;
  256. mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
  257. }
  258. }
  259. else
  260. {
  261. for (i=aIndex-1; i>=bIndex; i--)
  262. {
  263. U32 state = shape->triggers[i].state;
  264. bool on = (state & TSShape::Trigger::StateOn)!=0;
  265. if (state & TSShape::Trigger::InvertOnReverse)
  266. on = !on;
  267. mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
  268. }
  269. }
  270. }
  271. F32 TSThread::getPos()
  272. {
  273. return transitionData.inTransition ? transitionData.pos : pos;
  274. }
  275. F32 TSThread::getTime()
  276. {
  277. return transitionData.inTransition ? transitionData.pos * transitionData.duration : pos * getSequence()->duration;
  278. }
  279. F32 TSThread::getDuration()
  280. {
  281. return transitionData.inTransition ? transitionData.duration : getSequence()->duration;
  282. }
  283. F32 TSThread::getScaledDuration()
  284. {
  285. return getDuration() / mFabs(timeScale);
  286. }
  287. F32 TSThread::getTimeScale()
  288. {
  289. return timeScale;
  290. }
  291. void TSThread::setTimeScale(F32 ts)
  292. {
  293. timeScale = ts;
  294. }
  295. void TSThread::advancePos(F32 delta)
  296. {
  297. if (mFabs(delta)>0.00001f)
  298. {
  299. // make dirty what this thread changes
  300. U32 dirtyFlags = getSequence()->dirtyFlags | (transitionData.inTransition ? TSShapeInstance::TransformDirty : 0);
  301. for (S32 i=0; i<mShapeInstance->getShape()->subShapeFirstNode.size(); i++)
  302. mShapeInstance->mDirtyFlags[i] |= dirtyFlags;
  303. }
  304. if (transitionData.inTransition)
  305. {
  306. transitionData.pos += transitionData.direction * delta;
  307. if (transitionData.pos<0 || transitionData.pos>=1.0f)
  308. {
  309. mShapeInstance->clearTransition(this);
  310. if (transitionData.pos<0.0f)
  311. // return to old sequence
  312. mShapeInstance->setSequence(this,transitionData.oldSequence,transitionData.oldPos);
  313. }
  314. // re-adjust delta to be correct time-wise
  315. delta *= transitionData.targetScale * transitionData.duration / getSequence()->duration;
  316. }
  317. // even if we are in a transition, keep playing the sequence
  318. if (makePath)
  319. {
  320. path.start = pos;
  321. pos += delta;
  322. if (!getSequence()->isCyclic())
  323. {
  324. pos = mClampF(pos , 0.0f, 1.0f);
  325. path.loop = 0;
  326. }
  327. else
  328. {
  329. path.loop = (S32)pos;
  330. if (pos < 0.0f)
  331. path.loop--;
  332. pos -= path.loop;
  333. // following necessary because of floating point roundoff errors
  334. if (pos < 0.0f) pos += 1.0f;
  335. if (pos >= 1.0f) pos -= 1.0f;
  336. }
  337. path.end = pos;
  338. animateTriggers(); // do this automatically...no need for user to call it
  339. AssertFatal(pos>=0.0f && pos<=1.0f,"TSThread::advancePos (1)");
  340. AssertFatal(!getSequence()->isCyclic() || pos<1.0f,"TSThread::advancePos (2)");
  341. }
  342. else
  343. {
  344. pos += delta;
  345. if (!getSequence()->isCyclic())
  346. pos = mClampF(pos, 0.0f, 1.0f);
  347. else
  348. {
  349. pos -= S32(pos);
  350. // following necessary because of floating point roundoff errors
  351. if (pos < 0.0f) pos += 1.0f;
  352. if (pos >= 1.0f) pos -= 1.0f;
  353. }
  354. AssertFatal(pos>=0.0f && pos<=1.0f,"TSThread::advancePos (3)");
  355. AssertFatal(!getSequence()->isCyclic() || pos<1.0f,"TSThread::advancePos (4)");
  356. }
  357. // select keyframes
  358. selectKeyframes(pos,getSequence(),&keyNum1,&keyNum2,&keyPos);
  359. }
  360. void TSThread::advanceTime(F32 delta)
  361. {
  362. advancePos(timeScale * delta / getDuration());
  363. }
  364. void TSThread::setPos(F32 pos)
  365. {
  366. advancePos(pos-getPos());
  367. }
  368. void TSThread::setTime(F32 time)
  369. {
  370. setPos(timeScale * time/getDuration());
  371. }
  372. S32 TSThread::getKeyframeCount()
  373. {
  374. AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeCount: not while in transition");
  375. return getSequence()->numKeyframes + 1;
  376. }
  377. S32 TSThread::getKeyframeNumber()
  378. {
  379. AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeNumber: not while in transition");
  380. return keyNum1;
  381. }
  382. void TSThread::setKeyframeNumber(S32 kf)
  383. {
  384. AssertFatal(kf>=0 && kf<= getSequence()->numKeyframes,
  385. "TSThread::setKeyframeNumber: invalid frame specified.");
  386. AssertFatal(!transitionData.inTransition,"TSThread::setKeyframeNumber: not while in transition");
  387. keyNum1 = keyNum2 = kf;
  388. keyPos = 0;
  389. pos = 0;
  390. }
  391. TSThread::TSThread(TSShapeInstance * _shapeInst)
  392. {
  393. timeScale = 1.0f;
  394. mShapeInstance = _shapeInst;
  395. transitionData.inTransition = false;
  396. blendDisabled = false;
  397. setSequence(0,0.0f);
  398. }
  399. S32 TSThread::operator<(const TSThread & th2) const
  400. {
  401. if (getSequence()->isBlend() == th2.getSequence()->isBlend())
  402. {
  403. // both blend or neither blend, sort based on priority only -- higher priority first
  404. S32 ret = 0; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
  405. if (priority > th2.priority)
  406. ret = -1;
  407. if (th2.priority > priority)
  408. ret = 1;
  409. return ret;
  410. }
  411. else
  412. {
  413. // one is blend, the other is not...sort based on blend -- non-blended first
  414. AssertFatal(!getSequence()->isBlend() || !th2.getSequence()->isBlend(),"compareThreads: unequal 'trues'");
  415. S32 ret = -1; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
  416. if (getSequence()->isBlend())
  417. ret = 1;
  418. return ret;
  419. }
  420. }
  421. //-------------------------------------------------------------------------------------
  422. // TSShapeInstance Thread Interface -- more implemented in header file
  423. //-------------------------------------------------------------------------------------
  424. TSThread * TSShapeInstance::addThread()
  425. {
  426. if (mShape->sequences.empty())
  427. return NULL;
  428. mThreadList.increment();
  429. mThreadList.last() = new TSThread(this);
  430. setDirty(AllDirtyMask);
  431. return mThreadList.last();
  432. }
  433. TSThread * TSShapeInstance::getThread(S32 threadNumber)
  434. {
  435. AssertFatal(threadNumber < mThreadList.size() && threadNumber>=0,"TSShapeInstance::getThread: threadNumber out of bounds.");
  436. return mThreadList[threadNumber];
  437. }
  438. void TSShapeInstance::destroyThread(TSThread * thread)
  439. {
  440. if (!thread)
  441. return;
  442. clearTransition(thread);
  443. S32 i;
  444. for (i=0; i<mThreadList.size(); i++)
  445. if (thread==mThreadList[i])
  446. break;
  447. AssertFatal(i<mThreadList.size(),"TSShapeInstance::destroyThread was requested to destroy a thread that this instance doesn't own!");
  448. delete mThreadList[i];
  449. mThreadList.erase(i);
  450. setDirty(AllDirtyMask);
  451. checkScaleCurrentlyAnimated();
  452. }
  453. U32 TSShapeInstance::threadCount()
  454. {
  455. return mThreadList.size();
  456. }
  457. void TSShapeInstance::setSequence(TSThread * thread, S32 seq, F32 pos)
  458. {
  459. if ( (thread->transitionData.inTransition && mTransitionThreads.size()>1) || mTransitionThreads.size()>0)
  460. {
  461. // if we have transitions, make sure transforms are up to date...
  462. sortThreads();
  463. animateNodeSubtrees();
  464. }
  465. thread->setSequence(seq,pos);
  466. setDirty(AllDirtyMask);
  467. mGroundThread = NULL;
  468. if (mScaleCurrentlyAnimated && !thread->getSequence()->animatesScale())
  469. checkScaleCurrentlyAnimated();
  470. else if (!mScaleCurrentlyAnimated && thread->getSequence()->animatesScale())
  471. mScaleCurrentlyAnimated=true;
  472. updateTransitions();
  473. }
  474. U32 TSShapeInstance::getSequence(TSThread * thread)
  475. {
  476. //AssertFatal( thread->sequence >= 0, "TSShapeInstance::getSequence: range error A");
  477. //AssertFatal( thread->sequence < mShape->sequences.size(), "TSShapeInstance::getSequence: range error B");
  478. return (U32)thread->sequence;
  479. }
  480. void TSShapeInstance::transitionToSequence(TSThread * thread, S32 seq, F32 pos, F32 duration, bool continuePlay)
  481. {
  482. // make sure all transforms on all detail levels are accurate
  483. sortThreads();
  484. animateNodeSubtrees();
  485. thread->transitionToSequence(seq,pos,duration,continuePlay);
  486. setDirty(AllDirtyMask);
  487. mGroundThread = NULL;
  488. if (mScaleCurrentlyAnimated && !thread->getSequence()->animatesScale())
  489. checkScaleCurrentlyAnimated();
  490. else if (!mScaleCurrentlyAnimated && thread->getSequence()->animatesScale())
  491. mScaleCurrentlyAnimated=true;
  492. mTransitionRotationNodes.overlap(thread->transitionData.oldRotationNodes);
  493. mTransitionRotationNodes.overlap(thread->getSequence()->rotationMatters);
  494. mTransitionTranslationNodes.overlap(thread->transitionData.oldTranslationNodes);
  495. mTransitionTranslationNodes.overlap(thread->getSequence()->translationMatters);
  496. mTransitionScaleNodes.overlap(thread->transitionData.oldScaleNodes);
  497. mTransitionScaleNodes.overlap(thread->getSequence()->scaleMatters);
  498. // if we aren't already in the list of transition threads, add us now
  499. S32 i;
  500. for (i=0; i<mTransitionThreads.size(); i++)
  501. if (mTransitionThreads[i]==thread)
  502. break;
  503. if (i==mTransitionThreads.size())
  504. mTransitionThreads.push_back(thread);
  505. updateTransitions();
  506. }
  507. void TSShapeInstance::clearTransition(TSThread * thread)
  508. {
  509. if (!thread->transitionData.inTransition)
  510. return;
  511. // if other transitions are still playing,
  512. // make sure transforms are up to date
  513. if (mTransitionThreads.size()>1)
  514. animateNodeSubtrees();
  515. // turn off transition...
  516. thread->transitionData.inTransition = false;
  517. // remove us from transition list
  518. S32 i;
  519. if (mTransitionThreads.size() != 0) {
  520. for (i=0; i<mTransitionThreads.size(); i++)
  521. if (mTransitionThreads[i]==thread)
  522. break;
  523. AssertFatal(i!=mTransitionThreads.size(),"TSShapeInstance::clearTransition");
  524. mTransitionThreads.erase(i);
  525. }
  526. // recompute transitionNodes
  527. mTransitionRotationNodes.clearAll();
  528. mTransitionTranslationNodes.clearAll();
  529. mTransitionScaleNodes.clearAll();
  530. for (i=0; i<mTransitionThreads.size(); i++)
  531. {
  532. mTransitionRotationNodes.overlap(mTransitionThreads[i]->transitionData.oldRotationNodes);
  533. mTransitionRotationNodes.overlap(mTransitionThreads[i]->getSequence()->rotationMatters);
  534. mTransitionTranslationNodes.overlap(mTransitionThreads[i]->transitionData.oldTranslationNodes);
  535. mTransitionTranslationNodes.overlap(mTransitionThreads[i]->getSequence()->translationMatters);
  536. mTransitionScaleNodes.overlap(mTransitionThreads[i]->transitionData.oldScaleNodes);
  537. mTransitionScaleNodes.overlap(mTransitionThreads[i]->getSequence()->scaleMatters);
  538. }
  539. setDirty(ThreadDirty);
  540. updateTransitions();
  541. }
  542. void TSShapeInstance::updateTransitions()
  543. {
  544. if (mTransitionThreads.empty())
  545. return;
  546. TSIntegerSet transitionNodes;
  547. updateTransitionNodeTransforms(transitionNodes);
  548. S32 i;
  549. mNodeReferenceRotations.setSize(mShape->nodes.size());
  550. mNodeReferenceTranslations.setSize(mShape->nodes.size());
  551. for (i=0; i<mShape->nodes.size(); i++)
  552. {
  553. if (mTransitionRotationNodes.test(i))
  554. mNodeReferenceRotations[i].set(smNodeCurrentRotations[i]);
  555. if (mTransitionTranslationNodes.test(i))
  556. mNodeReferenceTranslations[i] = smNodeCurrentTranslations[i];
  557. }
  558. if (animatesScale())
  559. {
  560. // Make sure smNodeXXXScale arrays have been resized
  561. TSIntegerSet dummySet;
  562. handleDefaultScale(0, 0, dummySet);
  563. if (animatesUniformScale())
  564. {
  565. mNodeReferenceUniformScales.setSize(mShape->nodes.size());
  566. for (i=0; i<mShape->nodes.size(); i++)
  567. {
  568. if (mTransitionScaleNodes.test(i))
  569. mNodeReferenceUniformScales[i] = smNodeCurrentUniformScales[i];
  570. }
  571. }
  572. else if (animatesAlignedScale())
  573. {
  574. mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
  575. for (i=0; i<mShape->nodes.size(); i++)
  576. {
  577. if (mTransitionScaleNodes.test(i))
  578. mNodeReferenceScaleFactors[i] = smNodeCurrentAlignedScales[i];
  579. }
  580. }
  581. else
  582. {
  583. mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
  584. mNodeReferenceArbitraryScaleRots.setSize(mShape->nodes.size());
  585. for (i=0; i<mShape->nodes.size(); i++)
  586. {
  587. if (mTransitionScaleNodes.test(i))
  588. {
  589. mNodeReferenceScaleFactors[i] = smNodeCurrentArbitraryScales[i].mScale;
  590. mNodeReferenceArbitraryScaleRots[i].set(smNodeCurrentArbitraryScales[i].mRotate);
  591. }
  592. }
  593. }
  594. }
  595. // reset transition durations to account for new reference transforms
  596. for (i=0; i<mTransitionThreads.size(); i++)
  597. {
  598. TSThread * th = mTransitionThreads[i];
  599. if (th->transitionData.inTransition)
  600. {
  601. th->transitionData.duration *= 1.0f - th->transitionData.pos;
  602. th->transitionData.pos = 0.0f;
  603. }
  604. }
  605. }
  606. void TSShapeInstance::checkScaleCurrentlyAnimated()
  607. {
  608. mScaleCurrentlyAnimated=true;
  609. for (S32 i=0; i<mThreadList.size(); i++)
  610. if (mThreadList[i]->getSequence()->animatesScale())
  611. return;
  612. mScaleCurrentlyAnimated=false;
  613. }
  614. void TSShapeInstance::setBlendEnabled(TSThread * thread, bool blendOn)
  615. {
  616. thread->blendDisabled = !blendOn;
  617. }
  618. bool TSShapeInstance::getBlendEnabled(TSThread * thread)
  619. {
  620. return !thread->blendDisabled;
  621. }
  622. void TSShapeInstance::setPriority(TSThread * thread, F32 priority)
  623. {
  624. thread->priority = priority;
  625. }
  626. F32 TSShapeInstance::getPriority(TSThread * thread)
  627. {
  628. return thread->priority;
  629. }
  630. F32 TSShapeInstance::getTime(TSThread * thread)
  631. {
  632. return thread->getTime();
  633. }
  634. F32 TSShapeInstance::getPos(TSThread * thread)
  635. {
  636. return thread->getPos();
  637. }
  638. void TSShapeInstance::setTime(TSThread * thread, F32 time)
  639. {
  640. thread->setTime(time);
  641. }
  642. void TSShapeInstance::setPos(TSThread * thread, F32 pos)
  643. {
  644. thread->setPos(pos);
  645. }
  646. bool TSShapeInstance::isInTransition(TSThread * thread)
  647. {
  648. return thread->isInTransition();
  649. }
  650. F32 TSShapeInstance::getTimeScale(TSThread * thread)
  651. {
  652. return thread->getTimeScale();
  653. }
  654. void TSShapeInstance::setTimeScale(TSThread * thread, F32 timeScale)
  655. {
  656. thread->setTimeScale(timeScale);
  657. }
  658. F32 TSShapeInstance::getDuration(TSThread * thread)
  659. {
  660. return thread->getDuration();
  661. }
  662. F32 TSShapeInstance::getScaledDuration(TSThread * thread)
  663. {
  664. return thread->getScaledDuration();
  665. }
  666. S32 TSShapeInstance::getKeyframeCount(TSThread * thread)
  667. {
  668. return thread->getKeyframeCount();
  669. }
  670. S32 TSShapeInstance::getKeyframeNumber(TSThread * thread)
  671. {
  672. return thread->getKeyframeNumber();
  673. }
  674. void TSShapeInstance::setKeyframeNumber(TSThread * thread, S32 kf)
  675. {
  676. thread->setKeyframeNumber(kf);
  677. }
  678. // advance time on a particular thread
  679. void TSShapeInstance::advanceTime(F32 delta, TSThread * thread)
  680. {
  681. thread->advanceTime(delta);
  682. }
  683. // advance time on all threads
  684. void TSShapeInstance::advanceTime(F32 delta)
  685. {
  686. for (S32 i=0; i<mThreadList.size(); i++)
  687. mThreadList[i]->advanceTime(delta);
  688. }
  689. // advance pos on a particular thread
  690. void TSShapeInstance::advancePos(F32 delta, TSThread * thread)
  691. {
  692. thread->advancePos(delta);
  693. }
  694. // advance pos on all threads
  695. void TSShapeInstance::advancePos(F32 delta)
  696. {
  697. for (S32 i=0; i<mThreadList.size(); i++)
  698. mThreadList[i]->advancePos(delta);
  699. }