/// <summary>
        /// Shows a context menu to add a new parent.
        /// </summary>
        void OnContextMenu()
        {
            var menu = new UnityEditor.GenericMenu();
            // Get the active game object
            var gameObject = Selection.activeGameObject;

            // The selected game object is not null?
            if (gameObject != null)
            {
                // Gets all scripts that inherits from ParentBehaviour class
                MonoScript[] scripts = FileUtility.GetScripts <ParentBehaviour>();
                for (int i = 0; i < scripts.Length; i++)
                {
                    var type = scripts[i].GetClass();

                    // Get the component path
                    string           componentPath = "Add Parent/";
                    AddComponentMenu componentMenu = AttributeUtility.GetAttribute <AddComponentMenu>(type, false);
                    if (componentMenu == null || componentMenu.componentMenu != string.Empty)
                    {
                        componentMenu = AttributeUtility.GetAttribute <AddComponentMenu>(type, true);
                        if (componentMenu != null && componentMenu.componentMenu != string.Empty)
                        {
                            componentPath += componentMenu.componentMenu;
                        }
                        else
                        {
                            componentPath += type.ToString().Replace('.', '/');
                        }

                        // Add to menu
                        menu.AddItem(new GUIContent(componentPath), false, delegate() { BehaviourWindow.activeParent = StateUtility.AddState(gameObject, type) as ParentBehaviour; });
                    }
                }
            }
            else
            {
                menu.AddDisabledItem(new GUIContent("Add Parent/"));
                ShowNotification(new GUIContent("Select a Game Object and right click in this window!"));
            }

            // Add option to paste states
            if (Selection.activeGameObject != null && StateUtility.statesToPaste != null && StateUtility.statesToPaste.Length > 0)
            {
                menu.AddItem(new GUIContent("Paste State"), false, delegate() { StateUtility.CloneStates(Selection.activeGameObject, StateUtility.statesToPaste, null); });
            }
            else
            {
                menu.AddDisabledItem(new GUIContent("Paste State"));
            }

            // Refresh window?
            // menu.AddSeparator("");
            // menu.AddItem(new GUIContent("Refresh"), false ,Refresh);

            // Shows the controller menu
            menu.ShowAsContext();
        }
Esempio n. 2
0
        /// <summary>
        /// Paste the state in StateUtility.stateToPaste in the supplied fsm.
        /// <param name="gameObject">The target gameObject.</param>
        /// <param name="originalStates">The original states.</param>
        /// <param name="parent">Optionally parent for the cloned states.</param>
        /// </summary>
        public static void CloneStates(GameObject gameObject, InternalStateBehaviour[] originalStates, ParentBehaviour parent)
        {
            if (gameObject != null && originalStates != null && originalStates.Length > 0)
            {
                var orginalClone = new Dictionary <InternalStateBehaviour, InternalStateBehaviour>();
                var originalFsm = parent != null ? originalStates[0].parent as InternalStateMachine : null;
                var newFsm = parent as InternalStateMachine;
                InternalStateBehaviour startState = null, concurrentState = null;
                InternalAnyState       anyState = null;

                // Copy blackboard data?
                var newBlackboard = gameObject.GetComponent <InternalBlackboard>();
                if (newBlackboard == null)
                {
                    // Get the original blackboard
                    InternalBlackboard originalBlackboard = originalStates[0].GetComponent <InternalBlackboard>();

                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                    Undo.RegisterSceneUndo("Paste State");
                    // Create the new blacbkoard
                    newBlackboard = gameObject.AddComponent(originalBlackboard.GetType()) as InternalBlackboard;
                    #else
                    // Create the new blacbkoard
                    newBlackboard = gameObject.AddComponent(originalBlackboard.GetType()) as InternalBlackboard;
                    if (newBlackboard != null)
                    {
                        Undo.RegisterCreatedObjectUndo(newBlackboard, "Paste State");
                    }
                    #endif

                    // Copy serialized values
                    EditorUtility.CopySerialized(originalBlackboard, newBlackboard);
                }

                foreach (InternalStateBehaviour state in originalStates)
                {
                    // Don't clone AnyState in StateMachines
                    if (state != null && (newFsm == null || !(state is InternalAnyState) || newFsm.anyState == null))
                    {
                        #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                        Undo.RegisterSceneUndo("Paste State");
                        // Create a new state
                        var newState = gameObject.AddComponent(state.GetType()) as InternalStateBehaviour;
                        #else
                        // Create a new state
                        var newState = gameObject.AddComponent(state.GetType()) as InternalStateBehaviour;
                        if (newState != null)
                        {
                            Undo.RegisterCreatedObjectUndo(newState, "Paste State");
                        }
                        #endif

                        if (newState != null)
                        {
                            // Store state
                            orginalClone.Add(state, newState);

                            // Copy serialized values
                            EditorUtility.CopySerialized(state, newState);

                            // Update blackboard
                            if (state.gameObject != newState.gameObject)
                            {
                                var serialObj = new SerializedObject(newState);
                                serialObj.FindProperty("m_Blackboard").objectReferenceValue = newBlackboard;
                                serialObj.ApplyModifiedProperties();
                                serialObj.Dispose();
                            }

                            // Update the AnyState, StartState and ConcurrentState
                            if (newState is InternalStateMachine)
                            {
                                var fsm = newState as InternalStateMachine;
                                fsm.startState      = null;
                                fsm.concurrentState = null;
                                fsm.anyState        = null;
                            }

                            EditorUtility.SetDirty(newState);

                            // Set new parent
                            if (parent != null)
                            {
                                newState.parent = parent;

                                // Update position
                                if (parent == state.parent)
                                {
                                    newState.position += new Vector2(20f, 20f);
                                }
                            }
                            else
                            {
                                newState.parent = null;
                            }

                            // Saves state and sets dirty flag
                            INodeOwner nodeOwner = newState as INodeOwner;
                            if (nodeOwner != null)
                            {
                                nodeOwner.LoadNodes();
                                StateUtility.SetDirty(nodeOwner);
                            }
                            else
                            {
                                EditorUtility.SetDirty(newState);
                            }

                            // Try to get the StartState, AnyState and ConcurrentState
                            if (originalFsm != null)
                            {
                                if (originalFsm.startState == state)
                                {
                                    startState = newState;
                                }
                                if (anyState == null)
                                {
                                    anyState = newState as InternalAnyState;
                                }
                                if (originalFsm.concurrentState == state)
                                {
                                    concurrentState = newState;
                                }
                            }
                        }
                    }
                }

                // Set StartState, AnyState and ConcurrentState
                if (newFsm != null)
                {
                    if (newFsm.startState == null)
                    {
                        newFsm.startState = startState;
                    }
                    if (newFsm.anyState == null)
                    {
                        newFsm.anyState = anyState;
                    }
                    if (newFsm.concurrentState == null)
                    {
                        newFsm.concurrentState = concurrentState;
                    }
                    EditorUtility.SetDirty(newFsm);
                }

                // Try to update the transitions' destination
                foreach (KeyValuePair <InternalStateBehaviour, InternalStateBehaviour> pair in orginalClone)
                {
                    InternalStateBehaviour state    = pair.Key;
                    InternalStateBehaviour newState = pair.Value;

                    // Update the newState transition
                    for (int i = 0; i < newState.transitions.Length && i < state.transitions.Length; i++)
                    {
                        // The original destination is valid?
                        if (state.transitions[i].destination != null && orginalClone.ContainsKey(state.transitions[i].destination))
                        {
                            newState.transitions[i].destination = orginalClone[state.transitions[i].destination];
                        }
                    }

                    if (newState is ParentBehaviour)
                    {
                        var stateAsParent = state as ParentBehaviour;

                        // Removes the newState from the children state to avoid an infinite loop
                        List <InternalStateBehaviour> children = stateAsParent.states;
                        if (children.Contains(newState))
                        {
                            children.Remove(newState);
                        }

                        StateUtility.CloneStates(newState.gameObject, children.ToArray(), newState as ParentBehaviour);
                    }

                    EditorUtility.SetDirty(newState);
                }

                EditorUtility.SetDirty(gameObject);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Shows the context menu.
        /// </summary>
        protected virtual void OnContextMenu()
        {
            // Create the menu
            var menu = new UnityEditor.GenericMenu();

            if (m_State != null)
            {
                // Set as start state
                if (m_State.fsm != null && !(m_State is InternalAnyState))
                {
                    menu.AddItem(new GUIContent("Set as Start"), false, delegate() { StateUtility.SetAsStart(m_State); this.Refresh(); });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Set as Start"));
                }

                // Set as concurrent state
                if (m_State.fsm != null && !(m_State is InternalAnyState))
                {
                    if (m_IsConcurrent)
                    {
                        menu.AddItem(new GUIContent("Set as Not Concurrent"), false, delegate() { StateUtility.RemoveConcurrentState(m_State.fsm); this.Refresh(); });
                    }
                    else
                    {
                        menu.AddItem(new GUIContent("Set as Concurrent"), false, delegate() { StateUtility.SetAsConcurrent(m_State); this.Refresh(); });
                    }
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Set as Concurrent"));
                }

                // Set as enabled
                if (m_State.fsm != null /*&& m_State.fsm.enabled*/ && Application.isPlaying && !(m_State is InternalAnyState))
                {
                    menu.AddItem(new GUIContent("Set as Enabled"), false, delegate() { m_State.enabled = true; });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Set as Enabled"));
                }

                // Add Transitions
                // Add none
                menu.AddItem(new GUIContent("Add Transition/None"), false, delegate() { StateUtility.AddTransition(m_State, 0); CreateTransitionGUIs(); });

                // Add blackboard events
                var blackboard = m_State.blackboard;
                if (blackboard != null)
                {
                    foreach (var fsmEvent in blackboard.fsmEvents)
                    {
                        int eventId = fsmEvent.id;
                        menu.AddItem(new GUIContent("Add Transition/" + fsmEvent.name), false, delegate() { StateUtility.AddTransition(m_State, eventId); CreateTransitionGUIs(); });
                    }
                }

                // Add GlobalBlackboard events
                // This is not The GlobalBlackboard?
                if (InternalGlobalBlackboard.Instance != null && blackboard != InternalGlobalBlackboard.Instance)
                {
                    foreach (var globalEvent in InternalGlobalBlackboard.Instance.fsmEvents)
                    {
                        int eventId   = globalEvent.id;
                        var eventName = globalEvent.isSystem ? "Add Transition/System/" + globalEvent.name : "Add Transition/Global/" + globalEvent.name;
                        menu.AddItem(new GUIContent(eventName), false, delegate() { StateUtility.AddTransition(m_State, eventId); CreateTransitionGUIs(); });
                    }
                }

                // Separator
                menu.AddSeparator("");

                // Copy
                menu.AddItem(new GUIContent("Copy State"), false, delegate() { StateUtility.CopySelectedStates(); });

                // Paste
                if (StateUtility.statesToPaste != null && StateUtility.statesToPaste.Length > 0 && m_State.fsm != null)
                {
                    menu.AddItem(new GUIContent("Paste State"), false, delegate() { StateUtility.PasteStates(m_State.fsm); });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Paste State"));
                }

                // Duplicate
                if (m_State.fsm != null)
                {
                    menu.AddItem(new GUIContent("Duplicate State"), false, delegate()
                    {
                        var statesToPaste = new List <InternalStateBehaviour>(BehaviourWindow.activeStates);
                        if (!statesToPaste.Contains(m_State))
                        {
                            statesToPaste.Add(m_State);
                        }

                        StateUtility.CloneStates(m_State.gameObject, statesToPaste.ToArray(), m_State.fsm);
                    }
                                 );
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Duplicate State"));
                }

                // Separator
                menu.AddSeparator("");

                // Delete
                menu.AddItem(new GUIContent("Delete"), false, delegate() { StateUtility.Destroy(m_State); this.Refresh(); });
            }
            else
            {
                menu.AddDisabledItem(new GUIContent("Set as Start"));
                menu.AddDisabledItem(new GUIContent("Set as Enabled"));
                menu.AddDisabledItem(new GUIContent("Add Transition"));
                menu.AddSeparator("");
                menu.AddDisabledItem(new GUIContent("Copy State"));
                menu.AddDisabledItem(new GUIContent("Paste State"));
                menu.AddSeparator("");
                menu.AddDisabledItem(new GUIContent("Delete"));
            }

            // Show the context menu
            menu.ShowAsContext();
        }