Beispiel #1
0
    private bool addKeyOnUserInteraction(float value, float curveValue, AnimationCurve curve, float scrubberPosition)
    {
        bool differenceFound = false;

        if (!(Math.Abs(value - curveValue) < THRESHOLD))
        {
            differenceFound = true;
            if (hasUserInteracted)
            {
                bool doesKeyExist = false;
                for (int j = 0; j < curve.length; j++)
                {
                    Keyframe k = curve[j];
                    if (k.time == scrubberPosition)
                    {
                        Keyframe newKeyframe = new Keyframe(k.time, value, k.inTangent, k.outTangent);
                        newKeyframe.tangentMode = k.tangentMode;
                        AnimationCurveHelper.MoveKey(curve, j, newKeyframe);
                        doesKeyExist = true;
                    }
                }
                if (!doesKeyExist)
                {
                    Keyframe kf = new Keyframe(scrubberPosition, value);
                    AnimationCurveHelper.AddKey(curve, kf);
                }
            }
        }
        return(differenceFound);
    }
    private bool addKeyOnUserInteraction(float value, float curveValue, AnimationCurve curve, float scrubberPosition, bool inArea = true, float theshold = 0.000001f)
    {
        var  time            = (float)Mathf.RoundToInt(scrubberPosition * DirectorWindow.directorControl.frameRate) / DirectorWindow.directorControl.frameRate;
        bool differenceFound = false;
        var  v = Math.Abs(value - curveValue);

        if (v > theshold && !inArea)
        {
            differenceFound = true;
            if (hasUserInteracted)
            {
                AddOrMoveKey(time, curve, value);
            }
        }
        else if (Event.current.keyCode == KeyCode.K)
        {
            AnimationKeyTime akt = AnimationKeyTime.Time(time, DirectorWindow.directorControl.frameRate);
            for (int j = 0; j < curve.length; j++)
            {
                Keyframe k = curve[j];
                if (akt.ContainsTime(k.time))
                {
                    return(false);
                }
            }
            Keyframe kf = new Keyframe(time, value);
            AnimationCurveHelper.AddKey(curve, kf, akt);
            differenceFound = true;
        }
        else
        {
            RecordNeedKeyframeCurve(time, curve, value);
        }
        return(differenceFound);
    }
Beispiel #3
0
    public override void OnInspectorGUI()
    {
        info = target as AnimationCurveHelper;

        info.m_AnimClip  = (AnimationClip)EditorGUILayout.ObjectField(new GUIContent("TarAnimationClip"), info.m_AnimClip, typeof(AnimationClip), true);
        info.m_CurveName = EditorGUILayout.TextField(new GUIContent("CurveName"), info.m_CurveName);

        if (info.m_CurveName.Equals(m_LastName) == false)
        {
            for (int i = 0; i < info._CurveNames.Length; i++)
            {
                if (info._CurveNames[i].Equals(info.m_CurveName))
                {
                    info._SelectedCurveIndex = i;
                    break;
                }
            }
            m_LastName = info.m_CurveName;
        }

        info.m_LoadDataFromCurve = EditorGUILayout.Toggle(new GUIContent("LoadDataFromCurve"), info.m_LoadDataFromCurve);
        if (info.m_LoadDataFromCurve)
        {
            info.m_ExtraAnimClip = (AnimationClip)EditorGUILayout.ObjectField(new GUIContent("DataAnimationClip"), info.m_ExtraAnimClip, typeof(AnimationClip), true);
            if (info.m_ExtraAnimClip != null)
            {
                info.UpdateExtra();
                info._SelectedCurveIndex = EditorGUILayout.Popup("Node", info._SelectedCurveIndex, info._CurveNames);
                if (info._Curves != null &&
                    info._SelectedCurveIndex >= 0 &&
                    info._SelectedCurveIndex < info._Curves.Length)
                {
                    info.m_AnimCurve = AnimationUtility.GetEditorCurve(info.m_ExtraAnimClip, info._Curves[info._SelectedCurveIndex]);
                    info.m_AnimCurve = EditorGUILayout.CurveField(new GUIContent("CurCurve"), info.m_AnimCurve);
                }
            }
        }
        else
        {
            info.m_CurveData = EditorGUILayout.TextField(new GUIContent("CurveData"), info.m_CurveData);
            if (!string.IsNullOrEmpty(info.m_CurveData))
            {
                info.m_AnimCurve = info.CreateCurve();
                info.m_AnimCurve = EditorGUILayout.CurveField(new GUIContent("CurCurve"), info.m_AnimCurve);
            }
        }
    }
Beispiel #4
0
    private IEnumerator FadeCoroutine(AnimationCurve curve)
    {
        float endTime     = AnimationCurveHelper.LastKey(curve).time;
        float elapsedTime = 0;

        AnimationCurveHelper.ChangeFirstKeyframe(curve, Value);

        while (elapsedTime <= endTime)
        {
            Value = curve.Evaluate(elapsedTime);

            elapsedTime += Time.deltaTime;
            yield return(new WaitForEndOfFrame());
        }

        Value = AnimationCurveHelper.LastKey(curve).value;
    }
    private void AddOrMoveKey(float time, AnimationCurve curve, float value)
    {
        bool             doesKeyExist = false;
        AnimationKeyTime akt          = AnimationKeyTime.Time(time, DirectorWindow.directorControl.frameRate);

        for (int j = 0; j < curve.length; j++)
        {
            Keyframe k = curve[j];
            if (akt.ContainsTime(k.time))
            {
                Keyframe newKeyframe = new Keyframe(k.time, value, k.inTangent, k.outTangent);
                AnimationCurveHelper.MoveKey(curve, j, newKeyframe);
                doesKeyExist = true;
            }
        }
        if (!doesKeyExist)
        {
            Keyframe kf = new Keyframe(time, value);
            AnimationCurveHelper.AddKey(curve, kf, akt);
        }
    }
Beispiel #6
0
    private IEnumerator FadeCoroutine(AnimationCurve curve, FadeType type)
    {
        OnTransitionStart(type);
        Transitioning = true;

        AnimationCurveHelper.ChangeFirstKeyframeValue(curve, Value);
        AnimationCurveHelper.ChangeLastKeyframeTime(curve, Duration);

        float endTime     = Duration;
        float elapsedTime = 0;

        while (elapsedTime <= endTime)
        {
            Value = curve.Evaluate(elapsedTime);

            elapsedTime += Time.deltaTime;
            yield return(new WaitForEndOfFrame());
        }

        Value         = AnimationCurveHelper.LastKey(curve).value;
        Transitioning = false;
        OnTransitionStop(type);
    }
Beispiel #7
0
    private void checkToAddNewKeyframes(ActorClipCurve clipCurve, DirectorControlState state)
    {
        if (state.IsInPreviewMode && IsEditing &&
            clipCurve.Manager.State == TimelineManager.TimeLineState.Paused && GUIUtility.hotControl == 0 &&
            (clipCurve.Firetime <= state.ScrubberPosition &&
             state.ScrubberPosition <= clipCurve.Firetime + clipCurve.Duration) && clipCurve.Actor != null)
        {
            Undo.RecordObject(clipCurve, "Auto Key Created");
            bool hasDifferenceBeenFound = false;
            for (int i = 0; i < clipCurve.CurveData.Count; i++)
            {
                MemberClipCurveData data = clipCurve.CurveData[i];
                if (data.Type == string.Empty || data.PropertyName == string.Empty)
                {
                    continue;
                }

                Component component = clipCurve.Actor.GetComponent(data.Type);
                object    value     = clipCurve.GetCurrentValue(component, data.PropertyName, data.IsProperty);

                PropertyTypeInfo typeInfo = data.PropertyType;

                if (typeInfo == PropertyTypeInfo.Int || typeInfo == PropertyTypeInfo.Long)
                {
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(Convert.ToInt32(value), curve1Value, data.Curve1, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Float || typeInfo == PropertyTypeInfo.Double)
                {
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(Convert.ToSingle(value), curve1Value, data.Curve1, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Vector2)
                {
                    Vector2 vec2        = (Vector2)value;
                    float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec2.x, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec2.y, curve2Value, data.Curve2, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Vector3)
                {
                    Vector3 vec3        = (Vector3)value;
                    float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float   curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.x, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.y, curve2Value, data.Curve2, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.z, curve3Value, data.Curve3, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Vector4)
                {
                    Vector4 vec4        = (Vector4)value;
                    float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float   curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float   curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.x, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.y, curve2Value, data.Curve2, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.z, curve3Value, data.Curve3, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.w, curve4Value, data.Curve4, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Quaternion)
                {
                    Quaternion quaternion  = (Quaternion)value;
                    float      curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float      curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float      curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float      curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    for (int j = 0; j < data.Curve1.length; j++)
                    {
                        Keyframe k = data.Curve1[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.x, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve1, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve2.length; j++)
                    {
                        Keyframe k = data.Curve2[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.y, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve2, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve3.length; j++)
                    {
                        Keyframe k = data.Curve3[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.z, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve3, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve4.length; j++)
                    {
                        Keyframe k = data.Curve4[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.w, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve4, j, newKeyframe);
                        }
                    }

                    Quaternion curveValue = new Quaternion(curve1Value, curve2Value, curve3Value, curve4Value);
                    float      angle      = Vector3.Angle(quaternion.eulerAngles, curveValue.eulerAngles);
                    hasDifferenceBeenFound = hasDifferenceBeenFound || angle > QUATERNION_THRESHOLD;
                    if (angle > QUATERNION_THRESHOLD && hasUserInteracted)
                    {
                        data.Curve1.AddKey(state.ScrubberPosition, quaternion.x);
                        data.Curve2.AddKey(state.ScrubberPosition, quaternion.y);
                        data.Curve3.AddKey(state.ScrubberPosition, quaternion.z);
                        data.Curve4.AddKey(state.ScrubberPosition, quaternion.w);
                        hasUserInteracted = true;
                    }
                }
                else if (typeInfo == PropertyTypeInfo.Color)
                {
                    Color color       = (Color)value;
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.r, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.g, curve2Value, data.Curve2, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.b, curve3Value, data.Curve3, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.a, curve4Value, data.Curve4, state.ScrubberPosition);
                }
            }
            if (hasDifferenceBeenFound)
            {
                hasUserInteracted = true;
                EditorUtility.SetDirty(clipCurve);
            }
        }
    }
Beispiel #8
0
    // Update is called once per frame
    void Update()
    {
        //Debug.LogError("Agent Brain Update " + currentPlanExecutionIndex + " " + numGlobalPathWaypoints);

        // TODO
        // while time is remaining
        // pick current highest priority task and execute it
        // evaluate the status of the task -- and depending on status, evaluate new priority and add it back.
        // TODO : can exexcute multiple tasks ?

        float maxTime = 1.0F;

        Task task = taskManager.getHighestPriorityTask();

        if (task != null)
        {
            Debug.Log("Executing task " + task.taskName);
            task.execute(maxTime);
        }
        else
        {
            //Debug.Log ("task manager does not have task");
        }

        // clearing curves
        curves[0] = new AnimationCurve();
        curves[1] = new AnimationCurve();
        curves[2] = new AnimationCurve();
        curves[3] = new AnimationCurve();
        endTime   = 0.0f;
        // assigning curves

        //Debug.LogError("num global points " + numGlobalPathWaypoints + " num space time paths " + spaceTimePaths.Count + " grid tasks " + gridNavigationTasks.Count);
        for (int i = currentPlanExecutionIndex; i < Mathf.Min(currentPlanExecutionIndex + numGlobalPathWaypoints, spaceTimePaths.Count); i++)
        {
            // TODO CHECK HERE IF THE SPACE TIME PLAN IS CURRENTLY VALID OR NOT
            if (offMeshLinkWayPoint[i] == true)              // this one is an off mesh link -- does not have a space time path
            {
                spaceTimePaths[i].Clear();
                // TODO GET MOST RECENT POSITION FOR BETTER VIEWING
                spaceTimePaths[i].Add(gridNavigationTasks[i].startState);
                spaceTimePaths[i].Add(gridNavigationTasks[i].goalState);
            }
            else if (gridNavigationTasks[i].spaceTimePathStatus == false)              // not an off mesh link and does not have a path
            {
                break;
            }

            endTime = AnimationCurveHelper.GetPlanAnimationCurve(spaceTimePaths[i], curves);

            //Debug.LogError("we populated the curve till " + endTime);
        }


        // TODO CHECK HERE IF WE ARE CURRENTLY CONTROLLED BY THE MESH LINK
        if (moveAutomatically == true)
        {
            if (stop == false)
            {
                ExecuteNextAction(Time.deltaTime);
            }
            else
            {
                currentState._time += Time.deltaTime;                 // THIS HAPPENS WHEN OFF MESH LINK HAS CONTROL
            }
        }
        else if (Input.GetKeyDown(KeyCode.A))
        {
            ExecuteNextAction(0.2f);
        }


        // monitoring positions of agents in the polygon dictionary
        if (GlobalNavigator.usingDynamicNavigationMesh)
        {
            currentPolygonIndex = CentralizedManager.UpdatePolygonDictionary(currentState.getPosition(), currentPolygonIndex, null);
        }


        if (text != null)
        {
            string t = "";
            t = t + "global path " + numGlobalPathWaypoints.ToString() + "\n";
            t = t + "Current plan execution index : " + currentPlanExecutionIndex.ToString() + "\n";
            t = t + "current state " + currentState.getPosition().ToString() + " " + currentState._time.ToString() + " " + currentState._speed.ToString() + " \n";
            for (int i = 0; i < gridNavigationTasks.Count; i++)
            {
                t = t + offMeshLinkWayPoint[i].ToString() + " grid task " + i.ToString() + " " + gridNavigationTasks[i].taskPriority.ToString() + " " +
                    gridNavigationTasks[i].startState.getPosition().ToString() + " " + gridNavigationTasks[i].startState._time.ToString() + " " +
                    gridNavigationTasks[i].goalState.getPosition().ToString() + " " + gridNavigationTasks[i].goalState._time.ToString() + " " +
                    localPaths[i].Count.ToString() + " " + spaceTimePaths[i].Count.ToString() + "\n";
            }

            text.text = t;
        }

        // trying text mesh
        int timeLeftForGlobalGoal = Mathf.RoundToInt(goalState._time - currentState._time);

        int timeLeftForCurrentWaypoint;

        if (goalReached == false)
        {
            timeLeftForCurrentWaypoint = Mathf.RoundToInt(gridNavigationTasks[currentPlanExecutionIndex].goalState._time - currentState._time);
        }
        else
        {
            timeLeftForCurrentWaypoint = 0;
        }

        textMesh.text = timeLeftForGlobalGoal.ToString() + "/" + timeLeftForCurrentWaypoint.ToString();
    }
Beispiel #9
0
    void OnDrawGizmos()
    {
        if (goalReached)
        {
            return;
        }

        // drawing local path(s)
        if (drawGridPaths && localPaths != null)
        {
            for (int i = currentPlanExecutionIndex; i < Mathf.Min(currentPlanExecutionIndex + numGlobalPathWaypoints, localPaths.Count); i++)
            {
                foreach (State state in localPaths[i])
                {
                    state.drawStateGizmo(Color.green);
                }
            }
        }

        // drawing local path(s)
        if (drawSpaceTimePaths && spaceTimePaths != null)
        {
            for (int i = currentPlanExecutionIndex; i < Mathf.Min(currentPlanExecutionIndex + numGlobalPathWaypoints, spaceTimePaths.Count); i++)
            {
                foreach (State state in spaceTimePaths[i])
                {
                    state.drawStateGizmo(Color.blue);
                }
            }

            //Debug.LogWarning("end tiem " + endTime + " " + curves[0].length);
        }
        if (drawSpaceTimeCurve && spaceTimePaths != null)
        {
            AnimationCurveHelper.DrawAnimationCurveGizmos(curves, endTime, 0.1f, Color.red);
        }


        if (drawGlobalPath)
        {
            for (int i = 0; i < numGlobalPathWaypoints; i++)
            {
                //globalPath[i].drawStateGizmoWithTextDisplay(Color.red);
                globalPath[i].drawStateGizmo(Color.red);
            }
        }

        if (drawOpen)
        {
            gridNavigationTasks[currentPlanExecutionIndex].gridPlanner.VisualizeContainer(ContainerType.Open, Color.blue, 0.1f);
        }
        if (drawClosed)
        {
            gridNavigationTasks[currentPlanExecutionIndex].gridPlanner.VisualizeContainer(ContainerType.Close, Color.red, 0.1f);
        }
        if (drawPlan)
        {
            gridNavigationTasks[currentPlanExecutionIndex].gridPlanner.VisualizeContainer(ContainerType.Plan, Color.green, 0.1f);
        }
        if (drawVisited)
        {
            gridNavigationTasks[currentPlanExecutionIndex].gridPlanner.VisualizeContainer(ContainerType.Visited, Color.grey, 0.1f);
        }
    }
Beispiel #10
0
    public Vector3 GetPosition(float time)
    {
        Vector3 translation = AnimationCurveHelper.getPositionAt(curves, time);

        return(startPosition + translation);
    }
Beispiel #11
0
    private void checkToAddNewKeyframes(CinemaActorClipCurve clipCurve, DirectorControlState state)
    {
        if (state.IsInPreviewMode && IsEditing &&
            clipCurve.Cutscene.State == Cutscene.CutsceneState.Paused && GUIUtility.hotControl == 0 &&
            (clipCurve.Firetime <= state.ScrubberPosition &&
             state.ScrubberPosition <= clipCurve.Firetime + clipCurve.Duration) && clipCurve.Actor != null)
        {
            Undo.RecordObject(clipCurve, "Auto Key Created");
            bool hasDifferenceBeenFound = false;
            for (int i = 0; i < clipCurve.CurveData.Count; i++)
            {
                MemberClipCurveData data = clipCurve.CurveData[i];
                if (data.Type == string.Empty || data.PropertyName == string.Empty)
                {
                    continue;
                }

                Component component = clipCurve.Actor.GetComponent(data.Type);
                object    value     = null;

                //Specific hard-coded fix for the Rotation Curve Issue.
                currentlyEditingRotation = data.PropertyName == "localEulerAngles";
#if UNITY_2017_2_OR_NEWER
                if (component != null)
                {
                    Type type = component.GetType();
                    if (data.IsProperty)
                    {
                        // Deal with a special case, use the new TransformUtils to get the rotation value from the editor field.
                        if (type == typeof(Transform) && data.PropertyName == "localEulerAngles")
                        {
                            value = UnityEditor.TransformUtils.GetInspectorRotation(component.transform); // TransformUtils added in 2017.2
                        }
                        else
                        {
                            value = clipCurve.GetCurrentValue(component, data.PropertyName, data.IsProperty);
                        }
                    }
                }
#else
                value = clipCurve.GetCurrentValue(component, data.PropertyName, data.IsProperty);
#endif

                PropertyTypeInfo typeInfo = data.PropertyType;

                if (typeInfo == PropertyTypeInfo.Int || typeInfo == PropertyTypeInfo.Long)
                {
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(Convert.ToInt32(value), curve1Value, data.Curve1, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Float || typeInfo == PropertyTypeInfo.Double)
                {
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(Convert.ToSingle(value), curve1Value, data.Curve1, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Vector2)
                {
                    Vector2 vec2        = (Vector2)value;
                    float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec2.x, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec2.y, curve2Value, data.Curve2, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Vector3)
                {
                    //Special check for rotations
                    if (!currentlyEditingRotation || (currentlyEditingRotation && clipCurve.Actor.transform.hasChanged))
                    {
                        Vector3 vec3        = (Vector3)value;
                        float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                        float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                        float   curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);

                        hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.x, curve1Value, data.Curve1, state.ScrubberPosition);
                        hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.y, curve2Value, data.Curve2, state.ScrubberPosition);
                        hasDifferenceBeenFound |= addKeyOnUserInteraction(vec3.z, curve3Value, data.Curve3, state.ScrubberPosition);
                    }
                }
                else if (typeInfo == PropertyTypeInfo.Vector4)
                {
                    Vector4 vec4        = (Vector4)value;
                    float   curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float   curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float   curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float   curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.x, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.y, curve2Value, data.Curve2, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.z, curve3Value, data.Curve3, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(vec4.w, curve4Value, data.Curve4, state.ScrubberPosition);
                }
                else if (typeInfo == PropertyTypeInfo.Quaternion)
                {
                    Quaternion quaternion  = (Quaternion)value;
                    float      curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float      curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float      curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float      curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    for (int j = 0; j < data.Curve1.length; j++)
                    {
                        Keyframe k = data.Curve1[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.x, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve1, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve2.length; j++)
                    {
                        Keyframe k = data.Curve2[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.y, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve2, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve3.length; j++)
                    {
                        Keyframe k = data.Curve3[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.z, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve3, j, newKeyframe);
                        }
                    }

                    for (int j = 0; j < data.Curve4.length; j++)
                    {
                        Keyframe k = data.Curve4[j];
                        if (k.time == state.ScrubberPosition)
                        {
                            Keyframe newKeyframe = new Keyframe(k.time, quaternion.w, k.inTangent, k.outTangent);
                            newKeyframe.tangentMode = k.tangentMode;
                            AnimationCurveHelper.MoveKey(data.Curve4, j, newKeyframe);
                        }
                    }

                    Quaternion curveValue = new Quaternion(curve1Value, curve2Value, curve3Value, curve4Value);
                    float      angle      = Vector3.Angle(quaternion.eulerAngles, curveValue.eulerAngles);
                    hasDifferenceBeenFound = hasDifferenceBeenFound || angle > QUATERNION_THRESHOLD;
                    if (angle > QUATERNION_THRESHOLD && hasUserInteracted)
                    {
                        data.Curve1.AddKey(state.ScrubberPosition, quaternion.x);
                        data.Curve2.AddKey(state.ScrubberPosition, quaternion.y);
                        data.Curve3.AddKey(state.ScrubberPosition, quaternion.z);
                        data.Curve4.AddKey(state.ScrubberPosition, quaternion.w);
                        hasUserInteracted = true;
                    }
                }
                else if (typeInfo == PropertyTypeInfo.Color)
                {
                    Color color       = (Color)value;
                    float curve1Value = data.Curve1.Evaluate(state.ScrubberPosition);
                    float curve2Value = data.Curve2.Evaluate(state.ScrubberPosition);
                    float curve3Value = data.Curve3.Evaluate(state.ScrubberPosition);
                    float curve4Value = data.Curve4.Evaluate(state.ScrubberPosition);

                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.r, curve1Value, data.Curve1, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.g, curve2Value, data.Curve2, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.b, curve3Value, data.Curve3, state.ScrubberPosition);
                    hasDifferenceBeenFound |= addKeyOnUserInteraction(color.a, curve4Value, data.Curve4, state.ScrubberPosition);
                }
            }
            if (hasDifferenceBeenFound)
            {
                hasUserInteracted = true;
                EditorUtility.SetDirty(clipCurve);
            }
        }
    }