Пример #1
0
        /// <summary>
        /// Returns the distance this grid is drawing
        /// </summary>
        /// <param name="cam"></param>
        /// <param name="pivot"></param>
        /// <param name="tangent"></param>
        /// <param name="bitangent"></param>
        /// <param name="snapValue"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        internal static float SetPerspective(Camera cam, Vector3 pivot, Vector3 tangent, Vector3 bitangent, float snapValue, Color color)
        {
            if (!s_GridMesh || !s_GridMaterial)
            {
                Init();
            }

            s_GridMaterial.SetFloat("_AlphaCutoff", .1f);
            s_GridMaterial.SetFloat("_AlphaFade", .6f);

            pivot = Snapping.Round(pivot, snapValue);

            Vector3 p         = cam.WorldToViewportPoint(pivot);
            bool    inFrustum = (p.x >= 0f && p.x <= 1f) &&
                                (p.y >= 0f && p.y <= 1f) &&
                                p.z >= 0f;

            float[] distances = GetDistanceToFrustumPlanes(cam, pivot, tangent, bitangent, 24f);

            if (inFrustum)
            {
                s_TangentIteration   = (int)(Mathf.Ceil((Mathf.Abs(distances[0]) + Mathf.Abs(distances[2])) / snapValue));
                s_BitangentIteration = (int)(Mathf.Ceil((Mathf.Abs(distances[1]) + Mathf.Abs(distances[3])) / snapValue));

                s_MaxLines = Mathf.Max(s_TangentIteration, s_BitangentIteration);

                // if the s_MaxLines is around 3x greater than min, we're probably skewing the camera at near-plane
                // angle, so use the min instead.
                if (s_MaxLines > Mathf.Min(s_TangentIteration, s_BitangentIteration) * 2)
                {
                    s_MaxLines = (int)Mathf.Min(s_TangentIteration, s_BitangentIteration) * 2;
                }

                s_GridResolution = 1;

                float dot = Vector3.Dot(cam.transform.position - pivot, Vector3.Cross(tangent, bitangent));

                if (s_MaxLines > k_MaxLines)
                {
                    if (Vector3.Distance(cam.transform.position, pivot) > 50f * snapValue && Mathf.Abs(dot) > .8f)
                    {
                        while (s_MaxLines / s_GridResolution > k_MaxLines)
                        {
                            s_GridResolution += s_GridResolution;
                        }
                    }
                    else
                    {
                        s_MaxLines = k_MaxLines;
                    }
                }
            }

            // origin, tan, bitan, increment, iterations, divOffset, color, primary alpha bump
            RebuildPlane(cam, pivot, tangent, bitangent, snapValue * s_GridResolution, s_MaxLines / s_GridResolution, s_GridResolution, color);

            return((snapValue * s_GridResolution) * (s_MaxLines / s_GridResolution));
        }
Пример #2
0
        void SnapToGrid(Transform[] transforms)
        {
            if (transforms != null && transforms.Length > 0)
            {
                Undo.RecordObjects(transforms, "Snap to Grid");

                foreach (Transform t in transforms)
                {
                    t.position = Snapping.Round(t.position, SnapValueInUnityUnits);
                }
            }

            PushToGrid(SnapValueInUnityUnits);

            DoGridRepaint();
        }
Пример #3
0
        void DoTransformSnapping(Event currentEvent, Camera camera)
        {
            if (currentEvent.type == EventType.MouseUp)
            {
                m_IsFirstMove = true;
            }

            Transform selected = m_LastActiveTransform;

            if (selected == null)
            {
                return;
            }

            bool positionMoved = !Snapping.Approx(m_LastActiveTransform.position, m_LastPosition);
            bool scaleMoved    = !Snapping.Approx(m_LastActiveTransform.localScale, m_LastScale);

            if (!GetSnapEnabled() || !EditorUtility.SnapIsEnabled(selected) || GUIUtility.hotControl < 1)
            {
                m_LastPosition = m_LastActiveTransform.position;
                m_LastScale    = m_LastActiveTransform.localScale;
                return;
            }

            if (Tools.current == Tool.Move && positionMoved)
            {
                Vector3 old  = selected.position;
                Vector3 mask = old - m_LastPosition;

                bool constraintsOn = SnapMethod == SnapMethod.SnapOnSelectedAxis;

                if (m_ToggleAxisConstraint)
                {
                    constraintsOn = !constraintsOn;
                }

                Vector3 snapped;

                if (constraintsOn)
                {
                    snapped = Snapping.Round(old, mask, m_SnapSettings.SnapValueInUnityUnits());
                }
                else
                {
                    snapped = Snapping.Round(old, m_SnapSettings.SnapValueInUnityUnits());
                }

                Vector3 snapOffset = snapped - old;

                if (m_IsFirstMove)
                {
                    Undo.RecordObjects(Selection.transforms, "Move Objects");

                    m_IsFirstMove = false;

                    if (m_PredictiveGrid && !FullGridEnabled)
                    {
                        Axis dragAxis = EditorUtility.CalcDragAxis(snapOffset, camera);

                        if (dragAxis != Axis.None && dragAxis != m_RenderPlane)
                        {
                            SetRenderPlane(dragAxis);
                        }
                    }
                }

                selected.position = snapped;

                if (m_SnapSettings.SnapAsGroup)
                {
                    EditorUtility.OffsetTransforms(Selection.transforms, selected, snapOffset);
                }
                else
                {
                    foreach (Transform t in Selection.transforms)
                    {
                        t.position = constraintsOn
                                                        ? Snapping.Round(t.position, mask, m_SnapSettings.SnapValueInUnityUnits())
                                                        : Snapping.Round(t.position, m_SnapSettings.SnapValueInUnityUnits());
                    }
                }
            }

            if (Tools.current == Tool.Scale && ScaleSnapEnabled && scaleMoved)
            {
                Vector3 old  = m_LastActiveTransform.localScale;
                Vector3 mask = old - m_LastScale;

                if (m_PredictiveGrid)
                {
                    Axis dragAxis = EditorUtility.CalcDragAxis(Selection.activeTransform.TransformDirection(mask), camera);
                    if (dragAxis != Axis.None && dragAxis != m_RenderPlane)
                    {
                        SetRenderPlane(dragAxis);
                    }
                }

                // scale snapping does not respect the SnapMethod by design
                foreach (Transform t in Selection.transforms)
                {
                    t.localScale = Snapping.Round(t.localScale, mask, m_SnapSettings.SnapValueInUnityUnits());
                }
            }

            m_LastPosition = m_LastActiveTransform.position;
            m_LastScale    = m_LastActiveTransform.localScale;
        }
Пример #4
0
        void CalculateGridPlacement(SceneView view)
        {
            var cam = view.camera;

            bool wasOrtho = gridIsOrthographic;

            gridIsOrthographic = cam.orthographic && Snapping.IsRounded(view.rotation.eulerAngles.normalized);

            m_CameraDirection = Snapping.Sign(m_Pivot - cam.transform.position);

            if (wasOrtho != gridIsOrthographic)
            {
                m_DoGridRepaint = true;

                if (view == SceneView.lastActiveSceneView && gridIsOrthographic != menuIsOrtho)
                {
                    if (gridIsOrthographic)
                    {
                        m_savedAxis     = (Axis)EditorPrefs.GetInt(PreferenceKeys.GridAxis);
                        m_savedFullGrid = EditorPrefs.GetBool(PreferenceKeys.PerspGrid);
                    }
                    else
                    {
                        SetRenderPlane(m_savedAxis);
                        FullGridEnabled = m_savedFullGrid;
                    }
                    SetMenuIsExtended(menuOpen);
                }
            }

            if (gridIsOrthographic)
            {
                return;
            }

            if (FullGridEnabled)
            {
                m_Pivot = m_GridIsLocked || Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position;
            }
            else
            {
                Vector3 sceneViewPlanePivot = m_Pivot;

                Ray   ray   = new Ray(cam.transform.position, cam.transform.forward);
                Plane plane = new Plane(Vector3.up, m_Pivot);

                // the only time a locked grid should ever move is if it's m_Pivot is out
                // of the camera's frustum.
                if ((m_GridIsLocked && !cam.InFrustum(m_Pivot)) || !m_GridIsLocked || view != SceneView.lastActiveSceneView)
                {
                    float dist;

                    if (plane.Raycast(ray, out dist))
                    {
                        sceneViewPlanePivot = ray.GetPoint(Mathf.Min(dist, m_PlaneGridDrawDistance / 2f));
                    }
                    else
                    {
                        sceneViewPlanePivot = ray.GetPoint(Mathf.Min(cam.farClipPlane / 2f, m_PlaneGridDrawDistance / 2f));
                    }
                }

                if (m_GridIsLocked)
                {
                    m_Pivot = EnumExtension.InverseAxisMask(sceneViewPlanePivot, m_RenderPlane) + EnumExtension.AxisMask(m_Pivot, m_RenderPlane);
                }
                else
                {
                    m_Pivot = Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position;

                    if (Selection.activeTransform == null || !cam.InFrustum(m_Pivot))
                    {
                        m_Pivot = EnumExtension.InverseAxisMask(sceneViewPlanePivot, m_RenderPlane) + EnumExtension.AxisMask(Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position, m_RenderPlane);
                    }
                }
            }
        }
Пример #5
0
 /// <summary>
 /// Gets the origin point of the grid. If no instance is active, this method returns zero.
 /// </summary>
 /// <returns>The origin point of the grid or zero if no instance is active.</returns>
 public static Vector3 GetPivot()
 {
     return(s_Instance == null ? Vector3.zero : Snapping.Round(s_Instance.m_Pivot, s_Instance.GetSnapValue()));
 }
Пример #6
0
        static void DrawOrthographic(Camera cam, Axis camAxis, Color color, float snapValue, float angle)
        {
            Color previousColor = Handles.color;
            Color primaryColor  = new Color(color.r, color.g, color.b, color.a + s_AlphaBump);

            Vector3 bottomLeft  = Snapping.Floor(cam.ScreenToWorldPoint(Vector2.zero), snapValue);
            Vector3 bottomRight = Snapping.Floor(cam.ScreenToWorldPoint(new Vector2(cam.pixelWidth, 0f)), snapValue);
            Vector3 topLeft     = Snapping.Floor(cam.ScreenToWorldPoint(new Vector2(0f, cam.pixelHeight)), snapValue);
            Vector3 topRight    = Snapping.Floor(cam.ScreenToWorldPoint(new Vector2(cam.pixelWidth, cam.pixelHeight)), snapValue);

            Vector3 axis = EnumExtension.VectorWithAxis(camAxis);

            float width  = Vector3.Distance(bottomLeft, bottomRight);
            float height = Vector3.Distance(bottomRight, topRight);

            // Shift lines to 10m forward of the camera
            bottomLeft  += axis * 10f;
            topRight    += axis * 10f;
            bottomRight += axis * 10f;
            topLeft     += axis * 10f;

            // Draw Vertical Lines
            Vector3 camRight = cam.transform.right;
            Vector3 camUp    = cam.transform.up;

            float snapValueAtResolution = snapValue;

            int segs = (int)Mathf.Ceil(width / snapValueAtResolution) + 2;

            float n = 2f;

            while (segs > k_MaxLines)
            {
                snapValueAtResolution = snapValueAtResolution * n;
                segs = (int)Mathf.Ceil(width / snapValueAtResolution) + 2;
                n++;
            }

            // Screen start and end
            Vector3 bl = (camRight.x + camRight.y + camRight.z) > 0
                                ? Snapping.Floor(bottomLeft, camRight, snapValueAtResolution * k_PrimaryColorIncrement)
                                : Snapping.Ceil(bottomLeft, camRight, snapValueAtResolution * k_PrimaryColorIncrement);
            Vector3 start = bl - camUp * (height + snapValueAtResolution * 2);
            Vector3 end   = bl + camUp * (height + snapValueAtResolution * 2);

            segs += k_PrimaryColorIncrement;

            // The current line start and end
            Vector3 lineStart;
            Vector3 lineEnd;

            for (int i = -1; i < segs; i++)
            {
                lineStart     = start + (i * (camRight * snapValueAtResolution));
                lineEnd       = end + (i * (camRight * snapValueAtResolution));
                Handles.color = i % k_PrimaryColorIncrement == 0 ? primaryColor : color;
                Handles.DrawLine(lineStart, lineEnd);
            }

            // Draw Horizontal Lines
            segs = (int)Mathf.Ceil(height / snapValueAtResolution) + 2;

            n = 2;
            while (segs > k_MaxLines)
            {
                snapValueAtResolution = snapValueAtResolution * n;
                segs = (int)Mathf.Ceil(height / snapValueAtResolution) + 2;
                n++;
            }

            Vector3 tl = (camUp.x + camUp.y + camUp.z) > 0
                                ? Snapping.Ceil(topLeft, camUp, snapValueAtResolution * k_PrimaryColorIncrement)
                                : Snapping.Floor(topLeft, camUp, snapValueAtResolution * k_PrimaryColorIncrement);

            start = tl - camRight * (width + snapValueAtResolution * 2);
            end   = tl + camRight * (width + snapValueAtResolution * 2);

            segs += (int)k_PrimaryColorIncrement;

            for (int i = -1; i < segs; i++)
            {
                lineStart     = start + (i * (-camUp * snapValueAtResolution));
                lineEnd       = end + (i * (-camUp * snapValueAtResolution));
                Handles.color = i % k_PrimaryColorIncrement == 0 ? primaryColor : color;
                Handles.DrawLine(lineStart, lineEnd);
            }

            if (angle > 0f)
            {
                Vector3 cen = Snapping.Round(((topRight + bottomLeft) / 2f), snapValue);

                float half = (width > height) ? width : height;

                float opposite = Mathf.Tan(Mathf.Deg2Rad * angle) * half;

                Vector3 up    = cam.transform.up * opposite;
                Vector3 right = cam.transform.right * half;

                Vector3 bottomLeftAngle = cen - (up + right);
                Vector3 topRightAngle   = cen + (up + right);

                Vector3 bottomRightAngle = cen + (right - up);
                Vector3 topLeftAngle     = cen + (up - right);

                Handles.color = primaryColor;

                // y = 1x+1
                Handles.DrawLine(bottomLeftAngle, topRightAngle);

                // y = -1x-1
                Handles.DrawLine(topLeftAngle, bottomRightAngle);
            }

            Handles.color = previousColor;
        }
Пример #7
0
        /// <summary>
        /// Draws a plane grid using pivot point, the right and forward directions, and how far each direction should extend
        /// </summary>
        /// <param name="cam"></param>
        /// <param name="pivot"></param>
        /// <param name="tan"></param>
        /// <param name="bitan"></param>
        /// <param name="increment"></param>
        /// <param name="iterations"></param>
        /// <param name="div"></param>
        /// <param name="secondary"></param>
        /// <param name="alphaBump"></param>
        static void RebuildPlane(Camera cam, Vector3 pivot, Vector3 tan, Vector3 bitan, float increment, int iterations, int div, Color secondary)
        {
            Color primary = secondary;

            primary.a += s_AlphaBump;

            float len = iterations * increment;

            iterations++;

            Vector3 start = pivot - tan * (len / 2f) - bitan * (len / 2f);

            start = Snapping.Round(start, bitan + tan, increment);

            float inc = increment;
            int   highlightOffsetTan   = (int)((EditorUtility.ValueFromMask(start, tan) % (inc * majorLineIncrement)) / inc);
            int   highlightOffsetBitan = (int)((EditorUtility.ValueFromMask(start, bitan) % (inc * majorLineIncrement)) / inc);

            Vector3[] lines   = new Vector3[iterations * 4];
            int[]     indices = new int[iterations * 4];
            Color[]   colors  = new Color[iterations * 4];

            int v = 0, t = 0;

            for (int i = 0; i < iterations; i++)
            {
                Vector3 a = start + tan * i * increment;
                Vector3 b = start + bitan * i * increment;

                lines[v + 0] = a;
                lines[v + 1] = a + bitan * len;

                lines[v + 2] = b;
                lines[v + 3] = b + tan * len;

                indices[t++] = v;
                indices[t++] = v + 1;
                indices[t++] = v + 2;
                indices[t++] = v + 3;

                Color col = (i + highlightOffsetTan) % majorLineIncrement == 0 ? primary : secondary;

                // tan
                colors[v + 0] = col;
                colors[v + 1] = col;

                col = (i + highlightOffsetBitan) % majorLineIncrement == 0 ? primary : secondary;

                // bitan
                colors[v + 2] = col;
                colors[v + 3] = col;

                v += 4;
            }

            Vector3 nrm = Vector3.Cross(tan, bitan);

            Vector3[] nrms = new Vector3[lines.Length];
            for (int i = 0; i < lines.Length; i++)
            {
                nrms[i] = nrm;
            }


            s_GridMesh.Clear();
            s_GridMesh.vertices     = lines;
            s_GridMesh.normals      = nrms;
            s_GridMesh.subMeshCount = 1;
            s_GridMesh.uv           = new Vector2[lines.Length];
            s_GridMesh.colors       = colors;
            s_GridMesh.SetIndices(indices, MeshTopology.Lines, 0);
        }
Пример #8
0
        internal static void SetPerspective3D(Camera cam, Vector3 pivot, float snapValue)
        {
            if (!s_GridMesh || !s_GridMaterial)
            {
                Init();
            }

            s_GridMaterial.SetFloat("_AlphaCutoff", 0f);
            s_GridMaterial.SetFloat("_AlphaFade", 0f);

            Vector3 camDir = (pivot - cam.transform.position).normalized;

            pivot = Snapping.Round(pivot, snapValue);

            // Used to flip the grid to match whatever direction the cam is currently
            // coming at the pivot from
            Vector3 right   = camDir.x < 0f ? Vector3.right : Vector3.right * -1f;
            Vector3 up      = camDir.y < 0f ? Vector3.up : Vector3.up * -1f;
            Vector3 forward = camDir.z < 0f ? Vector3.forward : Vector3.forward * -1f;

            // Get intersecting point for each axis, if it exists
            Ray ray_x = new Ray(pivot, right);
            Ray ray_y = new Ray(pivot, up);
            Ray ray_z = new Ray(pivot, forward);

            float x_dist = 10f, y_dist = 10f, z_dist = 10f;
            bool  x_intersect = false, y_intersect = false, z_intersect = false;

            Plane[] planes = GeometryUtility.CalculateFrustumPlanes(cam);

            foreach (Plane p in planes)
            {
                float dist;
                float t = 0;

                if (p.Raycast(ray_x, out dist))
                {
                    t = Vector3.Distance(pivot, ray_x.GetPoint(dist));
                    if (t < x_dist || !x_intersect)
                    {
                        x_intersect = true;
                        x_dist      = t;
                    }
                }

                if (p.Raycast(ray_y, out dist))
                {
                    t = Vector3.Distance(pivot, ray_y.GetPoint(dist));
                    if (t < y_dist || !y_intersect)
                    {
                        y_intersect = true;
                        y_dist      = t;
                    }
                }

                if (p.Raycast(ray_z, out dist))
                {
                    t = Vector3.Distance(pivot, ray_z.GetPoint(dist));
                    if (t < z_dist || !z_intersect)
                    {
                        z_intersect = true;
                        z_dist      = t;
                    }
                }
            }

            int x_iter = (int)(Mathf.Ceil(Mathf.Max(x_dist, y_dist)) / snapValue);
            int y_iter = (int)(Mathf.Ceil(Mathf.Max(x_dist, z_dist)) / snapValue);
            int z_iter = (int)(Mathf.Ceil(Mathf.Max(z_dist, y_dist)) / snapValue);

            int max = Mathf.Max(Mathf.Max(x_iter, y_iter), z_iter);
            int div = 1;

            while (max / div > k_MaxLines)
            {
                div++;
            }

            Vector3[] vertices_t = null;
            Vector3[] normals_t  = null;
            Color[]   colors_t   = null;
            int[]     indices_t  = null;

            List <Vector3> vertices_m = new List <Vector3>();
            List <Vector3> normals_m  = new List <Vector3>();
            List <Color>   colors_m   = new List <Color>();
            List <int>     indices_m  = new List <int>();

            // X plane
            RebuildPerspectivePlane(cam, pivot, up, right, snapValue * div, x_iter / div, gridColorX, out vertices_t, out normals_t, out colors_t, out indices_t, 0);
            vertices_m.AddRange(vertices_t);
            normals_m.AddRange(normals_t);
            colors_m.AddRange(colors_t);
            indices_m.AddRange(indices_t);

            // Y plane
            RebuildPerspectivePlane(cam, pivot, right, forward, snapValue * div, y_iter / div, gridColorY, out vertices_t, out normals_t, out colors_t, out indices_t, vertices_m.Count);
            vertices_m.AddRange(vertices_t);
            normals_m.AddRange(normals_t);
            colors_m.AddRange(colors_t);
            indices_m.AddRange(indices_t);

            // Z plane
            RebuildPerspectivePlane(cam, pivot, forward, up, snapValue * div, z_iter / div, gridColorZ, out vertices_t, out normals_t, out colors_t, out indices_t, vertices_m.Count);
            vertices_m.AddRange(vertices_t);
            normals_m.AddRange(normals_t);
            colors_m.AddRange(colors_t);
            indices_m.AddRange(indices_t);

            s_GridMesh.Clear();
            s_GridMesh.vertices     = vertices_m.ToArray();
            s_GridMesh.normals      = normals_m.ToArray();
            s_GridMesh.subMeshCount = 1;
            s_GridMesh.uv           = new Vector2[vertices_m.Count];
            s_GridMesh.colors       = colors_m.ToArray();
            s_GridMesh.SetIndices(indices_m.ToArray(), MeshTopology.Lines, 0);
        }
Пример #9
0
        void CalculateGridPlacement(SceneView view)
        {
            var cam = view.camera;

            bool wasOrtho = GridIsOrthographic;

            GridIsOrthographic = cam.orthographic && Snapping.IsRounded(view.rotation.eulerAngles.normalized);

            m_CameraDirection = Snapping.Sign(m_Pivot - cam.transform.position);

            if (GridIsOrthographic && !wasOrtho || GridIsOrthographic != menuIsOrtho)
            {
                OnSceneBecameOrtho(view == SceneView.lastActiveSceneView);
            }

            if (!GridIsOrthographic && wasOrtho)
            {
                OnSceneBecamePersp(view == SceneView.lastActiveSceneView);
            }

            if (GridIsOrthographic)
            {
                return;
            }

            if (FullGridEnabled)
            {
                m_Pivot = m_GridIsLocked || Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position;
            }
            else
            {
                Vector3 sceneViewPlanePivot = m_Pivot;

                Ray   ray   = new Ray(cam.transform.position, cam.transform.forward);
                Plane plane = new Plane(Vector3.up, m_Pivot);

                // the only time a locked grid should ever move is if it's m_Pivot is out
                // of the camera's frustum.
                if ((m_GridIsLocked && !cam.InFrustum(m_Pivot)) || !m_GridIsLocked || view != SceneView.lastActiveSceneView)
                {
                    float dist;

                    if (plane.Raycast(ray, out dist))
                    {
                        sceneViewPlanePivot = ray.GetPoint(Mathf.Min(dist, m_PlaneGridDrawDistance / 2f));
                    }
                    else
                    {
                        sceneViewPlanePivot = ray.GetPoint(Mathf.Min(cam.farClipPlane / 2f, m_PlaneGridDrawDistance / 2f));
                    }
                }

                if (m_GridIsLocked)
                {
                    m_Pivot = EnumExtension.InverseAxisMask(sceneViewPlanePivot, m_RenderPlane) + EnumExtension.AxisMask(m_Pivot, m_RenderPlane);
                }
                else
                {
                    m_Pivot = Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position;

                    if (Selection.activeTransform == null || !cam.InFrustum(m_Pivot))
                    {
                        m_Pivot = EnumExtension.InverseAxisMask(sceneViewPlanePivot, m_RenderPlane) + EnumExtension.AxisMask(Selection.activeTransform == null ? m_Pivot : Selection.activeTransform.position, m_RenderPlane);
                    }
                }
            }
        }