Example #1
0
        /// <summary>
        /// Adds a keyframe at start and at end. Remove all keyframes in between.
        /// Used when starting to drag a curve to modify tangents.
        /// </summary>
        public void AddTangentKey(AnimationKey key, int start, int end)
        {
            if (keys.Count == 0)
            {
                return;
            }

            int startFrame = Mathf.Max(GlobalState.Animation.StartFrame, start);
            int endFrame   = Mathf.Min(GlobalState.Animation.EndFrame, end);

            int firstKeyIndex = Mathf.Max(cachedKeysIndices[startFrame - (GlobalState.Animation.StartFrame)], 0);
            int lastKeyIndex  = Mathf.Max(cachedKeysIndices[endFrame - (GlobalState.Animation.StartFrame)], 0);

            bool hasPrevValue = Evaluate(startFrame, out float prevValue);
            bool hasNextValue = Evaluate(endFrame, out float nextValue);

            if (keys[firstKeyIndex].frame != startFrame && hasPrevValue)
            {
                AddKey(new AnimationKey(startFrame, prevValue, Interpolation.Bezier), false);
            }
            if (keys[lastKeyIndex].frame != endFrame && hasNextValue)
            {
                AddKey(new AnimationKey(endFrame, nextValue, Interpolation.Bezier), false);
            }
            List <AnimationKey> toRemove = keys.FindAll(x => x.frame > startFrame && x.frame < endFrame);

            toRemove.ForEach(x => RemoveKey(x.frame));
        }
Example #2
0
        public void AddKey(AnimationKey key)
        {
            if (GetKeyIndex(key.frame, out int index))
            {
                keys[index] = key;
                ComputeCacheValuesAt(index);
            }
            else
            {
                index++;
                keys.Insert(index, key);

                int end = cachedKeysIndices.Length - 1;
                if (index + 1 < keys.Count)
                {
                    end = keys[index + 1].frame - GlobalState.Animation.StartFrame - 1;
                    end = Mathf.Clamp(end, 0, cachedKeysIndices.Length - 1);
                }

                int start = key.frame - GlobalState.Animation.StartFrame;
                start = Mathf.Clamp(start, 0, end);
                for (int i = start; i <= end; i++)
                {
                    cachedKeysIndices[i] = index;
                }
                for (int i = end + 1; i < cachedKeysIndices.Length; i++)
                {
                    cachedKeysIndices[i]++;
                }

                ComputeCacheValuesAt(index);
            }
        }
Example #3
0
        // To be used by in-app add key (not from networked keys)
        public void AddFilteredKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key)
        {
            AnimationSet animationSet = GetObjectAnimation(gobject);

            if (null == animationSet)
            {
                animationSet = new AnimationSet(gobject);
                animations.Add(gobject, animationSet);
            }
            Curve curve = animationSet.GetCurve(property);

            // Filter rotation
            if (property == AnimatableProperty.RotationX || property == AnimatableProperty.RotationY || property == AnimatableProperty.RotationZ)
            {
                AnimationKey previousKey = curve.GetPreviousKey(key.frame);
                if (null != previousKey)
                {
                    float delta = Mathf.DeltaAngle(previousKey.value, key.value);
                    key.value = previousKey.value + delta;
                }
            }

            curve.AddKey(key);
            onChangeCurve.Invoke(gobject, property);
        }
Example #4
0
        public void AddFilteredKeyframeTangent(GameObject gobjet, AnimatableProperty property, AnimationKey key, int start, int end, bool updateCurves = true)
        {
            AnimationSet animationSet = GetObjectAnimation(gobjet);
            Curve        curve        = animationSet.GetCurve(property);

            // Filter rotation
            if (property == AnimatableProperty.RotationX || property == AnimatableProperty.RotationY || property == AnimatableProperty.RotationZ)
            {
                AnimationKey previousKey = curve.GetPreviousKey(key.frame);
                if (null != previousKey)
                {
                    float delta = Mathf.DeltaAngle(previousKey.value, key.value);
                    key.value = previousKey.value + delta;
                }
                else
                {
                    float delta = Mathf.DeltaAngle(0, key.value);
                    key.value = delta;
                }
            }
            curve.AddTangentKey(key, start, end);
            if (updateCurves)
            {
                onChangeCurve.Invoke(gobjet, property);
            }
        }
Example #5
0
 public AnimationKey(AnimationKey key)
 {
     frame         = key.frame;
     value         = key.value;
     interpolation = key.interpolation;
     inTangent     = key.inTangent;
     outTangent    = key.outTangent;
 }
Example #6
0
 public void MoveKey(int oldFrame, int newFrame)
 {
     if (GetKeyIndex(oldFrame, out int index))
     {
         AnimationKey key = keys[index];
         RemoveKey(key.frame);
         key.frame = newFrame;
         AddKey(key);
     }
 }
Example #7
0
 public bool TryFindKey(int frame, out AnimationKey key)
 {
     if (GetKeyIndex(frame, out int index))
     {
         key = keys[index];
         return(true);
     }
     key = null;
     return(false);
 }
Example #8
0
 private void AppendFilteredKey(Curve curve, int frame, float value)
 {
     if (curve.keys.Count > 0)
     {
         AnimationKey previousKey = curve.keys[curve.keys.Count - 1];
         float        delta       = Mathf.DeltaAngle(previousKey.value, value);
         value = previousKey.value + delta;
     }
     curve.AppendKey(new AnimationKey(frame, value));
 }
Example #9
0
 private void GetTangents(int ac, AnimationKey previous1Key, AnimationKey next1Key)
 {
     theta[ac + 0] = previous1Key.inTangent.x;
     theta[ac + 1] = previous1Key.inTangent.y;
     theta[ac + 2] = previous1Key.outTangent.x;
     theta[ac + 3] = previous1Key.outTangent.y;
     theta[ac + 4] = next1Key.inTangent.x;
     theta[ac + 5] = next1Key.inTangent.y;
     theta[ac + 6] = next1Key.outTangent.x;
     theta[ac + 7] = next1Key.outTangent.y;
 }
Example #10
0
        public void AddKey(AnimationKey key, bool lockTangents = false)
        {
            if (GetKeyIndex(key.frame, out int index))
            {
                keys[index] = key;
                if (!lockTangents)
                {
                    PreviousTangent(index);
                    NextTangent(index);
                    if (key.inTangent == Vector2.zero && key.outTangent == Vector2.zero)
                    {
                        CurrentTangent(index);
                    }
                }

                ComputeCacheValuesAt(index);
            }
            else
            {
                index++;
                keys.Insert(index, key);

                int end = cachedKeysIndices.Length - 1;
                if (index + 1 < keys.Count)
                {
                    end = keys[index + 1].frame - GlobalState.Animation.StartFrame - 1;
                    end = Mathf.Clamp(end, 0, cachedKeysIndices.Length - 1);
                }

                int start = key.frame - GlobalState.Animation.StartFrame;
                start = Mathf.Clamp(start, 0, end);
                for (int i = start; i <= end; i++)
                {
                    cachedKeysIndices[i] = index;
                }
                for (int i = end + 1; i < cachedKeysIndices.Length; i++)
                {
                    cachedKeysIndices[i]++;
                }

                if (!lockTangents)
                {
                    PreviousTangent(index);
                    NextTangent(index);
                    if (key.inTangent == Vector2.zero && key.outTangent == Vector2.zero)
                    {
                        CurrentTangent(index);
                    }
                }

                ComputeCacheValuesAt(index);
            }
        }
Example #11
0
        private bool GetKeyIndex(int frame, out int index)
        {
            index = cachedKeysIndices[frame - GlobalState.Animation.StartFrame];
            if (index == -1)
            {
                return(false);
            }

            AnimationKey key = keys[index];

            return(key.frame == frame);
        }
Example #12
0
 private void AddFilteredKeyframeZone(GameObject target, AnimationKey posX, AnimationKey posY, AnimationKey posZ, AnimationKey rotX, AnimationKey rotY, AnimationKey rotZ, AnimationKey scalex, AnimationKey scaley, AnimationKey scalez)
 {
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.RotationX, rotX, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.RotationY, rotY, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.RotationZ, rotZ, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.ScaleX, scalex, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.ScaleY, scaley, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.ScaleZ, scalez, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.PositionX, posX, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.PositionY, posY, startFrame, endFrame, false);
     GlobalState.Animation.AddFilteredKeyframeZone(target, AnimatableProperty.PositionZ, posZ, startFrame, endFrame);
 }
Example #13
0
        public void AddKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key)
        {
            AnimationSet animationSet = GetObjectAnimation(gobject);

            if (null == animationSet)
            {
                animationSet = new AnimationSet(gobject);
                animations.Add(gobject, animationSet);
            }
            Curve curve = animationSet.GetCurve(property);

            curve.AddKey(key);
            onChangeCurve.Invoke(gobject, property);
        }
Example #14
0
        public void RemoveKey(int frame)
        {
            if (GetKeyIndex(frame, out int index))
            {
                AnimationKey key   = keys[index];
                int          start = key.frame - GlobalState.Animation.StartFrame;
                int          end   = cachedKeysIndices.Length - 1;
                for (int i = start; i <= end; i++)
                {
                    cachedKeysIndices[i]--;
                }

                keys.RemoveAt(index);

                ComputeCacheValuesAt(index);
            }
        }
Example #15
0
        /// <summary>
        /// Same as AddZoneKey, but fill oldKeys and newKeys instead of modifying the curve.
        /// Used when the curve is released, to apply changes through commands
        /// </summary>
        public void GetZoneKeyChanges(AnimationKey key, int startFrame, int endFrame, List <AnimationKey> oldKeys, List <AnimationKey> newKeys)
        {
            int firstKeyIndex = cachedKeysIndices[startFrame - (GlobalState.Animation.StartFrame - 1)];
            int lastKeyIndex  = cachedKeysIndices[endFrame - (GlobalState.Animation.StartFrame - 1)];

            if (!Evaluate(key.frame, out float value))
            {
                return;
            }
            if (keys[firstKeyIndex].frame != startFrame && Evaluate(startFrame, out float prevValue))
            {
                newKeys.Add(new AnimationKey(startFrame, prevValue, key.interpolation));
            }
            if (keys[lastKeyIndex].frame != endFrame && Evaluate(endFrame, out float nextValue))
            {
                newKeys.Add(new AnimationKey(endFrame, nextValue, key.interpolation));
            }

            float deltaValue = key.value - value;
            float zoneSize   = endFrame - startFrame;

            for (int i = firstKeyIndex; i <= lastKeyIndex; i++)
            {
                int   deltaFrame = Mathf.Abs(key.frame - keys[i].frame);
                float deltaTime  = 1 - (deltaFrame / (float)zoneSize);

                if (property == AnimatableProperty.RotationX || property == AnimatableProperty.RotationY || property == AnimatableProperty.RotationZ)
                {
                    oldKeys.Add(new AnimationKey(keys[i].frame, keys[i].value, keys[i].interpolation));
                    float newValue = Mathf.LerpAngle(keys[i].value, keys[i].value + deltaValue, deltaTime);
                    newKeys.Add(new AnimationKey(keys[i].frame, newValue, key.interpolation));
                }
                else
                {
                    oldKeys.Add(new AnimationKey(keys[i].frame, keys[i].value, keys[i].interpolation));
                    float newValue = Mathf.Lerp(keys[i].value, keys[i].value + deltaValue, deltaTime);
                    newKeys.Add(new AnimationKey(keys[i].frame, newValue, key.interpolation));
                }
            }
            if (TryFindKey(key.frame, out AnimationKey oldKey))
            {
                oldKeys.Add(new AnimationKey(oldKey.frame, oldKey.value, oldKey.interpolation));
            }
            newKeys.Add(new AnimationKey(key.frame, key.value, key.interpolation));
        }
Example #16
0
        private void DragObject(Matrix4x4 transformation, float scaleIndice)
        {
            Matrix4x4 transformed = objectData.InitialParentMatrixWorldToLocal *
                                    transformation * objectData.InitialParentMatrix *
                                    objectData.InitialTRS;

            Maths.DecomposeMatrix(transformed, out objectData.lastPosition, out objectData.lastQRotation, out objectData.lastScale);
            objectData.lastRotation = objectData.lastQRotation.eulerAngles;
            objectData.lastScale   *= scaleIndice;

            Interpolation interpolation = GlobalState.Settings.interpolation;
            AnimationKey  posX          = new AnimationKey(Frame, objectData.lastPosition.x, interpolation);
            AnimationKey  posY          = new AnimationKey(Frame, objectData.lastPosition.y, interpolation);
            AnimationKey  posZ          = new AnimationKey(Frame, objectData.lastPosition.z, interpolation);
            AnimationKey  rotX          = new AnimationKey(Frame, objectData.lastRotation.x, interpolation);
            AnimationKey  rotY          = new AnimationKey(Frame, objectData.lastRotation.y, interpolation);
            AnimationKey  rotZ          = new AnimationKey(Frame, objectData.lastRotation.z, interpolation);
            AnimationKey  scalex        = new AnimationKey(Frame, objectData.lastScale.z, interpolation);
            AnimationKey  scaley        = new AnimationKey(Frame, objectData.lastScale.z, interpolation);
            AnimationKey  scalez        = new AnimationKey(Frame, objectData.lastScale.z, interpolation);

            switch (manipulationMode)
            {
            case AnimationTool.CurveEditMode.AddKeyframe:
                AddFilteredKeyframe(Target, posX, posY, posZ, rotX, rotY, rotZ, scalex, scaley, scalez);
                break;

            case AnimationTool.CurveEditMode.Zone:
                AddFilteredKeyframeZone(Target, posX, posY, posZ, rotX, rotY, rotZ, scalex, scaley, scalez);
                break;

            case AnimationTool.CurveEditMode.Segment:
                objectData.Solver = new TangentSimpleSolver(objectData.lastPosition, objectData.lastQRotation, GlobalState.Animation.GetObjectAnimation(Target), Frame, startFrame, endFrame, continuity);
                objectData.Solver.TrySolver();
                GlobalState.Animation.onChangeCurve.Invoke(Target, AnimatableProperty.PositionX);
                break;

            case AnimationTool.CurveEditMode.Tangents:
                objectData.Solver = new TangentSimpleSolver(objectData.lastPosition, objectData.lastQRotation, GlobalState.Animation.GetObjectAnimation(Target), Frame, startFrame, endFrame, continuity);
                objectData.Solver.TrySolver();
                GlobalState.Animation.onChangeCurve.Invoke(Target, AnimatableProperty.PositionX);
                break;
            }
        }
Example #17
0
 /// <summary>
 /// Fill upper bounds array with delta from current values
 /// </summary>
 private void FillUpperBounds(int curveIndex, AnimationKey previous1Key, AnimationKey next1Key, AnimationKey previous2Key, AnimationKey next2Key, float Min, float Max)
 {
     //k- in.x
     upperBound[curveIndex * 8 + 0] = previous1Key.frame - previous2Key.frame - previous1Key.inTangent.x;
     //k- in.y
     upperBound[curveIndex * 8 + 1] = -Mathf.Min(0, Min - Mathf.Min(curvesMinMax[curveIndex, 0].x, curvesMinMax[curveIndex, 0].y));
     //k- out.x
     upperBound[curveIndex * 8 + 2] = currentFrame - previous1Key.frame - previous1Key.outTangent.x;
     //k- out.y
     upperBound[curveIndex * 8 + 3] = Mathf.Max(0, (4 / 3f) * (Max - (previous1Key.value + (3 / 4f) * previous1Key.outTangent.y)));
     //k+ in.x
     upperBound[curveIndex * 8 + 4] = next1Key.frame - currentFrame - next1Key.inTangent.x;
     //k+ in.y
     upperBound[curveIndex * 8 + 5] = Mathf.Max(0, -(4 / 3f) * (Min - (next1Key.value - (3 / 4f) * next1Key.inTangent.y)));
     //k+ out.x
     upperBound[curveIndex * 8 + 6] = next2Key.frame - next1Key.frame - next1Key.outTangent.x;
     //k+ out.y
     upperBound[curveIndex * 8 + 7] = Mathf.Max(0, Max - Mathf.Max(curvesMinMax[curveIndex, 1].x, curvesMinMax[curveIndex, 1].y));
 }
Example #18
0
        private double[] GetAllTangents(int p, int K, List <int> requieredKeys)
        {
            double[] theta = new double[p];
            for (int i = 0; i < 6; i++)
            {
                AnimatableProperty property = (AnimatableProperty)i;
                Curve curve = ObjectAnimation.GetCurve(property);
                for (int k = 0; k < K; k++)
                {
                    AnimationKey key = curve.keys[requieredKeys[k]];
                    theta[4 * (i * K + k) + 0] = key.inTangent.x;
                    theta[4 * (i * K + k) + 1] = key.inTangent.y;
                    theta[4 * (i * K + k) + 2] = key.outTangent.x;
                    theta[4 * (i * K + k) + 3] = key.outTangent.y;
                }
            }

            return(theta);
        }
Example #19
0
        public CommandAddKeyframe(GameObject obj, AnimatableProperty property, int frame, float value, Interpolation interpolation)
        {
            gObject         = obj;
            this.property   = property;
            newAnimationKey = new AnimationKey(frame, value, interpolation);

            AnimationSet animationSet = GlobalState.Animation.GetObjectAnimation(obj);

            if (null == animationSet)
            {
                return;
            }

            Curve curve = animationSet.GetCurve(property);

            if (null == curve)
            {
                return;
            }

            curve.TryFindKey(frame, out oldAnimationKey);
        }
Example #20
0
        /// <summary>
        /// Add a key at startFrame and endFrame. Move every keys in between towards the new key value. Then add the new keyframe.
        /// Used when draging a curve.
        /// </summary>
        public void AddZoneKey(AnimationKey key, int startFrame, int endFrame)
        {
            int firstKeyIndex = cachedKeysIndices[startFrame - (GlobalState.Animation.StartFrame - 1)];
            int lastKeyIndex  = cachedKeysIndices[endFrame - (GlobalState.Animation.StartFrame - 1)];

            if (!Evaluate(key.frame, out float value))
            {
                return;
            }
            if (keys[firstKeyIndex].frame != startFrame && Evaluate(startFrame, out float prevValue))
            {
                AddKey(new AnimationKey(startFrame, prevValue, key.interpolation));
            }
            if (keys[lastKeyIndex].frame != endFrame && Evaluate(endFrame, out float nextValue))
            {
                AddKey(new AnimationKey(endFrame, nextValue, key.interpolation));
            }

            float deltaValue = key.value - value;
            float zoneSize   = endFrame - startFrame;

            for (int i = firstKeyIndex; i <= lastKeyIndex; i++)
            {
                int   deltaFrame = Mathf.Abs(key.frame - keys[i].frame);
                float deltaTime  = 1 - (deltaFrame / (float)zoneSize);

                if (property == AnimatableProperty.RotationX || property == AnimatableProperty.RotationY || property == AnimatableProperty.RotationZ)
                {
                    keys[i].value = Mathf.LerpAngle(keys[i].value, keys[i].value + deltaValue, deltaTime);
                }
                else
                {
                    keys[i].value = Mathf.Lerp(keys[i].value, keys[i].value + deltaValue, deltaTime);
                }
                ComputeCacheValuesAt(i);
            }
            AddKey(key);
        }
        public CommandAddKeyframeZone(GameObject obj, AnimatableProperty property, int frame, float value, int startFrame, int endFrame, Interpolation interpolation)
        {
            gObject       = obj;
            this.property = property;
            oldKeys       = new List <AnimationKey>();
            newKeys       = new List <AnimationKey>();

            AnimationSet animationSet = GlobalState.Animation.GetObjectAnimation(gObject);

            if (null == animationSet)
            {
                return;
            }
            Curve curve = animationSet.GetCurve(property);

            if (null == curve)
            {
                return;
            }

            AnimationKey newKey = new AnimationKey(frame, value, interpolation);

            curve.GetZoneKeyChanges(newKey, startFrame, endFrame, oldKeys, newKeys);
        }
Example #22
0
        private Vector2 GetMinMax(AnimationKey previous1Key, AnimationKey next1Key)
        {
            float A = previous1Key.value;
            float B = A + previous1Key.outTangent.y;
            float D = next1Key.value;
            float C = D - next1Key.inTangent.y;

            float a = -A + (3 * B) - (3 * C) + D;
            float b = (3 * A) - (6 * B) + (3 * C);
            float c = (-3 * A) + (3 * B);

            float tMin = 0;
            float tMax = 1;

            if (a != 0 && ((b * b) - 3 * a * c) > 0)
            {
                tMin = (-b - Mathf.Sqrt((b * b) - 3 * a * c)) / (3 * a);
                tMax = (-b + Mathf.Sqrt((b * b) - 3 * a * c)) / (3 * a);
            }
            float MinValue = Bezier.CubicBezier(A, B, C, D, Mathf.Clamp01(tMin));
            float MaxValue = Bezier.CubicBezier(A, B, C, D, Mathf.Clamp01(tMax));

            return(new Vector2(MinValue, MaxValue));
        }
Example #23
0
        private bool EvaluateCache(int frame, out float value)
        {
            if (keys.Count == 0)
            {
                value = float.NaN;
                return(false);
            }

            int prevIndex = cachedKeysIndices[frame - GlobalState.Animation.StartFrame];

            if (prevIndex == -1)
            {
                value = keys[0].value;
                return(true);
            }
            if (prevIndex == keys.Count - 1)
            {
                value = keys[keys.Count - 1].value;
                return(true);
            }

            AnimationKey prevKey = keys[prevIndex];

            switch (prevKey.interpolation)
            {
            case Interpolation.Constant:
                value = prevKey.value;
                return(true);

            case Interpolation.Other:
            case Interpolation.Linear:
            {
                AnimationKey nextKey    = keys[prevIndex + 1];
                float        dt         = (float)(frame - prevKey.frame) / (float)(nextKey.frame - prevKey.frame);
                float        oneMinusDt = 1f - dt;
                value = prevKey.value * oneMinusDt + nextKey.value * dt;
                return(true);
            }

            case Interpolation.Bezier:
            {
                AnimationKey nextKey = keys[prevIndex + 1];

                Vector2 A = new Vector2(prevKey.frame, prevKey.value);
                Vector2 B, C;
                Vector2 D = new Vector2(nextKey.frame, nextKey.value);

                if (prevIndex == 0)
                {
                    B = A + (D - A) / 3f;
                }
                else
                {
                    AnimationKey prevPrevKey = keys[prevIndex - 1];
                    Vector2      V           = (D - new Vector2(prevPrevKey.frame, prevPrevKey.value)).normalized;
                    Vector2      AD          = D - A;
                    B = A + V * AD.magnitude / 3f;
                }

                if (prevIndex + 2 >= keys.Count)
                {
                    C = D - (D - A) / 3f;
                }
                else
                {
                    AnimationKey nextNextKey = keys[prevIndex + 2];
                    Vector2      V           = (new Vector2(nextNextKey.frame, nextNextKey.value) - A).normalized;
                    Vector2      AD          = D - A;
                    C = D - V * AD.magnitude / 3f;
                }

                value = EvaluateBezier(A, B, C, D, frame);
                return(true);
            }
            }
            value = float.NaN;
            return(false);
        }
Example #24
0
 public static void RemoveKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key)
 {
     GlobalState.Animation.RemoveKeyframe(gobject, property, key.frame);
     Instance.scene.RemoveKeyframe(gobject, property, key);
 }
Example #25
0
        public bool Setup()
        {
            Curve rotXCurve = objectAnimation.GetCurve(AnimatableProperty.RotationX);

            rotXCurve.GetKeyIndex(firstFrame, out int firstIndex);
            rotXCurve.GetKeyIndex(lastFrame, out int lastIndex);

            if (currentFrame < firstFrame)
            {
                return(false);
            }
            if (currentFrame > lastFrame)
            {
                return(false);
            }

            requiredKeyframe = new List <int>()
            {
                firstFrame, lastFrame
            };
            keyCount = requiredKeyframe.Count;
            int curveCount = curves.Count;

            //number of curve * (in tangent x , in tangent y, out tangent x, out tangent y) * (k- , k+)
            paramCount = curveCount * 4 * 2;

            ds_thetaJob(paramCount, keyCount);

            theta         = new double[paramCount];
            Stiffnes_D    = new double[paramCount, paramCount];
            Continuity_T  = new double[paramCount, paramCount];
            curvesMinMax  = new Vector2[curveCount, 2];
            lowerBound    = new double[paramCount];
            upperBound    = new double[paramCount];
            scale         = new double[paramCount];
            delta_theta_0 = new double[paramCount];

            //Hierarchy rotation curves
            for (int animIndex = 0; animIndex < animationCount; animIndex++)
            {
                for (int curve = 0; curve < 3; curve++)
                {
                    int          curveIndex   = animIndex * 3 + curve;
                    AnimationKey previous1Key = curves[curveIndex].keys[firstIndex];
                    AnimationKey previous2Key = firstIndex > 0 ? curves[curveIndex].keys[firstIndex - 1] : new AnimationKey(previous1Key.frame, previous1Key.value, inTangent: Vector2.zero, outTangent: Vector2.zero);
                    AnimationKey next1Key     = curves[curveIndex].keys[lastIndex];
                    AnimationKey next2key     = lastIndex < curves[curveIndex].keys.Count - 1 ? curves[curveIndex].keys[lastIndex + 1] : new AnimationKey(next1Key.frame, next1Key.value, inTangent: Vector2.zero, outTangent: Vector2.zero);
                    GetTangents(curveIndex * 8, previous1Key, next1Key);
                    curvesMinMax[curveIndex, 0] = GetMinMax(previous2Key, previous1Key);
                    curvesMinMax[curveIndex, 1] = GetMinMax(next1Key, next2key);

                    float Min = controllers[animIndex].LowerAngleBound[curve];
                    float Max = controllers[animIndex].UpperAngleBound[curve];
                    FillLowerBounds(curveIndex, previous1Key, next1Key, Min, Max);
                    FillUpperBounds(curveIndex, previous1Key, next1Key, previous2Key, next2key, Min, Max);
                    GetContinuity(curveIndex * 8, Min, Max);
                    //k- in x, k- in y, k- out x, k- out y, k+ in x, k+ in y, k+ out x, k+ out y
                    for (int tan = 0; tan < 8; tan++)
                    {
                        int tanIndice = curveIndex * 8 + tan;
                        Stiffnes_D[tanIndice, tanIndice] = animIndex == animationCount - 1 ? 0 : controllers[animIndex].stiffness;
                        scale[tanIndice]         = 1d;
                        delta_theta_0[tanIndice] = 0;
                    }
                }
            }

            //Root position curves
            int aIndex = animationCount;

            for (int curve = 0; curve < 3; curve++)
            {
                int          curveIndex   = aIndex * 3 + curve;
                AnimationKey previous1Key = curves[curveIndex].keys[firstIndex];
                AnimationKey previous2Key = firstIndex > 0 ? curves[curveIndex].keys[firstIndex - 1] : new AnimationKey(previous1Key.frame, previous1Key.value, inTangent: Vector2.zero, outTangent: Vector2.zero);
                AnimationKey next1Key     = curves[curveIndex].keys[lastIndex];
                AnimationKey next2Key     = lastIndex < curves[curveIndex].keys.Count - 1 ? curves[curveIndex].keys[lastIndex + 1] : new AnimationKey(next1Key.frame, next1Key.value, inTangent: Vector2.zero, outTangent: Vector2.zero);
                GetTangents(curveIndex * 8, previous1Key, next1Key);
                curvesMinMax[curveIndex, 0] = GetMinMax(previous2Key, previous1Key);
                curvesMinMax[curveIndex, 1] = GetMinMax(next1Key, next2Key);
                GetContinuity(curveIndex * 8);
                for (int tan = 0; tan < 8; tan++)
                {
                    int tanIndice = curveIndex * 8 + tan;
                    Stiffnes_D[tanIndice, tanIndice] = controllers[0].stiffness;
                    lowerBound[tanIndice]            = -10;
                    upperBound[tanIndice]            = 10;
                    scale[tanIndice]         = 1d;
                    delta_theta_0[tanIndice] = 0;
                }
            }
            currentState = GetCurrentState(currentFrame);
            targetState  = new State()
            {
                position = targetPosition,
                rotation = targetRotation,
                time     = currentFrame
            };

            Delta_s_prime = new double[7, 1];
            for (int i = 0; i < 3; i++)
            {
                Delta_s_prime[i, 0] = targetState.position[i] - currentState.position[i];
            }
            if ((currentState.rotation * Quaternion.Inverse(targetState.rotation)).w < 0)
            {
                targetState.rotation = new Quaternion(-targetState.rotation.x, -targetState.rotation.y, -targetState.rotation.z, -targetState.rotation.w);
            }
            for (int i = 0; i < 4; i++)
            {
                Delta_s_prime[i + 3, 0] = targetState.rotation[i] - currentState.rotation[i];
            }

            Theta = Maths.ColumnArrayToArray(theta);
            return(true);
        }
Example #26
0
 public static void RemoveKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key, bool updateCurves = true, bool lockTangents = false)
 {
     GlobalState.Animation.RemoveKeyframe(gobject, property, key.frame, updateCurves, lockTangents);
     Instance.scene.RemoveKeyframe(gobject, property, key);
 }
Example #27
0
 public static void AddObjectKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key)
 {
     GlobalState.Animation.AddFilteredKeyframe(gobject, property, key);
     Instance.scene.AddKeyframe(gobject, property, key);
 }
Example #28
0
 public void RemoveKeyframe(GameObject gobject, AnimatableProperty property, AnimationKey key)
 {
 }
Example #29
0
 // Don't compute cache. Should be called when adding a lot of keys in a row.
 // And then don't forget to call ComputeCache().
 public void AppendKey(AnimationKey key)
 {
     keys.Add(key);
 }