// Check the AnimOperator class for the different supported operator types.
        // This sample simply deletes the frames after the currently selected clip.
        public override bool OnFrameGroupInspectorGUI(tk2dSpriteAnimationClip selectedClip, 
					List<ClipEditor.FrameGroup> frameGroups, 
					TimelineEditor.State state )
        {
            // WrapMode.Single is a special case - you are only allowed to have one frame in a "Single" clip.
            // If you don't handle this, tk2d will truncate the list when it is Committed.
            if (selectedClip.wrapMode == tk2dSpriteAnimationClip.WrapMode.Single)
                return false;

            // Keep track of changes.
            // In a lot of cases, a simple bool will suffice. This is used later to
            // tell the system that something has changed.
            bool changed = false;
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Ins <-", EditorStyles.miniButton))
            {
                frameGroups.Insert(state.selectedFrame,
                    AnimOperatorUtil.NewFrameGroup(frameGroups, state.selectedFrame));
                // Make sure state is valid after performing your operation.
                // For instance, if the selected frame is deleted, ensure it isn't selected any more.
                state.selectedFrame++;
                changed = true;
            }
            if (GUILayout.Button("Ins ->", EditorStyles.miniButton))
            {
                frameGroups.Insert(state.selectedFrame + 1,
                    AnimOperatorUtil.NewFrameGroup(frameGroups, state.selectedFrame));
                changed = true;
            }
            GUILayout.EndHorizontal();

            // Tell the caller what has changed
            operations = changed ? AnimEditOperations.ClipContentChanged : AnimEditOperations.None;
            return changed;
        }
		public override bool OnFrameGroupInspectorGUI(tk2dSpriteAnimationClip selectedClip, List<ClipEditor.FrameGroup> frameGroups, TimelineEditor.State state)
		{
			if (selectedClip.wrapMode == tk2dSpriteAnimationClip.WrapMode.Single)
				return false;

			bool changed = false;
			GUILayout.BeginHorizontal();
			if (GUILayout.Button("Autofill 9..1", EditorStyles.miniButton) && AutoFill(frameGroups, state.selectedFrame, true)) { changed = true; }
			if (GUILayout.Button("Autofill 1..9", EditorStyles.miniButton) && AutoFill(frameGroups, state.selectedFrame, false)) { changed = true; }
			GUILayout.EndHorizontal();

			operations = changed ? AnimEditOperations.ClipContentChanged : AnimEditOperations.None;
			return changed;
		}		
		// Drawn in the frame group inspector GUI for the selected clip.
		// Return true when data has changed.
		public virtual bool OnFrameGroupInspectorGUI(tk2dSpriteAnimationClip selectedClip, List<ClipEditor.FrameGroup> frameGroups, TimelineEditor.State state ) { return false; }
		public override bool OnFrameGroupInspectorGUI(tk2dSpriteAnimationClip selectedClip, List<ClipEditor.FrameGroup> frameGroups, TimelineEditor.State state )
		{
			if (selectedClip.wrapMode == tk2dSpriteAnimationClip.WrapMode.Single)
				return false;

			bool changed = false;
			GUILayout.BeginHorizontal();
			if (GUILayout.Button("Insert <", EditorStyles.miniButton)) 
			{ 
				frameGroups.Insert(state.selectedFrame, AnimOperatorUtil.NewFrameGroup(frameGroups, state.selectedFrame)); 
				state.selectedFrame++; 
				changed = true;
			}
			if (GUILayout.Button("Insert >", EditorStyles.miniButton)) 
			{ 
				frameGroups.Insert(state.selectedFrame + 1, AnimOperatorUtil.NewFrameGroup(frameGroups, state.selectedFrame));
				changed = true;
			}
			GUILayout.EndHorizontal();

			operations = changed ? AnimEditOperations.ClipContentChanged : AnimEditOperations.None;
			return changed;
		}		
		public override bool OnFrameGroupInspectorGUI(tk2dSpriteAnimationClip selectedClip, List<ClipEditor.FrameGroup> frameGroups, TimelineEditor.State state )
		{
			bool changed = false;
			if (frameGroups.Count > 1)
			{
				GUILayout.Space(16);
				if (GUILayout.Button("Delete", EditorStyles.miniButton))
				{
					frameGroups.RemoveAt(state.selectedFrame);
					state.selectedFrame = -1;
					changed = true;
				}
				GUILayout.BeginHorizontal();
				if (GUILayout.Button("Delete <", EditorStyles.miniButton)) { frameGroups.RemoveRange(0, state.selectedFrame); changed = true; state.selectedFrame = 0; }
				if (GUILayout.Button("Delete >", EditorStyles.miniButton)) { frameGroups.RemoveRange(state.selectedFrame + 1, frameGroups.Count - 1 - state.selectedFrame); changed = true; state.selectedFrame = frameGroups.Count - 1; }
				GUILayout.EndHorizontal();
			}
			operations = changed ? AnimEditOperations.ClipContentChanged : AnimEditOperations.None;
			return changed;
		}		
		public override bool OnClipInspectorGUI(tk2dSpriteAnimationClip selectedClip, List<ClipEditor.FrameGroup> frameGroups, TimelineEditor.State state )
		{
			GUILayout.BeginHorizontal();

			bool changed = false;
			if (GUILayout.Button("Reverse", EditorStyles.miniButton))
			{
				frameGroups.Reverse();
				operations = AnimEditOperations.ClipContentChanged;
				state.selectedFrame = (state.selectedFrame == -1) ? state.selectedFrame : (frameGroups.Count - 1 - state.selectedFrame);
				changed = true;
			}
			GUIContent addTriggerContent = new GUIContent("Trigger", "You can also add a trigger by double clicking on the trigger area");
			if (GUILayout.Button(addTriggerContent, EditorStyles.miniButton))
			{
				for (int i = 0; i < selectedClip.frames.Length; ++i)
				{
					if (!selectedClip.frames[i].triggerEvent)
					{
						selectedClip.frames[i].triggerEvent = true;
						state.selectedTrigger = i;
						break;
					}
				}
				changed = true;
			}
			if (selectedClip.wrapMode != tk2dSpriteAnimationClip.WrapMode.Single)
			{
				bool newTextToggle = GUILayout.Toggle(textToggle, "Text", EditorStyles.miniButton);
				if (newTextToggle != textToggle)
				{
					if (newTextToggle == true)
					{
						textNames = BuildTextSpriteList(frameGroups);
						if (textNames.Length == 0) newTextToggle = false;
					}
					textToggle = newTextToggle;
				}
			}
			GUILayout.EndHorizontal();

			if (textToggle)
			{
				textNames = EditorGUILayout.TextArea(textNames, GUILayout.ExpandWidth(true));
				GUILayout.BeginHorizontal();
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("Process"))
				{
					if (ProcessSpriteImport(frameGroups, textNames))
					{
						textNames = "";
						textToggle = false;
						state.selectedFrame = -1;
						changed = true;
						GUIUtility.keyboardControl = 0;
					}
				}
				GUILayout.EndHorizontal();
			}

			return changed;
		}