123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "ts/tsShapeInstance.h"
- //-------------------------------------------------------------------------------------
- // This file contains the shape instance thread class (defined in tsShapeInstance.h)
- // and the tsShapeInstance functions to interface with the thread class.
- //-------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------
- // Thread class
- //-------------------------------------------------------------------------------------
- // given a position on the thread, choose correct keyframes
- // slight difference between one-shot and cyclic sequences -- see comments below for details
- void TSThread::selectKeyframes(F32 pos, const TSSequence * seq, S32 * k1, S32 * k2, F32 * kpos)
- {
- S32 numKF = seq->numKeyframes;
- F32 kf;
- if (seq->isCyclic())
- {
- // cyclic sequence:
- // pos=0 and pos=1 are equivalent, so we don't have a keyframe at pos=1
- // last keyframe corresponds to pos=n/(n-1) up to (not including) pos=1
- // (where n == num keyframes)
- AssertFatal(pos>=0.0f && pos<1.0f,"TSThread::selectKeyframes");
- kf = pos * (F32) (numKF);
- // set keyPos
- if (kpos)
- *kpos = kf - (S32) kf;
- // make sure compiler doing what we want...
- AssertFatal(*kpos>=0.0f && *kpos<1.0f,"TSThread::selectKeyframes");
- S32 kfIdx1 = (S32) kf;
- // following assert could happen if pos1<1 && pos1==1...paradoxically...
- AssertFatal(kfIdx1<=seq->numKeyframes,"TSThread::selectKeyframes");
- S32 kfIdx2 = (kfIdx1==seq->numKeyframes-1) ? 0 : kfIdx1+1;
- if (k1)
- *k1 = kfIdx1;
- if (k2)
- *k2 = kfIdx2;
- }
- else
- {
- // one-shot sequence:
- // pos=0 and pos=1 are now different, so we have a keyframe at pos=1
- // last keyframe corresponds to pos=1
- // rest of the keyframes are equally spaced (so 1/(n-1) pos units long)
- // (where n == num keyframes)
- AssertFatal(pos>=0.0f && pos<=1.0f,"TSThread::selectKeyframes");
- if (pos==1.0f)
- {
- if (kpos)
- *kpos = 0.0f;
- if (k1)
- *k1 = seq->numKeyframes-1;
- if (k2)
- *k2 = seq->numKeyframes-1;
- }
- else
- {
- kf = pos * (F32) (numKF-1);
- // set keyPos
- if (kpos)
- *kpos = kf - (S32) kf;
- S32 kfIdx1 = (S32) kf;
- // following assert could happen if pos1<1 && pos1==1...paradoxically...
- AssertFatal(kfIdx1<seq->numKeyframes,"TSThread::selectKeyFrames: invalid keyframe!");
- S32 kfIdx2 = kfIdx1+1;
- if (k1)
- *k1 = kfIdx1;
- if (k2)
- *k2 = kfIdx2;
- }
- }
- }
- void TSThread::getGround(F32 t, MatrixF * pMat)
- {
- static const QuatF unitRotation(0,0,0,1);
- static const Point3F unitTranslation = Point3F::Zero;
- const QuatF * q1, * q2;
- QuatF rot1,rot2;
- const Point3F * p1, * p2;
- // if N = sequence->numGroundFrames, then there are N+1 positions we
- // interpolate betweeen: 0/N, 1/N ... N/N
- // we need to convert the p passed to us into 2 ground keyframes:
- // the 0.99999f is in case 'p' is exactly 1.0f, which is legal but 'kf'
- // needs to be strictly less than 'sequence->numGroundFrames'
- F32 kf = 0.999999f * t * (F32) getSequence()->numGroundFrames;
- // get frame number and interp param (kpos)
- S32 frame = (S32)kf;
- F32 kpos = kf - (F32)frame;
- // now point pT1 and pT2 at transforms for keyframes 'frame' and 'frame+1'
- // following a little strange: first ground keyframe (0/N in comment above) is
- // assumed to be ident. and not found in the list.
- if (frame)
- {
- p1 = &mShapeInstance->mShape->groundTranslations[getSequence()->firstGroundFrame + frame - 1];
- q1 = &mShapeInstance->mShape->groundRotations[getSequence()->firstGroundFrame + frame - 1].getQuatF(&rot1);
- }
- else
- {
- p1 = &unitTranslation;
- q1 = &unitRotation;
- }
- // similar to above, ground keyframe number 'frame+1' is actually offset by 'frame'
- p2 = &mShapeInstance->mShape->groundTranslations[getSequence()->firstGroundFrame + frame];
- q2 = &mShapeInstance->mShape->groundRotations[getSequence()->firstGroundFrame + frame].getQuatF(&rot2);
- QuatF q;
- Point3F p;
- TSTransform::interpolate(*q1,*q2,kpos,&q);
- TSTransform::interpolate(*p1,*p2,kpos,&p);
- TSTransform::setMatrix(q,p,pMat);
- }
- void TSThread::setSequence(S32 seq, F32 toPos)
- {
- const TSShape * shape = mShapeInstance->mShape;
- AssertFatal(shape && shape->sequences.size()>seq && toPos>=0.0f && toPos<=1.0f,
- "TSThread::setSequence: invalid shape handle, sequence number, or position.");
- mShapeInstance->clearTransition(this);
- sequence = seq;
- priority = getSequence()->priority;
- mSeqPos = toPos;
- makePath = getSequence()->makePath();
- path.start = path.end = 0;
- path.loop = 0;
- // 1.0f doesn't exist on cyclic sequences
- if (mSeqPos>0.9999f && getSequence()->isCyclic())
- mSeqPos = 0.9999f;
- // select keyframes
- selectKeyframes(mSeqPos,getSequence(),&keyNum1,&keyNum2,&keyPos);
- }
- void TSThread::transitionToSequence(S32 seq, F32 toPos, F32 duration, bool continuePlay)
- {
- AssertFatal(duration>=0.0f,"TSThread::transitionToSequence: negative duration not allowed");
- // make sure these nodes are smoothly interpolated to new positions...
- // basically, any node we controlled just prior to transition, or at any stage
- // of the transition is interpolated. If we start to transtion from A to B,
- // but before reaching B we transtion to C, we interpolate all nodes controlled
- // by A, B, or C to their new position.
- if (transitionData.inTransition)
- {
- transitionData.oldRotationNodes.overlap(getSequence()->rotationMatters);
- transitionData.oldTranslationNodes.overlap(getSequence()->translationMatters);
- transitionData.oldScaleNodes.overlap(getSequence()->scaleMatters);
- }
- else
- {
- transitionData.oldRotationNodes = getSequence()->rotationMatters;
- transitionData.oldTranslationNodes = getSequence()->translationMatters;
- transitionData.oldScaleNodes = getSequence()->scaleMatters;
- }
- // set time characteristics of transition
- transitionData.oldSequence = sequence;
- transitionData.oldPos = mSeqPos;
- transitionData.duration = duration;
- transitionData.pos = 0.0f;
- transitionData.direction = timeScale>0.0f ? 1.0f : -1.0f;
- transitionData.targetScale = continuePlay ? 1.0f : 0.0f;
- // in transition...
- transitionData.inTransition = true;
- // set target sequence data
- sequence = seq;
- priority = getSequence()->priority;
- mSeqPos = toPos;
- makePath = getSequence()->makePath();
- path.start = path.end = 0;
- path.loop = 0;
- // 1.0f doesn't exist on cyclic sequences
- if (mSeqPos>0.9999f && getSequence()->isCyclic())
- mSeqPos = 0.9999f;
- // select keyframes
- selectKeyframes(mSeqPos,getSequence(),&keyNum1,&keyNum2,&keyPos);
- }
- bool TSThread::isInTransition()
- {
- return transitionData.inTransition;
- }
- void TSThread::animateTriggers()
- {
- if (!getSequence()->numTriggers)
- return;
- switch (path.loop)
- {
- case -1 :
- activateTriggers(path.start,0);
- activateTriggers(1,path.end);
- break;
- case 0 :
- activateTriggers(path.start,path.end);
- break;
- case 1 :
- activateTriggers(path.start,1);
- activateTriggers(0,path.end);
- break;
- default:
- {
- if (path.loop>0)
- {
- activateTriggers(path.end,1);
- activateTriggers(0,path.end);
- }
- else
- {
- activateTriggers(path.end,0);
- activateTriggers(1,path.end);
- }
- }
- }
- }
- void TSThread::activateTriggers(F32 a, F32 b)
- {
- S32 i;
- const TSShape * shape = mShapeInstance->mShape;
- S32 firstTrigger = getSequence()->firstTrigger;
- S32 numTriggers = getSequence()->numTriggers;
- // first find triggers at position a and b
- // we assume there aren't many triggers, so
- // search is linear
- F32 lastPos = -1.0f;
- S32 aIndex = numTriggers+firstTrigger; // initialized to handle case where pos past all triggers
- S32 bIndex = numTriggers+firstTrigger; // initialized to handle case where pos past all triggers
- for (i=firstTrigger; i<numTriggers+firstTrigger; i++)
- {
- TSShape::Trigger currentTrigger = shape->triggers[i];
- // is a between this trigger and previous one...
- if (a>lastPos && a <= currentTrigger.pos)
- aIndex = i;
- // is b between this trigger and previous one...
- if (b>lastPos && b <= currentTrigger.pos)
- bIndex = i;
- lastPos = currentTrigger.pos;
- }
- // activate triggers between aIndex and bIndex (depends on direction)
- if (aIndex<=bIndex)
- {
- for (i=aIndex; i<bIndex; i++)
- {
- U32 state = shape->triggers[i].state;
- bool on = (state & TSShape::Trigger::StateOn)!=0;
- mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
- }
- }
- else
- {
- for (i=aIndex-1; i>=bIndex; i--)
- {
- U32 state = shape->triggers[i].state;
- bool on = (state & TSShape::Trigger::StateOn)!=0;
- if (state & TSShape::Trigger::InvertOnReverse)
- on = !on;
- mShapeInstance->setTriggerStateBit(state & TSShape::Trigger::StateMask, on);
- }
- }
- }
- F32 TSThread::getPos()
- {
- return transitionData.inTransition ? transitionData.pos : mSeqPos;
- }
- F32 TSThread::getTime()
- {
- return transitionData.inTransition ? transitionData.pos * transitionData.duration : mSeqPos * getSequence()->duration;
- }
- F32 TSThread::getDuration()
- {
- return transitionData.inTransition ? transitionData.duration : getSequence()->duration;
- }
- F32 TSThread::getScaledDuration()
- {
- return getDuration() / mFabs(timeScale);
- }
- F32 TSThread::getTimeScale()
- {
- return timeScale;
- }
- void TSThread::setTimeScale(F32 ts)
- {
- timeScale = ts;
- }
- void TSThread::advancePos(F32 delta)
- {
- if (mFabs(delta)>0.00001f)
- {
- // make dirty what this thread changes
- U32 dirtyFlags = getSequence()->dirtyFlags | (transitionData.inTransition ? TSShapeInstance::TransformDirty : 0);
- for (S32 i=0; i<mShapeInstance->getShape()->subShapeFirstNode.size(); i++)
- mShapeInstance->mDirtyFlags[i] |= dirtyFlags;
- }
- if (transitionData.inTransition)
- {
- transitionData.pos += transitionData.direction * delta;
- if (transitionData.pos<0 || transitionData.pos>=1.0f)
- {
- mShapeInstance->clearTransition(this);
- if (transitionData.pos<0.0f)
- // return to old sequence
- mShapeInstance->setSequence(this,transitionData.oldSequence,transitionData.oldPos);
- }
- // re-adjust delta to be correct time-wise
- delta *= transitionData.targetScale * transitionData.duration / getSequence()->duration;
- }
- // even if we are in a transition, keep playing the sequence
- if (makePath)
- {
- path.start = mSeqPos;
- mSeqPos += delta;
- if (!getSequence()->isCyclic())
- {
- mSeqPos = mClampF(mSeqPos, 0.0f, 1.0f);
- path.loop = 0;
- }
- else
- {
- path.loop = (S32)mSeqPos;
- if (mSeqPos < 0.0f)
- path.loop--;
- mSeqPos -= path.loop;
- // following necessary because of floating point roundoff errors
- if (mSeqPos < 0.0f) mSeqPos += 1.0f;
- if (mSeqPos >= 1.0f) mSeqPos -= 1.0f;
- }
- path.end = mSeqPos;
- animateTriggers(); // do this automatically...no need for user to call it
- AssertFatal(mSeqPos >=0.0f && mSeqPos <=1.0f,"TSThread::advancePos (1)");
- AssertFatal(!getSequence()->isCyclic() || mSeqPos<1.0f,"TSThread::advancePos (2)");
- }
- else
- {
- mSeqPos += delta;
- if (!getSequence()->isCyclic())
- mSeqPos = mClampF(mSeqPos, 0.0f, 1.0f);
- else
- {
- mSeqPos -= S32(mSeqPos);
- // following necessary because of floating point roundoff errors
- if (mSeqPos < 0.0f) mSeqPos += 1.0f;
- if (mSeqPos >= 1.0f) mSeqPos -= 1.0f;
- }
- AssertFatal(mSeqPos >=0.0f && mSeqPos <=1.0f,"TSThread::advancePos (3)");
- AssertFatal(!getSequence()->isCyclic() || mSeqPos<1.0f,"TSThread::advancePos (4)");
- }
- // select keyframes
- selectKeyframes(mSeqPos,getSequence(),&keyNum1,&keyNum2,&keyPos);
- }
- void TSThread::advanceTime(F32 delta)
- {
- advancePos(timeScale * delta / getDuration());
- }
- void TSThread::setPos(F32 pos)
- {
- advancePos(pos-getPos());
- }
- void TSThread::setTime(F32 time)
- {
- setPos(timeScale * time/getDuration());
- }
- S32 TSThread::getKeyframeCount()
- {
- AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeCount: not while in transition");
- return getSequence()->numKeyframes + 1;
- }
- S32 TSThread::getKeyframeNumber()
- {
- AssertFatal(!transitionData.inTransition,"TSThread::getKeyframeNumber: not while in transition");
- return keyNum1;
- }
- void TSThread::setKeyframeNumber(S32 kf)
- {
- AssertFatal(kf>=0 && kf<= getSequence()->numKeyframes,
- "TSThread::setKeyframeNumber: invalid frame specified.");
- AssertFatal(!transitionData.inTransition,"TSThread::setKeyframeNumber: not while in transition");
- keyNum1 = keyNum2 = kf;
- keyPos = 0;
- mSeqPos = 0;
- }
- TSThread::TSThread(TSShapeInstance * _shapeInst)
- {
- timeScale = 1.0f;
- mShapeInstance = _shapeInst;
- transitionData.inTransition = false;
- blendDisabled = false;
- setSequence(0,0.0f);
- }
- S32 TSThread::operator<(const TSThread & th2) const
- {
- if (getSequence()->isBlend() == th2.getSequence()->isBlend())
- {
- // both blend or neither blend, sort based on priority only -- higher priority first
- S32 ret = 0; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
- if (priority > th2.priority)
- ret = -1;
- if (th2.priority > priority)
- ret = 1;
- return ret;
- }
- else
- {
- // one is blend, the other is not...sort based on blend -- non-blended first
- AssertFatal(!getSequence()->isBlend() || !th2.getSequence()->isBlend(),"compareThreads: unequal 'trues'");
- S32 ret = -1; // do it this way to (hopefully) take advantage of 'conditional move' assembly instruction
- if (getSequence()->isBlend())
- ret = 1;
- return ret;
- }
- }
- //-------------------------------------------------------------------------------------
- // TSShapeInstance Thread Interface -- more implemented in header file
- //-------------------------------------------------------------------------------------
- TSThread * TSShapeInstance::addThread()
- {
- if (mShape->sequences.empty())
- return NULL;
- mThreadList.increment();
- mThreadList.last() = new TSThread(this);
- setDirty(AllDirtyMask);
- return mThreadList.last();
- }
- TSThread * TSShapeInstance::getThread(S32 threadNumber)
- {
- AssertFatal(threadNumber < mThreadList.size() && threadNumber>=0,"TSShapeInstance::getThread: threadNumber out of bounds.");
- return mThreadList[threadNumber];
- }
- void TSShapeInstance::destroyThread(TSThread * thread)
- {
- if (!thread)
- return;
- clearTransition(thread);
- S32 i;
- for (i=0; i<mThreadList.size(); i++)
- if (thread==mThreadList[i])
- break;
- AssertFatal(i<mThreadList.size(),"TSShapeInstance::destroyThread was requested to destroy a thread that this instance doesn't own!");
- delete mThreadList[i];
- mThreadList.erase(i);
- setDirty(AllDirtyMask);
- checkScaleCurrentlyAnimated();
- }
- U32 TSShapeInstance::threadCount()
- {
- return mThreadList.size();
- }
- void TSShapeInstance::setSequence(TSThread * thread, S32 seq, F32 pos)
- {
- if ( (thread->transitionData.inTransition && mTransitionThreads.size()>1) || mTransitionThreads.size()>0)
- {
- // if we have transitions, make sure transforms are up to date...
- sortThreads();
- animateNodeSubtrees();
- }
- thread->setSequence(seq,pos);
- setDirty(AllDirtyMask);
- mGroundThread = NULL;
- if (mScaleCurrentlyAnimated && !thread->getSequence()->animatesScale())
- checkScaleCurrentlyAnimated();
- else if (!mScaleCurrentlyAnimated && thread->getSequence()->animatesScale())
- mScaleCurrentlyAnimated=true;
- updateTransitions();
- }
- U32 TSShapeInstance::getSequence(TSThread * thread)
- {
- //AssertFatal( thread->sequence >= 0, "TSShapeInstance::getSequence: range error A");
- //AssertFatal( thread->sequence < mShape->sequences.size(), "TSShapeInstance::getSequence: range error B");
- return (U32)thread->sequence;
- }
- void TSShapeInstance::transitionToSequence(TSThread * thread, S32 seq, F32 pos, F32 duration, bool continuePlay)
- {
- // make sure all transforms on all detail levels are accurate
- sortThreads();
- animateNodeSubtrees();
- thread->transitionToSequence(seq,pos,duration,continuePlay);
- setDirty(AllDirtyMask);
- mGroundThread = NULL;
- const TSShape::Sequence* threadSequence = thread->getSequence();
- if (mScaleCurrentlyAnimated && !threadSequence->animatesScale())
- checkScaleCurrentlyAnimated();
- else if (!mScaleCurrentlyAnimated && threadSequence->animatesScale())
- mScaleCurrentlyAnimated=true;
- mTransitionRotationNodes.overlap(thread->transitionData.oldRotationNodes);
- mTransitionRotationNodes.overlap(threadSequence->rotationMatters);
- mTransitionTranslationNodes.overlap(thread->transitionData.oldTranslationNodes);
- mTransitionTranslationNodes.overlap(threadSequence->translationMatters);
- mTransitionScaleNodes.overlap(thread->transitionData.oldScaleNodes);
- mTransitionScaleNodes.overlap(threadSequence->scaleMatters);
- // if we aren't already in the list of transition threads, add us now
- S32 i;
- for (i=0; i<mTransitionThreads.size(); i++)
- if (mTransitionThreads[i]==thread)
- break;
- if (i==mTransitionThreads.size())
- mTransitionThreads.push_back(thread);
- updateTransitions();
- }
- void TSShapeInstance::clearTransition(TSThread * thread)
- {
- if (!thread->transitionData.inTransition)
- return;
- // if other transitions are still playing,
- // make sure transforms are up to date
- if (mTransitionThreads.size()>1)
- animateNodeSubtrees();
- // turn off transition...
- thread->transitionData.inTransition = false;
- // remove us from transition list
- S32 i;
- if (mTransitionThreads.size() != 0) {
- for (i=0; i<mTransitionThreads.size(); i++)
- if (mTransitionThreads[i]==thread)
- break;
- AssertFatal(i!=mTransitionThreads.size(),"TSShapeInstance::clearTransition");
- mTransitionThreads.erase(i);
- }
- // recompute transitionNodes
- mTransitionRotationNodes.clearAll();
- mTransitionTranslationNodes.clearAll();
- mTransitionScaleNodes.clearAll();
- for (i=0; i<mTransitionThreads.size(); i++)
- {
- mTransitionRotationNodes.overlap(mTransitionThreads[i]->transitionData.oldRotationNodes);
- mTransitionRotationNodes.overlap(mTransitionThreads[i]->getSequence()->rotationMatters);
- mTransitionTranslationNodes.overlap(mTransitionThreads[i]->transitionData.oldTranslationNodes);
- mTransitionTranslationNodes.overlap(mTransitionThreads[i]->getSequence()->translationMatters);
- mTransitionScaleNodes.overlap(mTransitionThreads[i]->transitionData.oldScaleNodes);
- mTransitionScaleNodes.overlap(mTransitionThreads[i]->getSequence()->scaleMatters);
- }
- setDirty(ThreadDirty);
- updateTransitions();
- }
- void TSShapeInstance::updateTransitions()
- {
- if (mTransitionThreads.empty())
- return;
- TSIntegerSet transitionNodes;
- updateTransitionNodeTransforms(transitionNodes);
- S32 i;
- mNodeReferenceRotations.setSize(mShape->nodes.size());
- mNodeReferenceTranslations.setSize(mShape->nodes.size());
- for (i=0; i<mShape->nodes.size(); i++)
- {
- if (mTransitionRotationNodes.test(i))
- mNodeReferenceRotations[i].set(smNodeCurrentRotations[i]);
- if (mTransitionTranslationNodes.test(i))
- mNodeReferenceTranslations[i] = smNodeCurrentTranslations[i];
- }
- if (animatesScale())
- {
- // Make sure smNodeXXXScale arrays have been resized
- TSIntegerSet dummySet;
- handleDefaultScale(0, 0, dummySet);
- if (animatesUniformScale())
- {
- mNodeReferenceUniformScales.setSize(mShape->nodes.size());
- for (i=0; i<mShape->nodes.size(); i++)
- {
- if (mTransitionScaleNodes.test(i))
- mNodeReferenceUniformScales[i] = smNodeCurrentUniformScales[i];
- }
- }
- else if (animatesAlignedScale())
- {
- mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
- for (i=0; i<mShape->nodes.size(); i++)
- {
- if (mTransitionScaleNodes.test(i))
- mNodeReferenceScaleFactors[i] = smNodeCurrentAlignedScales[i];
- }
- }
- else
- {
- mNodeReferenceScaleFactors.setSize(mShape->nodes.size());
- mNodeReferenceArbitraryScaleRots.setSize(mShape->nodes.size());
- for (i=0; i<mShape->nodes.size(); i++)
- {
- if (mTransitionScaleNodes.test(i))
- {
- mNodeReferenceScaleFactors[i] = smNodeCurrentArbitraryScales[i].mScale;
- mNodeReferenceArbitraryScaleRots[i].set(smNodeCurrentArbitraryScales[i].mRotate);
- }
- }
- }
- }
- // reset transition durations to account for new reference transforms
- for (i=0; i<mTransitionThreads.size(); i++)
- {
- TSThread * th = mTransitionThreads[i];
- if (th->transitionData.inTransition)
- {
- th->transitionData.duration *= 1.0f - th->transitionData.pos;
- th->transitionData.pos = 0.0f;
- }
- }
- }
- void TSShapeInstance::checkScaleCurrentlyAnimated()
- {
- mScaleCurrentlyAnimated=true;
- for (S32 i=0; i<mThreadList.size(); i++)
- if (mThreadList[i]->getSequence()->animatesScale())
- return;
- mScaleCurrentlyAnimated=false;
- }
- void TSShapeInstance::setBlendEnabled(TSThread * thread, bool blendOn)
- {
- thread->blendDisabled = !blendOn;
- }
- bool TSShapeInstance::getBlendEnabled(TSThread * thread)
- {
- return !thread->blendDisabled;
- }
- void TSShapeInstance::setPriority(TSThread * thread, F32 priority)
- {
- thread->priority = priority;
- }
- F32 TSShapeInstance::getPriority(TSThread * thread)
- {
- return thread->priority;
- }
- F32 TSShapeInstance::getTime(TSThread * thread)
- {
- return thread->getTime();
- }
- F32 TSShapeInstance::getPos(TSThread * thread)
- {
- return thread->getPos();
- }
- void TSShapeInstance::setTime(TSThread * thread, F32 time)
- {
- thread->setTime(time);
- }
- void TSShapeInstance::setPos(TSThread * thread, F32 pos)
- {
- thread->setPos(pos);
- }
- bool TSShapeInstance::isInTransition(TSThread * thread)
- {
- return thread->isInTransition();
- }
- F32 TSShapeInstance::getTimeScale(TSThread * thread)
- {
- return thread->getTimeScale();
- }
- void TSShapeInstance::setTimeScale(TSThread * thread, F32 timeScale)
- {
- thread->setTimeScale(timeScale);
- }
- F32 TSShapeInstance::getDuration(TSThread * thread)
- {
- return thread->getDuration();
- }
- F32 TSShapeInstance::getScaledDuration(TSThread * thread)
- {
- return thread->getScaledDuration();
- }
- S32 TSShapeInstance::getKeyframeCount(TSThread * thread)
- {
- return thread->getKeyframeCount();
- }
- S32 TSShapeInstance::getKeyframeNumber(TSThread * thread)
- {
- return thread->getKeyframeNumber();
- }
- void TSShapeInstance::setKeyframeNumber(TSThread * thread, S32 kf)
- {
- thread->setKeyframeNumber(kf);
- }
- // advance time on a particular thread
- void TSShapeInstance::advanceTime(F32 delta, TSThread * thread)
- {
- thread->advanceTime(delta);
- }
- // advance time on all threads
- void TSShapeInstance::advanceTime(F32 delta)
- {
- for (S32 i=0; i<mThreadList.size(); i++)
- mThreadList[i]->advanceTime(delta);
- }
- // advance pos on a particular thread
- void TSShapeInstance::advancePos(F32 delta, TSThread * thread)
- {
- thread->advancePos(delta);
- }
- // advance pos on all threads
- void TSShapeInstance::advancePos(F32 delta)
- {
- for (S32 i=0; i<mThreadList.size(); i++)
- mThreadList[i]->advancePos(delta);
- }
|