/// <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.GetTimes (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.GetTimes (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; } } } }
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 ()) { //} } }
/// <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; } } } }