BTNode CreateNodeWithParent(Type nodeType, BTNode parent) { BTNode newNode = CreateNode(nodeType); EditorData nodeData = new EditorData(newNode, parent); nodeData.rect.position = _editorData[parent.id].rect.position + new Vector2(0.0f, 100.0f); _behaviorTree._editorData.Add(nodeData); BuildEditorData(); return(newNode); }
void ReplaceNode(EditorData nodeData, Type newType) { BTNode oldNode = nodeData.node; BTNode newNode = CreateNode(newType); // Transfer editor data. newNode.id = nodeData.id; nodeData.node = newNode; // Swap children, then delete old node. if (oldNode is BTDecorator && newNode is BTDecorator) { ((BTDecorator)newNode).child = ((BTDecorator)oldNode).child; ((BTDecorator)oldNode).child = null; } else if (oldNode is BTComposite && newNode is BTComposite) { ((BTComposite)newNode).children = ((BTComposite)oldNode).children; ((BTComposite)oldNode).children = null; } DeleteNode(oldNode, false); // Update parent's reference to the node. if (nodeData.parent) { if (nodeData.parent is BTDecorator) { BTDecorator parentDecorator = (BTDecorator)nodeData.parent; parentDecorator.child = nodeData.node; } else if (nodeData.parent is BTComposite) { BTComposite parentCompositor = (BTComposite)nodeData.parent; parentCompositor.children[nodeData.parentIndex] = nodeData.node; } else { Debug.LogError("Parent node is neither a Decorator nor a Compositor!"); } } else { // Node is root node. _behaviorTree.root = nodeData.node; } // Editor data will have changed, so we must rebuild // it before continuing with rendering the GUI. BuildEditorData(); }
void CreateNodeWindow(EditorData nodeData, float width, float height) { nodeData.rect.width = width; nodeData.rect.height = height; Rect tempRect = nodeData.rect; tempRect.position += offset; Rect resultRect = GUI.Window(nodeData.id, tempRect, DrawNodeWindow, ""); resultRect.position -= offset; // If the node was moved, save the change and mark the asset as dirty. if (resultRect != nodeData.rect) { nodeData.rect = resultRect; EditorUtility.SetDirty(_behaviorTree); } }
void DrawNodeWindow(int id) { // Get EditorNode EditorData nodeData = _editorData[id]; BTNode node = nodeData.node; Type selectedType = CreateNodeTypeDropdown(node); if (selectedType != node.GetType()) { ReplaceNode(nodeData, selectedType); node = nodeData.node; } if (node is BTComposite) { BTComposite compositor = (BTComposite)node; Rect rect = new Rect(0, 20, _nodeWidth, 20); if (GUI.Button(rect, "Add Child")) { BTNode childNode = CreateNodeWithParent(typeof(BTActionBlank), compositor); compositor.children.Add(childNode); } } else if (node is BTLeaf) { if (node == null) { // Passing null to Editor.CreateEditor() causes the whole editor to hard crash, // so we throw an exception to keep that from happening. node should never be // null in this case, anyway, but if it is we don't want the whole editor to shut down. throw new NullReferenceException(); } Editor editor = Editor.CreateEditor(node); editor.OnInspectorGUI(); } // Drag window last because otherwise you can't click on things GUI.DragWindow(); }
void DrawCompositor(BTComposite compositor) { EditorData nodeData = _editorData[compositor.id]; CreateNodeWindow(nodeData, _nodeWidth, _compositorHeight); for (int index = 0; index < compositor.children.Count; ++index) { BTNode child = compositor.children[index]; EditorData childData = _editorData[child.id]; if (DrawPlusButton(nodeData, childData)) { BTDecorator newChild = (BTDecorator)CreateNodeWithParent(typeof(BTInverter), compositor); newChild.child = child; compositor.children[index] = newChild; _editorData[newChild.id].parentIndex = index; child = newChild; } if (index > 0 && DrawLeftButton(childData)) { SwapCompositorChildren(compositor, index, index - 1); } if (index < compositor.children.Count - 1 && DrawRightButton(childData)) { SwapCompositorChildren(compositor, index, index + 1); } DrawNodeCurve(nodeData.rect, childData.rect, index, compositor.children.Count); DrawNode(child); } }
void SwapCompositorChildren(BTComposite compositor, int firstIndex, int secondIndex) { // Retrieve nodes and editor data. BTNode first = compositor.children[firstIndex]; EditorData childData = _editorData[first.id]; BTNode second = compositor.children[secondIndex]; EditorData secondData = _editorData[second.id]; // Swap the order of the children in the array. compositor.children[secondIndex] = first; compositor.children[firstIndex] = second; // Swap the positions of the two children's nodes. // TODO: Move the entire subtree under each node by the same amount. Vector2 tempPosition = secondData.rect.position; secondData.rect.position = childData.rect.position; childData.rect.position = tempPosition; // Update EditorData indices. secondData.parentIndex = firstIndex; childData.parentIndex = secondIndex; }
void DrawLeaf(BTLeaf leaf) { EditorData nodeData = _editorData[leaf.id]; CreateNodeWindow(nodeData, _nodeWidth, _leafHeight); }
void ReplaceNode( EditorData nodeData, Type newType ) { BTNode oldNode = nodeData.node; BTNode newNode = CreateNode( newType ); // Transfer editor data. newNode.id = nodeData.id; nodeData.node = newNode; // Swap children, then delete old node. if ( oldNode is BTDecorator && newNode is BTDecorator ) { ( (BTDecorator)newNode ).child = ( (BTDecorator)oldNode ).child; ( (BTDecorator)oldNode ).child = null; } else if ( oldNode is BTComposite && newNode is BTComposite ) { ( (BTComposite)newNode ).children = ( (BTComposite)oldNode ).children; ( (BTComposite)oldNode ).children = null; } DeleteNode( oldNode, false ); // Update parent's reference to the node. if ( nodeData.parent ) { if ( nodeData.parent is BTDecorator ) { BTDecorator parentDecorator = (BTDecorator)nodeData.parent; parentDecorator.child = nodeData.node; } else if ( nodeData.parent is BTComposite ) { BTComposite parentCompositor = (BTComposite)nodeData.parent; parentCompositor.children[nodeData.parentIndex] = nodeData.node; } else { Debug.LogError( "Parent node is neither a Decorator nor a Compositor!" ); } } else { // Node is root node. _behaviorTree.root = nodeData.node; } // Editor data will have changed, so we must rebuild // it before continuing with rendering the GUI. BuildEditorData(); }
BTNode CreateNodeWithParent( Type nodeType, BTNode parent ) { BTNode newNode = CreateNode( nodeType ); EditorData nodeData = new EditorData( newNode, parent ); nodeData.rect.position = _editorData[parent.id].rect.position + new Vector2( 0.0f, 100.0f ); _behaviorTree._editorData.Add( nodeData ); BuildEditorData(); return newNode; }
void CreateNodeWindow( EditorData nodeData, float width, float height ) { nodeData.rect.width = width; nodeData.rect.height = height; Rect tempRect = nodeData.rect; tempRect.position += offset; Rect resultRect = GUI.Window( nodeData.id, tempRect, DrawNodeWindow, "" ); resultRect.position -= offset; // If the node was moved, save the change and mark the asset as dirty. if ( resultRect != nodeData.rect ) { nodeData.rect = resultRect; EditorUtility.SetDirty( _behaviorTree ); } }
bool DrawRightButton( EditorData child ) { float left = child.rect.x - 18; float top = child.rect.y + ( child.parentIndex == 0 ? 0 : 18 ); Vector2 position = new Vector2( left, top ); return DrawEditorButton( position, _rightIcon ); }
bool DrawLeftButton( EditorData child ) { float left = child.rect.x - 18; float top = child.rect.y; return DrawEditorButton( new Vector2( left, top ), _leftIcon ); }
bool DrawPlusButton( EditorData parent, EditorData child ) { float midX = ( ( parent.rect.x + _nodeWidth * 0.5f ) + ( child.rect.x + _nodeWidth * 0.5f ) ) * 0.5f; float midY = ( ( parent.rect.y + parent.rect.height ) + child.rect.y ) * 0.5f; return DrawEditorButton( new Vector2( midX + 2, midY - 8 ), _plusIcon ); }