public static bool FindSurfaceIntersection(Camera camera, CSGBrush brush, Matrix4x4 modelTransformation, Int32 surfaceIndex, Vector2 screenPos, out LegacySurfaceIntersection intersection)
        {
            var worldRay  = HandleUtility.GUIPointToWorldRay(screenPos);
            var rayStart  = worldRay.origin;
            var rayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
            var rayEnd    = rayStart + rayVector;

            intersection = null;
            if (!brush ||
                InternalCSGModelManager.External.RayCastIntoBrushSurface == null)
            {
                return(false);
            }

            if (!InternalCSGModelManager.External.RayCastIntoBrushSurface(brush.brushNodeID,
                                                                          surfaceIndex,
                                                                          rayStart,
                                                                          rayEnd,
                                                                          modelTransformation,
                                                                          out intersection))
            {
                return(false);
            }

            if (BrushTraits.IsSurfaceUnselectable(brush, surfaceIndex, brush.ChildData.Model.IsTrigger))
            {
                return(false);
            }
            return(true);
        }
        public static bool FindBrushIntersection(CSGBrush brush, Matrix4x4 modelTransformation, Vector3 rayStart, Vector3 rayEnd, out LegacyBrushIntersection intersection)
        {
            intersection = null;
            if (!brush || InternalCSGModelManager.External.RayCastIntoBrush == null)
            {
                return(false);
            }

            if (!InternalCSGModelManager.External.RayCastIntoBrush(brush.brushNodeID,
                                                                   rayStart,
                                                                   rayEnd,
                                                                   modelTransformation,
                                                                   out intersection,
                                                                   false))
            {
                return(false);
            }

            if (BrushTraits.IsSurfaceUnselectable(brush, intersection.surfaceIndex, brush.ChildData.Model.IsTrigger))
            {
                return(false);
            }
            return(true);
        }
        public static bool FindWorldIntersection(Vector3 rayStart, Vector3 rayEnd, out LegacyBrushIntersection intersection, bool ignoreInvisibleSurfaces = true, bool ignoreUnrenderables = true, CSGBrush[] ignoreBrushes = null)
        {
            intersection = null;
            if (InternalCSGModelManager.External == null ||
                InternalCSGModelManager.External.RayCastMulti == null)
            {
                return(false);
            }

            var forceIgnoreInvisibleSurfaces = ignoreInvisibleSurfaces && !CSGSettings.ShowCulledSurfaces;

            var visibleLayers   = Tools.visibleLayers;
            int foundModelCount = 0;

            if (__foundModels.Length < InternalCSGModelManager.Models.Length)
            {
                __foundModels = new CSGModel[InternalCSGModelManager.Models.Length];
            }

            for (var g = 0; g < InternalCSGModelManager.Models.Length; g++)
            {
                var model = InternalCSGModelManager.Models[g];

                if (!ModelTraits.IsModelSelectable(model))
                {
                    continue;
                }

                if (ignoreUnrenderables && !ModelTraits.WillModelRender(model) &&
                    !Selection.Contains(model.gameObject.GetInstanceID()))
                {
                    continue;
                }

                __foundModels[foundModelCount] = model;
                foundModelCount++;
            }

            if (foundModelCount == 0)
            {
                return(false);
            }

            LegacyBrushIntersection[] modelIntersections;
            if (!InternalCSGModelManager.External.RayCastMulti(foundModelCount,
                                                               __foundModels,
                                                               rayStart,
                                                               rayEnd,
                                                               forceIgnoreInvisibleSurfaces,
                                                               out modelIntersections,
                                                               ignoreBrushes: ignoreBrushes))
            {
                return(false);
            }

            for (var i = 0; i < modelIntersections.Length; i++)
            {
                var modelIntersection = modelIntersections[i];

                if (intersection != null &&
                    modelIntersection.distance > intersection.distance)
                {
                    continue;
                }

                var brush = modelIntersection.gameObject.GetComponent <CSGBrush>();
                if (BrushTraits.IsSurfaceUnselectable(brush, modelIntersection.surfaceIndex, brush.ChildData.Model.IsTrigger, !ignoreInvisibleSurfaces))
                {
                    continue;
                }

                modelIntersection.brush = brush;

                intersection = modelIntersection;
            }

            if (intersection == null)
            {
                return(false);
            }

            return(true);
        }
        public static bool FindMultiWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, out LegacyBrushIntersection[] intersections, bool ignoreInvisibleSurfaces = true, bool ignoreUnrenderables = true, CSGBrush[] ignoreBrushes = null)
        {
            intersections = null;
            if (InternalCSGModelManager.External == null ||
                InternalCSGModelManager.External.RayCastIntoModelMulti == null)
            {
                return(false);
            }

            var foundIntersections = new Dictionary <CSGNode, LegacyBrushIntersection>();

            var visibleLayers = Tools.visibleLayers;

            ignoreInvisibleSurfaces = ignoreInvisibleSurfaces && !CSGSettings.ShowCulledSurfaces;
            for (var g = 0; g < InternalCSGModelManager.Models.Length; g++)
            {
                var model = InternalCSGModelManager.Models[g];
                if (!ModelTraits.IsModelSelectable(model))
                {
                    continue;
                }

                if (ignoreUnrenderables && !ModelTraits.WillModelRender(model) &&
                    !Selection.Contains(model.gameObject.GetInstanceID()))
                {
                    continue;
                }

                LegacyBrushIntersection[] modelIntersections;
                if (!InternalCSGModelManager.External.RayCastIntoModelMulti(model,
                                                                            worldRayStart,
                                                                            worldRayEnd,
                                                                            ignoreInvisibleSurfaces,
                                                                            out modelIntersections,
                                                                            ignoreBrushes: ignoreBrushes))
                {
                    continue;
                }

                for (var i = 0; i < modelIntersections.Length; i++)
                {
                    var intersection = modelIntersections[i];
                    var brush        = intersection.gameObject.GetComponent <CSGBrush>();
                    if (BrushTraits.IsSurfaceUnselectable(brush, intersection.surfaceIndex, brush.ChildData.Model.IsTrigger, ignoreSurfaceFlags: !ignoreInvisibleSurfaces))
                    {
                        continue;
                    }

                    var currentNode = GetTopMostGroupForNode(brush);
                    LegacyBrushIntersection other;
                    if (foundIntersections.TryGetValue(currentNode, out other) &&
                        other.distance <= intersection.distance)
                    {
                        continue;
                    }

                    intersection.brush = brush;
                    intersection.model = model;

                    foundIntersections[currentNode] = modelIntersections[i];
                }
            }

            if (foundIntersections.Count == 0)
            {
                return(false);
            }

            var sortedIntersections = foundIntersections.Values.ToArray();

            Array.Sort(sortedIntersections, (x, y) => (int)Mathf.Sign(x.distance - y.distance));

            intersections = sortedIntersections;
            return(true);
        }