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); }
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); } } }
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); } }
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); }
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); } } }
// 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(); }
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); } }
public Vector3 GetPosition(float time) { Vector3 translation = AnimationCurveHelper.getPositionAt(curves, time); return(startPosition + translation); }
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); } } }