public STreeNode(STreeNode a) { id = a.id; name = a.name; state = a.state; Type = a.Type; children = a.children; }
// Даёт возможность сохранять структуру делева в файл public void SaveTree(string fileName) { try { BinaryFormatter bin = new BinaryFormatter(); STreeNode strToBeGone = STROperation.fnPrepareToWrite(this.stepTree); FileStream fTree = new FileStream(fileName, FileMode.Create, FileAccess.Write); bin.Serialize(fTree, strToBeGone); fTree.Close(); } catch (IOException ex) { MessageBox.Show(ex.Message, "Save StepTree Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }
STreeNode GetTreeNode(Node node) { STreeNode mine = new STreeNode(); var nodeName = node.ToString(); // leaf node if (nodeName == "ActionNode") { ActionNode a = (ActionNode)node; mine.id = a.GetID(); mine.name = a.GetFunction().GetMethodInfo().Name; mine.state = a.NodeState; mine.Type = "ActionNode"; } // decorator node else if (nodeName == "Inverter" || nodeName == "Repeater" || nodeName == "RepeatTillFail" || nodeName == "Limiter" || nodeName == "Succeeder") { DecoratorNode d = (DecoratorNode)node; mine.id = d.GetID(); mine.name = d.ToString(); mine.state = d.NodeState; mine.Type = "DecoratorNode"; mine.children = new List <STreeNode>() { GetTreeNode(d.ChildNode) }; } // composite node else if (nodeName == "Selector" || nodeName == "Sequence") { CompositeNode c = (CompositeNode)node; mine.id = c.GetID(); mine.name = c.ToString(); mine.state = c.NodeState; mine.Type = "CompositeNode"; mine.children = new List <STreeNode>(); foreach (Node childNode in c.ChildNodeList) { mine.children.Add(GetTreeNode(childNode)); } } return(mine); }
// update a single node and call its children to update void UpdateNode(Transform transform, STreeNode node) { // update text var text = transform.GetChild(0).GetComponent <Text>(); text.text = "ID: " + node.id + "\n" + node.name + "\n" + node.state; // update image var image = transform.GetComponent <Image>(); switch (node.state) { case ENodeStates.FAILURE: image.color = Color.red; break; case ENodeStates.SUCCESS: image.color = Color.green; break; case ENodeStates.RUNNING: image.color = Color.yellow; break; default: image.color = Color.gray; break; } // update children if (node.children != null) { for (int i = 0; i < node.children.Count; ++i) { UpdateNode(transform.GetChild(i + 1), node.children[i]); } } }
// Загружает структуру дерева из файла (здесь не используется, но может пригодиться) public void LoadTree(string fileName) { this.stepTree.Nodes[0]?.Remove(); try { BinaryFormatter bin = new BinaryFormatter(); this.stepTree.Nodes.Clear(); FileStream fTree = new FileStream(fileName, FileMode.Open, FileAccess.Read); STreeNode str = (STreeNode)bin.Deserialize(fTree); fTree.Close(); TreeNode trParent = STROperation.fnPrepareToRead(str); foreach (TreeNode trn in trParent.Nodes) { this.stepTree.Nodes.Add(trn); } } catch (IOException ex) { MessageBox.Show(ex.Message, "ABS Treereader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } this.stepTree.ExpandAll(); }
// draw a single node in tree and then draw children SLiveTreeNode DrawNode(STreeNode tree) { // new object for each node var myObj = new SLiveTreeNode(); myObj.node = tree; // new image myObj.nodeObject = new GameObject("Image"); myObj.nodeObject.transform.SetParent(LiveTreeOverlay.transform.GetChild(0).GetChild(0).transform); // new text for image myObj.nodeObjectText = new GameObject("Text"); Text newText = myObj.nodeObjectText.AddComponent <Text>(); myObj.nodeObjectText.transform.SetParent(myObj.nodeObject.transform); newText.text = "ID: " + tree.id + "\n" + tree.name + "\n" + tree.state; newText.alignment = TextAnchor.MiddleCenter; newText.font = Resources.GetBuiltinResource <Font>("Arial.ttf"); newText.color = Color.black; Image newImage = myObj.nodeObject.AddComponent <Image>(); // Set image type switch (tree.Type) { case "ActionNode": newImage.sprite = Sprite.Create(CircleTex, new Rect(0.0f, 0.0f, CircleTex.width, CircleTex.height), new Vector2(0.5f, 0.5f), 100.0f); myObj.size = shapeSize; break; case "DecoratorNode": newImage.sprite = Sprite.Create(DiamondTex, new Rect(0.0f, 0.0f, DiamondTex.width, DiamondTex.height), new Vector2(0.5f, 0.5f), 100.0f); break; case "CompositeNode": newImage.sprite = Sprite.Create(SquareTex, new Rect(0.0f, 0.0f, SquareTex.width, SquareTex.height), new Vector2(0.5f, 0.5f), 100.0f); break; default: break; } // set colour switch (tree.state) { case ENodeStates.FAILURE: newImage.color = Color.red; break; case ENodeStates.SUCCESS: newImage.color = Color.green; break; case ENodeStates.RUNNING: newImage.color = Color.yellow; break; default: newImage.color = Color.gray; break; } // draw children if (myObj.node.children != null) { List <SLiveTreeNode> childList = new List <SLiveTreeNode>(); foreach (var child in myObj.node.children) { var childNode = DrawNode(child); var childTrans = childNode.nodeObject.transform; childTrans.SetParent(myObj.nodeObject.transform); childList.Add(childNode); } // positions get Vector2 childSumSize = new Vector2(); foreach (var child in childList) { childSumSize += child.size; } // set float x = -childSumSize.x / 2; foreach (var child in childList) { x += child.size.x / 2; child.nodeObject.transform.localPosition = new Vector3(x, -shapeSize.y * 1.5f, 0); x += child.size.x / 2; } // Add lines between nodes foreach (var child in childList) { // create line var line = Instantiate(NodeLine); // make this parent line.transform.SetParent(myObj.nodeObject.transform); // move to centre var pos = (myObj.nodeObject.transform.position + child.nodeObject.transform.position) / 2; line.transform.position = pos; // rotate var vec = myObj.nodeObject.transform.position - child.nodeObject.transform.position; vec.y -= shapeSize.y; var angle = -Mathf.Rad2Deg * Mathf.Atan(vec.x / vec.y); line.transform.Rotate(new Vector3(0, 0, angle)); // strech RectTransform rect = line.GetComponent <RectTransform>(); if (rect != null) { rect.sizeDelta = new Vector2(5, vec.magnitude); } } myObj.size = childSumSize + new Vector2(0, shapeSize.y * 1.5f); } return(myObj); }