Ejemplo n.º 1
0
        /// <summary>
        /// Attaches a dragged node from the node explorer to an existing node.
        /// </summary>
        /// <param name="nvd">The node the new node will be attached to.</param>
        /// <param name="mode">The way the new node will be attached.</param>
        /// <param name="nodetag">The tag of the you want to create.</param>
        /// <param name="label">The label of the new node.</param>
        private void InsertNewNode(NodeViewData nvd, NodeAttachMode mode, NodeTag nodetag, PointF mousePos) {
            if (nodetag.Type != NodeTagType.Behavior && nodetag.Type != NodeTagType.Prefab && nodetag.Type != NodeTagType.Node) {
                throw new Exception("Only behaviours, prefabs and nodes can be attached to a behaviour tree");
            }

            Node newnode = null;
            bool isPrefabInstance = false;

            // when we attach a behaviour we must create a special referenced behaviour node
            if (nodetag.Type == NodeTagType.Behavior || nodetag.Type == NodeTagType.Prefab) {
                if (!File.Exists(nodetag.Filename)) {
                    if (!SaveBehavior(nodetag.Filename)) {
                        return;
                    }
                }

                // get the behavior we want to reference
                BehaviorNode behavior = _behaviorTreeList.LoadBehavior(nodetag.Filename);

                // a behaviour reference itself
                if (nvd != null && nvd.IsBehaviorReferenced(behavior)) {
                    if (DialogResult.Cancel == MessageBox.Show(Resources.CircularReferencedInfo, Resources.Warning, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning)) {
                        return;
                    }
                }

                if (nodetag.Type == NodeTagType.Prefab) {
                    behavior = (BehaviorNode)behavior.Clone();
                }

                Behavior rootB = _rootNodeView.RootBehavior as Behavior;
                Behavior b = behavior as Behavior;

                if (rootB.AgentType == null) {
                    rootB.AgentType = b.AgentType;

                } else if (!IsCompatibleAgentType(rootB, b)) {
                    return;
                }

                // behavior
                if (nodetag.Type == NodeTagType.Behavior) {
                    // create the referenced behaviour node for the behaviour
                    ReferencedBehavior refnode = Node.CreateReferencedBehaviorNode(_rootNodeView.RootBehavior, behavior, mode == NodeAttachMode.None || ((Node)this.RootNode).IsFSM);

                    newnode = (Node)refnode;
                    //the comment seems too long to overlap the node
                    //newnode.CommentText = Resources.ThisIsReferenceTree;
                    newnode.CommentBackground = Node.CommentColor.Gray;
                }

                // prefab
                else {
                    // Copy all Pars from the prefab file into the current behavior node.
                    List<ParInfo> pars = new List<ParInfo>();
                    foreach(ParInfo par in b.LocalVars) {
                        bool found = false;
                        foreach(ParInfo rootPar in rootB.LocalVars) {
                            if (par.Name == rootPar.Name) {
                                if (par.Type != rootPar.Type) {
                                    string errorMsg = string.Format(Resources.ParErrorInfo, par.Name, b.Label, rootB.Label);
                                    MessageBox.Show(errorMsg, Resources.LoadError, MessageBoxButtons.OK);
                                    return;
                                }

                                found = true;
                                break;
                            }
                        }

                        if (!found) {
                            pars.Add(par);
                        }
                    }

                    rootB.LocalVars.AddRange(pars);

                    // The first child should be the root node of the prefab tree.
                    Node behaviorNode = (Node)behavior;

                    if (behaviorNode.Children.Count > 0) {
                        newnode = (Node)behaviorNode.Children[0];

                        string prefab = Path.GetFileNameWithoutExtension(behavior.Filename);
                        newnode.CommentText = string.Format("Prefab[{0}]", prefab);

                        isPrefabInstance = true;
                        string prefabName = FileManagers.FileManager.GetRelativePath(behavior.Filename);
                        newnode.SetPrefab(prefabName);
                    }
                }

            } else {
                // simply create the node which is supposed to be created.
                newnode = Node.Create(nodetag.NodeType);

                if (newnode != null)
                    newnode.PostCreatedByEditor();
            }

            if (newnode == null) {
                return;
            }

            // update label
            newnode.OnPropertyValueChanged(false);

            Node node = (nvd != null) ? nvd.Node : null;

            if (node == null) {
                mode = NodeAttachMode.None;
            }

            Attachments.Attachment startCondition = null;

            // attach the new node with the correct mode
            switch (mode) {
                    // the new node is inserted in front of the target node
                case NodeAttachMode.Left:
                    if (node != null) {
                        Node parent = (Node)node.Parent;

                        int k = node.ParentConnector.GetChildIndex(node);

                        Node.Connector conn = node.ParentConnector;
                        Debug.Check(conn != null);

                        parent.RemoveChild(conn, node);
                        parent.AddChild(conn, newnode, k);

                        Node.Connector newconn = newnode.GetConnector(conn.Identifier);
                        Debug.Check(newconn != null);
                        newnode.AddChild(newconn, node);

                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd.Parent;
                    }

                    break;

                    // the new node is simply added to the target node's children
                case NodeAttachMode.Right:
                    if (newnode != null && newnode.IsFSM) {
                        startCondition = this.addFSMNode(newnode, mousePos);

                        newnode.ScreenLocation = new PointF(_rootNodeView.BoundingBox.Left + _rootNodeView.BoundingBox.Width * 1.5f, _rootNodeView.BoundingBox.Top);

                    } else if (node != null) {
                        node.AddChild(_dragTargetConnector, newnode);

                        _dragTargetConnector.IsExpanded = true;

                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd;
                    }

                    break;

                    // the new node is placed above the target node
                case NodeAttachMode.Top:
                    if (node != null) {
                        int n = _dragTargetNode.Node.ParentConnector.GetChildIndex(node);
                        ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, n);

                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd.Parent;
                    }

                    break;

                    // the new node is placed below the target node
                case NodeAttachMode.Bottom:
                    if (node != null) {
                        int m = _dragTargetNode.Node.ParentConnector.GetChildIndex(node);
                        ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, m + 1);

                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd.Parent;
                    }

                    break;

                    // the node will replace the target node
                case NodeAttachMode.Center:
                    if (node != null && replaceNode(node, newnode)) {
                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd.Parent;

                        this.Redraw();
                    }

                    break;

                case NodeAttachMode.None:
                    if (newnode != null && newnode.IsFSM) {
                        startCondition = this.addFSMNode(newnode, mousePos);

                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = this.RootNodeView;
                    }

                    break;
            }

            // After being created, its Id should be reset.
            if (newnode != null) {
                newnode.ResetId(true);

                // set the prefab dirty for the current parent
                if (newnode.Parent != null) {
                    Node parent = (Node)newnode.Parent;

                    if (!string.IsNullOrEmpty(parent.PrefabName)) {
                        parent.HasOwnPrefabData = true;

                        if (!isPrefabInstance) {
                            newnode.SetPrefab(parent.PrefabName);
                            newnode.HasOwnPrefabData = true;
                        }
                    }
                }

                if (startCondition != null) {
                    startCondition.TargetFSMNodeId = newnode.Id;
                }

                UndoManager.Save(this.RootNode);
            }

            // the layout needs to be recalculated
            LayoutChanged();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Attaches a dragged node from the node explorer to an existing node.
        /// </summary>
        /// <param name="nvd">The node the new node will be attached to.</param>
        /// <param name="mode">The way the new node will be attached.</param>
        /// <param name="nodetag">The tag of the you want to create.</param>
        /// <param name="label">The label of the new node.</param>
        private void InsertNewNode(NodeViewData nvd, NodeAttachMode mode, NodeTag nodetag)
        {
            // check if the attach mode is valid
            if (mode == NodeAttachMode.Attachment || mode == NodeAttachMode.None)
                throw new Exception("A node cannot be created with the given attach mode");

            if (nodetag.Type != NodeTagType.Behavior && nodetag.Type != NodeTagType.Prefab && nodetag.Type != NodeTagType.Node)
                throw new Exception("Only behaviours, prefabs and nodes can be attached to a behaviour tree");

            Node node = nvd.Node;
            Node newnode = null;
            bool isPrefabInstance = false;

            // when we attach a behaviour we must create a special referenced behaviour node
            if (nodetag.Type == NodeTagType.Behavior || nodetag.Type == NodeTagType.Prefab)
            {
                if (!File.Exists(nodetag.Filename))
                {
                    if (!SaveBehavior(nodetag.Filename))
                        return;
                }

                // get the behavior we want to reference
                BehaviorNode behavior = _behaviorTreeList.LoadBehavior(nodetag.Filename);

                // a behaviour reference itself
                if (nvd.IsBehaviorReferenced(behavior))
                {
                    if (DialogResult.Cancel == MessageBox.Show(Resources.CircularReferencedInfo, Resources.Warning, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning))
                        return;
                }

                if (nodetag.Type == NodeTagType.Prefab)
                {
                    behavior = (BehaviorNode)behavior.Clone();
                }

                Behavior rootB = _rootNode.RootBehavior as Behavior;
                Behavior b = behavior as Behavior;

                if (rootB.AgentType == null)
                {
                    rootB.AgentType = b.AgentType;
                }
                else if (!IsCompatibleAgentType(rootB, b))
                {
                    return;
                }

                // behavior
                if (nodetag.Type == NodeTagType.Behavior)
                {
                    // create the referenced behaviour node for the behaviour
                    ReferencedBehaviorNode refnode = Node.CreateReferencedBehaviorNode(_rootNode.RootBehavior, behavior);

                    // register the view so it gets updated when the referenced behaviour gets updated.
                    refnode.ReferencedBehaviorWasModified += new ReferencedBehavior.ReferencedBehaviorWasModifiedEventDelegate(refnode_ReferencedBehaviorWasModified);

                    newnode = (Node)refnode;
                    newnode.CommentText = Resources.ThisIsReferenceTree;
                    newnode.CommentBackground = Node.CommentColor.Gray;
                }
                // prefab
                else
                {
                    // Copy all Pars from the prefab file into the current behavior node.
                    List<ParInfo> pars = new List<ParInfo>();
                    foreach (ParInfo par in b.Pars)
                    {
                        bool found = false;
                        foreach (ParInfo rootPar in rootB.Pars)
                        {
                            if (par.Name == rootPar.Name)
                            {
                                if (par.Type != rootPar.Type)
                                {
                                    string errorMsg = string.Format(Resources.ParErrorInfo, par.Name, b.Label, rootB.Label);
                                    MessageBox.Show(errorMsg, Resources.LoadError, MessageBoxButtons.OK);
                                    return;
                                }

                                found = true;
                                break;
                            }
                        }

                        if (!found)
                            pars.Add(par);
                    }

                    rootB.Pars.AddRange(pars);
                    if (ParSettingsDock.IsVisible())
                        ParSettingsDock.Inspect((Node)_rootNode.RootBehavior);

                    // The first child should be the root node of the prefab tree.
                    Node behaviorNode = (Node)behavior;
                    if (behaviorNode.Children.Count > 0)
                    {
                        newnode = (Node)behaviorNode.Children[0];

                        string prefab = Path.GetFileNameWithoutExtension(behavior.Filename);
                        newnode.CommentText = string.Format("Prefab[{0}]", prefab);

                        isPrefabInstance = true;
                        string prefabName = FileManagers.FileManager.GetRelativePath(behavior.Filename);
                        newnode.SetPrefab(prefabName);
                    }
                }
            }
            else
            {
                // simply create the node which is supposed to be created.
                newnode = Node.Create(nodetag.NodeType);
            }

            if (newnode == null)
                return;

            // update label
            newnode.OnPropertyValueChanged(false);

            // attach the new node with the correct mode
            switch (mode)
            {
                // the new node is inserted in front of the target node
                case (NodeAttachMode.Left):
                    Node parent = (Node)node.Parent;

                    int k = node.ParentConnector.GetChildIndex(node);

                    Node.Connector conn = node.ParentConnector;
                    Debug.Check(conn != null);

                    parent.RemoveChild(conn, node);
                    parent.AddChild(conn, newnode, k);

                    Node.Connector newconn = newnode.GetConnector(conn.Identifier);
                    Debug.Check(newconn != null);
                    newnode.AddChild(newconn, node);

                    // automatically select the new node
                    _selectedNodePending = newnode;
                    _selectedNodePendingParent = nvd.Parent;
                    break;

                // the new node is simply added to the target node's children
                case (NodeAttachMode.Right):
                    node.AddChild(_dragTargetConnector, newnode);

                    // automatically select the new node
                    _selectedNodePending = newnode;
                    _selectedNodePendingParent = nvd;
                    break;

                // the new node is placed above the target node
                case (NodeAttachMode.Top):
                    int n = _dragTargetNode.Node.ParentConnector.GetChildIndex(node);
                    ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, n);

                    // automatically select the new node
                    _selectedNodePending = newnode;
                    _selectedNodePendingParent = nvd.Parent;
                    break;

                // the new node is placed below the target node
                case (NodeAttachMode.Bottom):
                    int m = _dragTargetNode.Node.ParentConnector.GetChildIndex(node);
                    ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, m + 1);

                    // automatically select the new node
                    _selectedNodePending = newnode;
                    _selectedNodePendingParent = nvd.Parent;
                    break;

                // the node will replace the target node
                case (NodeAttachMode.Center):
                    if (replaceNode(node, newnode))
                    {
                        // automatically select the new node
                        _selectedNodePending = newnode;
                        _selectedNodePendingParent = nvd.Parent;
                    }
                    break;
            }

            // After being created, its Id should be reset.
            if (newnode != null)
            {
                newnode.ResetId(isPrefabInstance);

                // set the prefab dirty for the current parent
                if (newnode.Parent != null)
                {
                    Node parent = (Node)newnode.Parent;
                    if (!string.IsNullOrEmpty(parent.PrefabName))
                    {
                        parent.HasOwnPrefabData = true;
                        if (!isPrefabInstance)
                        {
                            newnode.SetPrefab(parent.PrefabName);
                            newnode.HasOwnPrefabData = true;
                        }
                    }
                }

                if (nodetag.Type == NodeTagType.Behavior || nodetag.Type == NodeTagType.Prefab)
                    ExpandedNodePool.SetExpandedNode(newnode.Behavior.RelativePath, newnode.Id.ToString(), false);

                UndoManager.Save(this.RootNode, newnode.Behavior);
            }

            // the layout needs to be recalculated
            LayoutChanged();
        }