()
| 818 | |
| 819 | /// <inheritdoc /> |
| 820 | protected override void DrawChildren() |
| 821 | { |
| 822 | // Draw all visible child controls |
| 823 | var children = _children; |
| 824 | if (children.Count == 0) |
| 825 | return; |
| 826 | var last = children.Count - 1; |
| 827 | |
| 828 | if (CullChildren) |
| 829 | { |
| 830 | Render2D.PeekClip(out var globalClipping); |
| 831 | Render2D.PeekTransform(out var globalTransform); |
| 832 | |
| 833 | // Try to estimate the rough location of the first and the last nodes, assuming the node height is constant |
| 834 | var firstChildGlobalRect = GetChildGlobalRectangle(children[0], ref globalTransform); |
| 835 | var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Top - firstChildGlobalRect.Top) / _headerHeight) + 1, 0, last); |
| 836 | if (GetChildGlobalRectangle(children[firstVisibleChild], ref globalTransform).Top > globalClipping.Top || !children[firstVisibleChild].Visible) |
| 837 | { |
| 838 | // Estimate overshoot, either it's partially visible or hidden in the tree |
| 839 | for (; firstVisibleChild > 0; firstVisibleChild--) |
| 840 | { |
| 841 | var child = children[firstVisibleChild]; |
| 842 | if (!child.Visible) |
| 843 | continue; |
| 844 | if (GetChildGlobalRectangle(child, ref globalTransform).Top < globalClipping.Top) |
| 845 | break; |
| 846 | } |
| 847 | } |
| 848 | var lastVisibleChild = Math.Clamp((int)Math.Ceiling((globalClipping.Bottom - firstChildGlobalRect.Top) / _headerHeight) + 1, firstVisibleChild, last); |
| 849 | if (GetChildGlobalRectangle(children[lastVisibleChild], ref globalTransform).Top < globalClipping.Bottom || !children[lastVisibleChild].Visible) |
| 850 | { |
| 851 | // Estimate overshoot, either it's partially visible or hidden in the tree |
| 852 | for (; lastVisibleChild < last; lastVisibleChild++) |
| 853 | { |
| 854 | var child = children[lastVisibleChild]; |
| 855 | if (!child.Visible) |
| 856 | continue; |
| 857 | if (GetChildGlobalRectangle(child, ref globalTransform).Top > globalClipping.Bottom) |
| 858 | break; |
| 859 | } |
| 860 | } |
| 861 | |
| 862 | for (int i = firstVisibleChild; i <= lastVisibleChild; i++) |
| 863 | { |
| 864 | var child = children[i]; |
| 865 | if (!child.Visible) |
| 866 | continue; |
| 867 | Render2D.PushTransform(ref child._cachedTransform); |
| 868 | child.Draw(); |
| 869 | Render2D.PopTransform(); |
| 870 | } |
| 871 | |
| 872 | static Rectangle GetChildGlobalRectangle(Control control, ref Matrix3x3 globalTransform) |
| 873 | { |
| 874 | Matrix3x3.Multiply(ref control._cachedTransform, ref globalTransform, out var globalChildTransform); |
| 875 | return new Rectangle(globalChildTransform.M31, globalChildTransform.M32, control.Width * globalChildTransform.M11, control.Height * globalChildTransform.M22); |
| 876 | } |
| 877 | } |
nothing calls this directly
no test coverage detected