public override void OnValidate() { if (state != null && state.parent != tree) { state = null; } }
/// <summary> /// Unity callback called when the script is loaded or a value is changed in the inspector (Called in the editor only). /// Validates the start, the AnyState and the enabled states. /// </summary> public override void OnValidate() { base.OnValidate(); // Validate the enabled state. if (m_EnabledState != null && m_EnabledState.parent != this) { m_EnabledState = null; } // Validate the start state and the currently enabled state if (m_StartState != null && m_StartState.parent != this) { m_StartState = null; } // Validate the any state if (m_AnyState != null && m_AnyState.parent != this) { m_AnyState = null; } // Validate the concurrent state if (m_ConcurrentState != null && m_ConcurrentState.parent != this) { m_ConcurrentState = null; } }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's enabled. /// </summary> protected override void OnEnableState(InternalStateBehaviour childState) { // Disable the enabled state if (m_EnabledState != null && m_EnabledState.enabled) { m_EnabledState.enabled = false; } // Update the the enabled member m_EnabledState = childState; }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's disabled. /// </summary> protected override void OnDisableState(InternalStateBehaviour childState) { // Store the last enabled state if (m_EnabledState.parent == this) { m_LastEnabledState = m_EnabledState; } // Update the enabled member m_EnabledState = null; }
/// <summary> /// Sets the state as dirty (editor only). /// </summary> public void StateSetDirty() { if (Application.isEditor) { if (InternalStateBehaviour.onUpdateHideFlag != null) { InternalStateBehaviour.onUpdateHideFlag(this); } this.SaveLastParent(); } }
/// <summary> /// Update the hideFlags of the supplied state. /// <param name ="state">The target state.</param> /// </summary> static void OnStateHideFlag (InternalStateBehaviour state) { // It's a valid state? if (state != null) { // It is not a prefab? if (!UnityEditor.AssetDatabase.Contains(state.gameObject)) { // The state is not a root parent and the hide flag is True? if (state.hideFlag && !state.isRoot) state.hideFlags = HideFlags.HideInInspector; else state.hideFlags = (HideFlags) 0; } } }
/// <summary> /// Callback called by a child InternalStateBehaviour to disabled it. /// </summary> public void DisableState(InternalStateBehaviour childState) { if (childState != null && this.IsEnabled(childState) && !(childState is InternalAnyState)) { // Call the Remove callback this.OnDisableState(childState); // Call the OnDisable callback on the childState if (childState.enabled) { ((MonoBehaviour)childState).enabled = false; } } }
public override Status Update() { // Get the last enabled state InternalStateBehaviour lastState = stateMachine != null ? stateMachine.lastEnabledState : null; // Validate members if (lastState == null) { return(Status.Error); } lastState.enabled = true; return(Status.Success); }
/// <summary> /// Class constructor. /// <param name="stateTransition">The target transition.</param> /// <param name="destination">The target destination.</param> /// <param name="index">The transition index.</param> /// <param name="blackboard">The state blackboard.</param> /// </summary> public TransitionGUI (StateTransition stateTransition, InternalStateBehaviour destination, int index, InternalBlackboard blackboard) { m_Transition = stateTransition; m_Destination = destination; // It's a global event? if (m_Transition.eventID < 0) { if (InternalGlobalBlackboard.Instance != null) m_FsmEvent = InternalGlobalBlackboard.Instance.GetFsmEvent(m_Transition.eventID); } // It's a local variable and the blackboard is not null? else if (m_Transition.eventID > 0 && blackboard != null) m_FsmEvent = blackboard.GetFsmEvent(m_Transition.eventID); // Get the transition arrow vertical offset m_VerticalOffset = StateGUI.defaultHeight + TransitionGUI.defaultHeight * (index + .35f); }
/// <summary> /// Unity callback called when the object becomes enabled and active. /// Enables the start state, if the start state is null then tries to enable the first one. /// </summary> public virtual void OnEnable() { #if UNITY_EDITOR if (!Application.isPlaying) { return; } #endif // Add this parent to the blackboard to receive system events if (isRoot) { blackboard.AddRootParent(this); } // Enable the concurrent state if (m_ConcurrentState != null && !m_ConcurrentState.enabled) { ((MonoBehaviour)m_ConcurrentState).enabled = true; } // There is not an enabled state? if (m_EnabledState == null || !m_EnabledState.enabled || m_EnabledState.parent != this) { // Enable the start state if (m_StartState != null && m_StartState.parent == this && !m_StartState.enabled) { m_StartState.enabled = true; } // Try to get the first state else { var states = this.states; var firstState = states.Count > 0 ? states[0] : null; if (firstState != null && !(firstState is InternalAnyState)) { m_StartState = firstState; m_StartState.enabled = true; Print.LogWarning("Start State not set in \'" + stateName + "\', getting the first one \'" + m_StartState.name + "\' (" + m_StartState.GetType().Name + ").", this); } else { Print.LogError("No state in \'" + stateName + "\' (" + GetType().Name + ").", this); } } } }
/// <summary> /// Sets the state as the concurrent state of the fsm. /// Automatically handles undo. /// <param name="state">The new fsm concurrent state.</param> /// </summary> public static void SetAsConcurrent (InternalStateBehaviour state) { // Get the fsm var fsm = state.fsm; // The fsm is valid and the state is not the start state? if (fsm != null && fsm.concurrentState != state) { // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo(fsm, "Concurrent State"); #else Undo.RecordObject(fsm, "Concurrent State"); #endif fsm.concurrentState = state; EditorUtility.SetDirty(fsm); // EditorUtility.SetDirty(state); // Repaint state inspector } }
/// <summary> /// Callback called by a child InternalStateBehaviour to enabled it. /// </summary> public void EnableState(InternalStateBehaviour childState) { if (childState != null && childState.parent == this && !(childState is InternalAnyState)) { // Call the Add callback OnEnableState(childState); // Call the OnEnable callback on the new Enabled state if (!childState.enabled) { ((MonoBehaviour)childState).enabled = true; } // If this state is disabled then enable it if (!this.enabled) { this.enabled = true; } } }
/// <summary> /// Returns true if the supplied child state is enabled; false otherwise. /// <param name="childState">A child state of the ParentBehaviour.</param> /// <returns>.</returns> /// </summary> public override bool IsEnabled(InternalStateBehaviour childState) { return(m_EnabledStates.Contains(childState)); }
/// <summary> /// Returns true if he supplied state is not null and is not a start state. /// <param name="state">The state to test.</param> /// <returns>False if the state is a start state; True otherwise.</returns> /// </summary> protected bool IsNotStart (InternalStateBehaviour state) { return state != null && state.fsm != null && state.fsm.startState != state; }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's disabled. /// </summary> protected override void OnDisableState(InternalStateBehaviour childState) { // Update the enabled list m_EnabledStates.Remove(childState); }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's enabled. /// </summary> protected override void OnEnableState (InternalStateBehaviour childState) { // Disable the enabled state if (m_EnabledState != null && m_EnabledState.enabled) m_EnabledState.enabled = false; // Update the the enabled member m_EnabledState = childState; }
/// <summary> /// Returns true if the supplied state is not null and is not a root. /// <param name="state">The state to test.</param> /// <returns>False if the state is a root; True otherwise.</returns> /// </summary> protected bool IsNotRoot (InternalStateBehaviour state) { return state != null && !state.isRoot; }
public override void OnValidate () { if (state != null && state.parent != tree) state = null; }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's enabled. /// </summary> protected override void OnEnableState (InternalStateBehaviour childState) { // Update the enabled list m_EnabledStates.Add(childState); }
/// <summary> /// Sets a new destination state to the supplied transition. /// <param name="state">The state that owns the target transition.</param> /// <param name="transition">The transition to set the new destination.</param> /// <param name="destination">The new destination state.</param> /// </summary> public static void SetNewDestination (InternalStateBehaviour state, StateTransition transition, InternalStateBehaviour destination) { // Validate members if (state != null && transition != null) { // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo(state,"Transition Destination"); #else Undo.RecordObject(state,"Transition Destination"); #endif // Create a connection to the destination transition.destination = destination; // Set state dirty flag EditorUtility.SetDirty(state); } }
/// <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); } }
/// <summary> /// Returns true if the supplied child state is enabled; false otherwise. /// <param name="childState">A child state of the ParentBehaviour.</param> /// <returns>.</returns> /// </summary> public override bool IsEnabled (InternalStateBehaviour childState) { return m_EnabledState == childState; }
/// <summary> /// Callback called by a child InternalStateBehaviour when it's disabled. /// </summary> protected override void OnDisableState (InternalStateBehaviour childState) { // Store the last enabled state if (m_EnabledState.parent == this) m_LastEnabledState = m_EnabledState; // Update the enabled member m_EnabledState = null; }
public override void Reset() { state = null; }
/// <summary> /// Unity callback called when the object becomes enabled and active. /// Enables the start state, if the start state is null then tries to enable the first one. /// </summary> public virtual void OnEnable () { #if UNITY_EDITOR if (!Application.isPlaying) return; #endif // Add this parent to the blackboard to receive system events if (isRoot) blackboard.AddRootParent(this); // Enable the concurrent state if (m_ConcurrentState != null && !m_ConcurrentState.enabled) ((MonoBehaviour)m_ConcurrentState).enabled = true; // There is not an enabled state? if (m_EnabledState == null || !m_EnabledState.enabled || m_EnabledState.parent != this) { // Enable the start state if (m_StartState != null && m_StartState.parent == this && !m_StartState.enabled) { m_StartState.enabled = true; } // Try to get the first state else { var states = this.states; var firstState = states.Count > 0 ? states[0] : null; if (firstState != null && !(firstState is InternalAnyState)) { m_StartState = firstState; m_StartState.enabled = true; Print.LogWarning("Start State not set in \'" + stateName + "\', getting the first one \'" + m_StartState.name + "\' (" + m_StartState.GetType().Name + ").", this); } else { Print.LogError("No state in \'" + stateName + "\' (" + GetType().Name + ").", this); } } } }
/// <summary> /// Shows a context menu to delete or unparent a state. /// <param name="state">The state to delete or unparent.</param> /// </summary> void OnDeleteUnparentContextMenu (InternalStateBehaviour state) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("Unparent"), false, this.OnUnparentState, state); menu.AddItem(new GUIContent("Delete"), false, this.OnDeleteState, state); menu.ShowAsContext(); }
/// <summary> /// Adds a new transition to the state. /// Automatically handles undo. /// <param name="state">The state to add a new transition.</param> /// <param name="eventID">The event id of the new transition.</param> /// </summary> public static void AddTransition (InternalStateBehaviour state, int eventID) { // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo (state, "Create Transition"); #else Undo.RecordObject (state, "Create Transition"); #endif state.AddTransition(eventID); EditorUtility.SetDirty(state); }
public SetParent (InternalStateBehaviour state, ParentBehaviour newParent) { this.state = state; this.newParent = newParent; }
/// <summary> /// Sets a new event id in the supplied transition. /// <param name="state">The state that owns the target transition.</param> /// <param name="transition">The transition to set the new event id.</param> /// <param name="eventId">The new event id.</param> /// </summary> public static void SetNewEvent (InternalStateBehaviour state, StateTransition transition, int eventId) { // Validate members if (state != null && transition != null) { // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo (state, "Transition Event"); #else Undo.RecordObject (state, "Transition Event"); #endif // Set transition event transition.eventID = eventId; // Set state dirty flag EditorUtility.SetDirty(state); } }
public override void Reset () { state = null; }
/// <summary> /// Removes the transition from the state. /// <param name="state">The state that owns the target transition.</param> /// <param name="transition">The transition to be removed.</param> /// </summary> public static void RemoveTransition (InternalStateBehaviour state, StateTransition transition) { // Validate members if (state != null && transition != null) { // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo (state, "Delete Transition"); #else Undo.RecordObject (state, "Delete Transition"); #endif // Remove transition state.RemoveTransition(transition); // Set state dirty flag EditorUtility.SetDirty(state); } }
/// <summary> /// Returns true if the supplied child state is enabled; false otherwise. /// <param name="childState">A child state of the ParentBehaviour.</param> /// <returns>.</returns> /// </summary> public abstract bool IsEnabled(InternalStateBehaviour childState);
/// <summary> /// Destroys the supplied state. /// Automatically handles undo. /// <param name="state">The state to be destroyed.</param> /// </summary> public static void Destroy (InternalStateBehaviour state) { // its a valid state if (state != null) { var gameObject = state.gameObject; // stores the gameObject to set dirty flag var isPrefab = FileUtility.IsPrefab(gameObject); var monoState = state as InternalMonoState; // its a mono state? // It is a fsm? if (state is ParentBehaviour) { var parent = state as ParentBehaviour; foreach (var child in parent.states) StateUtility.Destroy(child); } if (Application.isPlaying && !isPrefab) { // Its a MonoState and the user wants to destroy mono behaviour to? if (monoState != null && monoState.monoBehaviour != null && EditorUtility.DisplayDialog("Destroy MonoBehaviour?", "Do you want to destroy the " + monoState.monoBehaviour.GetType().ToString() + "?", "Ok", "Cancel")) { var monoStateGO = monoState.gameObject; Object.Destroy(monoState.monoBehaviour); EditorUtility.SetDirty(monoStateGO); } Object.Destroy(state); } else { // Register scene undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterSceneUndo("Delete"); #endif // Its a MonoState and the user wants to destroy the MonoBehaviour to? if (monoState != null && monoState.monoBehaviour != null && EditorUtility.DisplayDialog("Destroy MonoBehaviour?", "Do you want to destroy the " + monoState.monoBehaviour.GetType().ToString() + "?", "Ok", "Cancel")) { // Gets the MonoState game object var monoStateGO = monoState.gameObject; // Destroy the mono behaviour #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Object.DestroyImmediate(monoState.monoBehaviour, true); #else Undo.DestroyObjectImmediate(monoState.monoBehaviour); #endif // Set game object dirty flag EditorUtility.SetDirty(monoStateGO); } // Destroys the state #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Object.DestroyImmediate(state, true); #else Undo.DestroyObjectImmediate(state); #endif } EditorUtility.SetDirty(gameObject); } }
/// <summary> /// Returns true if the supplied child state is enabled; false otherwise. /// <param name="childState">A child state of the ParentBehaviour.</param> /// <returns>.</returns> /// </summary> public override bool IsEnabled(InternalStateBehaviour childState) { return(m_EnabledState == childState); }
/// <summary> /// Returns true if the supplied child state is enabled; false otherwise. /// <param name="childState">A child state of the ParentBehaviour.</param> /// <returns>.</returns> /// </summary> public override bool IsEnabled (InternalStateBehaviour childState) { return m_EnabledStates.Contains(childState); }
/// <summary> /// Callback called when a new child state is enabled. /// </summary> protected abstract void OnEnableState(InternalStateBehaviour childState);
/// <summary> /// Shows a menu to select states that are in the same parent as the supplied state. /// <param name="state">The target state.</param> /// </summary> void ShowStateSelectionMenu (InternalStateBehaviour state) { var menu = new GenericMenu(); var states = state.GetComponents<InternalStateBehaviour>(); var uniqueNames = new List<string>(); // Build the menu for (int i = 0; i < states.Length; i++) { // Get the current state var currentState = states[i]; // The current state has the same parent as the supplied state? if (currentState.parent == state.parent) { string currentName = StringHelper.GetUniqueNameInList(uniqueNames, currentState.stateName); uniqueNames.Add(currentName); menu.AddItem(new GUIContent(currentName), state == currentState, delegate () {activeParent = currentState as ParentBehaviour ?? currentState.parent; Selection.objects = new UnityEngine.Object[] {currentState};}); } } menu.ShowAsContext(); }
/// <summary> /// Unity callback called when the script is loaded or a value is changed in the inspector (Called in the editor only). /// Validates the start, the AnyState and the enabled states. /// </summary> public override void OnValidate () { base.OnValidate(); // Validate the enabled state. if (m_EnabledState != null && m_EnabledState.parent != this) m_EnabledState = null; // Validate the start state and the currently enabled state if (m_StartState != null && m_StartState.parent != this) m_StartState = null; // Validate the any state if (m_AnyState != null && m_AnyState.parent != this) m_AnyState = null; // Validate the concurrent state if (m_ConcurrentState != null && m_ConcurrentState.parent != this) m_ConcurrentState = null; }