// update cache (optimized) public override void updateCache(ITarget target) { base.updateCache(target); for (int i = 0; i < keys.Count; i++) { RotationKey key = keys[i] as RotationKey; key.version = version; //a.type = (keys[i] as RotationKey).type; if (keys.Count > (i + 1)) { key.endFrame = keys[i + 1].frame; } else { if (i > 0 && !keys[i - 1].canTween) { key.interp = Key.Interpolation.None; } key.endFrame = -1; } } }
// update cache (optimized) public override void updateCache(ITarget target) { base.updateCache(target); for (int i = 0; i < keys.Count; i++) { RotationKey key = keys[i] as RotationKey; key.GeneratePath(this, i); //invalidate some keys in between if (key.path != null) { int endInd = i + key.keyCount - 1; if (endInd < keys.Count - 1 || key.interp != keys[endInd].interp) //don't count the last element if there are more keys ahead { endInd--; } for (int j = i + 1; j <= endInd; j++) { var _key = keys[j] as RotationKey; _key.interp = key.interp; _key.easeType = key.easeType; _key.Invalidate(); } i = endInd; } } }
// add a new key public void addKey(ITarget target, int _frame, Quaternion _rotation) { foreach (RotationKey key in keys) { // if key exists on frame, update key if (key.frame == _frame) { key.rotation = _rotation; // update cache updateCache(target); return; } } RotationKey a = new RotationKey(); a.frame = _frame; a.rotation = _rotation; // set default ease type to linear a.easeType = Ease.Linear; // add a new key keys.Add(a); // update cache updateCache(target); }
// copy properties from key public override void CopyTo(Key key) { base.CopyTo(key); RotationKey a = key as RotationKey; //a.type = type; a.rotation = rotation; }
Quaternion getRotationAtFrame(int frame, int frameRate) { // if before or equal to first frame, or is the only frame RotationKey firstKey = keys[0] as RotationKey; if (firstKey.endFrame == -1 || (frame <= (float)firstKey.frame && !firstKey.canTween)) { return(firstKey.rotation); } // if lies on rotation action for (int i = 0; i < keys.Count; i++) { RotationKey key = keys[i] as RotationKey; RotationKey keyNext = i + 1 < keys.Count ? keys[i + 1] as RotationKey : null; if (frame >= (float)key.endFrame && keyNext != null && (!keyNext.canTween || keyNext.endFrame != -1)) { continue; } // if no ease if (!key.canTween || keyNext == null) { return(key.rotation); } // else find Quaternion using easing function float numFrames = (float)key.getNumberOfFrames(frameRate); float framePositionInAction = Mathf.Clamp(frame - (float)key.frame, 0f, numFrames); Quaternion qStart = key.rotation; Quaternion qEnd = keyNext.rotation; if (key.hasCustomEase()) { return(Quaternion.LerpUnclamped(qStart, qEnd, Utility.EaseCustom(0.0f, 1.0f, framePositionInAction / numFrames, key.easeCurve))); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); return(Quaternion.LerpUnclamped(qStart, qEnd, ease(framePositionInAction, numFrames, key.amplitude, key.period))); } } Debug.LogError("Animator: Could not get rotation at frame '" + frame + "'"); return(Quaternion.identity); }
// add a new key public void addKey(ITarget target, int _frame, Quaternion _rotation) { RotationKey prevKey = null; foreach (RotationKey key in keys) { // if key exists on frame, update key if (key.frame == _frame) { key.rotation = _rotation; // update cache updateCache(target); return; } else if (key.frame < _frame) { prevKey = key; } } RotationKey a = new RotationKey(); a.frame = _frame; a.rotation = _rotation; // copy interpolation and ease type from previous if (prevKey != null) { a.interp = prevKey.interp; a.easeType = prevKey.easeType; a.easeCurve = prevKey.easeCurve; } else { // set default a.interp = Key.Interpolation.Curve; a.easeType = Ease.Linear; } // add a new key keys.Add(a); // update cache updateCache(target); }
Quaternion getRotationAtFrame(Transform transform, float frame, int frameRate) { int keyCount = keys.Count; if (keyCount <= 0) { return(transform.localRotation); } int iFrame = Mathf.RoundToInt(frame); var firstKey = keys[0] as RotationKey; //check if only key or behind first key if (keyCount == 1 || iFrame <= firstKey.frame) { return(firstKey.rotation); } // if lies on rotation action for (int i = 0; i < keyCount; i++) { RotationKey key = keys[i] as RotationKey; if (key.endFrame == -1) //invalid { continue; } //end of last path in track? if (iFrame >= key.endFrame) { if (key.interp == Key.Interpolation.None) { if (i + 1 == keyCount) { return(key.rotation); } } else if (key.interp == Key.Interpolation.Linear || key.path == null) { if (i + 1 == keyCount - 1) { return(((RotationKey)keys[i + 1]).rotation); } } else if (key.interp == Key.Interpolation.Curve) { if (i + key.keyCount == keyCount) //end of last path in track? { return(((RotationKey)keys[i + key.keyCount - 1]).rotation); } } continue; } if (key.interp == Key.Interpolation.None) { return(key.rotation); } else if (key.interp == Key.Interpolation.Linear || key.path == null) { RotationKey keyNext = keys[i + 1] as RotationKey; float numFrames = (float)key.getNumberOfFrames(frameRate); float framePositionInAction = Mathf.Clamp(frame - (float)key.frame, 0f, numFrames); Quaternion qStart = key.rotation; Quaternion qEnd = keyNext.rotation; if (key.hasCustomEase()) { return(Quaternion.LerpUnclamped(qStart, qEnd, Utility.EaseCustom(0.0f, 1.0f, framePositionInAction / numFrames, key.easeCurve))); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); return(Quaternion.LerpUnclamped(qStart, qEnd, ease(framePositionInAction, numFrames, key.amplitude, key.period))); } } else { float _value = Mathf.Clamp01((frame - key.frame) / key.getNumberOfFrames(frameRate)); return(key.GetRotationFromPath(Mathf.Clamp01(_value))); } } return(transform.localRotation); }
// preview a frame in the scene view public override void previewFrame(ITarget target, float frame, int frameRate, bool play, float playSpeed) { Transform t = GetTarget(target) as Transform; int keyCount = keys.Count; if (!t) { return; } if (keys == null || keyCount <= 0) { return; } // if before or equal to first frame, or is the only frame RotationKey firstKey = keys[0] as RotationKey; if (firstKey.endFrame == -1 || (frame <= (float)firstKey.frame && !firstKey.canTween)) { t.localRotation = firstKey.rotation; return; } // if lies on rotation action for (int i = 0; i < keys.Count; i++) { RotationKey key = keys[i] as RotationKey; RotationKey keyNext = i + 1 < keys.Count ? keys[i + 1] as RotationKey : null; if (frame >= (float)key.endFrame && keyNext != null && (!keyNext.canTween || keyNext.endFrame != -1)) { continue; } // if no ease if (!key.canTween || keyNext == null) { t.localRotation = key.rotation; return; } // else find Quaternion using easing function float numFrames = (float)key.getNumberOfFrames(frameRate); float framePositionInAction = Mathf.Clamp(frame - (float)key.frame, 0f, numFrames); Quaternion qStart = key.rotation; Quaternion qEnd = keyNext.rotation; if (key.hasCustomEase()) { t.localRotation = Quaternion.LerpUnclamped(qStart, qEnd, Utility.EaseCustom(0.0f, 1.0f, framePositionInAction / numFrames, key.easeCurve)); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); t.localRotation = Quaternion.LerpUnclamped(qStart, qEnd, ease(framePositionInAction, numFrames, key.amplitude, key.period)); } return; } }