public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
                {
                    ScriptPlayable <Spine3DAnimatorChannelTrackMixer> playable = TimelineUtils.CreateTrackMixer <Spine3DAnimatorChannelTrackMixer>(this, graph, go, inputCount);
                    Spine3DAnimatorTrack parentTrack = this.parent as Spine3DAnimatorTrack;

                    if (parentTrack != null)
                    {
                        Spine3DAnimatorTrackMixer parentMixer = TimelineUtils.GetTrackMixer <Spine3DAnimatorTrackMixer>(graph, parentTrack);

                        if (parentMixer != null)
                        {
                            Spine3DAnimatorChannelTrackMixer mixer = playable.GetBehaviour();
                            mixer.Init(parentMixer);

                            IEnumerable <TimelineClip> clips = GetClips();

                            foreach (TimelineClip clip in clips)
                            {
                                Spine3DAnimationClipAsset animationClip = clip.asset as Spine3DAnimationClipAsset;

                                if (animationClip != null)
                                {
                                    clip.displayName = animationClip._animationId;
                                    animationClip.SetParentTrack(parentTrack);
                                }
                            }
                        }
                    }

                    return(playable);
                }
                    private static Spine3DAnimator GetClipBoundAnimator(Spine3DAnimationClipAsset clip)
                    {
                        PlayableDirector selectedDirector = TimelineEditor.inspectedDirector;

                        if (selectedDirector != null)
                        {
                            return(selectedDirector.GetGenericBinding(clip.GetParentTrack()) as Spine3DAnimator);
                        }

                        return(null);
                    }
                protected override void OnCreateClip(TimelineClip clip)
                {
                    Spine3DAnimatorTrack parentTrack = this.parent as Spine3DAnimatorTrack;

                    if (parentTrack != null)
                    {
                        Spine3DAnimationClipAsset animationClip = clip.asset as Spine3DAnimationClipAsset;

                        if (animationClip != null)
                        {
                            animationClip.SetParentTrack(parentTrack);
                        }
                    }
                }
                    public override void OnInspectorGUI()
                    {
                        serializedObject.Update();

                        SerializedProperty animationIdProperty       = serializedObject.FindProperty("_animationId");
                        SerializedProperty animationDurationProperty = serializedObject.FindProperty("_animationDuration");
                        SerializedProperty animationSpeedProperty    = serializedObject.FindProperty("_animationSpeed");

                        Spine3DAnimationClipAsset clip     = (Spine3DAnimationClipAsset)target;
                        Spine3DAnimator           animator = GetClipBoundAnimator(clip);

                        if (animator != null)
                        {
                            string[] animationNames = animator.GetAnimationNames();

                            int currentIndex = -1;

                            for (int i = 0; i < animationNames.Length; i++)
                            {
                                if (animationNames[i] == animationIdProperty.stringValue)
                                {
                                    currentIndex = i;
                                    break;
                                }
                            }

                            int index = EditorGUILayout.Popup("Animation", currentIndex == -1 ? 0 : currentIndex, animationNames);

                            if (currentIndex != index)
                            {
                                clip.name = animationNames[index];
                                animationIdProperty.stringValue       = animationNames[index];
                                animationDurationProperty.doubleValue = animator.GetAnimationLength(animationNames[index]);
                            }
                        }
                        else
                        {
                            GUI.enabled = false;
                            EditorGUILayout.PropertyField(animationIdProperty);
                            GUI.enabled = true;
                        }

                        EditorGUILayout.PropertyField(animationSpeedProperty);

                        serializedObject.ApplyModifiedProperties();
                    }