// add a new key public void addKey(ITarget itarget, int _frame, Vector3 _position, Key.Interpolation _interp, Ease _easeType) { foreach (TranslationKey key in keys) { // if key exists on frame, update key if (key.frame == _frame) { key.position = _position; key.interp = _interp; key.easeType = _easeType; // update cache updateCache(itarget); return; } } TranslationKey a = new TranslationKey(); a.frame = _frame; a.position = _position; a.interp = _interp; a.easeType = _easeType; // add a new key keys.Add(a); // update cache updateCache(itarget); }
public static PathData GenerateLinear(List <Key> keys, int _startIndex) { PathData newPath = new PathData(); // sort the keys by frame List <Vector3> _path = new List <Vector3>(); newPath.startIndex = _startIndex; newPath.endIndex = _startIndex; newPath.endFrame = keys[_startIndex].frame; _path.Add((keys[_startIndex] as TranslationKey).position); int nextIndex = _startIndex + 1; if (nextIndex < keys.Count) { TranslationKey key = keys[nextIndex] as TranslationKey; _path.Add(key.position); newPath.endFrame = keys[nextIndex].frame; newPath.endIndex = nextIndex; } newPath.interp = Key.Interpolation.Linear; newPath.path = _path.ToArray(); return(newPath); }
public int endIndex; // ending key index public static PathData GenerateCurve(List <Key> keys, int _startIndex) { PathData newPath = new PathData(); // sort the keys by frame List <Vector3> _path = new List <Vector3>(); newPath.startIndex = _startIndex; newPath.endIndex = _startIndex; newPath.endFrame = keys[_startIndex].frame; _path.Add((keys[_startIndex] as TranslationKey).position); // get path from startIndex until the next linear interpolation key (inclusive) for (int i = _startIndex + 1; i < keys.Count; i++) { TranslationKey key = keys[i] as TranslationKey; _path.Add(key.position); newPath.endFrame = keys[i].frame; newPath.endIndex = i; if (!keys[_startIndex].canTween || key.interp != Key.Interpolation.Curve) { break; } } newPath.interp = Key.Interpolation.Curve; newPath.path = _path.ToArray(); return(newPath); }
// copy properties from key public override void CopyTo(Key key) { base.CopyTo(key); TranslationKey a = key as TranslationKey; a.position = position; a.isConstSpeed = isConstSpeed; }
// copy properties from key public override void CopyTo(Key key) { base.CopyTo(key); TranslationKey a = (TranslationKey)key; a.position = position; a.orientMode = orientMode; a.orientLockAxis = orientLockAxis; }
public void DrawGizmos(TranslationKey nextKey, Transform transform, float ptSize) { Matrix4x4 mtx = transform.parent ? transform.parent.localToWorldMatrix : Matrix4x4.identity; if (interp == Interpolation.None) { Gizmos.color = Color.green; Gizmos.DrawSphere(mtx.MultiplyPoint3x4(position), ptSize); } else if (interp == Interpolation.Linear || path == null) { if (nextKey == null) { Gizmos.color = Color.green; Gizmos.DrawSphere(mtx.MultiplyPoint3x4(position), ptSize); } else { Vector3 pt1 = mtx.MultiplyPoint3x4(position), pt2 = mtx.MultiplyPoint3x4(nextKey.position); Gizmos.color = new Color(0.6f, 0.6f, 0.6f, 0.6f); Gizmos.DrawLine(pt1, pt2); Gizmos.color = Color.green; Gizmos.DrawSphere(pt1, ptSize); Gizmos.DrawSphere(pt2, ptSize); } } else if (interp == Interpolation.Curve) { Gizmos.color = new Color(0.6f, 0.6f, 0.6f, 0.6f); int subdivisions = pathResolution * keyCount; for (int i = 0; i < subdivisions; i++) { var pt = path.GetPoint(i / (float)subdivisions); var pt1 = pt.valueVector3; pt = path.GetPoint((i + 1) / (float)subdivisions); var pt2 = pt.valueVector3; Gizmos.DrawLine(mtx.MultiplyPoint3x4(pt1), mtx.MultiplyPoint3x4(pt2)); } Gizmos.color = Color.green; for (int i = 0; i < path.wps.Length; i++) { Gizmos.DrawSphere(mtx.MultiplyPoint3x4(path.wps[i].valueVector3), ptSize); } } }
// add a new key, default interpolation and easeType public void addKey(ITarget itarget, int _frame, Vector3 _position) { TranslationKey prevKey = null; foreach (TranslationKey key in keys) { // if key exists on frame, update key if (key.frame == _frame) { key.position = _position; // update cache updateCache(itarget); return; } else if (key.frame < _frame) { prevKey = key; } } TranslationKey a = new TranslationKey(); a.frame = _frame; a.position = _position; // copy interpolation and ease type from previous if (prevKey != null) { a.interp = prevKey.interp; a.easeType = prevKey.easeType; a.easeCurve = prevKey.easeCurve; a.isConstSpeed = prevKey.isConstSpeed; a.orientMode = prevKey.orientMode; a.orientLockAxis = prevKey.orientLockAxis; } // add a new key keys.Add(a); // update cache updateCache(itarget); }
// update cache (optimized) public override void updateCache(ITarget target) { base.updateCache(target); // get all paths and add them to the action list for (int i = 0; i < keys.Count; i++) { TranslationKey key = keys[i] as TranslationKey; var interp = key.interp; var easeType = key.easeType; var isConstSpeed = key.isConstSpeed; var orientMode = key.orientMode; var lockAxis = key.orientLockAxis; 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 TranslationKey; _key.interp = interp; _key.easeType = easeType; _key.isConstSpeed = isConstSpeed; _key.orientMode = orientMode; _key.orientLockAxis = lockAxis; _key.Invalidate(); } i = endInd; } } }
// update cache (optimized) public override void updateCache(ITarget target) { base.updateCache(target); // get all paths and add them to the action list for (int i = 0; i < keys.Count; i++) { TranslationKey key = keys[i] as TranslationKey; var interp = key.interp; var easeType = key.easeType; key.version = version; key.GeneratePath(this, i); key.ClearCache(); //invalidate some keys in between if (key.path.Length > 1) { int endInd = i + key.path.Length - 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++) { key = keys[j] as TranslationKey; key.version = version; key.interp = interp; key.easeType = easeType; key.endFrame = key.frame; key.path = new Vector3[0]; } i = endInd; } } }
// add a new key, default interpolation and easeType public void addKey(ITarget itarget, int _frame, Vector3 _position) { foreach (TranslationKey key in keys) { // if key exists on frame, update key if (key.frame == _frame) { key.position = _position; // update cache updateCache(itarget); return; } } TranslationKey a = new TranslationKey(); a.frame = _frame; a.position = _position; // add a new key keys.Add(a); // update cache updateCache(itarget); }
public Vector3 getPositionAtFrame(Transform t, float frame, int frameRate, bool forceWorld) { int keyCount = keys.Count; if (keyCount <= 0) { return(GetPosition(t)); } int iFrame = Mathf.RoundToInt(frame); TranslationKey firstKey = keys[0] as TranslationKey; //check if only key or behind first key if (keyCount == 1 || iFrame <= firstKey.frame) { return(convertPosition(t, firstKey.position, forceWorld)); } //check in-between for (int i = 0; i < keyCount; i++) { TranslationKey key = keys[i] as TranslationKey; if (key.canTween && key.path.Length <= 1) //invalid { continue; } if (iFrame >= key.endFrame) { if (key.path.Length > 0 && i + key.path.Length == keyCount) //end of last path in track? { return(convertPosition(t, key.path[key.path.Length - 1], forceWorld)); } else if (i + 1 == keyCount) //last non-tween key in track? { return(convertPosition(t, key.position, forceWorld)); } else { continue; } } if (!key.canTween) { return(convertPosition(t, key.position, forceWorld)); } else if (key.path.Length <= 1) //invalid key { return(GetPosition(t)); } float _value = Mathf.Clamp01((frame - key.frame) / key.getNumberOfFrames(frameRate)); return(convertPosition(t, key.GetPoint(t, frameRate, Mathf.Clamp01(_value)), forceWorld)); } return(GetPosition(t)); //last key is impartial tween }
// update cache (optimized) public override void updateCache(ITarget target) { base.updateCache(target); // get all paths and add them to the action list for (int i = 0; i < keys.Count; i++) { TranslationKey key = keys[i] as TranslationKey; var interp = key.interp; var easeType = key.easeType; key.version = version; PathData path; switch (key.interp) { case Key.Interpolation.Curve: path = PathData.GenerateCurve(keys, i); break; case Key.Interpolation.Linear: path = PathData.GenerateLinear(keys, i); break; default: int singleEndFrame = i < keys.Count - 1 ? keys[i + 1].frame : keys[i].frame; path = PathData.GenerateSingle(keys[i], i, singleEndFrame); break; } key.endFrame = path.endFrame; key.pathPreview = null; if (!key.canTween) { if (path.endIndex == keys.Count - 1) { TranslationKey lastKey = keys[path.endIndex] as TranslationKey; lastKey.interp = Key.Interpolation.None; lastKey.endFrame = lastKey.frame; lastKey.path = new Vector3[0]; } } else { key.path = path.path; } //invalidate some keys in between if (path.startIndex < keys.Count - 1) { int _endInd = path.endIndex; if (_endInd < keys.Count - 1) { _endInd--; } if (i < _endInd) { for (i = path.startIndex + 1; i <= _endInd; i++) { key = keys[i] as TranslationKey; key.version = version; key.interp = interp; key.easeType = easeType; key.endFrame = key.frame; key.path = new Vector3[0]; } i = _endInd; } } } }
public Vector3 getPositionAtFrame(Transform t, int frame, int frameRate, bool forceWorld) { int keyCount = keys.Count; if (keyCount <= 0) { return(GetPosition(t)); } TranslationKey firstKey = keys[0] as TranslationKey; //check if behind first key if (frame <= firstKey.frame && (!firstKey.canTween || firstKey.path.Length == 1)) { return(convertPosition(t, firstKey.position, forceWorld)); } TranslationKey lastKey = keyCount == 1 ? firstKey : keys[keyCount - 1] as TranslationKey; //check if past last key if (frame >= lastKey.endFrame && !lastKey.canTween) { return(convertPosition(t, lastKey.position, forceWorld)); } //check in-between for (int i = 0; i < keyCount; i++) { TranslationKey key = keys[i] as TranslationKey; TranslationKey keyNext = i < keyCount - 1 ? keys[i + 1] as TranslationKey : null; if (frame >= key.endFrame && keyNext != null && (!keyNext.canTween || keyNext.path.Length > 1)) { continue; } if (!key.canTween || key.path.Length == 1) { return(convertPosition(t, key.position, forceWorld)); } else if (key.path.Length == 0) { continue; } float fNumFrames = (float)key.getNumberOfFrames(frameRate); float _value; float framePositionInPath = Mathf.Clamp(frame - (float)key.frame, 0f, fNumFrames); if (key.hasCustomEase()) { _value = Utility.EaseCustom(0.0f, 1.0f, framePositionInPath / fNumFrames, key.easeCurve); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); _value = ease(framePositionInPath, fNumFrames, key.amplitude, key.period); if (float.IsNaN(_value)) //this really shouldn't happen... { break; } } return(convertPosition(t, key.GetPoint(Mathf.Clamp01(_value)), forceWorld)); } Debug.LogError("Animator: Could not get " + t.name + " position at frame '" + frame + "'"); return(GetPosition(t)); }
// preview a frame in the scene view public override void previewFrame(ITarget itarget, float frame, int frameRate, bool play, float playSpeed) { Transform t = GetTarget(itarget) as Transform; if (!t) { return; } int keyCount = keys.Count; if (keys == null || keyCount <= 0) { return; } int iFrame = Mathf.RoundToInt(frame); TranslationKey firstKey = keys[0] as TranslationKey; //check if behind first key if (iFrame <= firstKey.frame && (!firstKey.canTween || firstKey.path.Length == 1)) { SetPosition(t, firstKey.position); return; } TranslationKey lastKey = keyCount == 1 ? firstKey : keys[keyCount - 1] as TranslationKey; //check if past last key if (iFrame >= lastKey.endFrame) { SetPosition(t, lastKey.position); return; } //check in-between for (int i = 0; i < keyCount; i++) { TranslationKey key = keys[i] as TranslationKey; if (key.path == null) { continue; } if (iFrame >= key.endFrame && i < keyCount - 1) { continue; } if ((!key.canTween || key.path.Length <= 1)) { SetPosition(t, key.position); return; } float fNumFrames = (float)key.getNumberOfFrames(frameRate); float _value; float framePositionInPath = Mathf.Clamp(frame - (float)key.frame, 0f, fNumFrames); if (key.hasCustomEase()) { _value = Utility.EaseCustom(0.0f, 1.0f, framePositionInPath / fNumFrames, key.easeCurve); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); _value = ease(framePositionInPath, fNumFrames, key.amplitude, key.period); if (float.IsNaN(_value)) //this really shouldn't happen... { return; } } SetPosition(t, key.GetPoint(Mathf.Clamp01(_value))); return; } }
public Vector3 getPositionAtFrame(Transform t, float frame, int frameRate, bool forceWorld) { int keyCount = keys.Count; if (keyCount <= 0) { return(GetPosition(t)); } int iFrame = Mathf.RoundToInt(frame); TranslationKey firstKey = keys[0] as TranslationKey; //check if only key or behind first key if (keyCount == 1 || iFrame <= firstKey.frame) { return(convertPosition(t, firstKey.position, forceWorld)); } //check in-between for (int i = 0; i < keyCount; i++) { TranslationKey key = keys[i] as TranslationKey; 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(convertPosition(t, key.position, forceWorld)); } } else if (key.interp == Key.Interpolation.Linear || key.path == null) { if (i + 1 == keyCount - 1) { var pt = ((TranslationKey)keys[i + 1]).position; return(convertPosition(t, pt, forceWorld)); } } else if (key.interp == Key.Interpolation.Curve) { if (i + key.keyCount == keyCount) //end of last path in track? { return(convertPosition(t, ((TranslationKey)keys[i + key.keyCount - 1]).position, forceWorld)); } } continue; } if (key.interp == Key.Interpolation.None) { return(convertPosition(t, key.position, forceWorld)); } else if (key.interp == Key.Interpolation.Linear || key.path == null) { var keyNext = keys[i + 1] as TranslationKey; float numFrames = (float)key.getNumberOfFrames(frameRate); float framePositionInAction = Mathf.Clamp(frame - (float)key.frame, 0f, numFrames); var start = key.position; var end = keyNext.position; if (key.hasCustomEase()) { return(convertPosition(t, Vector3.Lerp(start, end, Utility.EaseCustom(0.0f, 1.0f, framePositionInAction / numFrames, key.easeCurve)), forceWorld)); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); return(convertPosition(t, Vector3.Lerp(start, end, ease(framePositionInAction, numFrames, key.amplitude, key.period)), forceWorld)); } } else { float _value = Mathf.Clamp01((frame - key.frame) / key.getNumberOfFrames(frameRate)); var pt = key.GetPoint(_value); return(convertPosition(t, pt, forceWorld)); } } return(GetPosition(t)); //last key is impartial tween }
// preview a frame in the scene view public override void previewFrame(ITarget itarget, float frame, int frameRate, bool play, float playSpeed) { Transform t = GetTarget(itarget) as Transform; if (!t) { return; } int keyCount = keys.Count; if (keyCount <= 0) { return; } int iFrame = Mathf.RoundToInt(frame); TranslationKey firstKey = keys[0] as TranslationKey; //check if only key or behind first key if (keyCount == 1 || iFrame < firstKey.frame) { t.localPosition = convertPosition(t, firstKey.position, false); return; } else if (iFrame == firstKey.frame) { if (firstKey.interp == Key.Interpolation.Linear || firstKey.path == null) //apply orientation { t.localPosition = convertPosition(t, firstKey.position, false); if (firstKey.orientMode != OrientMode.None) { var nextPt = ((TranslationKey)keys[1]).position; if (t.parent) { nextPt = t.parent.TransformPoint(nextPt); } t.rotation = firstKey.GetOrientation(t, nextPt); } } else if (firstKey.interp == Key.Interpolation.Curve) //apply orientation { t.localPosition = convertPosition(t, firstKey.position, false); if (firstKey.orientMode != OrientMode.None) { t.rotation = firstKey.GetOrientation(t, 0f); } } else { t.localPosition = convertPosition(t, firstKey.position, false); } return; } //check in-between for (int i = 0; i < keyCount; i++) { TranslationKey key = keys[i] as TranslationKey; 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) { t.localPosition = convertPosition(t, key.position, false); return; } } else if (key.interp == Key.Interpolation.Linear || key.path == null) { if (i + 1 == keyCount - 1) { var pt = ((TranslationKey)keys[i + 1]).position; t.localPosition = convertPosition(t, pt, false); if (key.orientMode != OrientMode.None && iFrame == key.endFrame) //only apply rotation if we are at end of frame { Vector3 ptW, prevPtW; if (t.parent) { ptW = t.parent.TransformPoint(pt); prevPtW = t.parent.TransformPoint(key.position); } else { ptW = pt; prevPtW = key.position; } var dir = (ptW - prevPtW).normalized; t.rotation = key.GetOrientation(t, ptW + dir); } return; } } else if (key.interp == Key.Interpolation.Curve) { if (i + key.keyCount == keyCount) //end of last path in track? { t.localPosition = convertPosition(t, ((TranslationKey)keys[i + key.keyCount - 1]).position, false); if (key.orientMode != OrientMode.None && iFrame == key.endFrame) //only apply rotation if we are at end of frame { t.rotation = key.GetOrientation(t, 1f); } return; } } continue; } if (key.interp == Key.Interpolation.None) { t.localPosition = convertPosition(t, key.position, false); } else if (key.interp == Key.Interpolation.Linear || key.path == null) { var keyNext = keys[i + 1] as TranslationKey; float numFrames = (float)key.getNumberOfFrames(frameRate); float framePositionInAction = Mathf.Clamp(frame - (float)key.frame, 0f, numFrames); var start = key.position; var end = keyNext.position; if (key.hasCustomEase()) { t.localPosition = convertPosition(t, Vector3.Lerp(start, end, Utility.EaseCustom(0.0f, 1.0f, framePositionInAction / numFrames, key.easeCurve)), false); } else { var ease = Utility.GetEasingFunction((Ease)key.easeType); t.localPosition = convertPosition(t, Vector3.Lerp(start, end, ease(framePositionInAction, numFrames, key.amplitude, key.period)), false); } if (key.orientMode != OrientMode.None) { t.rotation = key.GetOrientation(t, t.parent ? t.parent.TransformPoint(end) : end); } } else { float _value = Mathf.Clamp01((frame - key.frame) / key.getNumberOfFrames(frameRate)); var pt = key.GetPoint(_value); t.localPosition = convertPosition(t, pt, false); if (key.orientMode != OrientMode.None) { t.rotation = key.GetOrientation(t, _value); } } return; } //var lpos = getPositionAtFrame(t, frame, frameRate, false); //t.localPosition = lpos; }