private void AddNode(IBehaviorNode <AIContext> node, Func <float> rowWidth, Func <float> nodeWidth, Func <float> linkX, int nodeCount, int column, int depth) { string nodeType = node.GetType().Name; var nodeInfo = new RenderedNode( nodeType.Substring(0, nodeType.Count() - 2), depth, node.Name, () => AlignRelativeTo(() => linkX(), nodeWidth(), nodeCount, column, depth)); onAddAction(nodeInfo, node); nodeVisualizationInfo[depth].Add(nodeInfo); var subNodes = node.SubNodes.ToArray(); Func <float> linkPositionX = () => nodeInfo.PositionX; for (int nodeIndex = 0; nodeIndex < subNodes.Count(); nodeIndex++) { if (nodeIndex == 0) { var newLink = new LinkBase(nodeInfo, linkPositionX, subNodes.Count()); if (nodeVisualizationInfo.ContainsKey(depth + 1)) { nodeVisualizationInfo[depth + 1].Add(newLink); } else { nodeVisualizationInfo.Add(depth + 1, new List <IBehaviorVirtualizationPiece>(new[] { newLink as IBehaviorVirtualizationPiece, })); } } AddNode(subNodes[nodeIndex], () => NodeWidth() * (subNodes.Count()), () => NodeWidth(), linkPositionX, subNodes.Count() + 1, nodeIndex, depth + 1); } }
public TreeAnalyzer(Action <IBehaviorVirtualizationPiece, IBehaviorNode <AIContext> > onAddAction, IBehaviorNode <AIContext> root) { this.onAddAction = onAddAction; string nodeType = root.GetType().Name; var rootInfo = new RenderedNode( nodeType.Substring(0, nodeType.Count() - 2), 0, root.Name, () => AlignRelativeTo(() => TreeWidth() / 2, NodeWidth(), 1, 0, 0)); onAddAction(rootInfo, root); nodeVisualizationInfo.Add(0, new List <IBehaviorVirtualizationPiece>(new[] { rootInfo })); var subNodes = root.SubNodes.ToArray(); Func <float> linkPositionX = () => rootInfo.PositionX; LinkBase link = new LinkBase( rootInfo, linkPositionX, subNodes.Count()); nodeVisualizationInfo.Add(1, new List <IBehaviorVirtualizationPiece>(new[] { link as IBehaviorVirtualizationPiece, })); for (int nodeIndex = 0; nodeIndex < subNodes.Count(); nodeIndex++) { AddNode(subNodes[nodeIndex], () => TreeWidth(), () => NodeWidth(), linkPositionX, subNodes.Count() + 1, nodeIndex, 1); } }
public void Prepare <AIContext>(INodePainter painter, IBehaviorNode <AIContext> root) { this.painter = painter; var analyzer = new TreeAnalyzer <AIContext>(painter.Paint, root); nodeVisualizationInfo = analyzer.AnalyzedTree; //find the largest name and calculate the node width int largestCharacterCount = 0; foreach (var noddeInfo in nodeVisualizationInfo.SelectMany(x => x.Value)) { largestCharacterCount = CountLargestNameCharacters(noddeInfo as RenderedNode, largestCharacterCount); } nodeWidth = CalculateNodeWidth(largestCharacterCount + 3); int itemsPerRow = 1; foreach (var node in nodeVisualizationInfo.Values) { int countNodes = node.Where(item => item is RenderedNode).Count(); if (countNodes > itemsPerRow) { itemsPerRow = countNodes; } } treeWidth = itemsPerRow * nodeWidth; analyzer.SetNodeWidth(nodeWidth + nodeSpan); analyzer.SetTreeWidth(treeWidth); //find any overlapping nodes and recalculate the tree's row width foreach (var treeRow in nodeVisualizationInfo.Values) { int nodesIterated = 0; float lastPositionX = 0; LinkBase lastLink = null; foreach (var nodeInfo in treeRow) { var link = nodeInfo as LinkBase; if (link != null) { lastLink = link; nodesIterated = 0; } else { var node = (nodeInfo as RenderedNode); node.onTriggered += (sender, args) => { var senderNode = sender as RenderedNode; AddBehaviorCover(senderNode, args); AddIcon(senderNode, senderNode.BehaviorStatus); }; if (nodesIterated == 0 && lastPositionX != 0) { if (lastPositionX > node.PositionX) { lastLink.LinkedNode.OffsetX += lastPositionX - node.PositionX + nodeSpan; } } lastPositionX = node.PositionX + nodeWidth; nodesIterated++; } } } }