Esempio n. 1
0
        public void SetManualFaceToAuto_MatchesOriginalUVs(
            [ValueSource("AutoUVOffsetParameters")] Vector2 offset,
            [ValueSource("AutoUVRotationParameters")] float rotation,
            [ValueSource("AutoUVScaleParameters")] Vector2 scale)
        {
            var unwrap = face.uv;

            unwrap.offset   = offset;
            unwrap.rotation = rotation;
            unwrap.scale    = scale;

            face.uv = unwrap;

            // Verify that UV settings have actually been applied
            Assume.That(face.uv.offset, Is.EqualTo(offset));
            Assume.That(face.uv.rotation, Is.EqualTo(rotation));
            Assume.That(face.uv.scale, Is.EqualTo(scale));
            Assume.That(face.manualUV, Is.EqualTo(false));

            mesh.Refresh(RefreshMask.UV);

            // Verify that the UVs are in the correct place
            Assume.That(GetEdgeRotation(mesh, verticalEdge), Is.EqualTo(rotation).Within(.1f));
            Assume.That(GetEdgeScale(mesh, verticalEdge), Is.EqualTo(scale.y).Within(.1f));
            Assume.That(GetEdgeScale(mesh, horizontalEdge), Is.EqualTo(scale.x).Within(.1f));
            // Offset is flipped in code for legacy reasons
            var center = Bounds2D.Center(mesh.texturesInternal, face.distinctIndexesInternal);

            Assume.That(center.x, Is.EqualTo(-offset.x).Within(.1f));
            Assume.That(center.y, Is.EqualTo(-offset.y).Within(.1f));

            face.uv       = AutoUnwrapSettings.defaultAutoUnwrapSettings;
            face.manualUV = true;

            // Verify that UV settings have been reset
            Assume.That(face.uv.offset, Is.EqualTo(new Vector2(0f, 0f)));
            Assume.That(face.uv.rotation, Is.EqualTo(0f));
            Assume.That(face.uv.scale, Is.EqualTo(new Vector2(1f, 1f)));
            Assume.That(face.manualUV, Is.EqualTo(true));

            // This sets the manualFlag to false, sets the AutoUnwrap settings, and rebuilds UVs
            UVEditing.SetAutoAndAlignUnwrapParamsToUVs(mesh, new [] { face });

            Assert.That(face.uv.offset.x, Is.EqualTo(offset.x).Within(.1f));
            Assert.That(face.uv.offset.y, Is.EqualTo(offset.y).Within(.1f));
            Assert.That(face.uv.rotation, Is.EqualTo(rotation).Within(.1f));
            Assert.That(face.uv.scale.x, Is.EqualTo(scale.x).Within(.1f));
            Assert.That(face.uv.scale.y, Is.EqualTo(scale.y).Within(.1f));
            Assert.That(face.manualUV, Is.EqualTo(false));
        }
Esempio n. 2
0
            public override ProBuilderMesh Build(bool isPreview = false)
            {
                var mesh = ShapeGenerator.GenerateTorus(
                    EditorUtility.newShapePivotLocation,
                    s_Rows,
                    s_Columns,
                    s_Radius,
                    s_TubeRadius,
                    s_Smooth,
                    s_HorizontalCirumference,
                    s_VerticalCircumference,
                    true);

                UVEditing.ProjectFacesBox(mesh, mesh.facesInternal);

                return(mesh);
            }
Esempio n. 3
0
            public override ProBuilderMesh Build(bool preview = false)
            {
                // To keep the preview snappy, shared indexes aren't built in IcosahadreonGenerator
                var mesh = ShapeGenerator.GenerateIcosahedron(
                    EditorUtility.newShapePivotLocation,
                    s_Radius,
                    s_Subdivisions,
                    !preview);

                if (!preview)
                {
                    UVEditing.ProjectFacesBox(mesh, mesh.facesInternal);
                }

                for (int i = 0; i < mesh.facesInternal.Length; i++)
                {
                    mesh.facesInternal[i].manualUV = true;
                }

                return(mesh);
            }
Esempio n. 4
0
        protected override void OnToolDisengaged()
        {
            var isFaceMode = ProBuilderEditor.selectMode.ContainsFlag(SelectMode.TextureFace | SelectMode.Face);

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

                var textures = ((MeshAndTextures)mesh).textures;
                mesh.mesh.SetUVs(k_TextureChannel, textures);

                if (isFaceMode)
                {
                    UVEditing.SetAutoAndAlignUnwrapParamsToUVs(mesh.mesh, mesh.mesh.selectedFacesInternal.Where(x => !x.manualUV));
                }
                else
                {
                    var indices = new HashSet <int>(mesh.elementGroups.SelectMany(x => x.indices));

                    foreach (var face in mesh.mesh.facesInternal)
                    {
                        foreach (var index in face.distinctIndexesInternal)
                        {
                            if (indices.Contains(index))
                            {
                                face.manualUV = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
Esempio n. 5
0
        public override Bounds RebuildMesh(ProBuilderMesh mesh, Vector3 size, Quaternion rotation)
        {
            var meshSize = Math.Abs(rotation * size);

            var   xOuterRadius      = Mathf.Clamp(meshSize.x / 2f, .01f, 2048f);
            var   yOuterRadius      = Mathf.Clamp(meshSize.z / 2f, .01f, 2048f);
            int   clampedRows       = Mathf.Clamp(m_Rows + 1, 4, 128);
            int   clampedColumns    = Mathf.Clamp(m_Columns + 1, 4, 128);
            float clampedTubeRadius = Mathf.Clamp(m_TubeRadius, .01f, Mathf.Min(xOuterRadius, yOuterRadius) - .001f);

            xOuterRadius -= clampedTubeRadius;
            yOuterRadius -= clampedTubeRadius;
            float clampedHorizontalCircumference = Mathf.Clamp(m_HorizontalCircumference, .01f, 360f);
            float clampedVerticalCircumference   = Mathf.Clamp(m_VerticalCircumference, .01f, 360f);

            List <Vector3> vertices = new List <Vector3>();

            int col = clampedColumns - 1;

            float clampedRadius = xOuterRadius;

            Vector3[] cir = GetCirclePoints(clampedRows, clampedTubeRadius, clampedVerticalCircumference, Quaternion.Euler(0, 0, 0), clampedRadius);

            Vector2 ellipseCoord;

            for (int i = 1; i < clampedColumns; i++)
            {
                vertices.AddRange(cir);
                float angle = (i / (float)col) * clampedHorizontalCircumference;
                //Compute the coordinates of the current point
                ellipseCoord = new Vector2(xOuterRadius * Mathf.Cos(Mathf.Deg2Rad * angle),
                                           yOuterRadius * Mathf.Sin(Mathf.Deg2Rad * angle));

                //Compute the tangent direction to know how to orient the current slice
                var        tangent = new Vector2(-ellipseCoord.y / (yOuterRadius * yOuterRadius), ellipseCoord.x / (xOuterRadius * xOuterRadius));
                Quaternion rot     = Quaternion.Euler(Vector3.up * Vector2.SignedAngle(Vector2.up, tangent.normalized));

                //Get the slice/circle that must be placed at this position
                cir = GetCirclePoints(clampedRows, clampedTubeRadius, clampedVerticalCircumference, rot, new Vector3(ellipseCoord.x, 0, -ellipseCoord.y));
                vertices.AddRange(cir);
            }

            List <Face> faces = new List <Face>();
            int         fc    = 0;

            // faces
            for (int i = 0; i < (clampedColumns - 1) * 2; i += 2)
            {
                for (int n = 0; n < clampedRows - 1; n++)
                {
                    int a = (i + 0) * ((clampedRows - 1) * 2) + (n * 2);
                    int b = (i + 1) * ((clampedRows - 1) * 2) + (n * 2);

                    int c = (i + 0) * ((clampedRows - 1) * 2) + (n * 2) + 1;
                    int d = (i + 1) * ((clampedRows - 1) * 2) + (n * 2) + 1;

                    faces.Add(new Face(new int[] { a, b, c, b, d, c }));
                    faces[fc].smoothingGroup = m_Smooth ? 1 : -1;
                    faces[fc].manualUV       = true;

                    fc++;
                }
            }

            for (int i = 0; i < vertices.Count; ++i)
            {
                vertices[i] = rotation * vertices[i];
            }

            mesh.RebuildWithPositionsAndFaces(vertices, faces);

            mesh.TranslateVerticesInWorldSpace(mesh.mesh.triangles, mesh.transform.TransformDirection(-mesh.mesh.bounds.center));
            mesh.Refresh();

            UVEditing.ProjectFacesBox(mesh, mesh.facesInternal);

            return(UpdateBounds(mesh, size, rotation, new Bounds()));
        }
        public static bool OnGUI(ProBuilderMesh[] selection, float width)
        {
            UpdateDiffDictionary(selection);

            s_ScrollPosition = EditorGUILayout.BeginScrollView(s_ScrollPosition);
            float tempFloat = 0f;

            EditorGUI.BeginChangeCheck();

            /**
             * Set Tile mode
             */
            GUILayout.Label("Tiling & Alignment", EditorStyles.boldLabel);

            GUILayout.BeginHorizontal();
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["fill"];
            GUILayout.Label("Fill Mode", GUILayout.MaxWidth(80), GUILayout.MinWidth(80));
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.fill = (AutoUnwrapSettings.Fill)EditorGUILayout.EnumPopup(s_AutoUVSettings.fill);
            if (EditorGUI.EndChangeCheck())
            {
                SetFill(s_AutoUVSettings.fill, selection);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            bool enabled = GUI.enabled;

            GUI.enabled = !s_AutoUVSettings.useWorldSpace;
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["anchor"];
            EditorGUI.BeginChangeCheck();
            GUILayout.Label("Anchor", GUILayout.MaxWidth(80), GUILayout.MinWidth(80));
            s_AutoUVSettings.anchor = (AutoUnwrapSettings.Anchor)EditorGUILayout.EnumPopup(s_AutoUVSettings.anchor);
            if (EditorGUI.EndChangeCheck())
            {
                SetAnchor(s_AutoUVSettings.anchor, selection);
            }
            GUI.enabled = enabled;
            GUILayout.EndHorizontal();

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;

            GUILayout.Label("Transform", EditorStyles.boldLabel);

            /**
             * Offset
             */
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["offsetx"] || s_AutoUVSettingsDiff["offsety"];
            var tempVec2 = s_AutoUVSettings.offset;

            UnityEngine.GUI.SetNextControlName("offset");
            s_AutoUVSettings.offset = EditorGUILayout.Vector2Field("Offset", s_AutoUVSettings.offset, GUILayout.MaxWidth(width));
            if (tempVec2.x != s_AutoUVSettings.offset.x)
            {
                SetOffset(s_AutoUVSettings.offset, Axis2D.X, selection);
            }
            if (tempVec2.y != s_AutoUVSettings.offset.y)
            {
                SetOffset(s_AutoUVSettings.offset, Axis2D.Y, selection);
            }

            /**
             * Rotation
             */
            tempFloat = s_AutoUVSettings.rotation;
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["rotation"];
            GUILayout.Label(new GUIContent("Rotation", "Rotation around the center of face UV bounds."), GUILayout.MaxWidth(width - 64));
            UnityEngine.GUI.SetNextControlName("rotation");
            EditorGUI.BeginChangeCheck();
            tempFloat = EditorGUILayout.Slider(tempFloat, 0f, 360f, GUILayout.MaxWidth(width));
            if (EditorGUI.EndChangeCheck())
            {
                SetRotation(tempFloat, selection);
            }

            /**
             * Scale
             */
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["scalex"] || s_AutoUVSettingsDiff["scaley"];
            tempVec2 = s_AutoUVSettings.scale;
            GUI.SetNextControlName("scale");
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.scale = EditorGUILayout.Vector2Field("Tiling", s_AutoUVSettings.scale, GUILayout.MaxWidth(width));

            if (EditorGUI.EndChangeCheck())
            {
                if (tempVec2.x != s_AutoUVSettings.scale.x)
                {
                    SetScale(s_AutoUVSettings.scale, Axis2D.X, selection);
                }
                if (tempVec2.y != s_AutoUVSettings.scale.y)
                {
                    SetScale(s_AutoUVSettings.scale, Axis2D.Y, selection);
                }
            }

            // Draw tiling shortcuts
            GUILayout.BeginHorizontal();
            if (GUILayout.Button(".5", EditorStyles.miniButtonLeft))
            {
                SetScale(Vector2.one * 2f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("1", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one, Axis2D.XY, selection);
            }
            if (GUILayout.Button("2", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .5f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("4", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .25f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("8", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .125f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("16", EditorStyles.miniButtonRight))
            {
                SetScale(Vector2.one * .0625f, Axis2D.XY, selection);
            }
            GUILayout.EndHorizontal();

            GUILayout.Space(4);

            UnityEngine.GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            UnityEngine.GUI.backgroundColor = Color.white;

            /**
             * Special
             */
            GUILayout.Label("Special", EditorStyles.boldLabel);

            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["useWorldSpace"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.useWorldSpace = EditorGUILayout.Toggle("World Space", s_AutoUVSettings.useWorldSpace);
            if (EditorGUI.EndChangeCheck())
            {
                SetUseWorldSpace(s_AutoUVSettings.useWorldSpace, selection);
            }

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;


            // Flip U
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipU"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.flipU = EditorGUILayout.Toggle("Flip U", s_AutoUVSettings.flipU);
            if (EditorGUI.EndChangeCheck())
            {
                SetFlipU(s_AutoUVSettings.flipU, selection);
            }

            // Flip V
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipV"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.flipV = EditorGUILayout.Toggle("Flip V", s_AutoUVSettings.flipV);
            if (EditorGUI.EndChangeCheck())
            {
                SetFlipV(s_AutoUVSettings.flipV, selection);
            }

            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["swapUV"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.swapUV = EditorGUILayout.Toggle("Swap U/V", s_AutoUVSettings.swapUV);
            if (EditorGUI.EndChangeCheck())
            {
                SetSwapUV(s_AutoUVSettings.swapUV, selection);
            }

            /**
             * Texture Groups
             */
            GUILayout.Label("Texture Groups", EditorStyles.boldLabel);

            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["textureGroup"];

            GUI.SetNextControlName("textureGroup");
            textureGroup = UI.EditorGUIUtility.IntFieldConstrained(new GUIContent("Texture Group", "Faces in a texture group will be UV mapped as a group, just as though you had selected these faces and used the \"Planar Project\" action"), textureGroup, (int)width);

            if (EditorGUI.EndChangeCheck())
            {
                SetTextureGroup(selection, textureGroup);

                foreach (var kvp in MeshSelection.selectedFacesInEditZone)
                {
                    kvp.Key.RefreshUV(kvp.Value);
                }

                SceneView.RepaintAll();

                s_AutoUVSettingsDiff["textureGroup"] = false;
            }

            if (GUILayout.Button(new GUIContent("Group Selected Faces", "This sets all selected faces to share a texture group.  What that means is that the UVs on these faces will all be projected as though they are a single plane.  Ideal candidates for texture groups are floors with multiple faces, walls with edge loops, flat surfaces, etc.")))
            {
                for (int i = 0; i < selection.Length; i++)
                {
                    TextureGroupSelectedFaces(selection[i]);
                }

                ProBuilderEditor.Refresh();
            }

            if (GUILayout.Button(new GUIContent("Break Selected Groups", "This resets all the selected face Texture Groups.")))
            {
                SetTextureGroup(selection, -1);

                foreach (var kvp in MeshSelection.selectedFacesInEditZone)
                {
                    kvp.Key.ToMesh();
                    kvp.Key.Refresh();
                    kvp.Key.Optimize();
                }

                SceneView.RepaintAll();

                s_AutoUVSettingsDiff["textureGroup"] = false;

                ProBuilderEditor.Refresh();
            }

            /* Select all in current texture group */
            if (GUILayout.Button(new GUIContent("Select Texture Group", "Selects all faces contained in this texture group.")))
            {
                for (int i = 0; i < selection.Length; i++)
                {
                    selection[i].SetSelectedFaces(System.Array.FindAll(selection[i].facesInternal, x => x.textureGroup == textureGroup));
                }

                ProBuilderEditor.Refresh();
            }

            if (GUILayout.Button(new GUIContent("Reset UVs", "Reset UV projection parameters.")))
            {
                UndoUtility.RecordSelection(selection, "Reset UVs");

                for (int i = 0; i < selection.Length; i++)
                {
                    foreach (Face face in selection[i].GetSelectedFaces())
                    {
                        face.uv           = AutoUnwrapSettings.tile;
                        face.textureGroup = -1;
                        face.elementGroup = -1;
                    }

                    UVEditing.SplitUVs(selection[i], selection[i].GetSelectedFaces());
                }

                ProBuilderEditor.Refresh();
            }

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;

            /**
             * Clean up
             */
            GUILayout.EndScrollView();
            EditorGUI.showMixedValue = false;

            return(EditorGUI.EndChangeCheck());
        }
Esempio n. 7
0
            public TranslateTextureSelection(ProBuilderMesh mesh, PivotPoint pivot, HandleOrientation orientation)
                : base(mesh, pivot, orientation)
            {
                var faces = mesh.faces;

                m_FaceAndScale = mesh.selectedFaceIndexes.Select(x =>
                                                                 new SimpleTuple <Face, Vector2>(faces[x], UVEditing.GetUVTransform(mesh, faces[x]).scale))
                                 .ToArray();
            }
Esempio n. 8
0
        public static bool OnGUI(ProBuilderMesh[] selection, float width)
        {
            UpdateDiffDictionary(selection);

            s_ScrollPosition = EditorGUILayout.BeginScrollView(s_ScrollPosition);
            float tempFloat = 0f;

            EditorGUI.BeginChangeCheck();

            // Set Tile mode
            GUILayout.Label("Tiling & Alignment", EditorStyles.boldLabel);

            GUILayout.BeginHorizontal();
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["fill"];
            GUILayout.Label(gc_FillMode, GUILayout.MaxWidth(80), GUILayout.MinWidth(80));
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.fill = (AutoUnwrapSettings.Fill)EditorGUILayout.EnumPopup(s_AutoUVSettings.fill);
            if (EditorGUI.EndChangeCheck())
            {
                SetFill(s_AutoUVSettings.fill, selection);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            bool enabled = GUI.enabled;

            GUI.enabled = !s_AutoUVSettings.useWorldSpace;
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["anchor"];
            EditorGUI.BeginChangeCheck();
            GUILayout.Label(gc_Anchor, GUILayout.MaxWidth(80), GUILayout.MinWidth(80));
            s_AutoUVSettings.anchor = (AutoUnwrapSettings.Anchor)EditorGUILayout.EnumPopup(s_AutoUVSettings.anchor);
            if (EditorGUI.EndChangeCheck())
            {
                SetAnchor(s_AutoUVSettings.anchor, selection);
            }
            GUI.enabled = enabled;
            GUILayout.EndHorizontal();

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;

            GUILayout.Label("Transform", EditorStyles.boldLabel);

            //Offset
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["offsetx"] || s_AutoUVSettingsDiff["offsety"];
            var tempVec2 = s_AutoUVSettings.offset;

            UnityEngine.GUI.SetNextControlName("offset");
            s_AutoUVSettings.offset = EditorGUILayout.Vector2Field(gc_Offset, s_AutoUVSettings.offset, GUILayout.MaxWidth(width));
            if (tempVec2.x != s_AutoUVSettings.offset.x)
            {
                SetOffset(s_AutoUVSettings.offset, Axis2D.X, selection);
            }
            if (tempVec2.y != s_AutoUVSettings.offset.y)
            {
                SetOffset(s_AutoUVSettings.offset, Axis2D.Y, selection);
            }

            // Rotation
            tempFloat = s_AutoUVSettings.rotation;
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["rotation"];
            GUILayout.Label(gc_Rotation, GUILayout.MaxWidth(width - 64));
            UnityEngine.GUI.SetNextControlName("rotation");
            EditorGUI.BeginChangeCheck();
            tempFloat = EditorGUILayout.Slider(tempFloat, 0f, 360f, GUILayout.MaxWidth(width));
            if (EditorGUI.EndChangeCheck())
            {
                SetRotation(tempFloat, selection);
            }

            // Scale
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["scalex"] || s_AutoUVSettingsDiff["scaley"];
            tempVec2 = s_AutoUVSettings.scale;
            GUI.SetNextControlName("scale");
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.scale = EditorGUILayout.Vector2Field(gc_Tiling, s_AutoUVSettings.scale, GUILayout.MaxWidth(width));

            if (EditorGUI.EndChangeCheck())
            {
                if (tempVec2.x != s_AutoUVSettings.scale.x)
                {
                    SetScale(s_AutoUVSettings.scale, Axis2D.X, selection);
                }
                if (tempVec2.y != s_AutoUVSettings.scale.y)
                {
                    SetScale(s_AutoUVSettings.scale, Axis2D.Y, selection);
                }
            }

            // Draw tiling shortcuts
            GUILayout.BeginHorizontal();
            if (GUILayout.Button(".5", EditorStyles.miniButtonLeft))
            {
                SetScale(Vector2.one * 2f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("1", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one, Axis2D.XY, selection);
            }
            if (GUILayout.Button("2", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .5f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("4", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .25f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("8", EditorStyles.miniButtonMid))
            {
                SetScale(Vector2.one * .125f, Axis2D.XY, selection);
            }
            if (GUILayout.Button("16", EditorStyles.miniButtonRight))
            {
                SetScale(Vector2.one * .0625f, Axis2D.XY, selection);
            }
            GUILayout.EndHorizontal();

            GUILayout.Space(4);

            UnityEngine.GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            UnityEngine.GUI.backgroundColor = Color.white;

            // Special
            GUILayout.Label("Special", EditorStyles.boldLabel);

            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["useWorldSpace"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.useWorldSpace = EditorGUILayout.Toggle(gc_WorldSpace, s_AutoUVSettings.useWorldSpace);
            if (EditorGUI.EndChangeCheck())
            {
                SetUseWorldSpace(s_AutoUVSettings.useWorldSpace, selection);
            }

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;


            // Flip U
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipU"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.flipU = EditorGUILayout.Toggle(gc_FlipU, s_AutoUVSettings.flipU);
            if (EditorGUI.EndChangeCheck())
            {
                SetFlipU(s_AutoUVSettings.flipU, selection);
            }

            // Flip V
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipV"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.flipV = EditorGUILayout.Toggle(gc_FlipV, s_AutoUVSettings.flipV);
            if (EditorGUI.EndChangeCheck())
            {
                SetFlipV(s_AutoUVSettings.flipV, selection);
            }

            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["swapUV"];
            EditorGUI.BeginChangeCheck();
            s_AutoUVSettings.swapUV = EditorGUILayout.Toggle(gc_SwapUV, s_AutoUVSettings.swapUV);
            if (EditorGUI.EndChangeCheck())
            {
                SetSwapUV(s_AutoUVSettings.swapUV, selection);
            }

            // Texture Groups
            GUILayout.Label("Texture Groups", EditorStyles.boldLabel);

            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = s_AutoUVSettingsDiff["textureGroup"];

            GUI.SetNextControlName("textureGroup");
            textureGroup = UI.EditorGUIUtility.IntFieldConstrained(gc_TextureGroup, textureGroup, (int)width);

            if (EditorGUI.EndChangeCheck())
            {
                SetTextureGroup(selection, textureGroup);

                foreach (var kvp in MeshSelection.selectedFacesInEditZone)
                {
                    kvp.Key.RefreshUV(kvp.Value);
                }

                SceneView.RepaintAll();

                s_AutoUVSettingsDiff["textureGroup"] = false;
            }

            if (GUILayout.Button(gc_GroupSelected))
            {
                for (int i = 0; i < selection.Length; i++)
                {
                    TextureGroupSelectedFaces(selection[i]);
                }

                ProBuilderEditor.Refresh();
            }

            if (GUILayout.Button(gc_BreakSelected))
            {
                SetTextureGroup(selection, -1);

                foreach (var kvp in MeshSelection.selectedFacesInEditZone)
                {
                    kvp.Key.ToMesh();
                    kvp.Key.Refresh();
                    kvp.Key.Optimize();
                }

                SceneView.RepaintAll();

                s_AutoUVSettingsDiff["textureGroup"] = false;

                ProBuilderEditor.Refresh();
            }

            /* Select all in current texture group */
            if (GUILayout.Button(gc_SelectGroup))
            {
                for (int i = 0; i < selection.Length; i++)
                {
                    selection[i].SetSelectedFaces(System.Array.FindAll(selection[i].facesInternal, x => x.textureGroup == textureGroup));
                }

                ProBuilderEditor.Refresh();
            }

            if (GUILayout.Button(gc_Reset))
            {
                UndoUtility.RecordSelection(selection, "Reset UVs");

                for (int i = 0; i < selection.Length; i++)
                {
                    foreach (Face face in selection[i].GetSelectedFaces())
                    {
                        face.uv           = AutoUnwrapSettings.tile;
                        face.textureGroup = -1;
                        face.elementGroup = -1;
                    }

                    UVEditing.SplitUVs(selection[i], selection[i].GetSelectedFaces());
                }

                ProBuilderEditor.Refresh();
            }

            GUI.backgroundColor = PreferenceKeys.proBuilderLightGray;
            UI.EditorGUIUtility.DrawSeparator(1);
            GUI.backgroundColor = Color.white;

            GUILayout.EndScrollView();
            EditorGUI.showMixedValue = false;

            return(EditorGUI.EndChangeCheck());
        }