void SetTimeToLengthTables(TweenPlugPath p, int subdivisions) { TweenPlugPathPoint prevP = _cachePoint1, currP = _cachePoint2; var ptCount = p.pathPointCount; float pathLen = 0; float incr = 1f / subdivisions; float[] timesTable = new float[subdivisions]; float[] lengthsTable = new float[subdivisions]; GetPoint(prevP, 0, p.wps, p); for (int i = 1; i < subdivisions + 1; ++i) { float perc = incr * i; GetPoint(currP, perc, p.wps, p); pathLen += TweenPlugPathPoint.Distance(currP, prevP, ptCount); prevP.Copy(currP, ptCount); timesTable[i - 1] = perc; lengthsTable[i - 1] = pathLen; } // Assign p.length = pathLen; p.timesTable = timesTable; p.lengthsTable = lengthsTable; }
public void FinalizePath(TweenPlugPath p, TweenPlugPathPoint[] wps, bool isClosedPath) { p.controlPoints = null; var subdivisions = (wps.Length) * p.subdivisionsXSegment; // Unused SetTimeToLengthTables(p, subdivisions); }
/// <summary> /// Only uses modes: TwoDimension*. Grab orientation by looking ahead of path, returns rotation (Z) in world space. /// </summary> public static float GetOrientation2D(OrientMode orientMode, Transform trans, TweenPlugPath path, float t) { var lookatPt = GetLookAhead(trans, t, path); if (trans.parent) { lookatPt = trans.parent.TransformPoint(lookatPt); } return(GetOrientation2D(orientMode, trans, lookatPt)); }
public void FinalizePath(TweenPlugPath p, TweenPlugPathPoint[] wps, bool isClosedPath) { // Add starting and ending control points (uses only one vector per control point) int wpsLen = wps.Length; if (p.controlPoints == null || p.controlPoints.Length != 2) { p.controlPoints = new TweenPlugPathControlPoint[2]; } if (isClosedPath) { p.controlPoints[0] = new TweenPlugPathControlPoint(wps[wpsLen - 2], _emptyPoint); p.controlPoints[1] = new TweenPlugPathControlPoint(wps[1], _emptyPoint); } else { p.controlPoints[0] = new TweenPlugPathControlPoint(wps[1], _emptyPoint); var lastP = wps[wpsLen - 1]; var lastP2 = wps[wpsLen - 2]; var newPt = new TweenPlugPathPoint(lastP.vals.Length); for (int i = 0; i < newPt.vals.Length; i++) { var lastPVal = lastP.vals[i]; var diffVVal = lastPVal - lastP2.vals[i]; newPt.vals[i] = lastPVal + diffVVal; } p.controlPoints[1] = new TweenPlugPathControlPoint(newPt, _emptyPoint); } // p.subdivisions = (wpsLen + 2) * p.subdivisionsXSegment; var subdivisions = wpsLen * p.subdivisionsXSegment; if (p.isConstantSpeed) { // Store time to len tables SetTimeToLengthTables(p, subdivisions); } else { //only generate path length SetPathLength(p, subdivisions); } }
private static Vector3 GetLookAhead(Transform trans, float t, TweenPlugPath path) { if (path.type == TweenPlugPathType.Linear) { // Calculate lookAhead so that it doesn't turn until it starts moving on next waypoint return(trans.localPosition + path.wps[path.linearWPIndex].valueVector3 - path.wps[path.linearWPIndex - 1].valueVector3); } else { float lookAheadPerc = t + lookAhead; if (lookAheadPerc > 1) { lookAheadPerc = (path.isClosed ? lookAheadPerc - 1 : path.type == TweenPlugPathType.Linear ? 1 : 1.00001f); } return(path.GetPoint(lookAheadPerc).valueVector3); } }
// Linear exception: also sets waypoints lengths and doesn't set lengthsTable since it's useless void SetTimeToLengthTables(TweenPlugPath p, int subdivisions) { float pathLen = 0; int wpsLen = p.wps.Length; var ptCount = p.pathPointCount; var prevP = p.wps[0]; for (int i = 1; i < wpsLen; i++) { var currP = p.wps[i]; float dist = TweenPlugPathPoint.Distance(currP, prevP, ptCount); pathLen += dist; prevP = currP; } // Assign p.length = pathLen; p.lengthsTable = null; p.timesTable = null; }
void SetPathLength(TweenPlugPath p, int subdivisions) { TweenPlugPathPoint prevP = _cachePoint1, currP = _cachePoint2; var ptCount = p.pathPointCount; float pathLen = 0; float incr = 1f / subdivisions; GetPoint(prevP, 0, p.wps, p); for (int i = 1; i < subdivisions + 1; ++i) { float perc = incr * i; GetPoint(currP, perc, p.wps, p); pathLen += TweenPlugPathPoint.Distance(currP, prevP, ptCount); prevP.Copy(currP, ptCount); } // Assign p.length = pathLen; p.timesTable = null; p.lengthsTable = null; }
public override float GetSpeedBasedDuration(TOptions options, float unitsXSecond, TweenPlugPath changeValue) { return(changeValue.length / unitsXSecond); }
public override void SetFrom(TweenerCore <T, TweenPlugPath, TOptions> t, TweenPlugPath fromValue, bool setImmediately, bool isRelative) { }
public override void EvaluateAndApply(TweenPlugPathOrientOptions options, Tween t, bool isRelative, DOGetter <Vector3> getter, DOSetter <Vector3> setter, float elapsed, TweenPlugPath startValue, TweenPlugPath changeValue, float duration, bool usingInversePosition, UpdateNotice updateNotice) { var path = changeValue; float pathPerc = EaseManager.Evaluate(t, elapsed, duration, t.easeOvershootOrAmplitude, t.easePeriod); var pathPt = path.GetPoint(pathPerc); var pt = pathPt.valueVector3; setter(pt); if (t.target != null) { SetOrientation(t.target, options, path, pathPerc); } }
public void GetPoint(TweenPlugPathPoint output, float perc, TweenPlugPathPoint[] wps, TweenPlugPath p) { int numSections = wps.Length - 1; // Considering also control points int tSec = (int)Mathf.Floor(perc * numSections); int currPt = numSections - 1; if (currPt > tSec) { currPt = tSec; } float u = perc * numSections - currPt; var aPt = currPt == 0 ? p.controlPoints[0].a : wps[currPt - 1]; var bPt = wps[currPt]; var cPt = wps[currPt + 1]; var dPt = currPt + 2 > wps.Length - 1 ? p.controlPoints[1].a : wps[currPt + 2]; var ptCount = p.pathPointCount; for (int i = 0; i < ptCount; i++) { float a = aPt.vals[i], b = bPt.vals[i], c = cPt.vals[i], d = dPt.vals[i]; output.vals[i] = .5f * ( (-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b); } }
public override void EvaluateAndApply(TOptions options, Tween t, bool isRelative, DOGetter <T> getter, DOSetter <T> setter, float elapsed, TweenPlugPath startValue, TweenPlugPath changeValue, float duration, bool usingInversePosition, UpdateNotice updateNotice) { //TODO: figure out how to access tween's loopType /*if(t.loopType == LoopType.Incremental && !changeValue.isClosed) { * int increment = (t.IsComplete() ? t.CompletedLoops() - 1 : t.CompletedLoops()); * if(increment > 0) changeValue = changeValue.CloneIncremental(increment); * }*/ float pathPerc = EaseManager.Evaluate(t, elapsed, duration, t.easeOvershootOrAmplitude, t.easePeriod); var pt = changeValue.GetPoint(pathPerc); var val = GetValue(pt); setter(val); }
// Clones this path with the given loop increment public TweenPlugPath CloneIncremental(int loopIncrement) { if (_incrementalClone != null) { if (_incrementalIndex == loopIncrement) { return(_incrementalClone); } } var _incCachePt = new TweenPlugPathPoint(pathPointCount); int wpsLen = wps.Length; int ptCount = pathPointCount; //diff for (int i = 0; i < ptCount; i++) { _incCachePt.vals[i] = wps[wpsLen - 1].vals[i] - wps[0].vals[i]; } var incrWps = new TweenPlugPathPoint[wps.Length]; for (int i = 0; i < wpsLen; ++i) { incrWps[i] = new TweenPlugPathPoint(ptCount); for (int j = 0; j < ptCount; j++) { incrWps[i].vals[j] = wps[i].vals[j] + (_incCachePt.vals[j] * loopIncrement); //wps[i] + (diff * loopIncrement) } } int cpsLen = controlPoints.Length; var incrCps = new TweenPlugPathControlPoint[cpsLen]; for (int i = 0; i < cpsLen; ++i) { var a = new TweenPlugPathPoint(ptCount); var b = new TweenPlugPathPoint(ptCount); //incrCps[i] = controlPoints[i] + (diff * loopIncrement); for (int j = 0; j < ptCount; j++) { a.vals[j] = controlPoints[i].a.vals[j] + (_incCachePt.vals[j] * loopIncrement); b.vals[j] = controlPoints[i].b.vals[j] + (_incCachePt.vals[j] * loopIncrement); } incrCps[i] = new TweenPlugPathControlPoint(a, b); } _incrementalClone = new TweenPlugPath(); _incrementalIndex = loopIncrement; _incrementalClone.type = type; _incrementalClone.subdivisionsXSegment = subdivisionsXSegment; _incrementalClone.wps = incrWps; _incrementalClone.controlPoints = incrCps; _incrementalClone._cachePoint = _incCachePt; _incrementalClone.length = length; _incrementalClone.timesTable = timesTable; _incrementalClone.lengthsTable = lengthsTable; _incrementalClone._decoder = _decoder; return(_incrementalClone); }
/// <summary> /// Grab orientation by looking ahead of path, returns rotation in world space. /// </summary> public static Quaternion GetOrientation(OrientMode orientMode, AxisFlags orientLockAxis, Transform trans, TweenPlugPath path, float t) { var lookatPt = GetLookAhead(trans, t, path); if (trans.parent) { lookatPt = trans.parent.TransformPoint(lookatPt); } return(GetOrientation(orientMode, orientLockAxis, trans, lookatPt)); }
protected override void SetOrientation(object target, TweenPlugPathOrientOptions options, TweenPlugPath path, float pathPerc) { var body = (Rigidbody2D)target; var trans = body.transform; var rot = TweenPlugOrient.GetOrientation2D(options.orientMode, trans, path, pathPerc); body.MoveRotation(rot); }
protected override void SetOrientation(object target, TweenPlugPathOrientOptions options, TweenPlugPath path, float pathPerc) { var trans = (Transform)target; trans.rotation = TweenPlugOrient.GetOrientation(options.orientMode, options.lockAxis, trans, path, pathPerc); }
protected abstract void SetOrientation(object target, TweenPlugPathOrientOptions options, TweenPlugPath path, float pathPerc);
/// <summary> /// Generate path points and endFrame. keyInd is the index of this key in the track. /// </summary> public void GeneratePath(Track track, int keyInd) { switch (interp) { case Interpolation.None: _paths = new TweenPlugPath[0]; endFrame = keyInd + 1 < track.keys.Count ? track.keys[keyInd + 1].frame : frame; break; case Interpolation.Linear: _paths = new TweenPlugPath[0]; if (keyInd + 1 < track.keys.Count) { var nextKey = track.keys[keyInd + 1]; endFrame = nextKey.frame; } else //fail-safe { endFrame = -1; } break; case Interpolation.Curve: //if there's more than 2 keys, and next key is curve, then it's more than 2 pts. if (keyInd + 2 < track.keys.Count && track.keys[keyInd + 1].interp == Interpolation.Curve) { var pathList = new List <TweenPlugPathPoint>(); var timeList = new List <float>(); for (int i = keyInd; i < track.keys.Count; i++) { var key = (PathKeyBase)track.keys[i]; pathList.Add(key.GeneratePathPoint(track)); endFrame = key.frame; if (!isConstSpeed) { timeList.Add(key.frame); } if (key.interp != Interpolation.Curve) { break; } } //normalize frames (exclude beginning (0f) and end (1f)) if (timeList.Count > 0) { //remove first and last timeList.RemoveAt(timeList.Count - 1); timeList.RemoveAt(0); float frameCount = endFrame - frame; if (frameCount > 0f) { for (int i = 0; i < timeList.Count; i++) { timeList[i] = (timeList[i] - frame) / frameCount; } } else //fail-safe { for (int i = 0; i < timeList.Count; i++) { timeList[i] = 0f; } } } var newPath = new TweenPlugPath(TweenPlugPathType.CatmullRom, pathList.ToArray(), timeList.ToArray(), isConstSpeed, pathResolution); newPath.Init(); _paths = new TweenPlugPath[] { newPath }; } else { if (keyInd + 1 < track.keys.Count) { endFrame = track.keys[keyInd + 1].frame; _paths = new TweenPlugPath[0]; } else { Invalidate(); } } break; } }
public void GetPoint(TweenPlugPathPoint output, float perc, TweenPlugPathPoint[] wps, TweenPlugPath p) { var ptCount = p.pathPointCount; if (perc <= 0) { p.linearWPIndex = 1; output.Copy(wps[0], ptCount); return; } int startPIndex = 0; int endPIndex = 0; int count = p.timesTable.Length; for (int i = 1; i < count; i++) { if (p.timesTable[i] >= perc) { startPIndex = i - 1; endPIndex = i; break; } } float startPPerc = p.timesTable[startPIndex]; float partialPerc = perc - startPPerc; float partialLen = p.length * partialPerc; var wp0 = wps[startPIndex]; var wp1 = wps[endPIndex]; p.linearWPIndex = endPIndex; //output = wp0 + clamp(wp1 - wp0, partialLen) for (int i = 0; i < ptCount; i++) { output.vals[i] = wp1.vals[i] - wp0.vals[i]; } output.ClampMagnitude(partialLen, ptCount); for (int i = 0; i < ptCount; i++) { output.vals[i] += wp0.vals[i]; } }