static void Commit(Event evt, Rect dragArea, ref List <Vector3> points)
        {
            s_CurrentPointIndex++;
            UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea));

            // reset the starting position
            s_StartIntersection = CSGClickSelectionManager.GetPlaneIntersection(evt.mousePosition, dragArea);
            evt.Use();
        }
Beispiel #2
0
        // TODO: make selecting variants work when selecting in hierarchy/rect-select too
        public static void DoSelectionClick(SceneView sceneView, Vector2 mousePosition)
        {
            CSGTreeBrushIntersection intersection;
            var gameobject = CSGClickSelectionManager.PickClosestGameObject(Event.current.mousePosition, out intersection);

            // If we're a child of an operation that has a "handle as one" flag set, return that instead
            gameobject = CSGSceneQuery.GetContainerGameObject(gameobject);

            var selectionType = GetCurrentSelectionType();

            var selectedObjectsOnClick = new List <int>(Selection.instanceIDs);

            switch (selectionType)
            {
            case SelectionType.Additive:
            {
                if (!gameobject)
                {
                    break;
                }

                CSGSyncSelection.SelectBrushVariant(intersection.brush, uniqueSelection: false);
                var instanceID = gameobject.GetInstanceID();
                selectedObjectsOnClick.Add(instanceID);
                Selection.instanceIDs = selectedObjectsOnClick.ToArray();
                break;
            }

            case SelectionType.Subtractive:
            {
                if (!gameobject)
                {
                    break;
                }

                Undo.RecordObject(CSGSyncSelection.Instance, "Deselected brush variant");
                CSGSyncSelection.DeselectBrushVariant(intersection.brush);
                // Can only deselect brush if all it's synchronized brushes have also been deselected
                if (!CSGSyncSelection.IsAnyBrushVariantSelected(intersection.brush))
                {
                    var instanceID = gameobject.GetInstanceID();
                    selectedObjectsOnClick.Remove(instanceID);
                }
                Selection.instanceIDs = selectedObjectsOnClick.ToArray();
                return;
            }

            default:
            {
                Undo.RecordObject(CSGSyncSelection.Instance, "Selected brush variant");
                CSGSyncSelection.SelectBrushVariant(intersection.brush, uniqueSelection: true);
                Selection.activeGameObject = gameobject;
                break;
            }
            }
        }
Beispiel #3
0
        public static PlaneIntersection GetPlaneIntersection(Vector2 mousePosition)
        {
            CSGTreeBrushIntersection brushIntersection;
            var intersectionObject = CSGClickSelectionManager.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 CSGModel;
                    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 (CSGClickSelectionManager.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 void UpdateDrag()
        {
            var selectAllSurfaces = UnityEngine.Event.current.shift;

            CSGBrushMeshAsset[] brushMeshAssets;
            CSGSurfaceAsset[]   surfaces;
            CSGClickSelectionManager.FindSurfaceAsset(Event.current.mousePosition, out surfaces, out brushMeshAssets, selectAllSurfaces);
            if (!Equals(prevSurfaces, surfaces))
            {
                UndoPrevSurface();

                // Handle situation where we're hovering over a selected surface, then apply to all selected surfaces
                if (!selectAllSurfaces)
                {
                    surfaces = AddSelectedSurfaces(surfaces);
                }

                ApplyMaterialToSurface(brushMeshAssets, surfaces);
            }
        }
        static bool UpdateHoverSurfaces(Vector2 mousePosition, Rect dragArea, SelectionType selectionType, bool clearHovering)
        {
            try
            {
                hoverIntersection     = null;
                hoverSurfaceReference = null;

                bool modified = false;
                if (clearHovering || !InEditCameraMode)
                {
                    if (hoverSurfaces.Count != 0)
                    {
                        hoverSurfaces.Clear();
                        modified = true;
                    }
                }

                if (!dragArea.Contains(mousePosition))
                {
                    return(modified);
                }

                if (!InEditCameraMode)
                {
                    return(modified);
                }

                CSGTreeBrushIntersection intersection;
                SurfaceReference         surfaceReference;
                var foundSurfaces = CSGClickSelectionManager.FindSurfaceReference(mousePosition, false, out intersection, out surfaceReference);
                if (foundSurfaces == null)
                {
                    modified          = (hoverSurfaces != null) || modified;
                    hoverIntersection = null;
                    return(modified);
                }

                if (!float.IsInfinity(intersection.surfaceIntersection.distance))
                {
                    intersection.surfaceIntersection.worldIntersection = SnapIntersection(intersection.surfaceIntersection.worldIntersection, surfaceReference, out pointHasSnapped);
                }
                hoverIntersection     = intersection;
                hoverSurfaceReference = surfaceReference;
                if (foundSurfaces.Length == hoverSurfaces.Count)
                {
                    modified = !hoverSurfaces.ContainsAll(foundSurfaces) || modified;
                }
                else
                {
                    modified = true;
                }

                if (foundSurfaces.Length > 0)
                {
                    hoverSurfaces.AddRange(foundSurfaces);
                }
                return(modified);
            }
            finally
            {
                CSGSurfaceSelectionManager.SetHovering(selectionType, hoverSurfaces);
            }
        }
        static Vector3?GetPointAtPosition(Vector2 mousePosition, Rect dragArea)
        {
            UnitySceneExtensions.Grid.HoverGrid = null;
            if (s_CurrentPointIndex == 0)
            {
                s_StartIntersection = CSGClickSelectionManager.GetPlaneIntersection(mousePosition, dragArea);
                if (s_StartIntersection != null)
                {
                    // TODO: try to cache this ..
                    var activeGridUp       = UnitySceneExtensions.Grid.ActiveGrid.Up;
                    var activeGridForward  = UnitySceneExtensions.Grid.ActiveGrid.Forward;
                    var activeGridCenter   = UnitySceneExtensions.Grid.ActiveGrid.Center;
                    var surfaceGridPlane   = s_StartIntersection.plane;
                    var surfaceGridUp      = surfaceGridPlane.normal;
                    var surfaceGridForward = -MathExtensions.ClosestTangentAxis(surfaceGridUp);                              // Q: why if this is not negated, we end up-side-down?

                    var activeGridFromWorldRotation     = Quaternion.LookRotation(activeGridForward, activeGridUp);
                    var worldFromActiveGridRotation     = Quaternion.Inverse(activeGridFromWorldRotation);
                    var surfaceGridFromWorldRotation    = Quaternion.LookRotation(surfaceGridForward, surfaceGridUp);
                    var activeGridToSurfaceGridRotation = surfaceGridFromWorldRotation * worldFromActiveGridRotation;


                    // Make sure the center of the new grid is as close to the active grid center as possible
                    Vector3 surfaceGridCenter = activeGridCenter;
                    var     forwardRay        = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.up);
                    var     backRay           = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.down);
                    var     leftRay           = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.left);
                    var     rightRay          = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.right);
                    var     upRay             = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.forward);
                    var     downRay           = new Ray(activeGridCenter, worldFromActiveGridRotation * Vector3.back);

                    var   bestDist = float.PositiveInfinity;
                    float dist;

                    if (surfaceGridPlane.UnsignedRaycast(forwardRay, out dist))
                    {
                        var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                        {
                            bestDist = abs_dist; surfaceGridCenter = forwardRay.GetPoint(dist);
                        }
                    }
                    if (surfaceGridPlane.UnsignedRaycast(backRay, out dist))
                    {
                        var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                        {
                            bestDist = abs_dist; surfaceGridCenter = backRay.GetPoint(dist);
                        }
                    }
                    if (surfaceGridPlane.UnsignedRaycast(leftRay, out dist))
                    {
                        var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                        {
                            bestDist = abs_dist; surfaceGridCenter = leftRay.GetPoint(dist);
                        }
                    }
                    if (surfaceGridPlane.UnsignedRaycast(rightRay, out dist))
                    {
                        var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                        {
                            bestDist = abs_dist; surfaceGridCenter = rightRay.GetPoint(dist);
                        }
                    }
                    if (bestDist > 100000) // prefer rays on the active-grid, only go up/down from the active-grid when we have no other choice
                    {
                        if (surfaceGridPlane.UnsignedRaycast(upRay, out dist))
                        {
                            var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                            {
                                bestDist = abs_dist; surfaceGridCenter = upRay.GetPoint(dist);
                            }
                        }
                        if (surfaceGridPlane.UnsignedRaycast(downRay, out dist))
                        {
                            var abs_dist = Mathf.Abs(dist); if (abs_dist < bestDist)
                            {
                                bestDist = abs_dist; surfaceGridCenter = downRay.GetPoint(dist);
                            }
                        }
                    }

                    // TODO: try to snap the new surface grid point in other directions on the active-grid? (do we need to?)

                    s_Transform = Matrix4x4.TRS(surfaceGridCenter - activeGridCenter, activeGridToSurfaceGridRotation, Vector3.one) *
                                  UnitySceneExtensions.Grid.ActiveGrid.GridToWorldSpace;
                    s_InvTransform = s_Transform.inverse;

                    s_Snapping2D.Initialize(new UnitySceneExtensions.Grid(s_Transform), mousePosition, s_StartIntersection.point, UnityEditor.Handles.matrix);
                }
            }

            if (s_StartIntersection != null)
            {
                if (s_Snapping2D.DragTo(mousePosition, SnappingMode.Always))
                {
                    UnitySceneExtensions.Grid.HoverGrid = s_Snapping2D.WorldSlideGrid;
                    return(s_Snapping2D.WorldSnappedPosition);
                }
            }
            return(null);
        }