/// <summary>
        /// Called from ProGrids.
        /// </summary>
        /// <param name="snapVal"></param>
        void PushToGrid(float snapVal)
        {
            UndoUtility.RecordSelection(selection.ToArray(), "Push elements to Grid");

            if (selectMode == SelectMode.Object || selectMode == SelectMode.None)
            {
                return;
            }

            for (int i = 0, c = MeshSelection.selectedObjectCount; i < c; i++)
            {
                ProBuilderMesh mesh = selection[i];
                if (mesh.selectedVertexCount < 1)
                {
                    continue;
                }

                var indexes = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal);
                ProGridsSnapping.SnapVertices(mesh, indexes, Vector3.one * snapVal);

                mesh.ToMesh();
                mesh.Refresh();
                mesh.Optimize();
            }

            UpdateSelection();
        }
Beispiel #2
0
        /// <summary>
        /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled.
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public static float ProGridsSnap(float point)
        {
            if (GetProGridsType() == null)
            {
                return(point);
            }

            if (SnapEnabled())
            {
                return(ProGridsSnapping.SnapValue(point, ProGridsInterface.SnapValue()));
            }

            return(point);
        }
Beispiel #3
0
        /// <summary>
        /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled, with mask.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="mask"></param>
        /// <returns></returns>
        public static Vector3 ProGridsSnap(Vector3 point, Vector3 mask)
        {
            if (GetProGridsType() == null)
            {
                return(point);
            }

            if (ProGridsInterface.SnapEnabled())
            {
                float snap = ProGridsInterface.SnapValue();
                return(ProGridsSnapping.SnapValue(point, mask * snap));
            }

            return(point);
        }
        internal static void SetPivotLocationAndSnap(ProBuilderMesh mesh)
        {
            if (ProGridsInterface.SnapEnabled())
            {
                mesh.transform.position = ProGridsSnapping.SnapValue(mesh.transform.position, ProGridsInterface.SnapValue());
            }
            else if (s_SnapNewShapesToGrid)
            {
                mesh.transform.position = ProGridsSnapping.SnapValue(mesh.transform.position, new Vector3(
                                                                         EditorPrefs.GetFloat("MoveSnapX"),
                                                                         EditorPrefs.GetFloat("MoveSnapY"),
                                                                         EditorPrefs.GetFloat("MoveSnapZ")));
            }

            mesh.Optimize();
        }
Beispiel #5
0
        /// <summary>
        /// Return the last known grid pivot point.
        /// </summary>
        /// <param name="pivot"></param>
        /// <returns></returns>
        public static bool GetPivot(out Vector3 pivot)
        {
            pivot = Vector3.zero;

            if (s_GetPivotDelegate == null)
            {
                s_GetPivotDelegate = (Func <Vector3>)ReflectionUtility.GetOpenDelegate <Func <Vector3> >(GetProGridsType(), "GetPivot");
            }

            if (s_GetPivotDelegate != null)
            {
                pivot = s_GetPivotDelegate();

                // earlier version of progrids return a non-snapped pivot point
                pivot = ProGridsSnapping.SnapValue(pivot, SnapValue());
                return(true);
            }

            return(false);
        }
Beispiel #6
0
        void DoExistingPointsGUI()
        {
            Transform trs = polygon.transform;
            int       len = polygon.m_Points.Count;

            Vector3 up      = polygon.transform.up;
            Vector3 right   = polygon.transform.right;
            Vector3 forward = polygon.transform.forward;
            Vector3 center  = Vector3.zero;

            Event evt = Event.current;

            bool used = evt.type == EventType.Used;

            if (!used &&
                (evt.type == EventType.MouseDown &&
                 evt.button == 0 &&
                 !EditorHandleUtility.IsAppendModifier(evt.modifiers)))
            {
                m_SelectedIndex = -1;
                Repaint();
            }

            if (polygon.polyEditMode == PolyShape.PolyEditMode.Height)
            {
                if (!used && evt.type == EventType.MouseUp && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers))
                {
                    evt.Use();
                    SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                }

                bool sceneInUse = EditorHandleUtility.SceneViewInUse(evt);
                Ray  r          = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                Vector3 origin  = polygon.transform.TransformPoint(Math.Average(polygon.m_Points));
                float   extrude = polygon.extrude;

                if (evt.type == EventType.MouseMove && !sceneInUse)
                {
                    Vector3 p = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction);
                    extrude = ProGridsInterface.ProGridsSnap(s_HeightMouseOffset + Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up)));
                }

                Vector3 extrudePoint = origin + (extrude * up);

                if (m_DrawHeightHandles)
                {
                    Handles.color = k_HandleColor;
                    Handles.DotHandleCap(-1, origin, Quaternion.identity, HandleUtility.GetHandleSize(origin) * k_HandleSize, evt.type);
                    Handles.color = k_HandleColorGreen;
                    Handles.DrawLine(origin, extrudePoint);
                    Handles.DotHandleCap(-1, extrudePoint, Quaternion.identity, HandleUtility.GetHandleSize(extrudePoint) * k_HandleSize, evt.type);
                    Handles.color = Color.white;
                }

                if (!sceneInUse && polygon.extrude != extrude)
                {
                    OnBeginVertexMovement();
                    polygon.extrude = extrude;
                    RebuildPolyShapeMesh(false);
                }
            }
            else
            {
                // vertex dots
                for (int ii = 0; ii < len; ii++)
                {
                    Vector3 point = trs.TransformPoint(polygon.m_Points[ii]);

                    center.x += point.x;
                    center.y += point.y;
                    center.z += point.z;

                    float size = HandleUtility.GetHandleSize(point) * k_HandleSize;

                    Handles.color = ii == m_SelectedIndex ? k_HandleSelectedColor : k_HandleColor;

                    EditorGUI.BeginChangeCheck();

                    point = Handles.Slider2D(point, up, right, forward, size, Handles.DotHandleCap, Vector2.zero, true);

                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoUtility.RecordObject(polygon, "Move Polygon Shape Point");

                        Vector3 snapMask = ProGridsSnapping.GetSnappingMaskBasedOnNormalVector(m_Plane.normal);
                        polygon.m_Points[ii] = ProGridsInterface.ProGridsSnap(trs.InverseTransformPoint(point), snapMask);
                        OnBeginVertexMovement();
                        RebuildPolyShapeMesh(false);
                    }

                    // "clicked" a button
                    if (!used && evt.type == EventType.Used)
                    {
                        if (ii == 0 && polygon.m_Points.Count > 2 && polygon.polyEditMode == PolyShape.PolyEditMode.Path)
                        {
                            m_NextMouseUpAdvancesMode = true;
                            return;
                        }
                        else
                        {
                            used            = true;
                            m_SelectedIndex = ii;
                        }
                    }
                }

                Handles.color = Color.white;

                // height setting
                if (polygon.polyEditMode != PolyShape.PolyEditMode.Path && polygon.m_Points.Count > 2)
                {
                    center.x /= (float)len;
                    center.y /= (float)len;
                    center.z /= (float)len;

                    Vector3 extrude = center + (up * polygon.extrude);
                    m_DistanceFromHeightHandle = Vector2.Distance(HandleUtility.WorldToGUIPoint(extrude), evt.mousePosition);

                    EditorGUI.BeginChangeCheck();

                    if (m_DrawHeightHandles)
                    {
                        Handles.color = k_HandleColor;
                        Handles.DotHandleCap(-1, center, Quaternion.identity, HandleUtility.GetHandleSize(center) * k_HandleSize, evt.type);
                        Handles.DrawLine(center, extrude);
                        Handles.color = k_HandleColorGreen;
                        extrude       = Handles.Slider(extrude, up, HandleUtility.GetHandleSize(extrude) * k_HandleSize, Handles.DotHandleCap, 0f);
                        Handles.color = Color.white;
                    }

                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoUtility.RecordObject(polygon, "Set Polygon Shape Height");
                        polygon.extrude = ProGridsInterface.ProGridsSnap(Vector3.Distance(extrude, center) * Mathf.Sign(Vector3.Dot(up, extrude - center)));
                        OnBeginVertexMovement();
                        RebuildPolyShapeMesh(false);
                    }
                }
            }
        }
Beispiel #7
0
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            if (!isEditing)
            {
                m_Position = Vector3.zero;
            }

            EditorHandleUtility.PushMatrix();

            Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one);

            EditorGUI.BeginChangeCheck();

            Handles.color = Color.blue;

            m_Position = Handles.Slider2D(m_Position,
                                          Vector3.forward,
                                          Vector3.right,
                                          Vector3.up,
                                          HandleUtility.GetHandleSize(m_Position) * .2f,
                                          Handles.RectangleHandleCap,
                                          0f,
                                          false);

            Handles.color = Color.green;

            m_Position = Handles.Slider(m_Position, Vector3.up);

            Handles.color = Color.red;

            m_Position = Handles.Slider(m_Position, Vector3.right);

            Handles.color = Color.white;

            if (EditorGUI.EndChangeCheck())
            {
                if (!isEditing)
                {
                    BeginEdit("Translate Textures");
                }

                if (relativeSnapEnabled)
                {
                    m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, relativeSnapX);
                    m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, relativeSnapY);
                }
                else if (progridsSnapEnabled)
                {
                    m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, progridsSnapValue);
                    m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, progridsSnapValue);
                }

                // invert `y` because to users it's confusing that "up" in UV space visually moves the texture down
                var delta = new Vector4(m_Position.x, -m_Position.y, 0f, 0f);

                foreach (var value in elementSelection)
                {
                    var selection = value as TranslateTextureSelection;

                    if (selection == null)
                    {
                        continue;
                    }

                    // Account for object scale
                    delta *= k_Vector3Magnitude / selection.mesh.transform.lossyScale.magnitude;

                    var origins   = selection.origins;
                    var positions = selection.textures;

                    // Translating faces is treated as a special case because we want the textures in scene to visually
                    // match the movement of the translation handle. When UVs are scaled, they have the appearance of
                    // moving faster or slower (even though they are translating the correct distances). To avoid this,
                    // we cache the UV scale of each face and modify the translation delta accordingly. This isn't perfect,
                    // as it will not be able to find the scale for sheared or otherwise distorted face UVs. However, for
                    // most cases it maps quite well.
                    if (ProBuilderEditor.selectMode == SelectMode.TextureFace)
                    {
                        foreach (var face in selection.faceAndScale)
                        {
                            var faceDelta = new Vector4(delta.x / face.item2.x, delta.y / face.item2.y, 0f, 0f);

                            foreach (var index in face.item1.distinctIndexes)
                            {
                                positions[index] = origins[index] + faceDelta;
                            }
                        }
                    }
                    else
                    {
                        foreach (var group in value.elementGroups)
                        {
                            foreach (var index in group.indices)
                            {
                                positions[index] = origins[index] + delta;
                            }
                        }
                    }

                    selection.mesh.mesh.SetUVs(k_TextureChannel, positions);
                }
            }

            EditorHandleUtility.PopMatrix();
        }
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            if (!isEditing)
            {
                m_Rotation = 0f;
            }

            EditorGUI.BeginChangeCheck();

            var size = HandleUtility.GetHandleSize(handlePosition);

            EditorHandleUtility.PushMatrix();

            Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one);

            Handles.color = Color.blue;
            m_Euler.z     = m_Rotation;
            m_Quaternion  = Quaternion.Euler(m_Euler);
            m_Quaternion  = Handles.Disc(m_Quaternion, Vector3.zero, Vector3.forward, size, relativeSnapEnabled, relativeSnapRotation);
            m_Euler       = m_Quaternion.eulerAngles;
            m_Rotation    = m_Euler.z;

            EditorHandleUtility.PopMatrix();

            if (EditorGUI.EndChangeCheck())
            {
                if (!isEditing)
                {
                    BeginEdit("Rotate Textures");
                }

                if (relativeSnapEnabled)
                {
                    m_Rotation = ProGridsSnapping.SnapValue(m_Rotation, relativeSnapX);
                }
                else if (progridsSnapEnabled)
                {
                    m_Rotation = ProGridsSnapping.SnapValue(m_Rotation, progridsSnapValue);
                }

                foreach (var mesh in elementSelection)
                {
                    if (!(mesh is MeshAndTextures))
                    {
                        continue;
                    }
                    var mat = (MeshAndTextures)mesh;

                    var origins   = mat.origins;
                    var positions = mat.textures;

                    foreach (var group in mat.elementGroups)
                    {
                        foreach (var index in group.indices)
                        {
                            positions[index] = mat.postApplyMatrix.MultiplyPoint(
                                Math.RotateAroundPoint(
                                    mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), Vector2.zero, -m_Rotation));
                        }
                    }

                    mesh.mesh.mesh.SetUVs(k_TextureChannel, positions);
                }
            }
        }
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            base.DoTool(handlePosition, handleRotation);

            if (!isEditing)
            {
                m_HandlePosition = handlePosition;
            }

#if PROBUILDER_ENABLE_TRANSFORM_ORIGIN_GIZMO
            if (isEditing)
            {
                DrawSelectionOriginGizmos();
            }
#endif

            EditorGUI.BeginChangeCheck();

            m_HandlePosition = Handles.PositionHandle(m_HandlePosition, handleRotation);

            m_RawHandleDelta = m_HandlePosition - handlePositionOrigin;

            var delta = m_RawHandleDelta;

            if (EditorGUI.EndChangeCheck() && delta.sqrMagnitude > k_MinTranslateDeltaSqrMagnitude)
            {
                if (!isEditing)
                {
                    BeginEdit("Translate Selection");
                }

                if (vertexDragging)
                {
                    Vector3 nearest;

                    if (FindNearestVertex(currentEvent.mousePosition, out nearest))
                    {
                        var unrotated = handleRotationOriginInverse * delta;
                        var dir       = new Vector3Mask(unrotated, k_CardinalAxisError);

                        if (dir.active == 1)
                        {
                            var rotationDirection = handleRotationOrigin * dir * 10000f;

                            m_HandlePosition = HandleUtility.ProjectPointLine(nearest,
                                                                              handlePositionOrigin + rotationDirection,
                                                                              handlePositionOrigin - rotationDirection);

                            delta = m_HandlePosition - handlePositionOrigin;
                        }
                    }
                }
                else if (progridsSnapEnabled)
                {
                    if (snapAxisConstraint)
                    {
                        m_ActiveAxesModel |= new Vector3Mask(handleRotationOriginInverse * delta, k_CardinalAxisError);
                        m_ActiveAxesWorld  = new Vector3Mask(handleRotation * m_ActiveAxesModel);

                        if (m_ActiveAxesWorld.active == 1)
                        {
                            m_HandlePosition = ProGridsSnapping.SnapValueOnRay(
                                new Ray(handlePositionOrigin, delta),
                                delta.magnitude,
                                progridsSnapValue,
                                m_ActiveAxesWorld);
                        }
                        else
                        {
                            m_HandlePosition = ProGridsSnapping.SnapValue(m_HandlePosition, progridsSnapValue);
                        }
                    }
                    else
                    {
                        m_HandlePosition = ProGridsSnapping.SnapValue(m_HandlePosition, progridsSnapValue);
                    }

                    delta = m_HandlePosition - handlePositionOrigin;
                }

#if PROBUILDER_ENABLE_TRANSFORM_ORIGIN_GIZMO
                if (pivotPoint == PivotPoint.IndividualOrigins && !m_DirectionOriginInitialized)
                {
                    var mask = new Vector3Mask(handleRotationOriginInverse * delta, k_CardinalAxisError);

                    if (mask.active > 0)
                    {
                        m_IndividualOriginDirection  = mask;
                        m_DirectionOriginInitialized = true;
                    }
                }
#endif

                ApplyTranslation(handleRotationOriginInverse * delta);
            }

            // Draw at the end so we get the snapped value
            if (showHandleInfo && isEditing)
            {
                DrawDeltaInfo(string.Format("Translate: <b>{0:F2}</b>  {1}", delta.magnitude, (handleRotationOriginInverse * delta).ToString("0.00")));
            }
        }
        void ApplyTranslation(Vector3 translation)
        {
            var translationMagnitude = translation.magnitude;

            foreach (var key in elementSelection)
            {
                if (!(key is MeshAndPositions))
                {
                    continue;
                }

                var kvp          = (MeshAndPositions)key;
                var mesh         = kvp.mesh;
                var worldToLocal = mesh.transform.worldToLocalMatrix;
                var origins      = kvp.positions;
                var positions    = mesh.positionsInternal;

                foreach (var group in kvp.elementGroups)
                {
                    var postApplyMatrix = GetPostApplyMatrix(group);
                    var preApplyMatrix  = postApplyMatrix.inverse;

                    foreach (var index in group.indices)
                    {
                        // res = Group pre-apply matrix * world vertex position
                        // res += translation
                        // res = Group post-apply matrix * res
                        // positions[i] = mesh.worldToLocal * res
                        if (progridsSnapEnabled && !m_SnapAsGroup)
                        {
                            if (snapAxisConstraint && m_ActiveAxesWorld.active == 1)
                            {
                                var wp = postApplyMatrix.MultiplyPoint3x4(preApplyMatrix.MultiplyPoint3x4(origins[index]));

                                var snap = ProGridsSnapping.SnapValueOnRay(
                                    new Ray(wp, m_RawHandleDelta),
                                    translationMagnitude,
                                    progridsSnapValue,
                                    m_ActiveAxesWorld);

                                positions[index] = worldToLocal.MultiplyPoint3x4(snap);
                            }
                            else
                            {
                                var wp   = postApplyMatrix.MultiplyPoint3x4(translation + preApplyMatrix.MultiplyPoint3x4(origins[index]));
                                var snap = ProGridsSnapping.SnapValue(wp, Vector3.one * progridsSnapValue);
                                positions[index] = worldToLocal.MultiplyPoint3x4(snap);
                            }
                        }
                        else
                        {
                            positions[index] = worldToLocal.MultiplyPoint3x4(
                                postApplyMatrix.MultiplyPoint3x4(
                                    translation + preApplyMatrix.MultiplyPoint3x4(origins[index])));
                        }
                    }
                }

                mesh.mesh.vertices = positions;
                mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]);
                mesh.Refresh(RefreshMask.Normals);
            }

            ProBuilderEditor.Refresh(false);
        }