コード例 #1
0
ファイル: Control.HitTest.cs プロジェクト: sq/Libraries
        private int WalkTree(ControlCollection controls, RectF clip, Vector2 position, int depth, Func <Control, bool> predicate, float maxDistanceSquared)
        {
            var totalMatches = 0;

            var ordered = controls.InDisplayOrder(Context.FrameIndex);
            var stop    = false;

            for (int i = ordered.Count - 1; (i >= 0) && !stop; i--)
            {
                var control = ordered[i];
                if (control.IsTransparent || control.Intangible)
                {
                    continue;
                }

                var result = new Result {
                    Depth   = depth,
                    Control = control,
                    Rect    = control.GetRect(context: Context)
                };

                if (!result.Rect.Intersection(in clip, out result.ClippedRect))
                {
                    continue;
                }

                var inside = result.ClippedRect.Contains(position);
                stop = stop || inside;

                int localMatches = 0;
                var ifht         = control as IFuzzyHitTestTarget;
                if (ifht != null)
                {
                    localMatches += ifht.WalkTree(Results, ref result, position, predicate, maxDistanceSquared);
                }

                if (ifht?.WalkChildren != false)
                {
                    var icc = control as IControlContainer;
                    if (icc != null)
                    {
                        localMatches += WalkTree(icc.Children, result.ClippedRect, position, depth + 1, predicate, maxDistanceSquared);
                    }
                }

                totalMatches += localMatches;
                if (localMatches > 0)
                {
                    continue;
                }

                if ((predicate != null) && !predicate(control))
                {
                    continue;
                }

                float distanceSquared;
                if (inside)
                {
                    result.Distance     = distanceSquared = 0f;
                    result.ClosestPoint = position;
                }
                else
                {
                    result.ClosestPoint = result.ClippedRect.Clamp(position);
                    distanceSquared     = (position - result.ClosestPoint).LengthSquared();
                    if (distanceSquared > maxDistanceSquared)
                    {
                        continue;
                    }
                    result.Distance = (float)Math.Sqrt(distanceSquared);
                }

                var ipic = result.Control as IPartiallyIntangibleControl;
                result.IsIntangibleAtClosestPoint = (ipic?.IsIntangibleAtPosition(result.ClosestPoint) == true);
                Results.Add(result);
                totalMatches += 1;
            }

            return(totalMatches);
        }