/// <summary> /// Add a new blended animation, that will keep playing until you remove it or it /// completes. The animation must have been created with CreateBlendedAnimation() /// or CreateComposedAnimation(). /// </summary> /// <param name="nu">The animation to start blending.</param> /// <param name="weight">The relative weight of this animation, compared to other /// blended animations.</param> public void AddAnimation(IBlendedAnimation nu, float weight) { BlendedAnimation ba = (BlendedAnimation)nu; if (nu.BlendType == BlendType.NormalizedBlend) { blendedAnimations_.Add(ba); } else { composedAnimations_.Add(ba); } ba.Attach(this); nu.Weight = weight; }
internal void RemoveAnimation(BlendedAnimation anim) { System.Diagnostics.Debug.Assert(!inAdvance_); System.Diagnostics.Debug.Assert( (anim.BlendType == BlendType.NormalizedBlend && blendedAnimations_.Contains(anim)) || (anim.BlendType == BlendType.Compose && composedAnimations_.Contains(anim))); if (anim.BlendType == BlendType.NormalizedBlend) { blendedAnimations_.Remove(anim); } else { composedAnimations_.Remove(anim); } unchecked { for (int ti = 0, tn = transitions_.Count; ti != tn; ++ti) { transitions_[ti].OnRemove(anim); } } }
/// <summary> /// Advance all attached animations by a given amount of time. /// </summary> /// <param name="dt">How much to advance animations by.</param> public void Advance(float dt) { dirty_ = true; try { unchecked { // update transitions for (int ti = 0, tn = transitions_.Count; ti != tn; ++ti) { if (transitions_[ti].Update(dt)) { transitions_.RemoveAt(ti); --ti; --tn; } } inAdvance_ = true; // update blends float runningWeight = 0; for (int bi = 0, bn = blendedAnimations_.Count; bi != bn; ++bi) { BlendedAnimation ba = blendedAnimations_[bi]; ba.Instance.Advance(dt); float wt = ba.Weight; if (wt == 0) { continue; } Keyframe[] kfs = ba.Instance.CurrentPose; if (runningWeight == 0) { runningWeight = Math.Abs(wt); for (int i = 0, n = Math.Min(kfs.Length, keyframes_.Length); i != n; ++i) { Keyframe k = kfs[i]; if (k != null) { keyframes_[i].CopyFrom(k); } } } else { runningWeight += Math.Abs(wt); float t = wt / runningWeight; for (int i = 0, n = Math.Min(kfs.Length, keyframes_.Length); i != n; ++i) { Keyframe k = kfs[i]; Keyframe d = keyframes_[i]; if (k != null) { Keyframe.Interpolate(d, k, wt, d); } } } } // update composes // TODO: sort from smallest to biggest weight? for (int ci = 0, cn = composedAnimations_.Count; ci != cn; ++ci) { BlendedAnimation ca = composedAnimations_[ci]; ca.Instance.Advance(dt); float w = ca.Weight; if (w == 0) { continue; } Keyframe[] kfs = ca.Instance.CurrentPose; for (int i = 0, n = Math.Min(kfs.Length, keyframes_.Length); i != n; ++i) { Keyframe k = kfs[i]; Keyframe d = keyframes_[i]; if (k != null) { Keyframe.Compose(d, k, w, workItem_); d.CopyFrom(workItem_); } } } } } finally { inAdvance_ = false; } }
internal void RemoveAnimation(BlendedAnimation anim) { System.Diagnostics.Debug.Assert(!inAdvance_); System.Diagnostics.Debug.Assert( (anim.BlendType == BlendType.NormalizedBlend && blendedAnimations_.Contains(anim)) || (anim.BlendType == BlendType.Compose && composedAnimations_.Contains(anim))); if (anim.BlendType == BlendType.NormalizedBlend) blendedAnimations_.Remove(anim); else composedAnimations_.Remove(anim); unchecked { for (int ti = 0, tn = transitions_.Count; ti != tn; ++ti) transitions_[ti].OnRemove(anim); } }