public void DrawTree(Rect canvas)
        {
            // get total size of Research Tree
            int maxDepth = 0, totalWidth = 0;

            if (ResearchTree.Trees.Any())
            {
                maxDepth   = ResearchTree.Trees.Max(tree => tree.MaxDepth);
                totalWidth = ResearchTree.Trees.Sum(tree => tree.Width);
            }

            maxDepth    = Math.Max(maxDepth, ResearchTree.Orphans.MaxDepth);
            totalWidth += ResearchTree.Orphans.Width;

            float width  = (maxDepth + 1) * (Settings.NodeSize.x + Settings.NodeMargins.x);    // zero based
            float height = totalWidth * (Settings.NodeSize.y + Settings.NodeMargins.y);

            // main view rect
            Rect view = new Rect(0f, 0f, width, height);

            Widgets.BeginScrollView(canvas, ref _scrollPosition, view);
            GUI.BeginGroup(view);

            Text.Anchor = TextAnchor.MiddleCenter;

            // draw regular connections, not done first to better highlight done.
            foreach (Pair <Node, Node> connection in connections.Where(pair => !pair.Second.Research.IsFinished))
            {
                ResearchTree.DrawLine(connection, connection.First.Tree.GreyedColor);
            }

            // draw connections from completed nodes
            foreach (Pair <Node, Node> connection in connections.Where(pair => pair.Second.Research.IsFinished))
            {
                ResearchTree.DrawLine(connection, connection.First.Tree.MediumColor);
            }
            connections.Clear();

            // draw highlight connections on top
            foreach (Pair <Node, Node> connection in highlightedConnections)
            {
                ResearchTree.DrawLine(connection, GenUI.MouseoverColor, true);
            }
            highlightedConnections.Clear();

            // draw nodes on top of lines
            foreach (Node node in nodes)
            {
                node.Draw();
            }
            nodes.Clear();

            // register hub tooltips
            foreach (KeyValuePair <Rect, List <string> > pair in hubTips)
            {
                string text = string.Join("\n", pair.Value.ToArray());
                TooltipHandler.TipRegion(pair.Key, text);
            }
            hubTips.Clear();

            // draw Queue labels
            Queue.DrawLabels();

            // reset anchor
            Text.Anchor = TextAnchor.UpperLeft;

            GUI.EndGroup();
            Widgets.EndScrollView();
        }
        public void DrawTree(Rect canvas)
        {
            // get total size of Research Tree
            int maxDepth = 0, totalWidth = 0;

            if (ResearchTree.Trees.Any())
            {
                maxDepth   = ResearchTree.Trees.Max(tree => tree.MaxDepth);
                totalWidth = ResearchTree.Trees.Sum(tree => tree.Width);
            }

            maxDepth    = Math.Max(maxDepth, ResearchTree.Orphans.MaxDepth);
            totalWidth += ResearchTree.Orphans.Width;

            float width  = (maxDepth + 1) * (Settings.NodeSize.x + Settings.NodeMargins.x);    // zero based
            float height = (totalWidth - 1) * (Settings.NodeSize.y + Settings.NodeMargins.y);

            // main view rect
            Rect view = new Rect(0f, 0f, width, height);

            // create the scroll area below the search box (plus a small margin) so it stays on top
            Widgets.BeginScrollView(new Rect(canvas.x,
                                             canvas.y + filterManager.Height + Settings.NodeMargins.y,
                                             canvas.width, canvas.height - filterManager.Height - Settings.NodeMargins.y),
                                    ref _scrollPosition, view);
            GUI.BeginGroup(view);
            Text.Anchor = TextAnchor.MiddleCenter;

            // draw regular connections, not done first to better highlight done.
            foreach (Pair <Node, Node> connection in connections.Where(pair => !pair.Second.Research.IsFinished))
            {
                ResearchTree.DrawLine(connection,
                                      filterManager.FilterPhrase.NullOrEmpty() ? connection.First.Tree.GreyedColor : ColorHelper.AdjustAlpha(connection.First.Tree.GreyedColor, Settings.FilterNonMatchAlpha));
            }

            // draw connections from completed nodes
            foreach (Pair <Node, Node> connection in connections.Where(pair => pair.Second.Research.IsFinished))
            {
                if (!filterManager.FilterPhrase.NullOrEmpty())
                {
                    ResearchTree.DrawLine(connection, ColorHelper.AdjustAlpha(connection.First.Tree.GreyedColor, Settings.FilterNonMatchAlpha));
                }
                else
                {
                    ResearchTree.DrawLine(connection, connection.First.Tree.MediumColor);
                }
            }
            connections.Clear();

            // draw highlight connections on top
            foreach (Pair <Node, Node> connection in highlightedConnections)
            {
                ResearchTree.DrawLine(connection, GenUI.MouseoverColor, true);
            }
            highlightedConnections.Clear();

            // draw nodes on top of lines
            bool reqScroll    = true;
            Node scrollToNode = null;

            foreach (Node node in nodes)
            {
                // draw the node
                bool visible = node.Draw();

                // ensure that at least one matching node is visible, prioritize highest on the screen
                if (filterManager.FilterDirty)
                {
                    if (node.FilterMatch.IsValidMatch())
                    {
                        if (!reqScroll)
                        {
                            continue;
                        }

                        // this node is a match and is currently visible, we don't need to scroll
                        if (visible)
                        {
                            reqScroll    = false;
                            scrollToNode = null;
                        }
                        else
                        {
                            // this node is a match, but isn't visible. if it's the highest node then we'll scroll to it
                            if (scrollToNode == null || node.Pos.z < scrollToNode.Pos.z)
                            {
                                scrollToNode = node;
                            }
                        }
                    }
                }
            }

            if (filterManager.FilterDirty)
            {
                // scroll to a matching node if necessary
                if (scrollToNode != null)
                {
                    // scale the focus area to ensure it all fits on the screen
                    Rect r = scrollToNode.Rect.ScaledBy(2.0f);
                    _scrollPosition = new Vector2(r.xMin, r.yMin);
                }
                else if (filterManager.FilterPhrase == "")
                {
                    _scrollPosition = Vector2.zero;
                }
            }
            nodes.Clear();

            // register hub tooltips
            foreach (KeyValuePair <Rect, List <string> > pair in hubTips)
            {
                string text = string.Join("\n", pair.Value.ToArray());
                TooltipHandler.TipRegion(pair.Key, text);
            }
            hubTips.Clear();

            // draw Queue labels
            Queue.DrawLabels();

            // reset anchor
            Text.Anchor = TextAnchor.UpperLeft;

            GUI.EndGroup();
            Widgets.EndScrollView();
        }