/// <summary> /// A Unity callback called when the object is loaded. /// </summary> private void OnEnable() { m_ActionState = target as InternalActionState; BehaviourWindow.activeNodeChanged += this.ActiveNodeChanged; // Try to create an editor for the current active node this.ActiveNodeChanged(); // Register the visual debugging callback ActionNode.onNodeTick += OnNodeTick; // Register Update if (Application.isPlaying) { EditorApplication.update += this.Update; } else { m_ActionState.LoadNodes(); RegisterEditorOnGUI(); } }
/// <summary> /// Paste the supplied nodes in the supplied ActionState. /// <param name="actionState">The ActionState to paste the node.</param> /// <param name="nodes">The nodes to be pasted.</param> /// <returns>The pasted nodes.</returns> /// </summary> public static ActionNode[] PasteNodes(InternalActionState actionState, ActionNode[] nodes) { var newNodes = new List <ActionNode>(); // Validate parameters if (nodes != null && actionState != null) { // Register Undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterUndo(actionState, "Paste Node"); #else Undo.RecordObject(actionState, "Paste Node"); #endif // Copy nodes for (int i = 0; i < nodes.Length; i++) { if (nodes[i] != null && !(nodes[i] is BranchNode)) { ActionNode newNode = nodes[i].Copy(actionState); if (newNode != null) { newNodes.Add(newNode); } } } if (newNodes.Count > 0) { // Saves node and sets dirty flag StateUtility.SetDirty(actionState); // Reload actionState to update variables actionState.LoadNodes(); } } return(newNodes.ToArray()); }
/// <summary> /// Unity callback to draw a custom inspector. /// </summary> public override void OnInspectorGUI() { // Create styles? if (s_Styles == null) { s_Styles = new InternalActionStateEditor.Styles(); } // Workaround to update nodes if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed") { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; m_ActionState.LoadNodes(); UpdateActiveNode(); return; } // Reload nodes? if (m_ActionState.isDirty) { m_ActionState.LoadNodes(); UpdateActiveNode(); } // Register OnGUI node? if (!Application.isPlaying && m_ActionState.onGUINode != null && !GUICallback.HasCallbacks()) { this.RegisterEditorOnGUI(); } #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 EditorGUIUtility.LookLikeInspector(); #endif // Draw default inspector DrawDefaultInspector(); // Shows the node editor? bool showNodeEditor = m_ActionState.parent == null || BehaviourWindow.activeState == m_ActionState; // Draw Action List if (m_NodeList == null) { // m_NodeList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty("m_UpdateActions")); m_NodeList = new ReorderableList(m_ActionState.GetNodes(), typeof(ActionNode)); m_NodeList.drawHeaderCallback += delegate(Rect rect) { EditorGUI.LabelField(rect, "Nodes"); }; m_NodeList.drawElementCallback += DrawNode; m_NodeList.onAddCallback += this.OnAddNode; m_NodeList.onRemoveCallback += this.OnRemoveSelectedNode; m_NodeList.onSelectCallback += this.OnSelectNode; m_NodeList.onReorderCallback += this.OnReorderNode; // Select the active node UpdateActiveNode(); #if !UNITY_4_0_0 && !UNITY_4_1 && !UNITY_4_2 && !UNITY_4_3 m_NodeList.list = m_ActionState.GetNodes(); m_NodeList.DoLayoutList(); #else this.Repaint(); #endif } else if (showNodeEditor) { m_NodeList.list = m_ActionState.GetNodes(); m_NodeList.DoLayoutList(); } if (showNodeEditor) { GUILayout.Space(6f); #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 EditorGUIUtility.LookLikeControls(); #endif // Get the active node ActionNode activeNode = m_ActionState.isRoot ? this.GetActiveNode() : BehaviourWindow.activeNode; // Draw node properties if (m_NodeEditor != null) { // Is there an active node? if (activeNode != null && activeNode.owner as InternalActionState == m_ActionState) { // It's an Update node var oldGUIEnabled = GUI.enabled; GUI.enabled = !(activeNode is Update); m_NodeEditor.DrawNode(activeNode); GUI.enabled = oldGUIEnabled; GUILayout.Space(4f); } } // Copy/Paste/Cut/Duplicate/Delete keyboard shortcuts Event current = Event.current; if (current.type == EventType.ValidateCommand) { // Use event to call event ExecuteCommand if (current.commandName == "Paste") { ActionNode[] nodesToPaste = ActionStateUtility.GetActionsAndConditions(BehaviourTreeUtility.nodeToPaste != null ? new ActionNode[] { BehaviourTreeUtility.nodeToPaste } : new ActionNode[0]); if (nodesToPaste.Length > 0) { current.Use(); } } if (activeNode != null) { if (current.commandName == "Copy") { current.Use(); } else if (current.commandName == "Duplicate") { current.Use(); } else if (current.commandName == "Delete") { current.Use(); } else if (current.commandName == "Cut") { current.Use(); } } } else if (Event.current.type == EventType.ExecuteCommand) { if (current.commandName == "Paste") { ActionNode[] nodesToPaste = ActionStateUtility.GetActionsAndConditions(BehaviourTreeUtility.nodeToPaste != null ? new ActionNode[] { BehaviourTreeUtility.nodeToPaste } : new ActionNode[0]); ActionStateUtility.PasteNodes(m_ActionState, nodesToPaste); } else if (current.commandName == "Copy") { BehaviourTreeUtility.nodeToPaste = activeNode; } else if (current.commandName == "Duplicate") { ActionStateUtility.PasteNodes(m_ActionState, new ActionNode[] { activeNode }); } else if (current.commandName == "Delete") { this.OnDestroyNode(activeNode); } else if (current.commandName == "Cut") { BehaviourTreeUtility.nodeToPaste = activeNode; this.OnDestroyNode(activeNode); } } } }