From b25ee23b14e18877e19d6419b55bd9ce9f1d2c59 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 20 Apr 2024 14:12:53 +0300 Subject: [PATCH] Optimize TreeNode rendering --- Source/Editor/GUI/Tree/TreeNode.cs | 65 ++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs index 36331d6d2..62d4d5b6b 100644 --- a/Source/Editor/GUI/Tree/TreeNode.cs +++ b/Source/Editor/GUI/Tree/TreeNode.cs @@ -712,6 +712,71 @@ namespace FlaxEditor.GUI.Tree } } + /// + protected override void DrawChildren() + { + // Draw all visible child controls + var children = _children; + if (children.Count == 0) + return; + + if (CullChildren) + { + Render2D.PeekClip(out var globalClipping); + Render2D.PeekTransform(out var globalTransform); + + // Try to estimate the rough location of the first node, assuming the node height is constant + var firstChildGlobalRect = GetChildGlobalRectangle(children[0], ref globalTransform); + var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Y - firstChildGlobalRect.Top) / firstChildGlobalRect.Height) + 1, 0, children.Count - 1); + if (GetChildGlobalRectangle(children[firstVisibleChild], ref globalTransform).Top > globalClipping.Top) + { + // Overshoot... + for (; firstVisibleChild > 0; firstVisibleChild--) + { + var child = children[firstVisibleChild]; + if (GetChildGlobalRectangle(child, ref globalTransform).Top < globalClipping.Top) + break; + } + } + + for (int i = firstVisibleChild; i < children.Count; i++) + { + var child = children[i]; + if (child.Visible) + { + var childGlobalRect = GetChildGlobalRectangle(child, ref globalTransform); + if (globalClipping.Intersects(ref childGlobalRect)) + { + Render2D.PushTransform(ref child._cachedTransform); + child.Draw(); + Render2D.PopTransform(); + } + else + break; + } + } + + static Rectangle GetChildGlobalRectangle(Control control, ref Matrix3x3 globalTransform) + { + Matrix3x3.Multiply(ref control._cachedTransform, ref globalTransform, out var globalChildTransform); + return new Rectangle(globalChildTransform.M31, globalChildTransform.M32, control.Width * globalChildTransform.M11, control.Height * globalChildTransform.M22); + } + } + else + { + for (int i = 0; i < children.Count; i++) + { + var child = children[i]; + if (child.Visible) + { + Render2D.PushTransform(ref child._cachedTransform); + child.Draw(); + Render2D.PopTransform(); + } + } + } + } + /// public override bool OnMouseDown(Float2 location, MouseButton button) {