public static SurfaceIntersection FindSurfaceIntersection(Vector2 position)
        {
            try
            {
                CSGTreeBrushIntersection brushIntersection;
                if (!PickFirstGameObject(position, out brushIntersection))
                {
                    return(null);
                }

                var brush = brushIntersection.brush;

                var node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brush.UserID);
                if (!node)
                {
                    return(null);
                }

                var surface = node.FindSurfaceReference(brush, brushIntersection.surfaceID);
                if (surface == null)
                {
                    return(null);
                }
                return(new SurfaceIntersection {
                    surface = surface, intersection = brushIntersection.surfaceIntersection
                });
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                return(null);
            }
        }
        public static bool FindBrushMaterials(Vector2 position, out ChiselBrushMaterial[] brushMaterials, out ChiselBrushContainerAsset[] brushContainerAssets, bool selectAllSurfaces)
        {
            brushMaterials       = null;
            brushContainerAssets = null;
            try
            {
                CSGTreeBrushIntersection intersection;
                if (!PickFirstGameObject(Event.current.mousePosition, out intersection))
                {
                    return(false);
                }

                var brush = intersection.brush;

                var node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brush.UserID);
                if (!node)
                {
                    return(false);
                }

                if (selectAllSurfaces)
                {
                    brushContainerAssets = node.GetUsedGeneratedBrushes();
                    if (brushContainerAssets == null)
                    {
                        return(false);
                    }
                    brushMaterials = node.GetAllBrushMaterials(brush);
                    return(true);
                }
                else
                {
                    var surface = node.FindBrushMaterial(brush, intersection.surfaceID);
                    if (surface == null)
                    {
                        return(false);
                    }
                    brushContainerAssets = node.GetUsedGeneratedBrushes();
                    if (brushContainerAssets == null)
                    {
                        return(false);
                    }
                    brushMaterials = new ChiselBrushMaterial[] { surface };
                    return(true);
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                return(false);
            }
        }
        public static PlaneIntersection GetPlaneIntersection(Vector2 mousePosition)
        {
            CSGTreeBrushIntersection brushIntersection;
            var intersectionObject = ChiselClickSelectionManager.PickClosestGameObject(mousePosition, out brushIntersection);

            if (intersectionObject &&
                intersectionObject.activeInHierarchy)
            {
                if (brushIntersection.brushUserID != -1)
                {
                    var brush = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brushIntersection.brush.UserID);
                    var model = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brushIntersection.tree.UserID) as ChiselModel;
                    return(new PlaneIntersection(brushIntersection, brush, model));
                }

                var meshFilter = intersectionObject.GetComponent <MeshFilter>();
                if (meshFilter)
                {
                    var        mesh     = meshFilter.sharedMesh;
                    var        mouseRay = UnityEditor.HandleUtility.GUIPointToWorldRay(mousePosition);
                    RaycastHit hit;
                    if (ChiselClickSelectionManager.IntersectRayMesh(mouseRay, mesh, intersectionObject.transform.localToWorldMatrix, out hit))
                    {
                        var meshRenderer = intersectionObject.GetComponent <MeshRenderer>();
                        if (meshRenderer.enabled)
                        {
                            return(new PlaneIntersection(hit.point, hit.normal));
                        }
                    }
                }
            }
            else
            {
                var gridPlane = UnitySceneExtensions.Grid.ActiveGrid.PlaneXZ;
                var mouseRay  = UnityEditor.HandleUtility.GUIPointToWorldRay(mousePosition);
                var dist      = 0.0f;
                if (gridPlane.UnsignedRaycast(mouseRay, out dist))
                {
                    return(new PlaneIntersection(mouseRay.GetPoint(dist), gridPlane));
                }
            }
            return(null);
        }
        public static SurfaceReference[] FindSurfaceReference(Vector2 position, bool selectAllSurfaces, out CSGTreeBrushIntersection intersection, out SurfaceReference surfaceReference)
        {
            intersection     = CSGTreeBrushIntersection.None;
            surfaceReference = null;
            try
            {
                if (!PickFirstGameObject(position, out intersection))
                {
                    return(null);
                }

                var brush = intersection.brush;

                var node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brush.UserID);
                if (!node)
                {
                    return(null);
                }

                surfaceReference = node.FindSurfaceReference(brush, intersection.surfaceID);
                if (selectAllSurfaces)
                {
                    return(node.GetAllSurfaceReferences(brush));
                }

                if (surfaceReference == null)
                {
                    return(null);
                }
                return(new SurfaceReference[] { surfaceReference });
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                return(null);
            }
        }
        internal static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out ChiselNode node, out CSGTreeBrushIntersection intersection)
        {
TryNextSelection:
            intersection = new CSGTreeBrushIntersection {
                surfaceID = -1, brushUserID = -1
            };

            model = null;
            node  = null;
            Material sharedMaterial;
            var      gameObject = PickModel(camera, pickposition, layers, ref ignore, ref filter, out model, out sharedMaterial);

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (model)
            {
                int filterLayerParameter0 = (sharedMaterial) ? sharedMaterial.GetInstanceID() : 0;
                {
                    var worldRay       = camera.ScreenPointToRay(pickposition);
                    var worldRayStart  = worldRay.origin;
                    var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
                    var worldRayEnd    = worldRayStart + worldRayVector;

                    CSGTreeBrushIntersection tempIntersection;
                    if (ChiselSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out tempIntersection))
                    {
                        var clickedBrush = tempIntersection.brush;
                        node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(clickedBrush.UserID);
                        if (node)
                        {
                            if (ignore != null &&
                                ignore.Contains(node.gameObject))
                            {
                                node = null;
                                return(null);
                            }
                            intersection = tempIntersection;
                            return(node.gameObject);
                        }
                        else
                        {
                            node = null;
                        }
                    }
                }

                if (ignore == null)
                {
                    return(null);
                }

                ArrayUtility.Add(ref ignore, gameObject);
                goto TryNextSelection;
            }

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (ignore != null &&
                ignore.Contains(gameObject))
            {
                return(null);
            }

            return(gameObject);
        }