void AddTaskToAssets(BehaviourTreeExecutionNode node, BehaviourTreeTask oldTaskToRemove) { if (oldTaskToRemove != null) { DestroyImmediate(oldTaskToRemove, true); } AssetDatabase.AddObjectToAsset(node.task, behaviourTreeAssetFilesPath); AssetDatabase.ImportAsset(behaviourTreeAssetFilesPath); AssetDatabase.Refresh(); }
// Draw the property inside the given rect public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); object variable = property.serializedObject.targetObject; EditorSharedVariable sharedVariable = Base.Common.EditorHelpers.GetTargetObjectOfProperty(property) as EditorSharedVariable; BehaviourTreeTask objectVariable = variable as BehaviourTreeTask; // Draw label position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); // Don't make child fields be indented var indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; if (objectVariable.treeOwner == null) { return; } string[] possibleNames = objectVariable.treeOwner.Blackboard.getNamesOfVariablesByType(sharedVariable.type); selectedIndex = 0; for (int a = 0; a < possibleNames.Length; ++a) { if (possibleNames[a] == sharedVariable.name) { selectedIndex = a; break; } } // Calculate rect var nameRect = new Rect(position.x, position.y, 150, position.height); //choose from possible list int newIndex = EditorGUI.Popup(nameRect, selectedIndex, possibleNames); if (possibleNames.Length > 0) { sharedVariable.name = possibleNames[newIndex]; selectedIndex = newIndex; } // Set indent back to what it was EditorGUI.indentLevel = indent; EditorGUI.EndProperty(); }
private void DrawConnections(BehaviourTreeTask node) { Vector2 startPosition = new Vector2(node.NodeRect.center.x, node.NodeRect.yMax - 10); if (!selectedBehaviour.hasAnyChildren(node)) { return; } foreach (BehaviourTreeTask child in selectedBehaviour.getAllChildren(node)) { Vector2 endPosition = new Vector2(child.NodeRect.center.x, child.NodeRect.yMin + 10); Vector2 distance = endPosition - startPosition; distance.x = 0; distance.y *= 0.8f; Handles.DrawBezier(startPosition, endPosition, startPosition + distance, endPosition - distance, Color.white, null, 3.0f); } }
private Vector2 computeStartPositionFor(BehaviourTreeTask forTask) { Rect startRect = forTask.NodeRect; Vector2 pos = startRect.position; //check children and put it at the most right position BehaviourTreeTask lastChild = forTask.getLastChildPos(); if (lastChild == null) { pos.y += startRect.height * 2; } else { pos = lastChild.NodeRect.position; pos.x += startRect.width * 2; } return(pos); }
private BehaviourTreeTask getNodeAt(Vector2 pos) { BehaviourTreeTask selectedNode = null; pos += scrollPosition; pos /= scaling; foreach (BehaviourTreeTask current in selectedBehaviour.GetNodes()) { Rect local = current.NodeRect; //local.width *= scaling; // local.height *= scaling; if (local.Contains(pos)) { selectedNode = current; } } return(selectedNode); }
private void OnGUI() { if (selectedBehaviour == null) { EditorGUILayout.LabelField("No behaviour tree selected"); } else { processEvents(); GUILayout.BeginVertical(); drawTopPanel(); GUILayout.BeginHorizontal(); drawLeftPanel(); // drawTreeArea(); DrawScrollView(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); if (addNodeFor != null) { //add empty child node for selected node selectedBehaviour.createNode(addNodeFor, Event.current.mousePosition); addNodeFor = null; } if (nodeToRemove != null) { //remove selected node and all his connections Undo.RegisterCompleteObjectUndo(selectedBehaviour, "Remove objects"); selectedBehaviour.removeNode(nodeToRemove); EditorUtility.SetDirty(selectedBehaviour); nodeToRemove = null; } } }
public BehaviourTreeDecorator(BehaviourTreeTask Task) { this.Task = Task; }
public BehaviourTreeDecoratorInverter(BehaviourTreeTask task) : base(task) { }
public BehaviourTreeDecoratorFilter(Func <bool> Condition, BehaviourTreeTask task) : base(task) { this.Condition = Condition; }
public BehaviourTreeDecoratorUntilFail(BehaviourTreeTask task) : base(task) { }
public BehaviourTreeDecoratorLimit(int maxRepetition, BehaviourTreeTask task) : base(task) { this.maxRepetition = maxRepetition; count = 0; }
/////////////////////////////////////////////////////// #endregion private void processEvents() { Event currentEvent = Event.current; if (currentEvent.type == EventType.MouseDown && currentNode == null) { //Debug.Log("mouse pos scaled: " + mousePosition + " mouse position normal: " + currentEvent.mousePosition+" scaling: "+scaling); currentNode = getNodeAt(currentEvent.mousePosition - new Vector2(leftPanelSize.x, topPanelHeight)); if (currentNode != null) { localOffsetForDrag = currentEvent.mousePosition; Selection.activeObject = currentNode; //set as selectd node selectedNode = currentNode; ActionTreeTask actionTask = selectedNode as ActionTreeTask; if (actionTask != null) { //create serialized object for editor modification selectedSerializedAction = new SerializedObject(selectedNode); selectedSerializedAction.Update(); } GUI.changed = true; } else { if (currentEvent.mousePosition.x > leftPanelSize.x && currentEvent.mousePosition.x < this.position.width - GUI.skin.verticalScrollbar.fixedWidth * 2.5f && currentEvent.mousePosition.y < this.position.height - 20.0f) { draggingCanvas = true; draggingOffset = currentEvent.mousePosition + scrollPosition; Selection.activeObject = selectedBehaviour; } } } else if (currentEvent.type == EventType.MouseDrag && currentNode != null) { Undo.RecordObject(selectedBehaviour, "Drag panel"); Rect oldRect = currentNode.NodeRect; Vector2 offset = (currentEvent.mousePosition - localOffsetForDrag) / scaling; localOffsetForDrag = currentEvent.mousePosition; oldRect.position += offset; oldRect.position = new Vector2(Mathf.Clamp(oldRect.position.x, 0, 10000), Mathf.Clamp(oldRect.position.y, 0, 10000)); currentNode.NodeRect = oldRect; GUI.changed = true; } else if (currentEvent.type == EventType.MouseDrag && draggingCanvas) { Undo.RecordObject(selectedBehaviour, "Drag view"); scrollPosition = draggingOffset - currentEvent.mousePosition; GUI.changed = true; } else if (currentEvent.type == EventType.MouseUp && currentNode != null) { currentNode = null; } else if (currentEvent.type == EventType.MouseUp && draggingCanvas) { draggingCanvas = false; } }
private void onDrawTasksPanel() { if (selectedNode == null) { GUILayout.Label("No selected node"); } else if (selectedNode.taskType == TaskType.ACTION) { GUILayout.Label("Selected node is a leaf node"); } else if (selectedNode.taskType == TaskType.DECORATOR && selectedNode.children.Count > 0 && ((DecoratorTreeTask)selectedNode).OnlySingleChildAllowed) { GUILayout.Label("Selected node has OnlyOneChildAllowed flag enabled, cannot add new childen"); } else { GUILayout.BeginVertical(); GUILayout.Space(20); GUILayout.Label("__________________COMPOSITES__________________"); GUILayout.Space(20); foreach (BehaviourTreeTask current in behaviourTasks_Composite) { // Debug.Log(current.name); if (GUILayout.Button(current.taskTypeName)) { Type toCreate = current.GetType(); Vector2 createAt = computeStartPositionFor(selectedNode); var element = selectedBehaviour.createNodeOfType(toCreate, selectedNode, createAt); if (element != null) { selectedNode = element; selectedNode.editorTexture = current.editorTexture; selectedNode.taskTypeName = current.taskTypeName; selectedNode.taskType = current.taskType; } } } GUILayout.Space(20); GUILayout.Label("__________________DECORATORS__________________"); GUILayout.Space(20); foreach (BehaviourTreeTask current in behaviourTasks_Decorators) { // Debug.Log(current.name); if (GUILayout.Button(current.taskTypeName)) { Type toCreate = current.GetType(); Vector2 createAt = computeStartPositionFor(selectedNode); var element = selectedBehaviour.createNodeOfType(toCreate, selectedNode, createAt); if (element != null) { selectedNode = element; selectedNode.editorTexture = current.editorTexture; selectedNode.taskTypeName = current.taskTypeName; selectedNode.taskType = current.taskType; } } } GUILayout.Space(20); GUILayout.Label("__________________ACTIONS__________________"); GUILayout.Space(20); foreach (BehaviourTreeTask current in behaviourTasks_Actions) { // Debug.Log(current.name); if (GUILayout.Button(current.taskTypeName)) { Type toCreate = current.GetType(); Vector2 createAt = computeStartPositionFor(selectedNode); var element = selectedBehaviour.createNodeOfType(toCreate, selectedNode, createAt); selectedNode = element; selectedNode.editorTexture = current.editorTexture; selectedNode.taskTypeName = current.taskTypeName; selectedNode.taskType = current.taskType; } } GUILayout.EndVertical(); } }
/// <summary> /// DRAW UI /// </summary> private void DrawNode(BehaviourTreeTask node) { Color lastColor = GUI.backgroundColor; if (selectedNode == node) { GUI.backgroundColor = Color.green; } else { GUI.backgroundColor = lastColor; } if (node.taskType != TaskType.ROOT) { Rect upperPartRect = new Rect(node.NodeRect.x + node.NodeRect.width * 0.5f - node.NodeRect.width * 0.3f, node.NodeRect.y - node.NodeRect.height * 0.1f, node.NodeRect.width * 0.6f, node.NodeRect.height * 0.3f); GUILayout.BeginArea(upperPartRect, nodeStyle); GUILayout.EndArea(); } if (node.taskType != TaskType.ACTION) { Rect lowerPartRect = new Rect(node.NodeRect.x + node.NodeRect.width * 0.5f - node.NodeRect.width * 0.3f, node.NodeRect.y + node.NodeRect.height * 0.8f, node.NodeRect.width * 0.6f, node.NodeRect.height * 0.3f); GUILayout.BeginArea(lowerPartRect, nodeStyle); GUILayout.EndArea(); } GUILayout.BeginArea(node.NodeRect, nodeStyle); GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUI.skin.box.alignment = TextAnchor.MiddleCenter; GUILayout.BeginVertical(); GUILayout.Label(node.taskTypeName); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Box(node.editorTexture); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndArea(); if (node.taskType != TaskType.ROOT) { Rect nodeRectFull = node.NodeRect; Rect buttonRect = new Rect(nodeRectFull.x - 10.0f + nodeRectFull.width * 0.5f, nodeRectFull.y + nodeRectFull.height * 0.7f, 20.0f, 20.0f); //buttons for erasing if (GUI.Button(buttonRect, "x")) { //delete node if (!reparenting) { nodeToRemove = node; } } //draw option for reparenting Rect reparentRect = new Rect(nodeRectFull.x - 10.0f + nodeRectFull.width * 0.8f, nodeRectFull.y + nodeRectFull.height * 0.7f, 20.0f, 20.0f); if (reparenting) { if (selectedForReparenting == node) { var oldColor = GUI.backgroundColor; GUI.backgroundColor = Color.red; if (GUI.Button(reparentRect, "R")) { reparenting = false; selectedForReparenting = null; } GUI.backgroundColor = oldColor; } else { var oldColor = GUI.backgroundColor; GUI.backgroundColor = Color.green; if (GUI.Button(reparentRect, "R")) { BehaviourTree.Reparent(node, selectedForReparenting); reparenting = false; selectedForReparenting = null; } GUI.backgroundColor = oldColor; } } else { if (GUI.Button(reparentRect, "R")) { reparenting = true; selectedForReparenting = node; } } } GUI.backgroundColor = lastColor; }
public BehaviourTree(BehaviourTreeTask root) { this.root = root; }
void ExecutionWindowFunction(int windowID) { BehaviourTreeExecutionNode node = (BehaviourTreeExecutionNode)FindNodeByID(BehaviourTreeEditorWindow.behaviourTree, windowID); Event current = Event.current; if (current.mousePosition.x >= 0.0f && current.mousePosition.x <= nodeSize.x * zoomScale && current.mousePosition.y >= 0.0f && current.mousePosition.y <= nodeSize.y * zoomScale && DragAndDrop.objectReferences.Length == 1) { Object taskScriptAsset = DragAndDrop.objectReferences[0]; if (!(taskScriptAsset is MonoScript)) { DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; } else { DragAndDrop.visualMode = DragAndDropVisualMode.Link; } } if (current.type == EventType.MouseDown && current.button == 1) { this.selectedNode = node; if (Selection.activeObject != BehaviourTreeEditorWindow.behaviourTree) { SelectNodeButDontChangeProjectView(); } GenericMenu menu = new GenericMenu(); AddInsertNewParentOptions(menu); AddMoveOption(menu); menu.AddItem(new GUIContent("Delete Node"), false, DeleteNodeCallback); menu.ShowAsContext(); current.Use(); } else if (current.type.Equals(EventType.DragExited)) { Object taskScriptAsset = DragAndDrop.objectReferences[0]; if (!(taskScriptAsset is MonoScript)) { current.Use(); return; } System.Type taskType = (taskScriptAsset as MonoScript).GetClass(); ScriptableObject so = ScriptableObject.CreateInstance(taskType); if (!(so is BehaviourTreeTask)) { current.Use(); return; } BehaviourTreeTask oldTaskToRemove = node.task; node.task = so as BehaviourTreeTask; node.contextLink.Clear(); PropertyReader.Variable[] variables = PropertyReader.GetFields(node.task.GetType()); foreach (PropertyReader.Variable variable in variables) { if (variable.name.StartsWith("in_") || variable.name.StartsWith("out_")) { node.contextLink.Add(variable.name, variable.name.Split('_')[1]); } } node.displayedName = taskType.ToString(); AddTaskToAssets(node, oldTaskToRemove); BehaviourTreeEditorWindow.SaveBehaviourTree(); this.selectedNode = node; Selection.activeObject = taskScriptAsset; SelectNodeButDontChangeProjectView(); current.Use(); } else if (current.type == EventType.MouseDown && current.button == 0 && current.clickCount == 2) { this.selectedNode = node; if (Selection.activeObject != BehaviourTreeEditorWindow.behaviourTree) { SelectNodeButDontChangeProjectView(); } MonoScript monoscript = MonoScript.FromScriptableObject(node.task); string scriptPath = AssetDatabase.GetAssetPath(monoscript); UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(scriptPath, 0); current.Use(); } else if (current.type == EventType.MouseDown && current.button == 0) { this.selectedNode = node; if (Selection.activeObject != BehaviourTreeEditorWindow.behaviourTree) { SelectNodeButDontChangeProjectView(); } current.Use(); } }