public PlaneIntersection(ChiselIntersection chiselIntersection)
 {
     this.point = chiselIntersection.worldPlaneIntersection;
     this.plane = chiselIntersection.worldPlane;
     this.node  = chiselIntersection.node;
     this.model = chiselIntersection.model;
 }
        static bool PickFirstGameObject(Vector2 position, out ChiselIntersection intersection)
        {
            GameObject[] ignore = null;
            GameObject[] filter = null;
            if (!PickClosestGameObjectDelegated(position, ref ignore, ref filter, out intersection))
            {
                return(false);
            }

            return(intersection.brushIntersection.surfaceIndex != -1);
        }
        static GameObject PickClosestGameObjectDelegated(Vector2 position, ref GameObject[] ignore, ref GameObject[] filter, out ChiselIntersection intersection)
        {
            var camera       = Camera.current;
            int layers       = camera.cullingMask;
            var pickposition = GUIClip.GUIClipUnclip(position);

            pickposition   = EditorGUIUtility.PointsToPixels(pickposition);
            pickposition.y = Screen.height - pickposition.y - camera.pixelRect.yMin;

            var gameObject = PickNodeOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out var model, out var node, out intersection);

            if (!model)
            {
                return(gameObject);
            }

            if (node)
            {
                return(gameObject);
            }

            return(null);
        }
        static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out ChiselNode node, out ChiselIntersection intersection)
        {
TryNextSelection:
            intersection = ChiselIntersection.None;

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

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

            if (ChiselGeneratedComponentManager.IsValidModelToBeSelected(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;

                    if (ChiselSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out var tempIntersection))
                    {
                        node = tempIntersection.node;
                        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);
        }
        public static SurfaceReference[] FindSurfaceReferences(Vector2 position, bool selectAllSurfaces, out ChiselIntersection intersection, out SurfaceReference surfaceReference)
        {
            intersection     = ChiselIntersection.None;
            surfaceReference = null;
            try
            {
                if (!PickFirstGameObject(position, out intersection))
                {
                    return(null);
                }

                var node = intersection.node;
                if (!node)
                {
                    return(null);
                }

                var brush = intersection.brushIntersection.brush;

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

                if (surfaceReference == null)
                {
                    return(null);
                }
                return(new SurfaceReference[] { surfaceReference });
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                return(null);
            }
        }
        public static GameObject PickClosestGameObject(Vector2 screenPos, out ChiselIntersection intersection)
        {
            intersection = ChiselIntersection.None;
            var camera = Camera.current;

            if (!camera)
            {
                return(null);
            }

            // If we moved our mouse, reset our ignore list
            if (_prevSceenPos != screenPos ||
                _prevCamera != camera)
            {
                ResetDeepClick();
            }

            _prevSceenPos = screenPos;
            _prevCamera   = camera;

            // Get the first click that is not in our ignore list
            GameObject[] ignore      = deepClickIgnoreGameObjectList.ToArray();
            GameObject[] filter      = null;
            var          foundObject = PickClosestGameObjectDelegated(screenPos, ref ignore, ref filter, out intersection);

            // If we haven't found anything, try getting the first item in our list that's either a brush or a regular gameobject (loop around)
            if (object.Equals(foundObject, null))
            {
                bool found = false;
                for (int i = 0; i < deepClickIgnoreGameObjectList.Count; i++)
                {
                    foundObject = deepClickIgnoreGameObjectList[i];

                    // We don't want models or mesh containers since they're in this list to skip, and should never be selected
                    if (!IsValidNodeToBeSelected(foundObject))
                    {
                        continue;
                    }

                    found = true;
                    break;
                }

                if (!found)
                {
                    // We really didn't find anything
                    intersection = ChiselIntersection.None;
                    ResetDeepClick();
                    return(null);
                }
                else
                {
                    // Reset our list so we only skip our current selection on the next click
                    ResetDeepClick(
                        resetPosition: false // But make sure we remember our current mouse position
                        );
                }
            }

            // Remember our gameobject so we don't select it on the next click
            deepClickIgnoreGameObjectList.Add(foundObject);
            return(foundObject);
        }