/// <summary>
        /// The custom inspector.
        /// </summary>
        public override void OnInspectorGUI()
        {
            int i = 0;



            //////  RESTORE SAVED  //////
            //restore and delete clipboard


            mecanimNode = target as MecanimNode;

            if (mecanimNode != null)
            {
                Motion motion = null;



                //////////////////////////////////////////////////////////////
                ///                         PRESEVE RESTORE					//
                if (EditorApplication.isPlaying || EditorApplication.isPaused)
                {
                    if (GUILayout.Button("Preserve"))
                    {
                        serializedNode.ApplyModifiedProperties();

                        UnityVariable.SetDirty(mecanimNode.blendX);

                        UnityVariable.SetDirty(mecanimNode.blendY);
                        UnityVariable.SetDirty(mecanimNode.motionOverride);

//												if (variablesBindedToCurves != null) {
//														UnityVariable[] varArray = variablesBindedToCurves;
//
//														int varNumber = varArray.Length;
//														for (int varCurrent=0; varCurrent<varNumber; varCurrent++) {
//																varArray [varCurrent].OnBeforeSerialize ();
//
//														}
//												}


                        EditorUtilityEx.Clipboard.preserve(mecanimNode.instanceID, mecanimNode, mecanimNode.GetType().GetFields());
                    }
                }
                else
                {
                    if (EditorUtilityEx.Clipboard.HasBeenPreseved(mecanimNode.instanceID) && GUILayout.Button("Apply Playmode Changes"))
                    {
                        EditorUtilityEx.Clipboard.restore(mecanimNode.instanceID, mecanimNode);

                        animatorStateSerialized = null;
                        NodePropertyIterator iterator = serializedNode.GetIterator();



                        while (iterator.Next(true))
                        {
                            if (iterator.current.value is UnityVariable)
                            {
                                //Debug.Log("OnBeforeDeserialize:"+((UnityVariable)iterator.current.value).Value);
                                ((UnityVariable)iterator.current.value).OnAfterDeserialize();

                                //Debug.Log("OnAfterDeserialize:"+((UnityVariable)iterator.current.value).Value);
                            }
                            else if (iterator.current.value is UnityVariable[])
                            {
                                UnityVariable[] varArray  = (UnityVariable[])iterator.current.value;
                                int             varNumber = varArray.Length;
                                for (int varCurrent = 0; varCurrent < varNumber; varCurrent++)
                                {
                                    varArray [varCurrent].OnAfterDeserialize();
                                }
                            }


                            iterator.current.ValueChanged();

                            this.serializedNode.Update();

                            iterator.current.ApplyModifiedValue();
                        }
                    }
                }
                //////////////////////


                if (Event.current.type == EventType.Layout)
                {
                    this.serializedNode.Update();
                }



                DrawDefaultInspector();

//
//				if (EditorGUILayoutEx.ANIMATION_STYLES == null)
//					EditorGUILayoutEx.ANIMATION_STYLES = new EditorGUILayoutEx.AnimationStyles ();



                /////////////////////////////// ANIMATOR STATE /////////////////////////////////

                if (animatorStateSerialized == null)
                {
                    NodePropertyIterator iterator = this.serializedNode.GetIterator();
                    if (iterator.Find("animatorStateSelected"))
                    {
                        animatorStateSerialized = iterator.current;
                    }


                    if (iterator.Find("motionOverride"))
                    {
                        motionOverrideSerialized = iterator.current;
                    }
                }



                //////////  MOTION OVERRIDE HANDLING  //////////
                if (animatorStateSerialized.value != null)
                {
                    UnityVariable motionOverridVariable = (UnityVariable)motionOverrideSerialized.value;

                    //if there are no override use motion of selected AnimationState
                    //Debug.Log(((UnityEngine.Object)mecanimNode.motionOverride.Value).);
                    if (motionOverridVariable == null || motionOverridVariable.Value == null || motionOverridVariable.ValueType != typeof(AnimationClip))
                    {
                        motion = ((ws.winx.unity.AnimatorState)animatorStateSerialized.value).motion;
                    }
                    else                                                             //
                    {
                        motion = (Motion)motionOverridVariable.Value;
                    }



                    if (motionOverridVariable != null && motionOverridVariable.Value != null && ((ws.winx.unity.AnimatorState)animatorStateSerialized.value).motion == null)
                    {
                        Debug.LogError("Can't override state that doesn't contain motion");
                    }
                }
                ///////////////////////////////////////////////////

                if (GUILayout.Button("BindEditor") && motion != null)
                {
                    MecanimNodeEditorWindow.Show(mecanimNode.self, motion as AnimationClip, this.serializedNode, null);
                }

                /////////////   TIME CONTROL OF ANIMATION (SLIDER) /////////
                if (Application.isPlaying)
                {
                    if (animatorStateRuntimeControlEnabledSerialized == null)
                    {
                        NodePropertyIterator iterator = this.serializedNode.GetIterator();

                        if (iterator.Find("animationRunTimeControlEnabled"))
                        {
                            animatorStateRuntimeControlEnabledSerialized = iterator.current;
                        }

                        if (iterator.Find("animatorStateRunTimeControl"))
                        {
                            animatorStateRunTimeControlSerialized = iterator.current;
                        }
                    }



                    if (animatorStateRuntimeControlEnabledSerialized != null && animatorStateRunTimeControlSerialized != null && (bool)animatorStateRuntimeControlEnabledSerialized.value)
                    {
                        Rect timeControlRect = GUILayoutUtility.GetRect(Screen.width - 16f, 26f);
                        timeControlRect.xMin += 38f;
                        timeControlRect.xMax -= 70f;
                        animatorStateRunTimeControlSerialized.value = EditorGUILayoutEx.CustomHSlider(timeControlRect, (float)animatorStateRunTimeControlSerialized.value, 0f, 1f, EditorGUILayoutEx.ANIMATION_STYLES.timeScrubber);
                    }
                }
                ///////////////////////////////////////////////////////////////


                /////////// AVATAR Preview GUI ////////////


                if (!Application.isPlaying && motion != null)
                {
                    //This makes layout to work (Reserving space)
                    Rect avatarRect = GUILayoutUtility.GetRect(Screen.width - 16f, 200);
                    avatarRect.width -= 70f;
                    avatarRect.xMin  += 6f;


                    if (avatarPreview == null)
                    {
                        avatarPreview = new AvatarPreviewW(null, motion);
                    }
                    else
                    {
                        avatarPreview.SetPreviewMotion(motion);
                    }



                    EditorGUILayout.BeginHorizontal();



                    if (eventTimeValues != null && Event.current.type == EventType.Repaint)
                    {
                        //find first selected if exist
                        int eventTimeValueSelectedIndex = Array.IndexOf(eventTimeValuesSelected, true);



                        if (eventTimeValueSelectedIndex > -1)
                        {
                            avatarPreview.SetTimeAt(eventTimeValues [eventTimeValueSelectedIndex]);
                        }
                        else
                        {
                            //!!! changing
                            //avatarPreview.timeControl.startTime
                            // start/stop makes AvatarPreview to play from start to stop
                            // and the rest of animation isn't visible in Timeline so not good for selecting range
                            // but its not offer good usability of resized animation


                            if (avatarPreview.timeControl.playing)
                            {
                                //restrict animation into this range
                                if (avatarPreview.timeControl.normalizedTime < mecanimNode.range.rangeStart || avatarPreview.timeControl.normalizedTime > mecanimNode.range.rangeEnd)
                                {
                                    avatarPreview.timeControl.nextCurrentTime = avatarPreview.timeControl.startTime * (1f - mecanimNode.range.rangeStart) + avatarPreview.timeControl.stopTime * mecanimNode.range.rangeStart;
                                }
                            }
                            else
                            {
                                //set AvatarPreview animation time range depending of drag of range control handles
                                if (Math.Abs(mecanimNode.range.rangeStart - timeNormalizedStartPrev) > 0.01f)
                                {
                                    timeNormalizedStartPrev = mecanimNode.range.rangeStart;

                                    avatarPreview.SetTimeAt(timeNormalizedStartPrev);
                                }
                                else
                                if (Math.Abs(mecanimNode.range.rangeEnd - timeNormalizedEndPrev) > 0.01f)
                                {
                                    timeNormalizedEndPrev = mecanimNode.range.rangeEnd;
                                    avatarPreview.SetTimeAt(timeNormalizedEndPrev);
                                }
                            }
                        }
                    }



                    avatarPreview.timeControl.playbackSpeed = mecanimNode.speed;



                    avatarPreview.DoAvatarPreview(avatarRect, GUIStyle.none);



                    //Debug.Log(avatarPreview.timeControl.currentTime+" "+);
                    EditorGUILayout.EndHorizontal();



                    ////////// Events Timeline GUI //////////

                    if (!eventTimeLineInitalized)
                    {
                        //TODO calculate PopupRect

                        eventTimeLineValuePopUpRect = new Rect((Screen.width - 250) * 0.5f, (Screen.height - 150) * 0.5f, 250, 150);


                        //select the time values from nodes
                        //eventTimeValues = mecanimNode.children.Select ((val) => (float)((SendEventNormalized)val).timeNormalized.Value).ToArray ();


                        eventTimeValues = mecanimNode.children.Select((val) => (float)(((SendEventNormalizedNode)val).timeNormalized.serializedProperty as SerializedProperty).floatValue).ToArray();


                        eventDisplayNames       = mecanimNode.children.Select((val) => ((SendEventNormalizedNode)val).name).ToArray();
                        eventTimeValuesSelected = new bool[eventTimeValues.Length];

                        playButtonStyle = "TimeScrubberButton";

                        if (playButtonStyle != null)
                        {
                            playButtonSize = playButtonStyle.CalcSize(new GUIContent());
                        }

                        eventTimeLineInitalized = true;
                    }



                    Rect timeLineRect = GUILayoutUtility.GetRect(Screen.width - 16f, 50f);
                    //Rect timeLineRect = GUILayoutUtility.GetLastRect ();


                    Texture eventMarkerTexture = EditorGUILayoutEx.ANIMATION_STYLES.eventMarker.image;
                    timeLineRect.xMin += playButtonSize.x - eventMarkerTexture.width * 0.5f;
                    timeLineRect.xMax -= eventMarkerTexture.width * 0.5f;
                    //timeLineRect.height = EditorGUILayoutEx.eventMarkerTexture.height * 3 * 0.66f + playButtonSize.y;
                    timeLineRect.width -= 66f;
                    EditorGUILayoutEx.CustomTimeLine(ref timeLineRect, new GUIContent(eventMarkerTexture), ref eventTimeValues, ref eventTimeValuesPrev, ref eventDisplayNames, ref eventTimeValuesSelected, avatarPreview.timeControl.normalizedTime,
                                                     onMecanimEventAdd, onMecanimEventDelete, onMecanimEventClose, onMecanimEventEdit, onMecanimEventDragEnd
                                                     );

                    EditorGUILayout.LabelField("Events Timeline");

                    SendEventNormalizedNode ev;



                    //update time values
                    int eventTimeValuesNumber = mecanimNode.children.Length;
                    for (i = 0; i < eventTimeValuesNumber; i++)
                    {
                        ev = ((SendEventNormalizedNode)mecanimNode.children [i]);
                        //ev.timeNormalized.Value = eventTimeValues [i];
                        ev.timeNormalized.Value = eventTimeValues [i];

                        //if changes have been made in pop editor or SendEventNormailized inspector
                        if (ev.name != eventDisplayNames [i])
                        {
                            eventDisplayNames [i] = ((SendEventNormalizedNode)mecanimNode.children [i]).name;
                        }

                        EditorUtilityEx.ApplySerializedPropertyChangeTo(ev.timeNormalized);
                        //ev.timeNormalized.ApplyModifiedProperties ();
                    }



                    // Restore the indent level
                    //EditorGUI.indentLevel = indentLevel;

                    // Apply modified properties
                    this.serializedNode.ApplyModifiedProperties();
                }
            }
        }
Esempio n. 2
0
        /// <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;
                    }
                }
            }
        }