protected override void OnRuntimeEnable()
        {
            base.OnRuntimeEnable();

            Dictionary <Type, FiniteStateBase> states = Target.GetType().GetField("_stateInstances", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Target) as Dictionary <Type, FiniteStateBase>;

            _stateInstances = new Dictionary <string, Type>();
            foreach (var state in states)
            {
                FiniteStateNameAttribute attribute = state.Key.GetCustomAttribute <FiniteStateNameAttribute>();
                _stateInstances.Add(attribute != null ? attribute.Name : state.Key.Name, state.Key);
            }

            FiniteStateNameAttribute nameAttribute = Target.CurrentState.GetType().GetCustomAttribute <FiniteStateNameAttribute>();

            _currentStateName = nameAttribute != null ? nameAttribute.Name : Target.CurrentState.GetType().Name;
        }
Beispiel #2
0
        protected override void OnPlayingEnable()
        {
            base.OnPlayingEnable();

            Dictionary <Type, FiniteState> states = _target.GetType().GetField("_stateInstances", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_target) as Dictionary <Type, FiniteState>;

            _stateInstances = new Dictionary <string, Type>();
            foreach (KeyValuePair <Type, FiniteState> state in states)
            {
                FiniteStateNameAttribute attribute = state.Key.GetCustomAttribute <FiniteStateNameAttribute>();
                _stateInstances.Add(attribute != null ? attribute.Name : state.Key.Name, state.Key);
            }

            _currentState = _target.GetType().GetField("_currentState", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_target) as FiniteState;

            FiniteStateNameAttribute nameAttribute = _currentState.GetType().GetCustomAttribute <FiniteStateNameAttribute>();

            _currentStateName = nameAttribute != null ? nameAttribute.Name : _currentState.GetType().Name;
        }
Beispiel #3
0
        protected override void OnPlayingInspectorGUI()
        {
            base.OnPlayingInspectorGUI();

            GUILayout.BeginVertical("Helpbox");

            GUILayout.BeginHorizontal();
            GUILayout.Label("Runtime Data", "BoldLabel");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Current State: " + _currentStateName);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("States: ");
            GUILayout.EndHorizontal();

            foreach (KeyValuePair <string, Type> state in _stateInstances)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Space(20);
                GUILayout.Label(state.Key);
                GUILayout.FlexibleSpace();
                GUI.enabled = _currentStateName != state.Key;
                if (GUILayout.Button("Switch", "Minibutton"))
                {
                    _target.SwitchState(state.Value);

                    _currentState = _target.GetType().GetField("_currentState", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_target) as FiniteState;

                    FiniteStateNameAttribute nameAttribute = _currentState.GetType().GetCustomAttribute <FiniteStateNameAttribute>();
                    _currentStateName = nameAttribute != null ? nameAttribute.Name : _currentState.GetType().Name;
                }
                GUI.enabled = true;
                GUILayout.EndHorizontal();
            }

            GUILayout.EndVertical();
        }
        protected override void OnInspectorDefaultGUI()
        {
            base.OnInspectorDefaultGUI();

            GUILayout.BeginHorizontal();
            EditorGUILayout.HelpBox("State Count:" + Target.StateNames.Count, MessageType.Info);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            Toggle(Target.IsAutoRegister, out Target.IsAutoRegister, "Auto Register");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Name: ");
            TextField(Target.Name, out Target.Name);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Data: ");
            if (GUILayout.Button(Target.Data, "MiniPopup"))
            {
                GenericMenu gm    = new GenericMenu();
                List <Type> types = GlobalTools.GetTypesInRunTimeAssemblies();
                gm.AddItem(new GUIContent("<None>"), Target.Data == "<None>", () =>
                {
                    Undo.RecordObject(target, "Set FSM Data Class");
                    Target.Data = "<None>";
                    HasChanged();
                });
                for (int i = 0; i < types.Count; i++)
                {
                    if (types[i].IsSubclassOf(typeof(FSMData)))
                    {
                        int j = i;
                        gm.AddItem(new GUIContent(types[j].FullName), Target.Data == types[j].FullName, () =>
                        {
                            Undo.RecordObject(target, "Set FSM Data Class");
                            Target.Data = types[j].FullName;
                            HasChanged();
                        });
                    }
                }
                gm.ShowAsContext();
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUI.enabled = Target.DefaultStateName != "";
            GUILayout.Label("Default: " + Target.DefaultStateName);
            GUI.enabled = true;
            GUILayout.FlexibleSpace();
            GUI.enabled = Target.StateNames.Count > 0;
            if (GUILayout.Button("Set Default", "MiniPopup"))
            {
                GenericMenu gm = new GenericMenu();
                for (int i = 0; i < Target.StateNames.Count; i++)
                {
                    int j = i;
                    gm.AddItem(new GUIContent(Target.StateNames[j]), Target.DefaultStateName == Target.StateNames[j], () =>
                    {
                        Undo.RecordObject(target, "Set FSM Default State");
                        Target.DefaultState     = Target.States[j];
                        Target.DefaultStateName = Target.StateNames[j];
                        HasChanged();
                    });
                }
                gm.ShowAsContext();
            }
            GUI.enabled = true;
            GUILayout.EndHorizontal();

            for (int i = 0; i < Target.StateNames.Count; i++)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label(string.Format("{0}.{1}", i + 1, Target.StateNames[i]));
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Edit", "minibuttonleft"))
                {
                    if (_stateTypes.ContainsKey(Target.States[i]))
                    {
                        UnityEngine.Object classFile = AssetDatabase.LoadAssetAtPath(_stateTypes[Target.States[i]], typeof(TextAsset));
                        if (classFile)
                        {
                            AssetDatabase.OpenAsset(classFile);
                        }
                        else
                        {
                            GlobalTools.LogError("没有找到 " + Target.States[i] + " 脚本文件!");
                        }
                    }
                    else
                    {
                        GlobalTools.LogError("没有找到 " + Target.States[i] + " 脚本文件!");
                    }
                }
                if (GUILayout.Button("Delete", "minibuttonright"))
                {
                    Undo.RecordObject(target, "Delete FSM State");
                    if (Target.DefaultStateName == Target.StateNames[i])
                    {
                        Target.DefaultState     = "";
                        Target.DefaultStateName = "";
                    }

                    Target.States.RemoveAt(i);
                    Target.StateNames.RemoveAt(i);

                    if (Target.DefaultStateName == "" && Target.StateNames.Count > 0)
                    {
                        Target.DefaultState     = Target.States[0];
                        Target.DefaultStateName = Target.StateNames[0];
                    }
                    HasChanged();
                }
                GUILayout.EndHorizontal();
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Add State", "MiniPopup"))
            {
                GenericMenu gm    = new GenericMenu();
                List <Type> types = GlobalTools.GetTypesInRunTimeAssemblies();
                for (int i = 0; i < types.Count; i++)
                {
                    if (types[i].IsSubclassOf(typeof(FiniteState)))
                    {
                        int    j         = i;
                        string stateName = types[j].FullName;
                        FiniteStateNameAttribute fsmAtt = types[j].GetCustomAttribute <FiniteStateNameAttribute>();
                        if (fsmAtt != null)
                        {
                            stateName = fsmAtt.Name;
                        }

                        if (Target.States.Contains(types[j].FullName))
                        {
                            gm.AddDisabledItem(new GUIContent(stateName));
                        }
                        else
                        {
                            gm.AddItem(new GUIContent(stateName), false, () =>
                            {
                                Undo.RecordObject(target, "Add FSM State");
                                Target.States.Add(types[j].FullName);
                                Target.StateNames.Add(stateName);

                                if (Target.DefaultStateName == "")
                                {
                                    Target.DefaultState     = Target.States[0];
                                    Target.DefaultStateName = Target.StateNames[0];
                                }
                                HasChanged();
                            });
                        }
                    }
                }
                gm.ShowAsContext();
            }
            GUILayout.EndHorizontal();
        }
Beispiel #5
0
        protected override void OnInspectorDefaultGUI()
        {
            base.OnInspectorDefaultGUI();

            GUILayout.BeginHorizontal();
            EditorGUILayout.HelpBox("Finite state machine!", MessageType.Info);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            Toggle(Target.IsAutoRegister, out Target.IsAutoRegister, "Auto Register");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            TextField(Target.Name, out Target.Name, "Name");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            TextField(Target.Group, out Target.Group, "Group");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUI.color = Target.Data == "<None>" ? Color.gray : Color.white;
            GUILayout.Label("Data", GUILayout.Width(60));
            if (GUILayout.Button(Target.Data, EditorGlobalTools.Styles.MiniPopup))
            {
                GenericMenu gm = new GenericMenu();
                gm.AddItem(new GUIContent("<None>"), Target.Data == "<None>", () =>
                {
                    Undo.RecordObject(target, "Set FSM Data Class");
                    Target.Data = "<None>";
                    HasChanged();
                });
                List <Type> types = ReflectionToolkit.GetTypesInRunTimeAssemblies(type =>
                {
                    return(type.IsSubclassOf(typeof(FSMDataBase)) && !type.IsAbstract);
                });
                for (int i = 0; i < types.Count; i++)
                {
                    int j = i;
                    gm.AddItem(new GUIContent(types[j].FullName), Target.Data == types[j].FullName, () =>
                    {
                        Undo.RecordObject(target, "Set FSM Data Class");
                        Target.Data = types[j].FullName;
                        HasChanged();
                    });
                }
                gm.ShowAsContext();
            }
            GUI.color = Color.white;
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUI.enabled = Target.DefaultStateName != "";
            GUILayout.Label("Default: " + Target.DefaultStateName);
            GUI.enabled = true;
            GUILayout.FlexibleSpace();
            GUI.enabled = Target.StateNames.Count > 0;
            if (GUILayout.Button("Set Default", EditorGlobalTools.Styles.MiniPopup))
            {
                GenericMenu gm = new GenericMenu();
                for (int i = 0; i < Target.StateNames.Count; i++)
                {
                    int j = i;
                    gm.AddItem(new GUIContent(Target.StateNames[j]), Target.DefaultStateName == Target.StateNames[j], () =>
                    {
                        Undo.RecordObject(target, "Set FSM Default State");
                        Target.DefaultState     = Target.States[j];
                        Target.DefaultStateName = Target.StateNames[j];
                        HasChanged();
                    });
                }
                gm.ShowAsContext();
            }
            GUI.enabled = true;
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUI.enabled = Target.FinalStateName != "";
            GUILayout.Label("Final: " + Target.FinalStateName);
            GUI.enabled = true;
            GUILayout.FlexibleSpace();
            GUI.enabled = Target.StateNames.Count > 0;
            if (GUILayout.Button("Set Final", EditorGlobalTools.Styles.MiniPopup))
            {
                GenericMenu gm = new GenericMenu();
                for (int i = 0; i < Target.StateNames.Count; i++)
                {
                    int j = i;
                    gm.AddItem(new GUIContent(Target.StateNames[j]), Target.FinalStateName == Target.StateNames[j], () =>
                    {
                        Undo.RecordObject(target, "Set FSM Final State");
                        Target.FinalState     = Target.States[j];
                        Target.FinalStateName = Target.StateNames[j];
                        HasChanged();
                    });
                }
                gm.ShowAsContext();
            }
            GUI.enabled = true;
            GUILayout.EndHorizontal();

            GUILayout.BeginVertical(EditorGlobalTools.Styles.Box);

            GUILayout.BeginHorizontal();
            GUILayout.Label("Enabled State:");
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            for (int i = 0; i < Target.StateNames.Count; i++)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label(string.Format("{0}.{1}", i + 1, Target.StateNames[i]));
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Edit", EditorStyles.miniButtonLeft))
                {
                    MonoScriptToolkit.OpenMonoScript(Target.States[i]);
                }
                if (GUILayout.Button("Delete", EditorStyles.miniButtonRight))
                {
                    Undo.RecordObject(target, "Delete FSM State");

                    if (Target.DefaultStateName == Target.StateNames[i])
                    {
                        Target.DefaultState     = "";
                        Target.DefaultStateName = "";
                    }
                    if (Target.FinalStateName == Target.StateNames[i])
                    {
                        Target.FinalState     = "";
                        Target.FinalStateName = "";
                    }

                    Target.States.RemoveAt(i);
                    Target.StateNames.RemoveAt(i);

                    if (Target.DefaultStateName == "" && Target.StateNames.Count > 0)
                    {
                        Target.DefaultState     = Target.States[0];
                        Target.DefaultStateName = Target.StateNames[0];
                    }
                    if (Target.FinalStateName == "" && Target.StateNames.Count > 0)
                    {
                        Target.FinalState     = Target.States[0];
                        Target.FinalStateName = Target.StateNames[0];
                    }

                    HasChanged();
                }
                GUILayout.EndHorizontal();
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Add State", EditorGlobalTools.Styles.MiniPopup))
            {
                GenericMenu gm    = new GenericMenu();
                List <Type> types = ReflectionToolkit.GetTypesInRunTimeAssemblies(type =>
                {
                    return(type.IsSubclassOf(typeof(FiniteStateBase)) && !type.IsAbstract);
                });
                for (int i = 0; i < types.Count; i++)
                {
                    int    j         = i;
                    string stateName = types[j].FullName;
                    FiniteStateNameAttribute fsmAtt = types[j].GetCustomAttribute <FiniteStateNameAttribute>();
                    if (fsmAtt != null)
                    {
                        stateName = fsmAtt.Name;
                    }

                    if (Target.States.Contains(types[j].FullName))
                    {
                        gm.AddDisabledItem(new GUIContent(stateName));
                    }
                    else
                    {
                        gm.AddItem(new GUIContent(stateName), false, () =>
                        {
                            Undo.RecordObject(target, "Add FSM State");
                            Target.States.Add(types[j].FullName);
                            Target.StateNames.Add(stateName);

                            if (Target.DefaultStateName == "")
                            {
                                Target.DefaultState     = Target.States[0];
                                Target.DefaultStateName = Target.StateNames[0];
                            }
                            if (Target.FinalStateName == "")
                            {
                                Target.FinalState     = Target.States[0];
                                Target.FinalStateName = Target.StateNames[0];
                            }
                            HasChanged();
                        });
                    }
                }
                gm.ShowAsContext();
            }
            GUILayout.EndHorizontal();

            GUILayout.EndVertical();
        }
        protected override void OnDefaultEnable()
        {
            base.OnDefaultEnable();

            if (Targets.Length > 1)
            {
                return;
            }

            _stateGC           = new GUIContent();
            _stateGC.image     = EditorGUIUtility.IconContent("AnimatorState Icon").image;
            _addGC             = new GUIContent();
            _addGC.image       = EditorGUIUtility.IconContent("d_Toolbar Plus More").image;
            _addGC.tooltip     = "Add a new state";
            _removeGC          = new GUIContent();
            _removeGC.image    = EditorGUIUtility.IconContent("d_Toolbar Minus").image;
            _removeGC.tooltip  = "Remove select state";
            _defaultGC         = new GUIContent();
            _defaultGC.image   = EditorGUIUtility.IconContent("TimelineEditModeRippleON").image;
            _defaultGC.tooltip = "Default state";
            _finalGC           = new GUIContent();
            _finalGC.image     = EditorGUIUtility.IconContent("TimelineEditModeReplaceON").image;
            _finalGC.tooltip   = "Final state";
            _editGC            = new GUIContent();
            _editGC.image      = EditorGUIUtility.IconContent("d_editicon.sml").image;
            _editGC.tooltip    = "Edit state script";

            _states    = GetProperty("States");
            _stateList = new ReorderableList(serializedObject, _states, true, true, false, false);
            _stateList.drawHeaderCallback = (Rect rect) =>
            {
                Rect sub = rect;
                sub.Set(rect.x, rect.y, 200, rect.height);
                GUI.Label(sub, "Enabled States:");

                if (!EditorApplication.isPlaying)
                {
                    sub.Set(rect.x + rect.width - 40, rect.y - 2, 20, 20);
                    if (GUI.Button(sub, _addGC, "InvisibleButton"))
                    {
                        GenericMenu gm    = new GenericMenu();
                        List <Type> types = ReflectionToolkit.GetTypesInRunTimeAssemblies(type =>
                        {
                            return(type.IsSubclassOf(typeof(FiniteStateBase)) && !type.IsAbstract);
                        });
                        for (int i = 0; i < types.Count; i++)
                        {
                            int    j         = i;
                            string stateName = types[j].FullName;
                            FiniteStateNameAttribute fsmAtt = types[j].GetCustomAttribute <FiniteStateNameAttribute>();
                            if (fsmAtt != null)
                            {
                                stateName = fsmAtt.Name;
                            }

                            if (Target.States.Contains(types[j].FullName))
                            {
                                gm.AddDisabledItem(new GUIContent(stateName));
                            }
                            else
                            {
                                gm.AddItem(new GUIContent(stateName), false, () =>
                                {
                                    Undo.RecordObject(target, "Add FSM State");
                                    Target.States.Add(types[j].FullName);
                                    if (string.IsNullOrEmpty(Target.DefaultState))
                                    {
                                        Target.DefaultState = Target.States[0];
                                    }
                                    if (string.IsNullOrEmpty(Target.FinalState))
                                    {
                                        Target.FinalState = Target.States[0];
                                    }
                                    HasChanged();
                                });
                            }
                        }
                        gm.ShowAsContext();
                    }

                    sub.Set(rect.x + rect.width - 20, rect.y - 2, 20, 20);
                    GUI.enabled = _stateList.index >= 0 && _stateList.index < Target.States.Count;
                    if (GUI.Button(sub, _removeGC, "InvisibleButton"))
                    {
                        Undo.RecordObject(target, "Delete FSM State");

                        if (Target.DefaultState == Target.States[_stateList.index])
                        {
                            Target.DefaultState = null;
                        }
                        if (Target.FinalState == Target.States[_stateList.index])
                        {
                            Target.FinalState = null;
                        }

                        Target.States.RemoveAt(_stateList.index);

                        if (string.IsNullOrEmpty(Target.DefaultState) && Target.States.Count > 0)
                        {
                            Target.DefaultState = Target.States[0];
                        }
                        if (string.IsNullOrEmpty(Target.FinalState) && Target.States.Count > 0)
                        {
                            Target.FinalState = Target.States[0];
                        }

                        HasChanged();
                    }
                    GUI.enabled = true;
                }
            };
            _stateList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                if (index >= 0 && index < Target.States.Count)
                {
                    SerializedProperty property  = _states.GetArrayElementAtIndex(index);
                    string             stateType = property.stringValue;
                    if (!_stateNames.ContainsKey(stateType))
                    {
                        Type type = ReflectionToolkit.GetTypeInRunTimeAssemblies(stateType);
                        if (type != null)
                        {
                            string stateName = type.FullName;
                            FiniteStateNameAttribute fsmAtt = type.GetCustomAttribute <FiniteStateNameAttribute>();
                            if (fsmAtt != null)
                            {
                                stateName = fsmAtt.Name;
                            }
                            _stateNames.Add(stateType, stateName);
                        }
                        else
                        {
                            _stateNames.Add(stateType, "<Missing>");
                        }
                    }

                    Rect subrect = rect;
                    subrect.Set(rect.x, rect.y + 2, rect.width, 16);
                    _stateGC.text = _stateNames[stateType];
                    GUI.color     = _stateGC.text != "<Missing>" ? Color.white : Color.red;
                    GUI.Label(subrect, _stateGC);
                    GUI.color = Color.white;

                    int size = 20;
                    if (Target.FinalState == stateType)
                    {
                        subrect.Set(rect.x + rect.width - size, rect.y + 2, 20, 16);
                        if (GUI.Button(subrect, _finalGC, "InvisibleButton"))
                        {
                            GenericMenu gm = new GenericMenu();
                            foreach (var state in _stateNames)
                            {
                                gm.AddItem(new GUIContent(state.Value), Target.FinalState == state.Key, () =>
                                {
                                    Undo.RecordObject(target, "Set FSM Final State");
                                    Target.FinalState = state.Key;
                                    HasChanged();
                                });
                            }
                            gm.ShowAsContext();
                        }
                        size += 20;
                    }
                    if (Target.DefaultState == stateType)
                    {
                        subrect.Set(rect.x + rect.width - size, rect.y + 2, 20, 16);
                        if (GUI.Button(subrect, _defaultGC, "InvisibleButton"))
                        {
                            GenericMenu gm = new GenericMenu();
                            foreach (var state in _stateNames)
                            {
                                gm.AddItem(new GUIContent(state.Value), Target.DefaultState == state.Key, () =>
                                {
                                    Undo.RecordObject(target, "Set FSM Default State");
                                    Target.DefaultState = state.Key;
                                    HasChanged();
                                });
                            }
                            gm.ShowAsContext();
                        }
                        size += 20;
                    }
                    if (isActive && isFocused)
                    {
                        subrect.Set(rect.x + rect.width - size, rect.y, 20, 20);
                        if (GUI.Button(subrect, _editGC, "InvisibleButton"))
                        {
                            MonoScriptToolkit.OpenMonoScript(stateType);
                        }
                        size += 20;
                    }
                }
            };
            _stateList.drawElementBackgroundCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                if (Event.current.type == EventType.Repaint)
                {
                    GUIStyle gUIStyle = (index % 2 != 0) ? "CN EntryBackEven" : "CN EntryBackodd";
                    gUIStyle    = (!isActive && !isFocused) ? gUIStyle : "RL Element";
                    rect.x     += 2;
                    rect.width -= 6;
                    gUIStyle.Draw(rect, false, isActive, isActive, isFocused);
                }
            };
            _stateNames = new Dictionary <string, string>();

            if (Target.Args == null)
            {
                FSMArgsBase args = Target.GetComponent <FSMArgsBase>();
                if (args != null)
                {
                    Target.Args = args;
                    HasChanged();
                }
            }
            if (Target.Args != null)
            {
                Target.Args.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
            }
        }
Beispiel #7
0
        public override void OnInspectorGUI()
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.HelpBox("State Count:" + _target.StateNames.Count, MessageType.Info);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Name: ");
            this.TextField(_target.Name, out _target.Name);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Data: ");
            if (GUILayout.Button(_target.Data, "MiniPopup"))
            {
                GenericMenu gm    = new GenericMenu();
                List <Type> types = GlobalTools.GetTypesInRunTimeAssemblies();
                gm.AddItem(new GUIContent("<None>"), _target.Data == "<None>", () =>
                {
                    Undo.RecordObject(target, "Set FSM Data Class");
                    _target.Data = "<None>";
                    this.HasChanged();
                });
                for (int i = 0; i < types.Count; i++)
                {
                    if (types[i].BaseType == typeof(FSMData))
                    {
                        int j = i;
                        gm.AddItem(new GUIContent(types[j].FullName), _target.Data == types[j].FullName, () =>
                        {
                            Undo.RecordObject(target, "Set FSM Data Class");
                            _target.Data = types[j].FullName;
                            this.HasChanged();
                        });
                    }
                }
                gm.ShowAsContext();
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUI.enabled = _target.DefaultStateName != "";
            GUILayout.Label("Default: " + _target.DefaultStateName);
            GUI.enabled = true;
            GUILayout.FlexibleSpace();
            GUI.enabled = _target.StateNames.Count > 0;
            if (GUILayout.Button("Set Default", "MiniPopup"))
            {
                GenericMenu gm = new GenericMenu();
                for (int i = 0; i < _target.StateNames.Count; i++)
                {
                    int j = i;
                    gm.AddItem(new GUIContent(_target.StateNames[j]), _target.DefaultStateName == _target.StateNames[j], () =>
                    {
                        Undo.RecordObject(target, "Set FSM Default State");
                        _target.DefaultState     = _target.States[j];
                        _target.DefaultStateName = _target.StateNames[j];
                        this.HasChanged();
                    });
                }
                gm.ShowAsContext();
            }
            GUI.enabled = true;
            GUILayout.EndHorizontal();

            for (int i = 0; i < _target.StateNames.Count; i++)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label(string.Format("{0}.{1} [{2}]", i + 1, _target.StateNames[i], _target.States[i]));
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Delete", "MiniButton"))
                {
                    Undo.RecordObject(target, "Delete FSM State");
                    if (_target.DefaultStateName == _target.StateNames[i])
                    {
                        _target.DefaultState     = "";
                        _target.DefaultStateName = "";
                    }

                    _target.States.RemoveAt(i);
                    _target.StateNames.RemoveAt(i);

                    if (_target.DefaultStateName == "" && _target.StateNames.Count > 0)
                    {
                        _target.DefaultState     = _target.States[0];
                        _target.DefaultStateName = _target.StateNames[0];
                    }
                    this.HasChanged();
                }
                GUILayout.EndHorizontal();
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Add State", "MiniPopup"))
            {
                GenericMenu gm    = new GenericMenu();
                List <Type> types = GlobalTools.GetTypesInRunTimeAssemblies();
                for (int i = 0; i < types.Count; i++)
                {
                    if (types[i].BaseType == typeof(FiniteState))
                    {
                        int      j         = i;
                        string   stateName = types[j].FullName;
                        object[] atts      = types[j].GetCustomAttributes(false);
                        foreach (object att in atts)
                        {
                            FiniteStateNameAttribute fsmAtt = att as FiniteStateNameAttribute;
                            if (fsmAtt != null)
                            {
                                stateName = fsmAtt.Name;
                                break;
                            }
                        }

                        if (_target.States.Contains(types[j].FullName))
                        {
                            gm.AddDisabledItem(new GUIContent(stateName));
                        }
                        else
                        {
                            gm.AddItem(new GUIContent(stateName), false, () =>
                            {
                                Undo.RecordObject(target, "Add FSM State");
                                _target.States.Add(types[j].FullName);
                                _target.StateNames.Add(stateName);

                                if (_target.DefaultStateName == "")
                                {
                                    _target.DefaultState     = _target.States[0];
                                    _target.DefaultStateName = _target.StateNames[0];
                                }
                                this.HasChanged();
                            });
                        }
                    }
                }
                gm.ShowAsContext();
            }
            GUILayout.EndHorizontal();
        }