Пример #1
0
        /// <summary>
        /// Returns the behavior which is associated with a tree node.
        /// </summary>
        /// <param name="nodetag">The NodeTag of the tree node.</param>
        /// <param name="label">The label of the tree node.</param>
        /// <returns>Returns null if no matching behavior could be found or loaded.</returns>
        internal BehaviorNode GetBehavior(NodeTag nodetag, string label)
        {
            BehaviorNode behavior = LoadBehavior(nodetag.Filename);
            if (behavior != null)
                return behavior;

            MessageBox.Show(string.Format(Resources.NoBehaviorInfo, label, nodetag.Filename), Resources.FileError, MessageBoxButtons.OK);
            return null;
        }
Пример #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, 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();
        }
Пример #3
0
        /// <summary>
        /// Returns the behavior which is associated with a tree node.
        /// </summary>
        /// <param name="nodetag">The NodeTag of the tree node.</param>
        /// <param name="label">The label of the tree node.</param>
        /// <returns>Returns null if no matching behavior could be found or loaded.</returns>
        internal BehaviorNode GetBehavior(NodeTag nodetag, string label, List<Nodes.Node.ErrorCheck> result = null)
        {
            BehaviorNode behavior = LoadBehavior(nodetag.Filename, false, result);

            if (behavior != null)
            {
                return behavior;
            }

            MessageBox.Show(string.Format(Resources.NoBehaviorInfo, label, nodetag.Filename), Resources.FileError, MessageBoxButtons.OK);
            return null;
        }
Пример #4
0
        private static void resetPar(NodeTag.DefaultObject obj, ParInfo par, string newName)
        {
            Node node = getNode(obj);

            if (node != null && par != null)
            {
                Type type = obj.GetType();
                foreach (PropertyInfo property in type.GetProperties())
                {
                    try
                    {
                        object value = property.GetValue(obj, null);
                        if (value != null)
                        {
                            if (property.PropertyType == typeof(MethodDef))
                            {
                                MethodDef method = value as MethodDef;
                                Debug.Check(method != null);

                                method.ResetPar(par, newName);
                            }
                            else if (property.PropertyType == typeof(VariableDef))
                            {
                                VariableDef var = value as VariableDef;
                                Debug.Check(var != null);

                                var.ResetPar(par, newName);
                            }
                            else if (property.PropertyType == typeof(RightValueDef))
                            {
                                RightValueDef rv = value as RightValueDef;
                                Debug.Check(rv != null);

                                rv.ResetPar(par, newName);
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Adds this NodeGroup to the TreeView of the node explorer.
        /// </summary>
        /// <param name="pool">The TreeNodeCollection the group and its sub-groups and childrens will be added.</param>
        public void Register(TreeNodeCollection pool)
        {
            // check if this NodeGroup already exists in the node explorer
            TreeNode tnode = null;
            foreach(TreeNode node in pool) {
                if (node.Text == _name) {
                    tnode = node;
                    break;
                }
            }

            // create a new group if it does not yet exist
            if (tnode == null) {
                tnode = new TreeNode(_name, (int)_icon, (int)_icon);
                tnode.Tag = new NodeTag(NodeTagType.NodeFolder, null, string.Empty);
                pool.Add(tnode);
            }

            // add the nodes which will be shown in this group
            foreach(NodeItem item in _items) {
                NodeTagType ntt = NodeTagType.Node;

                if (item.Type.IsSubclassOf(typeof(Attachments.Attachment))) {
                    ntt = NodeTagType.Attachment;
                }

                NodeTag nodetag = new NodeTag(ntt, item.Type, string.Empty);
                TreeNode inode = new TreeNode(nodetag.Defaults.Label, (int)item.Icon, (int)item.Icon);
                inode.Tag = nodetag;
                inode.ToolTipText = nodetag.Defaults.Description;

                tnode.Nodes.Add(inode);
            }

            // add any sub-group
            foreach(NodeGroup group in _children)
            group.Register(tnode.Nodes);

            tnode.ExpandAll();
        }
Пример #6
0
        private static Node getNode(NodeTag.DefaultObject obj)
        {
            Node node = obj as Node;
            if (node == null)
            {
                Attachments.Attachment attach = obj as Attachments.Attachment;
                if (attach != null)
                    node = attach.Node;
            }

            return node;
        }
Пример #7
0
        private static void checkPar(NodeTag.DefaultObject obj, ParInfo par, ref List<Node.ErrorCheck> result)
        {
            Node node = getNode(obj);

            if (node != null && par != null)
            {
                Type type = obj.GetType();
                foreach (PropertyInfo property in type.GetProperties())
                {
                    try
                    {
                        object value = property.GetValue(obj, null);
                        if (value != null)
                        {
                            if (property.PropertyType == typeof(MethodDef))
                            {
                                MethodDef method = value as MethodDef;
                                Debug.Check(method != null);

                                if (method.CheckPar(par))
                                    result.Add(new Node.ErrorCheck(node, ErrorCheckLevel.Error, "Par as a parameter of the method."));
                            }
                            else if (property.PropertyType == typeof(VariableDef))
                            {
                                VariableDef var = value as VariableDef;
                                Debug.Check(var != null);

                                if (var.CheckPar(par))
                                    result.Add(new Node.ErrorCheck(node, ErrorCheckLevel.Error, "Par as a value."));
                            }
                            else if (property.PropertyType == typeof(RightValueDef))
                            {
                                RightValueDef rv = value as RightValueDef;
                                Debug.Check(rv != null);

                                if (rv.CheckPar(par))
                                    result.Add(new Node.ErrorCheck(node, ErrorCheckLevel.Error, "Par as a right value."));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }
Пример #8
0
        public static bool InvokeTypeParser(Type type, string parStr, SetValue setter, NodeTag.DefaultObject node, string paramName = null)
        {
            Debug.Check(type != null);

            if (_typeHandlers.ContainsKey(type))
            {
                Type typeHandler = _typeHandlers[type];

                MethodInfo parserMethod = typeHandler.GetMethod("Parse");
                Debug.Check(parserMethod != null);

                if (string.IsNullOrEmpty(parStr) && type.IsPrimitive && type == typeof(string))
                {
                    return false;
                }

                object[] pars = { node, paramName, parStr, setter };

                return (bool)parserMethod.Invoke(null, pars);
            }
            else if (type.IsEnum)
            {
                Array values = Enum.GetValues(type);

                foreach (object enumVal in values)
                {
                    string enumValueName = Enum.GetName(type, enumVal);
                    if (enumValueName == parStr)
                    {
                        setter(enumVal);
                        return true;
                    }
                }
            }
            else if (Plugin.IsArrayType(type))
            {
                object obj = DesignerArray.ParseStringValue(type, parStr, node);
                setter(obj);
                return true;
            }
            else if (Plugin.IsCustomClassType(type))
            {
                object obj = Behaviac.Design.Attributes.DesignerStruct.ParseStringValue(type, paramName, parStr, node);
                setter(obj);
                return true;
            }
            else
            {
                string message = string.Format("parser for {0} is not registered!", type.Name);
                throw new Exception(message);
            }

            return false;
        }
Пример #9
0
        public static NodeTag.DefaultObject GetPreviousObjectById(Node root, int id, NodeTag.DefaultObject currentObj)
        {
            if (root == null || root == currentObj)
                return null;

            if (root.Id == id)
                return root;

            foreach (Attachments.Attachment attach in root.Attachments)
            {
                if (attach == currentObj)
                    return null;

                if (attach.Id == id)
                    return attach;
            }

            if (!(root is ReferencedBehavior))
            {
                foreach (Node child in root.Children)
                {
                    NodeTag.DefaultObject obj = GetPreviousObjectById(child, id, currentObj);
                    if (null != obj)
                        return obj;
                }
            }

            return null;
        }
Пример #10
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();
        }