public PlaneIntersection(CSGTreeBrushIntersection brushIntersection, ChiselNode node, ChiselModel model)
 {
     this.point = brushIntersection.surfaceIntersection.worldIntersection;
     this.plane = brushIntersection.surfaceIntersection.worldPlane;
     this.node  = node;
     this.model = model;
 }
        public static bool PickFirstGameObject(Vector2 position, out CSGTreeBrushIntersection intersection)
        {
            GameObject[] ignore = null;
            GameObject[] filter = null;
            if (!PickClosestGameObjectDelegated(position, ref ignore, ref filter, out intersection))
            {
                return(false);
            }

            return(intersection.surfaceID != -1);
        }
        public static ChiselNode PickClosestNode(Vector2 position, out CSGTreeBrushIntersection 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;

            GameObject[] ignore = new GameObject[0];
            GameObject[] filter = null;
            return(PickNode(camera, pickposition, layers, ref ignore, ref filter, out intersection));
        }
        internal static GameObject PickClosestGameObjectDelegated(Vector2 position, ref GameObject[] ignore, ref GameObject[] filter, out CSGTreeBrushIntersection 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;

            /*
             * GameObject picked = null;
             * if (pickClosestGameObjectDelegate != null)
             * {
             *  // TODO: figure out how to call a delegate through reflection with an out parameter ...
             * }*/

            intersection = new CSGTreeBrushIntersection
            {
                surfaceID   = -1,
                brushUserID = -1
            };

            //if (picked == null)
            {
                ChiselNode  node;
                ChiselModel model;
                var         gameObject = PickNodeOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out model, out node, out intersection);
                if (!model)
                {
                    return(gameObject);
                }

                if (node)
                {
                    return(gameObject);
                }

                return(null);
            }

            /*
             * if (CSGGeneratedComponentManager.IsObjectGenerated(picked))
             * {
             *  if (ignore == null)
             *      return null;
             *  ArrayUtility.Add(ref ignore, picked);
             *  return PickClosestGameObjectDelegated(position, ref ignore, ref filter, out intersection);
             * }
             * return picked;*/
        }
Exemple #5
0
        static ChiselIntersection Convert(CSGTreeBrushIntersection intersection)
        {
            var node  = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(intersection.brush.UserID);
            var model = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(intersection.tree.UserID) as ChiselModel;

            var treeLocalToWorldMatrix = model.transform.localToWorldMatrix;

            var worldPlaneIntersection = treeLocalToWorldMatrix.MultiplyPoint(intersection.surfaceIntersection.treePlaneIntersection);
            var worldPlane             = treeLocalToWorldMatrix.TransformPlane(intersection.surfaceIntersection.treePlane);

            return(new ChiselIntersection()
            {
                treeNode = node,
                model = model,
                worldPlane = worldPlane,
                worldPlaneIntersection = worldPlaneIntersection,
                brushIntersection = intersection
            });
        }
Exemple #6
0
        public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out CSGTreeBrushIntersection foundIntersection)
        {
            foundIntersection = new CSGTreeBrushIntersection();
            foundIntersection.surfaceIntersection.distance = float.PositiveInfinity;

            if (!model || !model.isActiveAndEnabled)
            {
                return(false);
            }

            CSGTreeNode[] ignoreBrushes     = null;
            HashSet <int> ignoreInstanceIDs = null;
            HashSet <int> filterInstanceIDs = null;

            if (ignore != null)
            {
                //var ignoreBrushList = new HashSet<CSGTreeBrush>();
                ignoreInstanceIDs = new HashSet <int>();
                foreach (var go in ignore)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        //node.GetAllTreeBrushes(ignoreBrushList);
                        ignoreInstanceIDs.Add(node.GetInstanceID());
                    }
                }/*
                  * if (ignoreBrushList.Count > 0)
                  * {
                  * // TODO: fix this, ignorebrushes doesn't remove the brush completely, but that's not necessarily correct
                  * //			for example: another brush that is not ignored, subtracts from a brush that's ignored (so its insides should be selectable)
                  * ignoreBrushes = new CSGTreeNode[ignoreBrushList.Count];
                  * int index = 0;
                  * foreach(var brush in ignoreBrushList)
                  * {
                  *     ignoreBrushes[index] = brush;
                  *     index++;
                  * }
                  * }*/
            }
            if (filter != null)
            {
                filterInstanceIDs = new HashSet <int>();
                foreach (var go in filter)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        filterInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }


            var tree = model.Node;

            if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(model.GetInstanceID())))
            {
                return(false);
            }

            if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(model.GetInstanceID())))
            {
                return(false);
            }

            if (((1 << model.gameObject.layer) & visibleLayers) == 0)
            {
                return(false);
            }

            var query = CSGMeshQueryManager.GetMeshQuery(model);

            // We only accept RayCasts into this model if it's visible
            if (!CSGMeshQueryManager.IsVisible(query))
            {
                return(false);
            }

            Vector3 treeRayStart;
            Vector3 treeRayEnd;

            var transform = model.transform;

            if (transform)
            {
                var worldToLocalMatrix = transform.worldToLocalMatrix;
                treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart);
                treeRayEnd   = worldToLocalMatrix.MultiplyPoint(worldRayEnd);
            }
            else
            {
                treeRayStart = worldRayStart;
                treeRayEnd   = worldRayEnd;
            }

            var treeIntersections = tree.RayCastMulti(CSGMeshQueryManager.GetMeshQuery(model), treeRayStart, treeRayEnd, model.transform.localToWorldMatrix, filterLayerParameter0, ignoreBrushes);

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

            bool found = false;

            for (var i = 0; i < treeIntersections.Length; i++)
            {
                var intersection = treeIntersections[i];
                var brush        = intersection.brush;
                var instanceID   = brush.UserID;

                if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(instanceID)))
                {
                    continue;
                }

                if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(instanceID)))
                {
                    continue;
                }

                if (intersection.surfaceIntersection.distance < foundIntersection.surfaceIntersection.distance)
                {
                    foundIntersection = intersection;
                    found             = true;
                }
            }
            return(found);
        }
Exemple #7
0
 public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, out CSGTreeBrushIntersection foundIntersection)
 {
     return(FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, visibleLayers, null, null, out foundIntersection));
 }
Exemple #8
0
        public static bool FindFirstWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out CSGTreeBrushIntersection foundIntersection)
        {
            bool found = false;

            foundIntersection = new CSGTreeBrushIntersection();
            foundIntersection.surfaceIntersection.distance = float.PositiveInfinity;

            HashSet <int> ignoreInstanceIDs = null;
            HashSet <int> filterInstanceIDs = null;

            if (ignore != null)
            {
                ignoreInstanceIDs = new HashSet <int>();
                foreach (var go in ignore)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        ignoreInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }
            if (filter != null)
            {
                filterInstanceIDs = new HashSet <int>();
                foreach (var go in filter)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        filterInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }

            var allTrees = CSGManager.AllTrees;

            for (var t = 0; t < allTrees.Length; t++)
            {
                var tree  = allTrees[t];
                var model = CSGNodeHierarchyManager.FindCSGNodeByTreeNode(tree) as ChiselModel;
                if (!model || !model.isActiveAndEnabled)
                {
                    continue;
                }

                if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(model.GetInstanceID())))
                {
                    return(false);
                }

                if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(model.GetInstanceID())))
                {
                    return(false);
                }

                if (((1 << model.gameObject.layer) & visibleLayers) == 0)
                {
                    continue;
                }

                var query = CSGMeshQueryManager.GetMeshQuery(model);

                // We only accept RayCasts into this model if it's visible
                if (!CSGMeshQueryManager.IsVisible(query))
                {
                    continue;
                }

                Vector3 treeRayStart;
                Vector3 treeRayEnd;

                var transform = model.transform;
                if (transform)
                {
                    var worldToLocalMatrix = transform.worldToLocalMatrix;
                    treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart);
                    treeRayEnd   = worldToLocalMatrix.MultiplyPoint(worldRayEnd);
                }
                else
                {
                    treeRayStart = worldRayStart;
                    treeRayEnd   = worldRayEnd;
                }

                var treeIntersections = tree.RayCastMulti(CSGMeshQueryManager.GetMeshQuery(model), treeRayStart, treeRayEnd, model.transform.localToWorldMatrix, filterLayerParameter0);
                if (treeIntersections == null)
                {
                    continue;
                }

                for (var i = 0; i < treeIntersections.Length; i++)
                {
                    var intersection = treeIntersections[i];
                    var brush        = intersection.brush;
                    var instanceID   = brush.UserID;

                    if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(instanceID)))
                    {
                        continue;
                    }

                    if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(instanceID)))
                    {
                        continue;
                    }

                    if (intersection.surfaceIntersection.distance < foundIntersection.surfaceIntersection.distance)
                    {
                        foundIntersection = intersection;
                        found             = true;
                    }
                }
            }
            return(found);
        }
        internal static ChiselNode PickNode(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGTreeBrushIntersection intersection)
        {
TryNextNode:
            ChiselModel model;
            ChiselNode node;
            var        gameObject = PickNodeOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out model, out node, out intersection);

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

            if (model)
            {
                return(node);
            }

            ArrayUtility.Add(ref ignore, gameObject);
            goto TryNextNode;
        }
        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);
        }
        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);
            }
        }
        // TODO: rewrite this, why do we need hashes?
        public static GameObject PickClosestGameObject(Vector2 mousePosition, out CSGTreeBrushIntersection intersection)
        {
            intersection = new CSGTreeBrushIntersection
            {
                surfaceID   = -1,
                brushUserID = -1
            };

            s_RetainHashes = true;

            if (enumerator == null ||
                (prevMousePosition - mousePosition).sqrMagnitude > 2)
            {
                enumerator        = GetAllOverlapping(mousePosition).GetEnumerator();
                prevMousePosition = mousePosition;
            }
            if (!enumerator.MoveNext())
            {
                enumerator = GetAllOverlapping(mousePosition).GetEnumerator();
                if (!enumerator.MoveNext())
                {
                    return(null);
                }
            }

            var topmost = enumerator.Current;

            var selectionBase = GUIClip.FindSelectionBase(topmost.Key);
            var first         = (selectionBase == null ? topmost.Key : selectionBase);
            int topmostHash   = topmost.GetHashCode();
            int prefixHash    = topmostHash;

            if (Selection.activeGameObject == null)
            {
                // Nothing selected
                // Return selection base if it exists, otherwise topmost game object
                s_PreviousTopmostHash = topmostHash;
                s_PreviousPrefixHash  = prefixHash;
                intersection          = topmost.Value;
                return(first);
            }

            if (topmostHash != s_PreviousTopmostHash)
            {
                // Topmost game object changed
                // Return selection base if exists and is not already selected, otherwise topmost game object
                s_PreviousTopmostHash = topmostHash;
                s_PreviousPrefixHash  = prefixHash;
                intersection          = topmost.Value;
                return(Selection.activeGameObject == selectionBase ? topmost.Key : first);
            }

            s_PreviousTopmostHash = topmostHash;

            // Pick potential selection base before topmost game object
            if (Selection.activeGameObject == selectionBase)
            {
                intersection = topmost.Value;
                if (prefixHash != s_PreviousPrefixHash)
                {
                    s_PreviousPrefixHash = prefixHash;
                    return(selectionBase);
                }
                return(topmost.Key);
            }

            // Check if active game object will appear in selection stack
            GameObject[] ignore = null;
            GameObject[] filter = new GameObject[] { Selection.activeGameObject };
            var          picked = PickClosestGameObjectDelegated(mousePosition, ref ignore, ref filter, out intersection);

            if (picked == Selection.activeGameObject)
            {
                // Advance enumerator to active game object
                while (enumerator.Current.Key != Selection.activeGameObject)
                {
                    if (!enumerator.MoveNext())
                    {
                        s_PreviousPrefixHash = topmostHash;
                        intersection         = topmost.Value;
                        return(first); // Should not occur
                    }

                    UpdateHash(ref prefixHash, enumerator.Current);
                }
            }

            if (prefixHash != s_PreviousPrefixHash)
            {
                // Prefix hash changed, start over
                s_PreviousPrefixHash = topmostHash;
                intersection         = topmost.Value;
                return(first);
            }

            // Move on to next game object
            if (!enumerator.MoveNext())
            {
                s_PreviousPrefixHash = topmostHash;
                intersection         = topmost.Value;
                return(first); // End reached, start over
            }

            UpdateHash(ref prefixHash, enumerator.Current);

            if (enumerator.Current.Key == selectionBase)
            {
                // Skip selection base
                if (!enumerator.MoveNext())
                {
                    s_PreviousPrefixHash = topmostHash;
                    intersection         = topmost.Value;
                    return(first); // End reached, start over
                }

                UpdateHash(ref prefixHash, enumerator.Current);
            }

            s_PreviousPrefixHash = prefixHash;

            return(enumerator.Current.Key);
        }