private static void DeserializeCurveFromClassLegacy(BezierAnimationCurve curve, JSONNode curveJSON)
        {
            var keysJSON = curveJSON["keys"].AsArray;

            if (keysJSON.Count == 0)
            {
                return;
            }

            var last = -1f;

            foreach (JSONNode keyframeJSON in keysJSON)
            {
                var time = DeserializeFloat(keyframeJSON["time"]).Snap();
                if (time == last)
                {
                    continue;
                }
                last = time;
                var value    = DeserializeFloat(keyframeJSON["value"]);
                var keyframe = new BezierKeyframe(
                    time,
                    value,
                    CurveTypeValues.SmoothLocal
                    );
                curve.AddKey(keyframe);
            }
        }
 private static void SmoothLocalInterpolation(BezierKeyframe previous, float previousTime, ref BezierKeyframe current, BezierKeyframe next, float nextTime)
 {
     if (next.HasValue() && previous.HasValue())
     {
         var inHandle             = (current.value - previous.value) / 3f;
         var outHandle            = (next.value - current.value) / 3f;
         var bothSegmentsDuration = nextTime - previousTime;
         var inRatio  = (current.time - previousTime) / bothSegmentsDuration;
         var outRatio = (nextTime - current.time) / bothSegmentsDuration;
         var avg      = inHandle * inRatio + outHandle * outRatio;
         if (inRatio > outRatio)
         {
             current.controlPointIn  = current.value - avg;
             current.controlPointOut = current.value + avg * outRatio;
         }
         else
         {
             current.controlPointIn  = current.value - avg * inRatio;
             current.controlPointOut = current.value + avg;
         }
     }
     else if (previous.IsNull())
     {
         current.controlPointIn  = current.value;
         current.controlPointOut = current.value + (next.value - current.value) / 3f;
     }
     else if (next.IsNull())
     {
         current.controlPointIn  = current.value - (current.value - previous.value) / 3f;
         current.controlPointOut = current.value;
     }
 }
        public static float ComputeValue(BezierKeyframe current, BezierKeyframe next, float time)
        {
            if (next.IsNull())
            {
                return(current.value);
            }
            var t = (time - current.time) / (next.time - current.time);

            switch (current.curveType)
            {
            case CurveTypeValues.Constant:
                return(current.value);

            case CurveTypeValues.Linear:
            case CurveTypeValues.FlatLinear:
            {
                return(current.value + (next.value - current.value) * t);
            }
            }

            var w0 = current.value;
            var w1 = current.controlPointOut;
            var w2 = next.controlPointIn;
            var w3 = next.value;

            // See https://pomax.github.io/bezierinfo/#how-to-implement-the-weighted-basis-function
            var mt  = 1f - t;
            var mt2 = mt * mt;
            var mt3 = mt2 * mt;
            var t2  = t * t;
            var t3  = t2 * t;

            return(w0 * mt3 + 3f * w1 * mt2 * t + 3f * w2 * mt * t2 + w3 * t3);
        }
        public int AddKey(BezierKeyframe keyframe)
        {
            if (keyframe.time > duration)
            {
                keys.Add(keyframe);
                return(_lastReferencedKey = keys.Count - 1);
            }

            var nearestKey      = KeyframeBinarySearch(keyframe.time, true);
            var nearestKeyframe = keys[nearestKey];

            if (Mathf.Abs(nearestKeyframe.time - keyframe.time) < _epsilon)
            {
                return(-1);
            }
            if (nearestKeyframe.time < keyframe.time)
            {
                var key = nearestKey + 1;
                keys.Insert(key, keyframe);
                _lastReferencedKey = key;
                return(key);
            }
            keys.Insert(nearestKey, keyframe);
            _lastReferencedKey = nearestKey;
            return(nearestKey);
        }
Beispiel #5
0
        private static void SmoothLocalInterpolation(BezierKeyframe previous, float previousTime, ref BezierKeyframe current, BezierKeyframe next, float nextTime)
        {
            if (next.HasValue() && previous.HasValue())
            {
                var inHandle             = (current.value - previous.value) / 3f;
                var outHandle            = (next.value - current.value) / 3f;
                var bothSegmentsDuration = nextTime - previousTime;
                var inRatio  = (current.time - previousTime) / bothSegmentsDuration;
                var outRatio = (nextTime - current.time) / bothSegmentsDuration;

                /* // SMOOTH
                 * // The larger the incoming curve, the weaker the effect on the other side
                 * var weightedAvg = inHandle * outRatio + outHandle * inRatio;
                 * if (inRatio > outRatio)
                 * {
                 *  current.controlPointIn = current.value - weightedAvg * (inRatio / outRatio);
                 *  current.controlPointOut = current.value + weightedAvg;
                 * }
                 * else
                 * {
                 *  current.controlPointIn = current.value - weightedAvg;
                 *  current.controlPointOut = current.value + weightedAvg * (outRatio / inRatio);
                 * }
                 */
                // NO_OVERSHOOT
                // The larger the incoming curve, the stronger the effect on the other side
                var weightedAvg = inHandle * inRatio + outHandle * outRatio;
                if (inRatio > outRatio)
                {
                    current.controlPointIn  = current.value - weightedAvg;
                    current.controlPointOut = current.value + weightedAvg * (outRatio / inRatio);
                }
                else
                {
                    current.controlPointIn  = current.value - weightedAvg * (inRatio / outRatio);
                    current.controlPointOut = current.value + weightedAvg;
                }
            }
            else if (previous.IsNull())
            {
                current.controlPointIn  = current.value;
                current.controlPointOut = current.value + (next.value - current.value) / 3f;
            }
            else if (next.IsNull())
            {
                current.controlPointIn  = current.value - (current.value - previous.value) / 3f;
                current.controlPointOut = current.value;
            }
        }
        private static void DeserializeCurveFromArray(BezierAnimationCurve curve, JSONArray curveJSON, ref bool dirty)
        {
            if (curveJSON.Count == 0)
            {
                return;
            }

            var last = -1f;

            foreach (JSONClass keyframeJSON in curveJSON)
            {
                try
                {
                    var time = float.Parse(keyframeJSON["t"], CultureInfo.InvariantCulture).Snap();
                    if (time == last)
                    {
                        continue;
                    }
                    last = time;
                    var value    = DeserializeFloat(keyframeJSON["v"]);
                    var keyframe = new BezierKeyframe
                    {
                        time            = time,
                        value           = value,
                        curveType       = int.Parse(keyframeJSON["c"]),
                        controlPointIn  = DeserializeFloat(keyframeJSON["i"]),
                        controlPointOut = DeserializeFloat(keyframeJSON["o"])
                    };
                    // Backward compatibility, tangents are not supported since bezier conversion.
                    if (keyframeJSON.HasKey("ti"))
                    {
                        dirty = true;
                        if (keyframe.curveType == CurveTypeValues.LeaveAsIs)
                        {
                            keyframe.curveType = CurveTypeValues.SmoothLocal;
                        }
                    }
                    curve.AddKey(keyframe);
                }
                catch (IndexOutOfRangeException exc)
                {
                    throw new InvalidOperationException($"Failed to read curve: {keyframeJSON}", exc);
                }
            }
        }
 private static void LinearInterpolation(BezierKeyframe previous, ref BezierKeyframe current, BezierKeyframe next)
 {
     if (previous.HasValue())
     {
         current.controlPointIn = current.value - (current.value - previous.value) / 3f;
     }
     else
     {
         current.controlPointIn = current.value;
     }
     if (next.HasValue())
     {
         current.controlPointOut = current.value + (next.value - current.value) / 3f;
     }
     else
     {
         current.controlPointOut = current.value;
     }
 }
        private static void DeserializeCurveFromStringLegacy(BezierAnimationCurve curve, JSONNode curveJSON)
        {
            var strFrames = curveJSON.Value.Split(';').Where(x => x != "").ToList();

            if (strFrames.Count == 0)
            {
                return;
            }

            var last = -1f;

            foreach (var strFrame in strFrames)
            {
                var parts = strFrame.Split(',');
                try
                {
                    var time = float.Parse(parts[0], CultureInfo.InvariantCulture).Snap();
                    if (time == last)
                    {
                        continue;
                    }
                    last = time;
                    var value    = DeserializeFloat(parts[1]);
                    var keyframe = new BezierKeyframe
                    {
                        time      = time,
                        value     = value,
                        curveType = int.Parse(parts[2])
                    };
                    // Backward compatibility, tangents are not supported since bezier conversion.
                    if (keyframe.curveType == CurveTypeValues.LeaveAsIs)
                    {
                        keyframe.curveType = CurveTypeValues.SmoothLocal;
                    }
                    curve.AddKey(keyframe);
                }
                catch (IndexOutOfRangeException exc)
                {
                    throw new InvalidOperationException($"Failed to read curve: {strFrame}", exc);
                }
            }
        }
        public void SetKeySnapshot(float time, BezierKeyframe keyframe)
        {
            keyframe.time = time;

            if (length == 0)
            {
                AddKey(keyframe);
                return;
            }

            var index = KeyframeBinarySearch(time);

            if (index == -1)
            {
                AddKey(keyframe);
            }
            else
            {
                keys[index] = keyframe;
            }
        }
 protected static float Weighting(BezierKeyframe k1, BezierKeyframe k2)
 {
     return(k2.time - k1.time);
     // if (_totalDistance == 0) return 1f;
     // return Vector2.Distance(new Vector2(1f - (k1.time / _totalTime), k1.value / _totalDistance), new Vector2(1f - (k2.time / _totalTime), k2.value / _totalDistance));
 }
 public void SetLastFrame(BezierKeyframe keyframe)
 {
     keys[keys.Count - 1] = keyframe;
 }
 public int SetKeyframeByKey(int key, BezierKeyframe keyframe)
 {
     keys[key] = keyframe;
     return(key);
 }