void _ReadSequence(BinaryReader bin, ref Sequence seq, bool readNameIndex) { if (readNameIndex) seq.NameIndex = bin.ReadInt32(); seq.Flags = (SequenceFlags)bin.ReadUInt32(); seq.KeyframeCount = bin.ReadInt32(); seq.Duration = bin.ReadSingle(); seq.Priority = bin.ReadInt32(); seq.FirstGroundFrame = bin.ReadInt32(); seq.GroundFrameCount = bin.ReadInt32(); seq.BaseRotation = bin.ReadInt32(); seq.BaseTranslation = bin.ReadInt32(); seq.BaseScale = bin.ReadInt32(); seq.BaseObjectState = bin.ReadInt32(); int baseDecalState = bin.ReadInt32(); // deprecated seq.FirstTrigger = bin.ReadInt32(); seq.TriggerCount = bin.ReadInt32(); seq.ToolBegin = bin.ReadSingle(); seq.DoesRotationMatter.Read(bin); seq.DoesTranslationMatter.Read(bin); seq.DoesScaleMatter.Read(bin); BitVector decalMatters = new BitVector(); // deprecated decalMatters.Read(bin); seq.DoesIflMatter.Read(bin); seq.DoesVisibilityMatter.Read(bin); seq.DoesFrameMatter.Read(bin); seq.DoesMaterialFrameMatter.Read(bin); // figure out dirty _flags seq.DirtyFlags = 0; if (seq.DoesRotationMatter.TestAll() || seq.DoesTranslationMatter.TestAll() || seq.DoesScaleMatter.TestAll()) seq.DirtyFlags |= DirtyFlags.TransformDirty; if (seq.DoesVisibilityMatter.TestAll()) seq.DirtyFlags |= DirtyFlags.VisDirty; if (seq.DoesFrameMatter.TestAll()) seq.DirtyFlags |= DirtyFlags.FrameDirty; if (seq.DoesMaterialFrameMatter.TestAll()) seq.DirtyFlags |= DirtyFlags.MatFrameDirty; if (seq.DoesIflMatter.TestAll()) seq.DirtyFlags |= DirtyFlags.IflDirty; }
/// <summary> /// Gets the object state of a sequence at the specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number.</param> /// <param name="objectNum">The object index.</param> /// <returns>The object state.</returns> public ObjectState GetObjectState(Sequence seq, int keyframeNum, int objectNum) { return ObjectStates[seq.BaseObjectState + objectNum * seq.KeyframeCount + keyframeNum]; }
/// <summary> /// Gets the rotation of a sequence at a specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number</param> /// <param name="rotNum">The node index.</param> /// <param name="rot">Receives the rotation.</param> public void GetRotation(Sequence seq, int keyframeNum, int rotNum, out Quaternion rot) { NodeRotations[seq.BaseRotation + rotNum * seq.KeyframeCount + keyframeNum].Get(out rot); }
/// <summary> /// Gets the aligned scale of a sequence at a specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number</param> /// <param name="scaleNum">The node index.</param> /// <returns>The scale.</returns> public Vector3 GetAlignedScale(Sequence seq, int keyframeNum, int scaleNum) { return NodeAlignedScales[seq.BaseScale + scaleNum * seq.KeyframeCount + keyframeNum]; }
/// <summary> /// Gets the arbitrary scale of a sequence at a specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number</param> /// <param name="scaleNum">The node index.</param> /// <param name="scale">Receives the scale.</param> public void GetArbitraryScale(Sequence seq, int keyframeNum, int scaleNum, out ArbitraryScale scale) { NodeArbitraryScaleRotations[seq.BaseScale + scaleNum * seq.KeyframeCount + keyframeNum].Get(out scale.Rotate); scale.Scale = NodeArbitraryScaleFactors[seq.BaseScale + scaleNum * seq.KeyframeCount + keyframeNum]; }
/// <summary> /// Gets the translation of a sequence at a specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number</param> /// <param name="tranNum">The node index.</param> /// <returns>The translation.</returns> public Vector3 GetTranslation(Sequence seq, int keyframeNum, int tranNum) { return NodeTranslations[seq.BaseTranslation + tranNum * seq.KeyframeCount + keyframeNum]; }
/// <summary> /// Gets the uniform scale of a sequence at a specified keyframe. /// </summary> /// <param name="seq">The sequence.</param> /// <param name="keyframeNum">The keyframe number</param> /// <param name="scaleNum">The node index.</param> /// <returns>The scale.</returns> public float GetUniformScale(Sequence seq, int keyframeNum, int scaleNum) { return NodeUniformScales[seq.BaseScale + scaleNum * seq.KeyframeCount + keyframeNum]; }
void _SelectKeyframes(float pos, Sequence seq, out int k1, out int k2, out float kpos) { Shape shape = _shapeInstance.GetShape(); int numKF = seq.KeyframeCount; float 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) Assert.Fatal(pos >= 0.0f && pos < 1.0f, "Thread.SelectKeyframes - Invalid thread position."); kf = pos * (float)(numKF); // Set _keyPos kpos = kf - (int)kf; // make sure compiler doing what we want... Assert.Fatal(kpos >= 0.0f && kpos < 1.0f, "Thread.SelectKeyframes - Invalid thread position."); int kfIdx1 = (int)kf; // following assert could happen if pos1<1 && pos1==1...paradoxically... Assert.Fatal(kfIdx1 <= seq.KeyframeCount, "Thread.SelectKeyframes - Invalid keyframe."); int kfIdx2 = (kfIdx1 == seq.KeyframeCount - 1) ? 0 : kfIdx1 + 1; k1 = kfIdx1; 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) Assert.Fatal(pos >= 0.0f && pos <= 1.0f, "Thread.SelectKeyframes - Invalid thread position."); if (pos == 1.0f) { kpos = 0.0f; k1 = seq.KeyframeCount - 1; k2 = seq.KeyframeCount - 1; } else { kf = pos * (float)(numKF - 1); // Set _keyPos kpos = kf - (int)kf; int kfIdx1 = (int)kf; // following assert could happen if pos1<1 && pos1==1...paradoxically... Assert.Fatal(kfIdx1 < seq.KeyframeCount, "TSThread.SelectKeyFrames - Invalid keyframe."); int kfIdx2 = kfIdx1 + 1; k1 = kfIdx1; k2 = kfIdx2; } } }
internal void _SetSequence(Sequence seq, float toPos) { Shape shape = _shapeInstance.GetShape(); Assert.Fatal(shape != null && toPos >= 0.0f && toPos <= 1.0f, "Thread.SetSequence - Invalid shape handle, sequence number, or position."); _shapeInstance.ClearTransition(this); _sequence = seq; _priority = _sequence.Priority; _pos = toPos; _makePath = _sequence.MakePath(); // 1.0f doesn't exist on cyclic sequences if (_pos > 0.9999f && _sequence.IsCyclic()) _pos = 0.9999f; // select keyframes _SelectKeyframes(_pos, _sequence, out _keyNum1, out _keyNum2, out _keyPos); }
/// <summary> /// Sets a new sequence on the thread by transitioning to it. /// </summary> /// <param name="seq">The sequence to transition to.</param> /// <param name="toPos">The position of the new sequence to start at.</param> /// <param name="duration">The length of the transition.</param> /// <param name="continuePlay">Whether or not to continue playing the thread.</param> public void TransitionToSequence(Sequence seq, float toPos, float duration, bool continuePlay) { Assert.Fatal(duration > 0.0f, "Thread.TransitionToSequence - Must pass a positive non zero duration."); Shape shape = _shapeInstance.GetShape(); // 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(_sequence.DoesRotationMatter); _transitionData._oldTranslationNodes.Overlap(_sequence.DoesTranslationMatter); _transitionData._oldScaleNodes.Overlap(_sequence.DoesScaleMatter); } else { _transitionData._oldRotationNodes.Copy(ref _sequence.DoesRotationMatter); _transitionData._oldTranslationNodes.Copy(ref _sequence.DoesTranslationMatter); _transitionData._oldScaleNodes.Copy(ref _sequence.DoesScaleMatter); } // Set time characteristics of transition _transitionData._oldSequence = _sequence; _transitionData._oldPos = _pos; _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 = _sequence.Priority; _pos = toPos; _makePath = _sequence.MakePath(); // 1.0f doesn't exist on cyclic sequences if (_pos > 0.9999f && _sequence.IsCyclic()) _pos = 0.9999f; // select keyframes _SelectKeyframes(_pos, _sequence, out _keyNum1, out _keyNum2, out _keyPos); }
/// <summary> /// Transitions from the current sequence to a new sequence. /// </summary> /// <param name="thread">The thread to transition on.</param> /// <param name="seq">The sequence to transition to.</param> /// <param name="pos">The position of the sequence to start at.</param> /// <param name="duration">The length of the transition.</param> /// <param name="continuePlay">Whether or not to continue playing the thread.</param> public void TransitionToSequence(Thread thread, Sequence seq, float pos, float duration, bool continuePlay) { // make sure all transforms on all detail levels are accurate _AnimateNodeSubtrees(true); thread.TransitionToSequence(seq, pos, duration, continuePlay); _SetDirty(DirtyFlags.AllDirtyMask); // cafTODO: don't use this, remove it altogether? //_groundThread = null; if (_scaleCurrentlyAnimated && !thread.Sequence.IsScaleAnimated()) _CheckScaleCurrentlyAnimated(); else if (!_scaleCurrentlyAnimated && thread.Sequence.IsScaleAnimated()) _scaleCurrentlyAnimated = true; _transitionRotationNodes.Overlap(thread._transitionData._oldRotationNodes); _transitionRotationNodes.Overlap(thread.Sequence.DoesRotationMatter); _transitionTranslationNodes.Overlap(thread._transitionData._oldTranslationNodes); _transitionTranslationNodes.Overlap(thread.Sequence.DoesTranslationMatter); _transitionScaleNodes.Overlap(thread._transitionData._oldScaleNodes); _transitionScaleNodes.Overlap(thread.Sequence.DoesScaleMatter); // if we aren't already in the list of transition threads, add us now int i; for (i = 0; i < _transitionThreads.Count; i++) { if (ReferenceEquals(_transitionThreads[i], thread)) break; } if (i == _transitionThreads.Count) _transitionThreads.Add(thread); _UpdateTransitions(); }
/// <summary> /// Sets a sequence as the currently playing sequence. /// </summary> /// <param name="thread">The thread to play the sequence on.</param> /// <param name="seq">The sequence to play.</param> /// <param name="pos">The position to start the sequence at.</param> public void SetSequence(Thread thread, Sequence seq, float pos) { if ((thread._transitionData._inTransition && _transitionThreads.Count > 1) || _transitionThreads.Count > 0) { // if we have transitions, make sure transforms are up to date... _AnimateNodeSubtrees(true); } thread._SetSequence(seq, pos); _SetDirty(DirtyFlags.AllDirtyMask); if (_scaleCurrentlyAnimated && !thread.Sequence.IsScaleAnimated()) _CheckScaleCurrentlyAnimated(); else if (!_scaleCurrentlyAnimated && thread.Sequence.IsScaleAnimated()) _scaleCurrentlyAnimated = true; _UpdateTransitions(); }