protected virtual void OnDrawSubTrack(Rect rect, int index, bool selected, bool focused)
                    {
                        float columnWidth = rect.width / 3f;
                        SpineAnimatorChannelTrack track = _channelTracks.list[index] as SpineAnimatorChannelTrack;

                        if (track != null)
                        {
                            rect.width = columnWidth;
                            GUI.Label(rect, track._animationChannel.ToString(), EditorStyles.label);
                            rect.x += columnWidth;
                            GUI.Label(rect, track.duration.ToString(), EditorStyles.label);
                            rect.x += columnWidth;
                            GUI.Label(rect, ArrayUtils.GetCount(track.GetClips()).ToString(), EditorStyles.label);
                        }
                    }
                    protected virtual void AddChanelToTrack(SpineAnimatorTrack spineAnimatorTrack)
                    {
                        if (spineAnimatorTrack != null)
                        {
                            //Work out next free channel to add
                            int channel = 0;

                            foreach (SpineAnimatorChannelTrack track in spineAnimatorTrack.GetChildTracks())
                            {
                                if (track != null)
                                {
                                    channel = Mathf.Max(channel, track._animationChannel + 1);
                                }
                            }

                            SpineAnimatorChannelTrack newTrack = TimelineEditorUtils.CreateChildTrack <SpineAnimatorChannelTrack>(spineAnimatorTrack, "Channel " + channel);
                            newTrack._animationChannel = channel;
                        }
                    }
                protected virtual void PrepareChannelFrame(Playable playable)
                {
                    int numInputs = playable.GetInputCount();

                    SpineAnimatorTrackMixer.ChannelAnimationData        primaryAnimation     = new SpineAnimatorTrackMixer.ChannelAnimationData();
                    List <SpineAnimatorTrackMixer.ChannelAnimationData> backgroundAnimations = new List <SpineAnimatorTrackMixer.ChannelAnimationData>();

                    for (int i = 0; i < numInputs; i++)
                    {
                        ScriptPlayable <SpineAnimatorPlayableBehaviour> scriptPlayable = (ScriptPlayable <SpineAnimatorPlayableBehaviour>)playable.GetInput(i);
                        SpineAnimatorPlayableBehaviour inputBehaviour = scriptPlayable.GetBehaviour();

                        if (inputBehaviour != null && inputBehaviour._animation != null)
                        {
                            float inputWeight = playable.GetInputWeight(i);

                            if (inputWeight > 0.0f)
                            {
                                TimelineClip clip = TimelineUtils.GetClip(_trackAsset, inputBehaviour._clipAsset);

                                if (clip != null)
                                {
                                    double clipStart    = clip.hasPreExtrapolation ? clip.extrapolatedStart : clip.start;
                                    double clipDuration = clip.hasPreExtrapolation || clip.hasPostExtrapolation ? clip.extrapolatedDuration : clip.duration;

                                    if (_director.time >= clipStart && _director.time <= clipStart + clipDuration)
                                    {
                                        bool isPrimaryClip = IsPrimaryClip(clip);

                                        //Work out track time
                                        float animationDuration = inputBehaviour._animation.Duration;
                                        float trackTime         = GetExtrapolatedTrackTime(clip, _director.time, animationDuration);

                                        if (isPrimaryClip)
                                        {
                                            primaryAnimation._animation       = inputBehaviour._animation;
                                            primaryAnimation._animationTime   = trackTime;
                                            primaryAnimation._animationWeight = inputWeight;
                                            primaryAnimation._animationSpeed  = inputBehaviour._animationSpeed;
                                        }
                                        else
                                        {
                                            SpineAnimatorTrackMixer.ChannelAnimationData backroundAnimation = new SpineAnimatorTrackMixer.ChannelAnimationData
                                            {
                                                _animation       = inputBehaviour._animation,
                                                _animationTime   = trackTime,
                                                _animationWeight = 1.0f,
                                                _animationSpeed  = inputBehaviour._animationSpeed,
                                            };
                                            backgroundAnimations.Add(backroundAnimation);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    SpineAnimatorTrackMixer   parentMixer = (SpineAnimatorTrackMixer)_parentMixer;
                    SpineAnimatorChannelTrack track       = (SpineAnimatorChannelTrack)_trackAsset;

                    parentMixer.SetChannelData(track._animationChannel, primaryAnimation, backgroundAnimations.ToArray());
                }