private static void MoveKey(EditorCurveBinding binding, AnimationClip clip, int keyframeInx, float time) { AnimationCurve curve; if (binding.isPPtrCurve) { ObjectReferenceKeyframe[] keyframesCurveReferenced = AnimationUtility.GetObjectReferenceCurve(clip, binding); if (keyframesCurveReferenced != null && keyframesCurveReferenced.Length > keyframeInx) { keyframesCurveReferenced [keyframeInx].time = time; AnimationUtility.SetObjectReferenceCurve(clip, binding, keyframesCurveReferenced); } } else { curve = AnimationUtility.GetEditorCurve(clip, binding); if (curve != null) { Keyframe key = curve.keys [keyframeInx]; key.time = time; curve.MoveKey(keyframeInx, key); AnimationModeUtility.SaveCurve(curve, clip, binding); } } }
/// <summary> /// Adds the keyframe to clip at time based of current values of root GameObject. /// <param name="curveBindingCurrent">Curve binding current.</param> /// </summary> /// <param name="root">Root.</param> /// <param name="clip">Clip.</param> /// <param name="time">Time.</param> public static void AddKeyframeTo(EditorCurveBinding binding, GameObject root, AnimationClip clip, float time) { object valueCurrent = AnimationModeUtility.GetCurrentValue(root, binding); //if property is "m_LocalRotation.y" create "m_LocalRotation.x" "m_LocalRotation.z" and "m_LocalRotation.w" EditorCurveBinding[] array = RotationCurveInterpolationW.RemapAnimationBindingForAddKey(binding, clip); if (array != null) { for (int j = 0; j < array.Length; j++) { AddKey(array [j], root, clip, valueCurrent, time); } } else { AddKey(binding, root, clip, valueCurrent, time); } }
/// <summary> /// Removes the keyframe from clip (!!! Inserts hidden keyframes in between) /// </summary> /// <param name="clip">Clip.</param> /// <param name="keyframeInx">Keyframe inx.</param> public static void RemoveKeyframeFrom(AnimationClip clip, EditorCurveBinding binding, int keyframeInx) { if (keyframeInx < 0) { Debug.LogWarning("Try to remove keyframe at index " + keyframeInx + " from prop:" + binding.propertyName + " from " + clip.name); return; } EditorCurveBinding[] curveBindings = RotationCurveInterpolationW.RemapAnimationBindingForAddKey(binding, clip); AnimationCurve curve; EditorCurveBinding curveBindingCurrent; if (curveBindings != null) { int curveBindingsNum = curveBindings.Length; for (int i = 0; i < curveBindingsNum; i++) { curveBindingCurrent = curveBindings [i]; curve = AnimationUtility.GetEditorCurve(clip, curveBindingCurrent); if (curve != null && curve.length > keyframeInx) { curve.RemoveKey(keyframeInx); AnimationModeUtility.SaveCurve(curve, clip, curveBindingCurrent); } } } else { curve = AnimationUtility.GetEditorCurve(clip, binding); if (curve != null && curve.length > keyframeInx) { curve.RemoveKey(keyframeInx); AnimationModeUtility.SaveCurve(curve, clip, binding); } } }
// // Custom Gizmos, Create as many as you'd like // [DrawGizmo(GizmoType.NotSelected | GizmoType.Selected)] // private static void DrawGizmo (Transform aTarget, GizmoType aGizmoType) // { // // if (__gameObjectClipList == null) // return; // // int gameObjectCount = __gameObjectClipList.count; // // Vector3[] gameObjectPositionsInTime = null; // Vector3 cubeSize = new Vector3 (0.1f, 0.1f, 0.1f); // AnimationClip clip = null; // Color clr = Color.green; // // for (int i=0; i<gameObjectCount; i++) { // // clip = (__gameObjectClipList.list [i] as EditorClipBinding).clip; // // if (clip != null) { // gameObjectPositionsInTime = AnimationUtilityEx.GetPositions (clip); // // clr = Gizmos.color; // // // Gizmos.color = Color.green; // // for (int j=0; j<gameObjectPositionsInTime.Length; j++) // Gizmos.DrawCube (gameObjectPositionsInTime [j], cubeSize); // // Gizmos.color = clr; // // } // } // } /// <summary> /// Postprocesses the animation recording and property modifications. /// </summary> /// <returns>The animation recording modifications.</returns> /// <param name="modifications">Modifications.</param> private static UndoPropertyModification[] PostprocessAnimationRecordingModifications(UndoPropertyModification[] modifications) { List <UndoPropertyModification> propertyModificationList = new List <UndoPropertyModification> (); EditorClipBinding[] clipBindings = clipBindingsSerialized.value as EditorClipBinding[]; List <EditorClipBinding> list = clipBindings.ToList(); list.Add(__mecanimNodeClipBinding); list.ForEach((itm) => { if (itm.gameObject != null && itm.clip != null) { propertyModificationList.Concat(AnimationModeUtility.Process(itm.gameObject, itm.clip, modifications, __timeCurrent)); } }); return(propertyModificationList.ToArray()); }
void OnGUI() { if (__binding != default(EditorCurveBinding)) { if (__curveEditor == null) { CurveWrapperW[] curveWrappers; __bindings = RotationCurveInterpolationW.RemapAnimationBindingForAddKey(__binding, __clip); CurveWrapperW curveWrapperNew; Color curveColor = Color.red; int curveBindingsNum = 0; EditorCurveBinding curveBindingCurrent; if (__bindings != null) { curveBindingsNum = __bindings.Length; __curves = new AnimationCurve[curveBindingsNum]; curveWrappers = new CurveWrapperW[curveBindingsNum]; for (int i = 0; i < curveBindingsNum; i++) { curveBindingCurrent = __bindings [i]; __curves [i] = AnimationUtility.GetEditorCurve(__clip, curveBindingCurrent); curveWrapperNew = new CurveWrapperW(); curveWrapperNew.curve = __curves [i]; if (i == 1) { curveColor = Color.green; } else if (i == 2) { curveColor = Color.blue; } curveWrapperNew.color = curveColor; curveWrappers [i] = curveWrapperNew; } } else { __bindings = new EditorCurveBinding[] { __binding }; __curves = new AnimationCurve[1]; __curves [0] = AnimationUtility.GetEditorCurve(__clip, __binding); curveWrappers = new CurveWrapperW[1]; curveWrapperNew = new CurveWrapperW(); curveWrapperNew.curve = __curves [0]; curveWrapperNew.color = curveColor; curveWrappers [0] = curveWrapperNew; } //This makes layout to work (Reserving space) __curveEditorRect = new Rect(0, 0, Screen.width, Screen.height); //GUILayoutUtility.GetRect (Screen.width - 16f, 200); __curveEditor = new CurveEditorW(__curveEditorRect, curveWrappers, false); __curveEditor.FrameSelected(false, true); //scale y auto __curveEditor.scaleWithWindow = true; __curveEditor.hSlider = false; __curveEditor.vSlider = false; __curveEditor.hRangeMin = __curves [0].keys [0].time; __curveEditor.hRangeMax = __clip.length; // __curves [0].keys [__curves [0].length - 1].time; __curveEditor.hRangeLocked = true; __curveEditor.Scale = new Vector2(__window.position.width / __clip.length, __curveEditor.Scale.y); //scale x manually __curveEditor.leftmargin = 0f; __curveEditor.rightmargin = 0; // __window.position.width - __curveEditor.hRangeMax * __clip.length / __window.position.width; //__curveEditor.onSelect += onCurveSelect; } else { __curveEditorRect = new Rect(0, 0, Screen.width, Screen.height); __curveEditor.rect = __curveEditorRect; //__curveEditor.Scale=new Vector2(237,__curveEditor.Scale.y); //__curveEditor.FrameSelected (false, false); } //if(Event.current.type==EventType.MouseMove || Event.current.type==EventType.ScrollWheel && !__window.position.Contains(Event.current.mousePosition)) //this.Close(); //EditorGUI.BeginChangeCheck (); // if (Event.current.type == EventType.MouseMove && !__window.position.Contains (Event.current.mousePosition)) { // this.Close (); // } if (Event.current.type == EventType.MouseDrag && Event.current.button == 0) { //if change happen change curve for (int k = 0; k < __bindings.Length; k++) { AnimationModeUtility.SaveCurve(__curves [k], __clip, __bindings [k]); //Debug.Log ("Save"); } } __curveEditor.DoEditor(); // Debug.Log ("CurveEditorWindow:"+__curveEditor.Scale + " " + __window.position.width + " " + Event.current.type); //if (EditorGUI.EndChangeCheck ()) { //} } }
private static void AddKey(EditorCurveBinding curveBindingCurrent, GameObject root, AnimationClip clip, object valueCurrent, float time) { AnimationCurve curve; Type type = null; int frameCurrent = (int)(time * clip.frameRate); UnityEngine.Object objectAnimated = AnimationUtility.GetAnimatedObject(root, curveBindingCurrent); if (curveBindingCurrent.type == TransformType) { type = typeof(float); } else { type = objectAnimated.GetType().GetField(curveBindingCurrent.propertyName).FieldType; } if (curveBindingCurrent.isPPtrCurve) { ObjectReferenceKeyframe[] keyframesCurveReferenced = AnimationUtility.GetObjectReferenceCurve(clip, curveBindingCurrent); if (keyframesCurveReferenced == null) { keyframesCurveReferenced = new ObjectReferenceKeyframe[0]; } //if you put first frame somewhere in time there should be one at 0f so curve can be made //also if you put first frame in 0f then create one in 1f if (keyframesCurveReferenced.Length == 0) { if (frameCurrent != 0) { AnimationModeUtility.AddKeyframeToObjectReferenceCurve(keyframesCurveReferenced, clip, curveBindingCurrent, valueCurrent, type, 0); } else { AnimationModeUtility.AddKeyframeToObjectReferenceCurve(keyframesCurveReferenced, clip, curveBindingCurrent, valueCurrent, type, 1f); } } AnimationModeUtility.AddKeyframeToObjectReferenceCurve(keyframesCurveReferenced, clip, curveBindingCurrent, valueCurrent, type, time); } else { curve = AnimationUtility.GetEditorCurve(clip, curveBindingCurrent); if (curve == null) { curve = new AnimationCurve(); } //if you put first frame somewhere in time there should be one at 0f so curve can be made //also if you put first frame in 0f then create one in 1f if (curve.length == 0) { if (frameCurrent != 0) { AnimationModeUtility.AddKeyframeToCurve(curve, clip, curveBindingCurrent, (float)valueCurrent, type, 0); } else { AnimationModeUtility.AddKeyframeToCurve(curve, clip, curveBindingCurrent, (float)valueCurrent, type, 1f); } } //Debug.Log("Add key at some other frame"); AnimationModeUtility.AddKeyframeToCurve(curve, clip, curveBindingCurrent, (float)valueCurrent, type, time); } }
/// <summary> /// Show the specified space, clip, node and position. /// </summary> /// <param name="space">Space.</param> /// <param name="clip">Clip.</param> /// <param name="node">Node.</param> /// <param name="position">Position.</param> public static void Show(GameObject space, AnimationClip clip, SerializedNode node, Rect?position) { MecanimNodeEditorWindow.__spaceGameObject = space; //in this case is character MecanimNodeEditorWindow.__spaceGameObjectAnimationClip = clip; MecanimNodeEditorWindow.__serializedNode = node; /////// ACCESS SERIALIZED DATA ///////// NodePropertyIterator iterator = node.GetIterator(); __isPlaying = false; __isRecording = false; __variableSelected = null; __timeNormalized = 0f; __timeNormalizedUpdate = false; __timeCurrent = 0f; AnimationMode.StopAnimationMode(); Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; SceneView.onSceneGUIDelegate += OnSceneGUI; if (iterator.Find("clipBindings")) { clipBindingsSerialized = iterator.current; } if (__mecanimNodeClipBinding == null) { __mecanimNodeClipBinding = ScriptableObject.CreateInstance <EditorClipBinding> (); } __mecanimNodeClipBinding.gameObject = __spaceGameObject; __mecanimNodeClipBinding.clip = __spaceGameObjectAnimationClip; /////// INIT SERIALIZED NODE PROPERTIES - CURVES, COLORS, VARIABLES ////// if (iterator.Find("curves")) { curvesSerialized = iterator.current; } else { Debug.LogError("MecananimNode should have public field 'curves'"); } if (iterator.Find("curvesColors")) { curvesColorsSerialized = iterator.current; } else { Debug.LogError("MecananimNode should have public field 'curvesColors'"); } if (iterator.Find("variablesBindedToCurves")) { variablesBindedToCurvesSerialized = iterator.current; } else { Debug.LogError("MecananimNode should have public field 'variablesBindedToCurves'"); } curves = (AnimationCurve[])curvesSerialized.value; curveColors = (Color[])curvesColorsSerialized.value; variablesBindedToCurves = (UnityVariable[])variablesBindedToCurvesSerialized.value; AnimationModeUtility.ResetBindingsTransformPropertyModification(clipBindingsSerialized.value as EditorClipBinding[]); AnimationModeUtility.ResetBindingTransformPropertyModification(__mecanimNodeClipBinding); keyframeTimeValues = new float[0]; eventTimeValuesPrev = new float[0]; keyframeTimeValuesSelected = new bool[0]; keyframesDisplayNames = new string[0]; ///////////// create Reordable list of gameObject-animationClip ////////////////// __gameObjectClipList = new ReorderableList(clipBindingsSerialized.value as IList, typeof(EditorClipBinding), true, true, true, true); __gameObjectClipList.drawElementCallback = onDrawElement; __gameObjectClipList.drawHeaderCallback = onDrawHeaderElement; __gameObjectClipList.onRemoveCallback = onRemoveCallback; __gameObjectClipList.onAddCallback = onAddCallback; __gameObjectClipList.onSelectCallback = onSelectCallback; //__gameObjectClipList.elementHeight = 32f; if (MecanimNodeEditorWindow.__window != null) //restore last { position = __window.position; } MecanimNodeEditorWindow.__window = (MecanimNodeEditorWindow)EditorWindow.GetWindow(typeof(MecanimNodeEditorWindow)); if (position.HasValue) { MecanimNodeEditorWindow.__window.position = position.Value; } MecanimNodeEditorWindow.__window.Show(); }
/// <summary> /// Handles the GUI event. /// </summary> void OnGUI() { if (_keyframeMarker == null) { _keyframeMarker = new GUIContent(EditorGUILayoutEx.ANIMATION_STYLES.pointIcon); } if (!Application.isPlaying && __gameObjectClipList != null) { _curvesEditorShow = EditorGUILayout.Foldout(_curvesEditorShow, "Curves"); //int indentLevel = 0; Rect curveEditorRect = new Rect(0, 0, 0, 0); int i = 0; if (_curvesEditorShow) { //This makes layout to work (Reserving space) curveEditorRect = GUILayoutUtility.GetRect(Screen.width - 16f, 200); /////// CURVE EDITOR //////// curveEditorRect.width = curveEditorRect.width - 32f; curveEditorRect.x = 16f; if (curveEditor == null) { CurveWrapperW[] curveWrappers; int numCurves = curves.Length; curveWrappers = new CurveWrapperW[numCurves]; CurveWrapperW curveWrapperNew; for (i = 0; i < numCurves; i++) { curveWrapperNew = new CurveWrapperW(); curveWrapperNew.curve = curves [i]; curveWrapperNew.color = curveColors [i]; curveWrappers [i] = curveWrapperNew; } curveEditor = new CurveEditorW(curveEditorRect, curveWrappers, false); curveEditor.FrameSelected(true, true); curveEditor.scaleWithWindow = true; curveEditor.hSlider = false; curveEditor.hRangeMin = 0f; curveEditor.hRangeMax = 1f; curveEditor.hRangeLocked = true; curveEditor.onSelect += onCurveSelect; } else { curveEditor.rect = curveEditorRect; curveEditor.FrameSelected(false, false); } curveEditor.DoEditor(); /////////////////////////////////////////////////////////////////////////////// ///////////// ADD/REMOVE CURVE BINDED TO OBJECT PROP OR GLOBAL VARIABLE ///////////// /// // EditorGUILayout.BeginHorizontal(); //if curve is selected display curve properties if (_curveIndexSelected > -1 && _curveIndexSelected < variablesBindedToCurves.Length) { UnityVariable variableSelected = variablesBindedToCurves [_curveIndexSelected]; try { bindingCurvesGUIContent.text = variableSelected.instanceBinded.name + "." + variableSelected.memberPath; EditorGUILayout.LabelField(bindingCurvesGUIContent, new GUILayoutOption[] {}); EditorGUI.BeginChangeCheck(); Color colorNew = EditorGUILayout.ColorField(curveColors [_curveIndexSelected]); if (EditorGUI.EndChangeCheck()) { curveEditor.animationCurves [_curveIndexSelected].color = colorNew; curveColors [_curveIndexSelected] = colorNew; curvesColorsSerialized.ValueChanged(); curvesColorsSerialized.ApplyModifiedValue(); } } catch (MissingReferenceException ex) { bindingCurvesGUIContent.text = "Invalid UVariable " + ex.Message; } } else { bindingCurvesGUIContent.text = "Curve binding:"; List <UnityVariable> blackboardLocalList = (MecanimNodeEditorWindow.__serializedNode.target.blackboard as BlackboardCustom).GetVariableBy(typeof(float)); List <GUIContent> displayOptionsList = blackboardLocalList.Select((item) => new GUIContent("Local/" + item.name)).ToList(); __variableSelected = EditorGUILayoutEx.UnityVariablePopup(bindingCurvesGUIContent, __variableSelected, typeof(float), displayOptionsList, blackboardLocalList); _colorSelected = EditorGUILayout.ColorField(_colorSelected); } /////////////// ADD CURVE(+) ///////// if (GUILayout.Button("Add") && __variableSelected != null) { List <UnityVariable> vList = variablesBindedToCurves.ToList(); vList.Add(__variableSelected); variablesBindedToCurvesSerialized.value = variablesBindedToCurves = vList.ToArray(); variablesBindedToCurvesSerialized.ValueChanged(); //variablesBindedToCurvesSerialized.ApplyModifiedValue (); List <Color> cList = curveColors.ToList(); _colorSelected.a = 1; cList.Add(_colorSelected); curvesColorsSerialized.value = curveColors = cList.ToArray(); curvesColorsSerialized.ValueChanged(); //curvesColorsSerialized.ApplyModifiedValue (); AnimationCurve curveAnimationNew; List <AnimationCurve> crList = curves.ToList(); curveAnimationNew = new AnimationCurve(new Keyframe[] { new Keyframe(0f, (float)__variableSelected.Value), new Keyframe(1f, 1f) }); //TODO add from preset crList.Add(curveAnimationNew); curvesSerialized.value = curves = crList.ToArray(); curvesSerialized.ValueChanged(); //curvesColorsSerialized.ApplyModifiedValue (); ///add curve wrapped to CurveEditor CurveWrapperW curveWrapperW = new CurveWrapperW(); curveWrapperW.color = _colorSelected; curveWrapperW.curve = curveAnimationNew; curveEditor.AddCurve(curveWrapperW); curveEditor.FrameSelected(true, true); __serializedNode.Update(); __serializedNode.ApplyModifiedProperties(); __variableSelected = null; } ///////////// DELETE CURVE //////////// if (GUILayout.Button("Del") || Event.current.keyCode == KeyCode.Delete) { curveEditor.RemoveCurveAt(_curveIndexSelected); List <UnityVariable> vList = variablesBindedToCurves.ToList(); vList.RemoveAt(_curveIndexSelected); variablesBindedToCurvesSerialized.value = variablesBindedToCurves = vList.ToArray(); variablesBindedToCurvesSerialized.ValueChanged(); List <Color> cList = curveColors.ToList(); cList.RemoveAt(_curveIndexSelected); curvesColorsSerialized.value = curveColors = cList.ToArray(); curvesColorsSerialized.ValueChanged(); List <AnimationCurve> crList = curves.ToList(); crList.RemoveAt(_curveIndexSelected); curvesSerialized.value = curves = crList.ToArray(); curvesSerialized.ValueChanged(); _curveIndexSelected = -1; __variableSelected = null; __serializedNode.ApplyModifiedProperties(); } EditorGUILayout.EndHorizontal(); } else //NOT CURVE EDITOR ///////////// GAMEOBJECT - CLIP BINDINGS ////////// { __gameObjectClipList.DoLayoutList(); ////////////////////////////////////////////// } EditorGUILayout.Space(); __mecanimNodeClipBinding.clip = __spaceGameObjectAnimationClip; ///////////// TIME CONTROL OF ANIMATION (SLIDER) ///////// Rect timeControlRect = GUILayoutUtility.GetRect(Screen.width, 26f); timeControlRect.xMax = 32f; ///////////// PLAY ANIMATION TOGGLE ///////// __isPlaying = GUI.Toggle(timeControlRect, __isPlaying, !__isPlaying ? EditorGUILayoutEx.ANIMATION_STYLES.playIcon : EditorGUILayoutEx.ANIMATION_STYLES.pauseIcon, EditorGUILayoutEx.ANIMATION_STYLES.playButton); if (__isPlaying) { } else { } timeControlRect.xMin = timeControlRect.xMax + 1f; timeControlRect.xMax = timeControlRect.xMin + 21f; timeControlRect.yMin += 2f; EditorGUI.BeginChangeCheck(); Color color = GUI.color; //save color if (AnimationMode.InAnimationMode()) { GUI.color = AnimationMode.animatedPropertyColor; //change color of record button to red } ///////////// RECORD ANIMATION TOGGLE ///////// __isRecording = GUI.Toggle(timeControlRect, __isRecording, EditorGUILayoutEx.ANIMATION_STYLES.recordIcon, EditorStyles.toolbarButton); GUI.color = color; //restore color if (EditorGUI.EndChangeCheck()) { if (__isRecording) { if (!AnimationMode.InAnimationMode()) { List <EditorClipBinding> list = (clipBindingsSerialized.value as EditorClipBinding[]).ToList(); list.Add(__mecanimNodeClipBinding); __clipBindingsToBeAnimated = list.ToArray(); AnimationMode.StartAnimationMode(); Undo.postprocessModifications += PostprocessAnimationRecordingModifications; //calculate offset of boonRoot position before animation from boonRoot position at time=0s. AnimationModeUtility.SaveBindingsOffset(clipBindingsSerialized.value as EditorClipBinding[]); AnimationModeUtility.SaveBindingOffset(__mecanimNodeClipBinding); //calculate time in seconds from the current postion of time scrubber __timeCurrent = __timeNormalized * __spaceGameObjectAnimationClip.length; //apply clip animaiton at __timeCurrent AnimationModeUtility.SampleClipBindingAt(__clipBindingsToBeAnimated , __timeCurrent); LockRootGameObject(true); SceneView.RepaintAll(); } } else { //Remove Undo property modificaiton handlers Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; AnimationMode.StopAnimationMode(); //reset gameobject with bones to state before animation AnimationModeUtility.ResetBindingsTransformPropertyModification(clipBindingsSerialized.value as EditorClipBinding[]); //reset Node.self gameObject AnimationModeUtility.ResetBindingTransformPropertyModification(__mecanimNodeClipBinding); LockRootGameObject(false); } } timeControlRect.xMin = 40f + 16f; timeControlRect.xMax = Screen.width - 68f; timeControlRect.yMin -= 2f; EditorGUI.BeginChangeCheck(); /// TIMELINE SLIDER /// __timeNormalized = EditorGUILayoutEx.CustomHSlider(timeControlRect, __timeNormalized, 0f, 1f, EditorGUILayoutEx.ANIMATION_STYLES.timeScrubber); if (EditorGUI.EndChangeCheck() || __timeNormalizedUpdate) { __timeCurrent = __timeNormalized * __spaceGameObjectAnimationClip.length; __timeNormalizedUpdate = false; if (!AnimationMode.InAnimationMode()) { AnimationMode.StartAnimationMode(); //calculate offset of boonRoot position before animation from boonRoot position at time=0s. AnimationModeUtility.SaveBindingsOffset(clipBindingsSerialized.value as EditorClipBinding[]); AnimationModeUtility.SaveBindingOffset(__mecanimNodeClipBinding); LockRootGameObject(true); } if (!__isRecording) { __isRecording = true; //add recording Undo events handlers Undo.postprocessModifications += PostprocessAnimationRecordingModifications; List <EditorClipBinding> list = (clipBindingsSerialized.value as EditorClipBinding[]).ToList(); list.Add(__mecanimNodeClipBinding); __clipBindingsToBeAnimated = list.ToArray(); } //moves clip to time: __timeCurrent AnimationModeUtility.SampleClipBindingAt(__clipBindingsToBeAnimated, __timeCurrent); } ///////////// ROTATION/SCALE KEYFRAMES ///////////////////////// Rect keyframesRect = GUILayoutUtility.GetRect(Screen.width - 16f, 16f); keyframesRect.xMax = timeControlRect.xMax + _keyframeMarker.image.width * 0.5f; keyframesRect.xMin = timeControlRect.xMin - _keyframeMarker.image.width * 0.5f; //Show rotation or scale keyframes if Rotation or Scale tools are selected if (Selection.activeGameObject != null) { if (Tools.current == Tool.Rotate) { EditorClipBinding clipBindingCurrent = (clipBindingsSerialized.value as EditorClipBinding[]).FirstOrDefault((itm) => itm.gameObject != null && itm.gameObject.transform.childCount > 0 && itm.gameObject.transform.GetChild(0).gameObject == Selection.activeGameObject); if (clipBindingCurrent != null && clipBindingCurrent.visible && clipBindingCurrent.clip != null) { EditorCurveBinding curveBinding = AnimationUtilityEx.EditorCurveBinding_RotX; curveBinding.path = AnimationUtility.CalculateTransformPath(clipBindingCurrent.gameObject.transform.GetChild(0), clipBindingCurrent.gameObject.transform.root); keyframeTimeValues = AnimationUtilityEx.GetTimesNormalized(clipBindingCurrent.clip, curveBinding, __spaceGameObjectAnimationClip.length); } else { keyframeTimeValues = new float[0]; } } else if (Tools.current == Tool.Scale) { EditorClipBinding clipBindingCurrent = (clipBindingsSerialized.value as EditorClipBinding[]).FirstOrDefault((itm) => itm.gameObject != null && itm.gameObject.transform.childCount > 0 && itm.gameObject.transform.GetChild(0).gameObject == Selection.activeGameObject); if (clipBindingCurrent != null && clipBindingCurrent.visible && clipBindingCurrent.clip != null) { EditorCurveBinding curveBinding = AnimationUtilityEx.EditorCurveBinding_SclX; curveBinding.path = AnimationUtility.CalculateTransformPath(clipBindingCurrent.gameObject.transform.GetChild(0), clipBindingCurrent.gameObject.transform.root); keyframeTimeValues = AnimationUtilityEx.GetTimesNormalized(clipBindingCurrent.clip, curveBinding, __spaceGameObjectAnimationClip.length); } else { keyframeTimeValues = new float[0]; } } else { keyframeTimeValues = new float[0]; } } else { keyframeTimeValues = new float[0]; } keyframesDisplayNames = keyframeTimeValues.Select((itm) => { return(Decimal.Round(Convert.ToDecimal(itm * __spaceGameObjectAnimationClip.length), 2).ToString() + ".s"); }).ToArray(); keyframeTimeValuesSelected = new bool[keyframeTimeValues.Length]; //used for multiselection option not used here //create custom timeline showing rotation or scale keyframes EditorGUILayoutEx.CustomTimeLine(ref keyframesRect, _keyframeMarker, ref keyframeTimeValues, ref eventTimeValuesPrev, ref keyframesDisplayNames, ref keyframeTimeValuesSelected, -1f, null, onKeyframeDelete, null, onKeyframeEdit, null ); // DISPLAY TIME in [s] and in [%] EditorGUILayout.LabelField("Time: " + Decimal.Round(Convert.ToDecimal(__timeCurrent), 2).ToString() + "s (" + Mathf.FloorToInt(__timeNormalized * 100) + "%) Frame:" + Mathf.FloorToInt(__timeCurrent * __spaceGameObjectAnimationClip.frameRate).ToString()); /////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// /// /// Draw red time scrubber line on top of Curve Editor /// ////////////////////////////////////////////////////////////// if (_curvesEditorShow) { Handles.color = Color.red; float leftrightMargin = 39f; // 40f; float effectiveWidth = curveEditorRect.width - 2 * leftrightMargin - curveEditorRect.xMin; float timeLineX = curveEditorRect.xMin + leftrightMargin + effectiveWidth * __timeNormalized; Handles.DrawLine(new Vector2(timeLineX, curveEditorRect.y), new Vector2(timeLineX, curveEditorRect.y + curveEditorRect.height)); } ////////// EVALUATE CURVES ////////// int variablesNum = variablesBindedToCurves.Length; for (int varriableCurrentinx = 0; varriableCurrentinx < variablesNum; varriableCurrentinx++) { try { variablesBindedToCurves [varriableCurrentinx].Value = curves [varriableCurrentinx].Evaluate(__timeNormalized); } catch (Exception ex) { variablesBindedToCurves [varriableCurrentinx].name = "Invalid UVariable" + ex.Message; } } } }