override public void OnInspectorGUI() { BehaviourTreeData activeTreeData = BTEditor.activeTreeData; if (activeTreeData != null && behaviourTree != null && activeTreeData.GetInstanceID() == behaviourTree.GetInstanceID()) { BehaviourNodeEditor node = BTEditor.lastActiveNode; if (node != null && node.nodeID < behaviourTree.nodeName.Count) { switch (node.type) { case BehaviourNodeType.action: EditorGUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Node ID: " + node.nodeID.ToString()); } EditorGUILayout.EndHorizontal(); behaviourTree.nodeName[node.nodeID] = EditorGUILayout.TextField("Node Name", behaviourTree.nodeName[node.nodeID], EditorStyles.textField); break; default: DrawDefaultInspector(); break; } } else { DrawDefaultInspector(); } if (GUI.changed) { EditorUtility.SetDirty(behaviourTree); } } Repaint(); }
public void OnGUI() { if (Selection.activeObject != null && Selection.activeObject is BehaviourTreeData) { if (activeTreeData == null || activeTreeData != Selection.activeObject || editorTree.root == null || lastSelectedObject != Selection.activeObject) { activeTreeData = Selection.activeObject as BehaviourTreeData; activeNode = null; lastActiveNode = null; editorTree.buildTree(activeTreeData); } } lastSelectedObject = Selection.activeObject; #if true //title and asset name GUILayout.Label("Behaviour Tree Editor", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Name"); if (activeTreeData != null) { GUILayout.Label(activeTreeData.name, EditorStyles.label); } else { GUILayout.Label("none", EditorStyles.label); } } EditorGUILayout.EndHorizontal(); #endif editorTree.OnGUI(new Rect(0, 50, position.width, position.height - 50)); if (activeNode != null) { lastActiveNode = activeNode; } activeNode = editorTree.clickedNode; #if true //context menu Event evt = Event.current; if (evt.button == 1 && (activeNode != null || evt.rawType == EventType.MouseUp)) { GenericMenu menu = new GenericMenu(); if (activeNode == null) { if (editorTree.root == null) { AddActionItem(menu); menu.AddSeparator(""); AddInverterItem(menu); menu.AddSeparator(""); AddPrioritySelectorItem(menu); AddSequenceSelectorItem(menu); } } else { switch (activeNode.type) { case BehaviourNodeType.action: AddDeleteNodeItem(menu); break; case BehaviourNodeType.inverter: AddDeleteNodeItem(menu); menu.AddSeparator(""); AddActionItem(menu); menu.AddSeparator(""); AddPrioritySelectorItem(menu); AddSequenceSelectorItem(menu); break; case BehaviourNodeType.prioritySelector: AddDeleteNodeItem(menu); menu.AddSeparator(""); AddActionItem(menu); menu.AddSeparator(""); AddInverterItem(menu); menu.AddSeparator(""); AddPrioritySelectorItem(menu); AddSequenceSelectorItem(menu); break; case BehaviourNodeType.sequenceSelector: AddDeleteNodeItem(menu); menu.AddSeparator(""); AddActionItem(menu); menu.AddSeparator(""); AddInverterItem(menu); menu.AddSeparator(""); AddPrioritySelectorItem(menu); break; } } menu.ShowAsContext(); evt.Use(); } #endif if (evt.commandName == "UndoRedoPerformed" && activeTreeData != null) { editorTree.buildTree(activeTreeData); } }
public void buildTree(BehaviourTreeData treeData) { nodeList.Clear(); dim = Vector2.zero; if (treeData.nodeDepth != null && treeData.nodeDepth.Count > 0) { Vector2[] leftRight = new Vector2[treeData.nodeDepth.Count]; int x = 0; int oldDepth = treeData.nodeDepth[treeData.nodeDepth.Count - 1]; int deepestDepth = 0; //set type and y position and work out an x value for each node for (int i = treeData.nodeDepth.Count - 1; i >= 0; --i) { int depth = treeData.nodeDepth[i]; deepestDepth = Mathf.Max(deepestDepth, depth); BehaviourNodeEditor editorNode = new BehaviourNodeEditor(); editorNode.type = treeData.nodeList[i]; editorNode.position.x = x; editorNode.position.y = depth * yGap; editorNode.nodeID = i; editorNode.depth = depth; Vector2 position = leftRight[depth]; if (depth < oldDepth) { Vector2 childPos = leftRight[depth + 1]; editorNode.position.x = Mathf.Lerp(childPos.x, childPos.y, 0.5f); position.x = x + 1; } else if (depth > oldDepth) { for (int j = oldDepth + 1; j < depth; ++j) { leftRight[j] = new Vector2(x, x); } position = new Vector2(x, x); --x; } else { position.x = x; --x; } leftRight[depth] = position; nodeList.Insert(0, editorNode); //as we're going backwards through the behaviour tree, we add nodes to the front of the list oldDepth = depth; } //calculate x position x = Mathf.Abs(x + 1); dim.x = x * (xGap + nodeWidth); dim.y = deepestDepth * yGap + nodeHeight; for (int i = 0; i < nodeList.Count; ++i) { BehaviourNodeEditor editorNode = nodeList[i]; editorNode.position.x += x; editorNode.position.x *= nodeWidth + xGap; nodeList[i] = editorNode; } } root = null; if (nodeList.Count > 0) { root = nodeList[0]; } }
public void OnGUI(Rect position) { if (nodeList == null) { return; } float width = Mathf.Max(dim.x, position.width); scrollPosition = GUI.BeginScrollView(position, scrollPosition, new Rect((width - dim.x) * -0.5f, 0, width, dim.y)); clickedNode = null; nodeStack.Clear(); foreach (BehaviourNodeEditor editorNode in nodeList) { #if true //render lines while (nodeStack.Count > 0 && editorNode.depth <= nodeStack[nodeStack.Count - 1].depth) { nodeStack.RemoveAt(nodeStack.Count - 1); } if (nodeStack.Count > 0) { BehaviourNodeEditor parentNode = nodeStack[nodeStack.Count - 1]; Handles.color = new Color(0, 0, 0); Handles.DrawLine(new Vector3(parentNode.position.x, parentNode.position.y + nodeHeight), new Vector3(editorNode.position.x, editorNode.position.y)); } nodeStack.Add(editorNode); #endif #if true //render icons Rect rect = new Rect(editorNode.position.x - nodeHalfWidth, editorNode.position.y, nodeWidth, nodeHeight); switch (editorNode.type) { case BehaviourNodeType.action: if (GUI.Button(rect, "A!")) { clickedNode = editorNode; } break; case BehaviourNodeType.inverter: if (GUI.Button(rect, "IN")) { clickedNode = editorNode; } break; case BehaviourNodeType.prioritySelector: if (GUI.Button(rect, "PS")) { clickedNode = editorNode; } break; case BehaviourNodeType.sequenceSelector: if (GUI.Button(rect, "SS")) { clickedNode = editorNode; } break; } #endif } GUI.EndScrollView(); }