tsThread.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  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. mSeqPos = 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 (mSeqPos>0.9999f && getSequence()->isCyclic())
  145. mSeqPos = 0.9999f;
  146. // select keyframes
  147. selectKeyframes(mSeqPos,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 = mSeqPos;
  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. mSeqPos = 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 (mSeqPos>0.9999f && getSequence()->isCyclic())
  187. mSeqPos = 0.9999f;
  188. // select keyframes
  189. selectKeyframes(mSeqPos,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. TSShape::Trigger currentTrigger = shape->triggers[i];
  242. // is a between this trigger and previous one...
  243. if (a>lastPos && a <= currentTrigger.pos)
  244. aIndex = i;
  245. // is b between this trigger and previous one...
  246. if (b>lastPos && b <= currentTrigger.pos)
  247. bIndex = i;
  248. lastPos = currentTrigger.pos;
  249. }
  250. // activate triggers between aIndex and bIndex (depends on direction)
  251. if (aIndex<=bIndex)
  252. {
  253. for (i=aIndex; i<bIndex; i++)
  254. {
  255. U32 state = shape->triggers[i].state;
  256. bool on = (state & TSShape::Trigger::StateOn)!=0;
  257. mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
  258. }
  259. }
  260. else
  261. {
  262. for (i=aIndex-1; i>=bIndex; i--)
  263. {
  264. U32 state = shape->triggers[i].state;
  265. bool on = (state & TSShape::Trigger::StateOn)!=0;
  266. if (state & TSShape::Trigger::InvertOnReverse)
  267. on = !on;
  268. mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
  269. }
  270. }
  271. }
  272. F32 TSThread::getPos()
  273. {
  274. return transitionData.inTransition ? transitionData.pos : mSeqPos;
  275. }
  276. F32 TSThread::getTime()
  277. {
  278. return transitionData.inTransition ? transitionData.pos * transitionData.duration : mSeqPos * getSequence()->duration;
  279. }
  280. F32 TSThread::getDuration()
  281. {
  282. return transitionData.inTransition ? transitionData.duration : getSequence()->duration;
  283. }
  284. F32 TSThread::getScaledDuration()
  285. {
  286. return getDuration() / mFabs(timeScale);
  287. }
  288. F32 TSThread::getTimeScale()
  289. {
  290. return timeScale;
  291. }
  292. void TSThread::setTimeScale(F32 ts)
  293. {
  294. timeScale = ts;
  295. }
  296. void TSThread::advancePos(F32 delta)
  297. {
  298. if (mFabs(delta)>0.00001f)
  299. {
  300. // make dirty what this thread changes
  301. U32 dirtyFlags = getSequence()->dirtyFlags | (transitionData.inTransition ? TSShapeInstance::TransformDirty : 0);
  302. for (S32 i=0; i<mShapeInstance->getShape()->subShapeFirstNode.size(); i++)
  303. mShapeInstance->mDirtyFlags[i] |= dirtyFlags;
  304. }
  305. if (transitionData.inTransition)
  306. {
  307. transitionData.pos += transitionData.direction * delta;
  308. if (transitionData.pos<0 || transitionData.pos>=1.0f)
  309. {
  310. mShapeInstance->clearTransition(this);
  311. if (transitionData.pos<0.0f)
  312. // return to old sequence
  313. mShapeInstance->setSequence(this,transitionData.oldSequence,transitionData.oldPos);
  314. }
  315. // re-adjust delta to be correct time-wise
  316. delta *= transitionData.targetScale * transitionData.duration / getSequence()->duration;
  317. }
  318. // even if we are in a transition, keep playing the sequence
  319. if (makePath)
  320. {
  321. path.start = mSeqPos;
  322. mSeqPos += delta;
  323. if (!getSequence()->isCyclic())
  324. {
  325. mSeqPos = mClampF(mSeqPos, 0.0f, 1.0f);
  326. path.loop = 0;
  327. }
  328. else
  329. {
  330. path.loop = (S32)mSeqPos;
  331. if (mSeqPos < 0.0f)
  332. path.loop--;
  333. mSeqPos -= path.loop;
  334. // following necessary because of floating point roundoff errors
  335. if (mSeqPos < 0.0f) mSeqPos += 1.0f;
  336. if (mSeqPos >= 1.0f) mSeqPos -= 1.0f;
  337. }
  338. path.end = mSeqPos;
  339. animateTriggers(); // do this automatically...no need for user to call it
  340. AssertFatal(mSeqPos >=0.0f && mSeqPos <=1.0f,"TSThread::advancePos (1)");
  341. AssertFatal(!getSequence()->isCyclic() || mSeqPos<1.0f,"TSThread::advancePos (2)");
  342. }
  343. else
  344. {
  345. mSeqPos += delta;
  346. if (!getSequence()->isCyclic())
  347. mSeqPos = mClampF(mSeqPos, 0.0f, 1.0f);
  348. else
  349. {
  350. mSeqPos -= S32(mSeqPos);
  351. // following necessary because of floating point roundoff errors
  352. if (mSeqPos < 0.0f) mSeqPos += 1.0f;
  353. if (mSeqPos >= 1.0f) mSeqPos -= 1.0f;
  354. }
  355. AssertFatal(mSeqPos >=0.0f && mSeqPos <=1.0f,"TSThread::advancePos (3)");
  356. AssertFatal(!getSequence()->isCyclic() || mSeqPos<1.0f,"TSThread::advancePos (4)");
  357. }
  358. // select keyframes
  359. selectKeyframes(mSeqPos,getSequence(),&keyNum1,&keyNum2,&keyPos);
  360. }
  361. void TSThread::advanceTime(F32 delta)
  362. {
  363. advancePos(timeScale * delta / getDuration());
  364. }
  365. void TSThread::setPos(F32 pos)
  366. {
  367. advancePos(pos-getPos());
  368. }
  369. void TSThread::setTime(F32 time)
  370. {
  371. setPos(timeScale * time/getDuration());
  372. }
  373. S32 TSThread::getKeyframeCount()
  374. {
  375. AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeCount: not while in transition");
  376. return getSequence()->numKeyframes + 1;
  377. }
  378. S32 TSThread::getKeyframeNumber()
  379. {
  380. AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeNumber: not while in transition");
  381. return keyNum1;
  382. }
  383. void TSThread::setKeyframeNumber(S32 kf)
  384. {
  385. AssertFatal(kf>=0 && kf<= getSequence()->numKeyframes,
  386. "TSThread::setKeyframeNumber: invalid frame specified.");
  387. AssertFatal(!transitionData.inTransition,"TSThread::setKeyframeNumber: not while in transition");
  388. keyNum1 = keyNum2 = kf;
  389. keyPos = 0;
  390. mSeqPos = 0;
  391. }
  392. TSThread::TSThread(TSShapeInstance * _shapeInst)
  393. {
  394. timeScale = 1.0f;
  395. mShapeInstance = _shapeInst;
  396. transitionData.inTransition = false;
  397. blendDisabled = false;
  398. setSequence(0,0.0f);
  399. }
  400. S32 TSThread::operator<(const TSThread & th2) const
  401. {
  402. if (getSequence()->isBlend() == th2.getSequence()->isBlend())
  403. {
  404. // both blend or neither blend, sort based on priority only -- higher priority first
  405. S32 ret = 0; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
  406. if (priority > th2.priority)
  407. ret = -1;
  408. if (th2.priority > priority)
  409. ret = 1;
  410. return ret;
  411. }
  412. else
  413. {
  414. // one is blend, the other is not...sort based on blend -- non-blended first
  415. AssertFatal(!getSequence()->isBlend() || !th2.getSequence()->isBlend(),"compareThreads: unequal 'trues'");
  416. S32 ret = -1; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
  417. if (getSequence()->isBlend())
  418. ret = 1;
  419. return ret;
  420. }
  421. }
  422. //-------------------------------------------------------------------------------------
  423. // TSShapeInstance Thread Interface -- more implemented in header file
  424. //-------------------------------------------------------------------------------------
  425. TSThread * TSShapeInstance::addThread()
  426. {
  427. if (mShape->sequences.empty())
  428. return NULL;
  429. mThreadList.increment();
  430. mThreadList.last() = new TSThread(this);
  431. setDirty(AllDirtyMask);
  432. return mThreadList.last();
  433. }
  434. TSThread * TSShapeInstance::getThread(S32 threadNumber)
  435. {
  436. AssertFatal(threadNumber < mThreadList.size() && threadNumber>=0,"TSShapeInstance::getThread: threadNumber out of bounds.");
  437. return mThreadList[threadNumber];
  438. }
  439. void TSShapeInstance::destroyThread(TSThread * thread)
  440. {
  441. if (!thread)
  442. return;
  443. clearTransition(thread);
  444. S32 i;
  445. for (i=0; i<mThreadList.size(); i++)
  446. if (thread==mThreadList[i])
  447. break;
  448. AssertFatal(i<mThreadList.size(),"TSShapeInstance::destroyThread was requested to destroy a thread that this instance doesn't own!");
  449. delete mThreadList[i];
  450. mThreadList.erase(i);
  451. setDirty(AllDirtyMask);
  452. checkScaleCurrentlyAnimated();
  453. }
  454. U32 TSShapeInstance::threadCount()
  455. {
  456. return mThreadList.size();
  457. }
  458. void TSShapeInstance::setSequence(TSThread * thread, S32 seq, F32 pos)
  459. {
  460. if ( (thread->transitionData.inTransition && mTransitionThreads.size()>1) || mTransitionThreads.size()>0)
  461. {
  462. // if we have transitions, make sure transforms are up to date...
  463. sortThreads();
  464. animateNodeSubtrees();
  465. }
  466. thread->setSequence(seq,pos);
  467. setDirty(AllDirtyMask);
  468. mGroundThread = NULL;
  469. if (mScaleCurrentlyAnimated && !thread->getSequence()->animatesScale())
  470. checkScaleCurrentlyAnimated();
  471. else if (!mScaleCurrentlyAnimated && thread->getSequence()->animatesScale())
  472. mScaleCurrentlyAnimated=true;
  473. updateTransitions();
  474. }
  475. U32 TSShapeInstance::getSequence(TSThread * thread)
  476. {
  477. //AssertFatal( thread->sequence >= 0, "TSShapeInstance::getSequence: range error A");
  478. //AssertFatal( thread->sequence < mShape->sequences.size(), "TSShapeInstance::getSequence: range error B");
  479. return (U32)thread->sequence;
  480. }
  481. void TSShapeInstance::transitionToSequence(TSThread * thread, S32 seq, F32 pos, F32 duration, bool continuePlay)
  482. {
  483. // make sure all transforms on all detail levels are accurate
  484. sortThreads();
  485. animateNodeSubtrees();
  486. thread->transitionToSequence(seq,pos,duration,continuePlay);
  487. setDirty(AllDirtyMask);
  488. mGroundThread = NULL;
  489. const TSShape::Sequence* threadSequence = thread->getSequence();
  490. if (mScaleCurrentlyAnimated && !threadSequence->animatesScale())
  491. checkScaleCurrentlyAnimated();
  492. else if (!mScaleCurrentlyAnimated && threadSequence->animatesScale())
  493. mScaleCurrentlyAnimated=true;
  494. mTransitionRotationNodes.overlap(thread->transitionData.oldRotationNodes);
  495. mTransitionRotationNodes.overlap(threadSequence->rotationMatters);
  496. mTransitionTranslationNodes.overlap(thread->transitionData.oldTranslationNodes);
  497. mTransitionTranslationNodes.overlap(threadSequence->translationMatters);
  498. mTransitionScaleNodes.overlap(thread->transitionData.oldScaleNodes);
  499. mTransitionScaleNodes.overlap(threadSequence->scaleMatters);
  500. // if we aren't already in the list of transition threads, add us now
  501. S32 i;
  502. for (i=0; i<mTransitionThreads.size(); i++)
  503. if (mTransitionThreads[i]==thread)
  504. break;
  505. if (i==mTransitionThreads.size())
  506. mTransitionThreads.push_back(thread);
  507. updateTransitions();
  508. }
  509. void TSShapeInstance::clearTransition(TSThread * thread)
  510. {
  511. if (!thread->transitionData.inTransition)
  512. return;
  513. // if other transitions are still playing,
  514. // make sure transforms are up to date
  515. if (mTransitionThreads.size()>1)
  516. animateNodeSubtrees();
  517. // turn off transition...
  518. thread->transitionData.inTransition = false;
  519. // remove us from transition list
  520. S32 i;
  521. if (mTransitionThreads.size() != 0) {
  522. for (i=0; i<mTransitionThreads.size(); i++)
  523. if (mTransitionThreads[i]==thread)
  524. break;
  525. AssertFatal(i!=mTransitionThreads.size(),"TSShapeInstance::clearTransition");
  526. mTransitionThreads.erase(i);
  527. }
  528. // recompute transitionNodes
  529. mTransitionRotationNodes.clearAll();
  530. mTransitionTranslationNodes.clearAll();
  531. mTransitionScaleNodes.clearAll();
  532. for (i=0; i<mTransitionThreads.size(); i++)
  533. {
  534. mTransitionRotationNodes.overlap(mTransitionThreads[i]->transitionData.oldRotationNodes);
  535. mTransitionRotationNodes.overlap(mTransitionThreads[i]->getSequence()->rotationMatters);
  536. mTransitionTranslationNodes.overlap(mTransitionThreads[i]->transitionData.oldTranslationNodes);
  537. mTransitionTranslationNodes.overlap(mTransitionThreads[i]->getSequence()->translationMatters);
  538. mTransitionScaleNodes.overlap(mTransitionThreads[i]->transitionData.oldScaleNodes);
  539. mTransitionScaleNodes.overlap(mTransitionThreads[i]->getSequence()->scaleMatters);
  540. }
  541. setDirty(ThreadDirty);
  542. updateTransitions();
  543. }
  544. void TSShapeInstance::updateTransitions()
  545. {
  546. if (mTransitionThreads.empty())
  547. return;
  548. TSIntegerSet transitionNodes;
  549. updateTransitionNodeTransforms(transitionNodes);
  550. S32 i;
  551. mNodeReferenceRotations.setSize(mShape->nodes.size());
  552. mNodeReferenceTranslations.setSize(mShape->nodes.size());
  553. for (i=0; i<mShape->nodes.size(); i++)
  554. {
  555. if (mTransitionRotationNodes.test(i))
  556. mNodeReferenceRotations[i].set(smNodeCurrentRotations[i]);
  557. if (mTransitionTranslationNodes.test(i))
  558. mNodeReferenceTranslations[i] = smNodeCurrentTranslations[i];
  559. }
  560. if (animatesScale())
  561. {
  562. // Make sure smNodeXXXScale arrays have been resized
  563. TSIntegerSet dummySet;
  564. handleDefaultScale(0, 0, dummySet);
  565. if (animatesUniformScale())
  566. {
  567. mNodeReferenceUniformScales.setSize(mShape->nodes.size());
  568. for (i=0; i<mShape->nodes.size(); i++)
  569. {
  570. if (mTransitionScaleNodes.test(i))
  571. mNodeReferenceUniformScales[i] = smNodeCurrentUniformScales[i];
  572. }
  573. }
  574. else if (animatesAlignedScale())
  575. {
  576. mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
  577. for (i=0; i<mShape->nodes.size(); i++)
  578. {
  579. if (mTransitionScaleNodes.test(i))
  580. mNodeReferenceScaleFactors[i] = smNodeCurrentAlignedScales[i];
  581. }
  582. }
  583. else
  584. {
  585. mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
  586. mNodeReferenceArbitraryScaleRots.setSize(mShape->nodes.size());
  587. for (i=0; i<mShape->nodes.size(); i++)
  588. {
  589. if (mTransitionScaleNodes.test(i))
  590. {
  591. mNodeReferenceScaleFactors[i] = smNodeCurrentArbitraryScales[i].mScale;
  592. mNodeReferenceArbitraryScaleRots[i].set(smNodeCurrentArbitraryScales[i].mRotate);
  593. }
  594. }
  595. }
  596. }
  597. // reset transition durations to account for new reference transforms
  598. for (i=0; i<mTransitionThreads.size(); i++)
  599. {
  600. TSThread * th = mTransitionThreads[i];
  601. if (th->transitionData.inTransition)
  602. {
  603. th->transitionData.duration *= 1.0f - th->transitionData.pos;
  604. th->transitionData.pos = 0.0f;
  605. }
  606. }
  607. }
  608. void TSShapeInstance::checkScaleCurrentlyAnimated()
  609. {
  610. mScaleCurrentlyAnimated=true;
  611. for (S32 i=0; i<mThreadList.size(); i++)
  612. if (mThreadList[i]->getSequence()->animatesScale())
  613. return;
  614. mScaleCurrentlyAnimated=false;
  615. }
  616. void TSShapeInstance::setBlendEnabled(TSThread * thread, bool blendOn)
  617. {
  618. thread->blendDisabled = !blendOn;
  619. }
  620. bool TSShapeInstance::getBlendEnabled(TSThread * thread)
  621. {
  622. return !thread->blendDisabled;
  623. }
  624. void TSShapeInstance::setPriority(TSThread * thread, F32 priority)
  625. {
  626. thread->priority = priority;
  627. }
  628. F32 TSShapeInstance::getPriority(TSThread * thread)
  629. {
  630. return thread->priority;
  631. }
  632. F32 TSShapeInstance::getTime(TSThread * thread)
  633. {
  634. return thread->getTime();
  635. }
  636. F32 TSShapeInstance::getPos(TSThread * thread)
  637. {
  638. return thread->getPos();
  639. }
  640. void TSShapeInstance::setTime(TSThread * thread, F32 time)
  641. {
  642. thread->setTime(time);
  643. }
  644. void TSShapeInstance::setPos(TSThread * thread, F32 pos)
  645. {
  646. thread->setPos(pos);
  647. }
  648. bool TSShapeInstance::isInTransition(TSThread * thread)
  649. {
  650. return thread->isInTransition();
  651. }
  652. F32 TSShapeInstance::getTimeScale(TSThread * thread)
  653. {
  654. return thread->getTimeScale();
  655. }
  656. void TSShapeInstance::setTimeScale(TSThread * thread, F32 timeScale)
  657. {
  658. thread->setTimeScale(timeScale);
  659. }
  660. F32 TSShapeInstance::getDuration(TSThread * thread)
  661. {
  662. return thread->getDuration();
  663. }
  664. F32 TSShapeInstance::getScaledDuration(TSThread * thread)
  665. {
  666. return thread->getScaledDuration();
  667. }
  668. S32 TSShapeInstance::getKeyframeCount(TSThread * thread)
  669. {
  670. return thread->getKeyframeCount();
  671. }
  672. S32 TSShapeInstance::getKeyframeNumber(TSThread * thread)
  673. {
  674. return thread->getKeyframeNumber();
  675. }
  676. void TSShapeInstance::setKeyframeNumber(TSThread * thread, S32 kf)
  677. {
  678. thread->setKeyframeNumber(kf);
  679. }
  680. // advance time on a particular thread
  681. void TSShapeInstance::advanceTime(F32 delta, TSThread * thread)
  682. {
  683. thread->advanceTime(delta);
  684. }
  685. // advance time on all threads
  686. void TSShapeInstance::advanceTime(F32 delta)
  687. {
  688. for (S32 i=0; i<mThreadList.size(); i++)
  689. mThreadList[i]->advanceTime(delta);
  690. }
  691. // advance pos on a particular thread
  692. void TSShapeInstance::advancePos(F32 delta, TSThread * thread)
  693. {
  694. thread->advancePos(delta);
  695. }
  696. // advance pos on all threads
  697. void TSShapeInstance::advancePos(F32 delta)
  698. {
  699. for (S32 i=0; i<mThreadList.size(); i++)
  700. mThreadList[i]->advancePos(delta);
  701. }