示例#1
0
        internal void DuplicatePreview(Vector3 position)
        {
            if (position.Equals(Vector3.positiveInfinity) || !Event.current.isMouse)
            {
                return;
            }

            var pivotLocation = (PivotLocation)s_LastPivotLocation.value;
            var size          = currentShapeInOverlay.size;

            m_Bounds.size = size;

            Vector3 cornerPosition;

            switch (pivotLocation)
            {
            case PivotLocation.FirstCorner:
                cornerPosition  = GetPoint(position);
                m_PlaneRotation = Quaternion.LookRotation(m_PlaneForward, m_Plane.normal);
                m_Bounds.center = cornerPosition + m_PlaneRotation * size / 2f;

                m_BB_Origin         = cornerPosition;
                m_BB_HeightCorner   = m_Bounds.center + m_PlaneRotation * (size / 2f);
                m_BB_OppositeCorner = m_BB_HeightCorner - m_PlaneRotation * new Vector3(0, size.y, 0);
                break;

            case PivotLocation.Center:
            default:
                position         = GetPoint(position);
                cornerPosition   = position - size / 2f;
                cornerPosition.y = position.y;
                m_Bounds.center  = cornerPosition + new Vector3(size.x / 2f, 0, size.z / 2f) + (size.y / 2f) * m_Plane.normal;
                m_PlaneRotation  = Quaternion.LookRotation(m_PlaneForward, m_Plane.normal);

                m_BB_Origin         = m_Bounds.center - m_PlaneRotation * (size / 2f);
                m_BB_HeightCorner   = m_Bounds.center + m_PlaneRotation * (size / 2f);
                m_BB_OppositeCorner = m_BB_HeightCorner - m_PlaneRotation * new Vector3(0, size.y, 0);
                break;
            }

            ProBuilderShape proBuilderShape;

            if (m_DuplicateGO == null)
            {
                var instantiated = ShapeFactory.Instantiate(activeShapeType, ((PivotLocation)s_LastPivotLocation.value));
                proBuilderShape         = instantiated.GetComponent <ProBuilderShape>();
                m_DuplicateGO           = proBuilderShape.gameObject;
                m_DuplicateGO.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;
                ApplyPrefsSettings(proBuilderShape);
                proBuilderShape.GetComponent <MeshRenderer>().sharedMaterial = m_ShapePreviewMaterial;
            }
            else
            {
                proBuilderShape = m_DuplicateGO.GetComponent <ProBuilderShape>();
            }

            EditorShapeUtility.CopyLastParams(proBuilderShape.shape, proBuilderShape.shape.GetType());
            proBuilderShape.Rebuild(m_Bounds, m_PlaneRotation);
            ProBuilderEditor.Refresh(false);
        }
        internal void RebuildShape()
        {
            RecalculateBounds();

            if (m_Bounds.size.sqrMagnitude < .01f ||
                Mathf.Abs(m_Bounds.extents.x) < 0.001f ||
                Mathf.Abs(m_Bounds.extents.z) < 0.001f)
            {
                if (m_ShapeComponent.mesh.vertexCount > 0)
                {
                    m_ShapeComponent.mesh.Clear();
                    m_ShapeComponent.mesh.Rebuild();
                    ProBuilderEditor.Refresh(true);
                }
                return;
            }

            if (!m_IsShapeInit)
            {
                EditorShapeUtility.CopyLastParams(m_ShapeComponent.shape, m_ShapeComponent.shape.GetType());
                m_ShapeComponent.gameObject.hideFlags = HideFlags.None;
                UndoUtility.RegisterCreatedObjectUndo(m_ShapeComponent.gameObject, "Draw Shape");
            }

            m_ShapeComponent.Rebuild(m_Bounds, m_PlaneRotation);
            ProBuilderEditor.Refresh(false);

            if (!m_IsShapeInit)
            {
                EditorUtility.InitObject(m_ShapeComponent.mesh);
                m_IsShapeInit = true;
            }

            SceneView.RepaintAll();
        }
        protected void FinishEdit()
        {
            if (!m_IsEditing)
            {
                return;
            }

            Lightmapping.PopGIWorkflowMode();

            OnToolDisengaged();

            var selection = MeshSelection.topInternal.ToArray();

            foreach (var mesh in selection)
            {
                mesh.ToMesh();
                mesh.Refresh();
                mesh.Optimize();
            }

            ProBuilderEditor.Refresh();

            if (afterMeshModification != null)
            {
                afterMeshModification(selection);
            }

            m_IsEditing = false;
        }
        void SetGroup(ProBuilderMesh pb, int index)
        {
            UndoUtility.RecordObject(pb, "Set Smoothing Group");

            foreach (Face face in pb.selectedFaceCount < 1 ? pb.facesInternal : pb.selectedFacesInternal)
            {
                face.smoothingGroup = index;
            }

            // todo pb.Rebuild
            pb.ToMesh();
            pb.Refresh();
            pb.Optimize();

            SmoothGroupData data;

            if (!m_SmoothGroups.TryGetValue(pb, out data))
            {
                m_SmoothGroups.Add(pb, new SmoothGroupData(pb));
            }
            else
            {
                data.Rebuild(pb);
            }

            ProBuilderEditor.Refresh();
        }
 void OnFinishVertexModification()
 {
     m_IsMoving = false;
     Lightmapping.PopGIWorkflowMode();
     m_CurrentObject.Optimize();
     ProBuilderEditor.Refresh();
 }
示例#6
0
        public void CreateLastShape()
        {
            var shape = ShapeFactory.Instantiate(DrawShapeTool.activeShapeType, (PivotLocation)DrawShapeTool.s_LastPivotLocation.value).GetComponent <ProBuilderShape>();

            shape.gameObject.name = shape.gameObject.name + "-Copy";
            EditorUtility.InitObject(shape.mesh);
            DrawShapeTool.ApplyPrefsSettings(shape);

            UndoUtility.RegisterCreatedObjectUndo(shape.gameObject, "Create Shape Copy");

            EditorShapeUtility.CopyLastParams(shape.shape, shape.shape.GetType());
            shape.Rebuild(tool.m_Bounds, tool.m_PlaneRotation);

            //Finish initializing object and collider once it's completed
            ProBuilderEditor.Refresh(false);

            tool.m_ProBuilderShape  = null;
            tool.m_LastShapeCreated = shape;

            if (tool.m_DuplicateGO != null)
            {
                GameObject.DestroyImmediate(tool.m_DuplicateGO);
            }

            MeshSelection.SetSelection(shape.gameObject);
        }
        void ApplyRotation(Quaternion rotation)
        {
            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)
                    {
                        positions[index] = worldToLocal.MultiplyPoint3x4(
                            postApplyMatrix.MultiplyPoint3x4(
                                rotation * preApplyMatrix.MultiplyPoint3x4(origins[index])));
                    }
                }

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

            ProBuilderEditor.Refresh(false);
        }
示例#8
0
        internal void RebuildShape()
        {
            RecalculateBounds();

            if (m_Bounds.size.sqrMagnitude < .01f ||
                Mathf.Abs(m_Bounds.extents.x) < 0.001f ||
                Mathf.Abs(m_Bounds.extents.z) < 0.001f)
            {
                if (m_ProBuilderShape != null &&
                    m_ProBuilderShape.mesh.vertexCount > 0)
                {
                    m_ProBuilderShape.mesh.Clear();
                    m_ProBuilderShape.mesh.Rebuild();
                    ProBuilderEditor.Refresh(true);
                }
                return;
            }

            if (!m_IsShapeInit)
            {
                var shapeComponent = currentShapeInOverlay;
                EditorShapeUtility.CopyLastParams(shapeComponent.shape, shapeComponent.shape.GetType());
                shapeComponent.gameObject.hideFlags         = HideFlags.HideInHierarchy;
                shapeComponent.mesh.renderer.sharedMaterial = EditorMaterialUtility.GetUserMaterial();
                UndoUtility.RegisterCreatedObjectUndo(shapeComponent.gameObject, "Draw Shape");
                m_IsShapeInit = true;
            }

            m_ProBuilderShape.Rebuild(m_Bounds, m_PlaneRotation);
            ProBuilderEditor.Refresh(false);

            SceneView.RepaintAll();
        }
示例#9
0
        public void RebuildPolyShapeMesh(bool vertexCountChanged = false)
        {
            // If Undo is called immediately after creation this situation can occur
            if (polygon == null)
            {
                return;
            }

            if (polygon.polyEditMode != PolyShape.PolyEditMode.Path)
            {
                var result = polygon.CreateShapeFromPolygon();
                if (result.status == ActionResult.Status.Failure)
                {
                    m_CurrentLineColor = k_InvalidLineColor;
                    // hide the handle to change the height of the invalid mesh
                    m_DrawHeightHandles = false;

                    // skip height edit mode if the mesh is invalid
                    if (polygon.polyEditMode == PolyShape.PolyEditMode.Height)
                    {
                        SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                    }
                }
                else
                {
                    // make sure everything set to normal if polygon creation succeeded
                    m_CurrentLineColor  = k_LineColor;
                    m_DrawHeightHandles = true;
                }
            }

            // While the vertex count may not change, the triangle winding might. So unfortunately we can't take
            // advantage of the `vertexCountChanged = false` optimization here.
            ProBuilderEditor.Refresh();
        }
示例#10
0
        static void DoOrientationHandles(ProBuilderShape proBuilderShape, bool updatePrefs)
        {
            if (GUIUtility.hotControl != 0 && !k_OrientationControlIDs.Contains(GUIUtility.hotControl))
            {
                return;
            }

            foreach (var f in faces)
            {
                if (f.IsVisible && EditorShapeUtility.PointerIsInFace(f))
                {
                    if (DoOrientationHandle(f, proBuilderShape))
                    {
                        UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(proBuilderShape.GetComponents(typeof(Component)), "Rotate Shape");
                        proBuilderShape.RotateInsideBounds(s_ShapeRotation);

                        ProBuilderEditor.Refresh();

                        if (updatePrefs)
                        {
                            DrawShapeTool.SaveShapeParams(proBuilderShape);
                        }
                    }
                }
            }
        }
        static void UndoRedoPerformed()
        {
            // material preview when dragging in scene-view is done by applying then undoing changes. we don't want to
            // rebuild the mesh every single frame when dragging.
            if (SceneDragAndDropListener.isDragging)
            {
                return;
            }

            // Synchronize just checks that the mesh is not null, and UV2 is still valid. This should be very cheap except
            // for the FindObjectsOfType call.
            foreach (var mesh in Object.FindObjectsOfType <ProBuilderMesh>())
            {
                EditorUtility.SynchronizeWithMeshFilter(mesh);
                mesh.InvalidateCaches();
            }

            foreach (var mesh in InternalUtility.GetComponents <ProBuilderMesh>(Selection.transforms))
            {
                mesh.InvalidateCaches();
                mesh.Rebuild();
                mesh.Optimize();
            }

            ProBuilderEditor.Refresh();
            SceneView.RepaintAll();
        }
示例#12
0
        void RebuildPolyShapeMesh(bool vertexCountChanged = false)
        {
            // If Undo is called immediately after creation this situation can occur
            if (polygon == null)
            {
                return;
            }

            if (ToolManager.activeToolType == typeof(PolyShapeTool))
            {
                PolyShapeTool tool = ((PolyShapeTool)EditorToolManager.activeTool);
                if (tool.polygon == polygon)
                {
                    tool.RebuildPolyShapeMesh(vertexCountChanged);
                }
            }

            if (polygon.polyEditMode != PolyShape.PolyEditMode.Path)
            {
                var result = polygon.CreateShapeFromPolygon();
            }

            // While the vertex count may not change, the triangle winding might. So unfortunately we can't take
            // advantage of the `vertexCountChanged = false` optimization here.
            ProBuilderEditor.Refresh();
        }
        static void DoHandleSettings(Rect rect)
        {
            Handles.BeginGUI();
            using (new EditorGUI.DisabledScope(k_EnableHandleSettingInput))
            {
                GUILayout.BeginArea(rect);
                EditorGUI.BeginChangeCheck();

                GUILayout.BeginHorizontal();
                EditorGUIUtility.labelWidth = 80;

                EditorGUILayout.EnumPopup("Pivot Point", VertexManipulationTool.pivotPoint);
                EditorGUILayout.EnumPopup("Orientation", VertexManipulationTool.handleOrientation);

                EditorGUIUtility.labelWidth = 0;
                GUILayout.EndHorizontal();

                if (EditorGUI.EndChangeCheck())
                {
                    ProBuilderEditor.Refresh();
                }
                GUILayout.EndArea();
            }
            Handles.EndGUI();
        }
 void UpdateMesh(bool vertexCountChanged)
 {
     if (m_Target != null)
     {
         m_Target.Refresh();
         UpdateControlPoints();
         ProBuilderEditor.Refresh(vertexCountChanged);
     }
 }
示例#15
0
        static void ApplyProperties(ProBuilderShape proBuilderShape, Vector3 newCenterPosition, Vector3 newSize)
        {
            var bounds = new Bounds();

            bounds.center = newCenterPosition;
            bounds.size   = newSize;

            UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(proBuilderShape.GetComponents(typeof(Component)), "Resize Shape");
            proBuilderShape.UpdateBounds(bounds);

            ProBuilderEditor.Refresh(false);
        }
示例#16
0
        void DrawShapeGUI()
        {
            if (m_BoldCenteredStyle == null)
            {
                m_BoldCenteredStyle = new GUIStyle("BoldLabel")
                {
                    alignment = TextAnchor.MiddleCenter
                }
            }
            ;

            EditorGUILayout.LabelField(EditorShapeUtility.shapeTypes[s_ActiveShapeIndex.value], m_BoldCenteredStyle, GUILayout.ExpandWidth(true));

            if (EditorShapeUtility.s_ResetUserPrefs.value)
            {
                ResetPrefs();
            }

            var shape = currentShapeInOverlay.shape;

            int groupCount = EditorShapeUtility.shapeTypesGUI.Count;

            for (int i = 0; i < groupCount; i++)
            {
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                int index = GUILayout.Toolbar(s_ActiveShapeIndex.value - +i * EditorShapeUtility.MaxContentPerGroup, EditorShapeUtility.shapeTypesGUI[i], Styles.command);
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
                if (EditorGUI.EndChangeCheck())
                {
                    s_ActiveShapeIndex.value = index + i * EditorShapeUtility.MaxContentPerGroup;

                    var type = EditorShapeUtility.availableShapeTypes[s_ActiveShapeIndex];
                    if (shape.GetType() != type)
                    {
                        if (currentShapeInOverlay == m_LastShapeCreated)
                        {
                            m_LastShapeCreated = null;
                        }

                        UndoUtility.RegisterCompleteObjectUndo(currentShapeInOverlay, "Change Shape");
                        Selection.activeObject = null;
                        currentShapeInOverlay.SetShape(EditorShapeUtility.CreateShape(type), currentShapeInOverlay.pivotLocation);
                        SetBounds(currentShapeInOverlay.size);

                        ProBuilderEditor.Refresh();
                    }
                }
            }
        }
    }
        static void Extrude()
        {
            int ef = 0;

            var selection  = MeshSelection.topInternal;
            var selectMode = ProBuilderEditor.selectMode;

            foreach (var mesh in selection)
            {
                switch (selectMode)
                {
                case SelectMode.Edge:
                    if (mesh.selectedFaceCount > 0)
                    {
                        goto default;
                    }

                    Edge[] newEdges = mesh.Extrude(mesh.selectedEdges,
                                                   0.0001f,
                                                   s_ExtrudeEdgesAsGroup,
                                                   ProBuilderEditor.s_AllowNonManifoldActions);

                    if (newEdges != null)
                    {
                        ef += newEdges.Length;
                        mesh.SetSelectedEdges(newEdges);
                    }
                    break;

                default:
                    int len = mesh.selectedFacesInternal.Length;

                    if (len > 0)
                    {
                        mesh.Extrude(mesh.selectedFacesInternal, s_ExtrudeMethod, 0.0001f);
                        mesh.SetSelectedFaces(mesh.selectedFacesInternal);
                        ef += len;
                    }

                    break;
                }

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

            if (ef > 0)
            {
                EditorUtility.ShowNotification("Extrude");
                ProBuilderEditor.Refresh();
            }
        }
示例#18
0
        void ResetPrefs()
        {
            var type = EditorShapeUtility.availableShapeTypes[s_ActiveShapeIndex];

            if (currentShapeInOverlay == m_LastShapeCreated)
            {
                m_LastShapeCreated = null;
            }

            UndoUtility.RegisterCompleteObjectUndo(currentShapeInOverlay, "Change Shape");
            currentShapeInOverlay.SetShape(EditorShapeUtility.CreateShape(type), currentShapeInOverlay.pivotLocation);
            SetBounds(currentShapeInOverlay.size);

            ProBuilderEditor.Refresh();
        }
示例#19
0
        static void SelectGroups(ProBuilderMesh pb, HashSet <int> groups)
        {
            UndoUtility.RecordSelection(pb, "Select with Smoothing Group");

            if ((Event.current.modifiers & EventModifiers.Shift) == EventModifiers.Shift ||
                (Event.current.modifiers & EventModifiers.Control) == EventModifiers.Control)
            {
                pb.SetSelectedFaces(pb.facesInternal.Where(x => groups.Contains(x.smoothingGroup) || pb.selectedFacesInternal.Contains(x)));
            }
            else
            {
                pb.SetSelectedFaces(pb.facesInternal.Where(x => groups.Contains(x.smoothingGroup)));
            }
            ProBuilderEditor.Refresh();
        }
示例#20
0
        void RebuildPolyShapeMesh(bool vertexCountChanged = false)
        {
            // If Undo is called immediately after creation this situation can occur
            if (polygon == null)
            {
                return;
            }

            DrawPolyLine(polygon.m_Points);

            polygon.CreateShapeFromPolygon();

            // While the vertex count may not change, the triangle winding might. So unfortunately we can't take
            // advantage of the `vertexCountChanged = false` optimization here.
            ProBuilderEditor.Refresh();
        }
        /**
         * Used to catch prefab modifications that otherwise wouldn't be registered on the usual 'Awake' verify.
         *  - Dragging prefabs out of Project
         *  - 'Revert' prefab changes
         *  - 'Apply' prefab changes
         */
        static void HierarchyWindowChanged()
        {
            if (!EditorApplication.isPlaying)
            {
                bool meshesAreAssets = Experimental.meshesAreAssets;

                // on duplication, or copy paste, this rebuilds the mesh structures of the new objects
                foreach (ProBuilderMesh pb in Selection.transforms.GetComponents <ProBuilderMesh>())
                {
                    if (!meshesAreAssets)
                    {
                        EditorUtility.SynchronizeWithMeshFilter(pb);
                    }
                }
            }

            ProBuilderEditor.Refresh();
        }
        public void DrawShapeGUI(DrawShapeTool tool = null)
        {
            if (target == null || serializedObject == null)
            {
                return;
            }

            serializedObject.Update();

            int editedShapesCount = 0;

            foreach (var comp in targets)
            {
                editedShapesCount += ((ShapeComponent)comp).isEditable ? 0 : 1;
            }

            if (editedShapesCount > 0)
            {
                EditorGUILayout.BeginVertical();
                EditorGUILayout.HelpBox(
                    L10n.Tr(
                        "You have manually modified Shape(s). Revert manual changes to access to procedural parameters"),
                    MessageType.Info);

                if (GUILayout.Button("Reset Shape"))
                {
                    foreach (var comp in targets)
                    {
                        var shapeComponent = comp as ShapeComponent;
                        UndoUtility.RecordComponents <Transform, ProBuilderMesh, ShapeComponent>(shapeComponent.GetComponents(typeof(Component)), "Reset Shape");
                        shapeComponent.UpdateComponent();
                        ProBuilderEditor.Refresh();
                    }
                }

                EditorGUILayout.EndHorizontal();
            }

            if (editedShapesCount == targets.Length)
            {
                GUI.enabled = false;
            }
        }
        void RebuildPolyShapeMesh(bool vertexCountChanged = false)
        {
            // If Undo is called immediately after creation this situation can occur
            if (polygon == null)
            {
                return;
            }

            DrawPolyLine(polygon.m_Points);

            if (polygon.polyEditMode != PolyShape.PolyEditMode.Path)
            {
                var result = polygon.CreateShapeFromPolygon(SceneView.lastActiveSceneView.camera.transform.forward);
                if (result.status == ActionResult.Status.Failure)
                {
                    m_LineMaterial.SetColor("_Highlight", k_InvalidLineMaterialColor);
                    m_LineMaterial.SetColor("_Base", k_InvalidLineMaterialColor);

                    // hide the handle to change the height of the invalid mesh
                    m_DrawHeightHandles = false;

                    // skip height edit mode if the mesh is invalid
                    if (polygon.polyEditMode == PolyShape.PolyEditMode.Height)
                    {
                        SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                    }
                }
                else
                {
                    // make sure everything set to normal if polygon creation succeeded
                    m_LineMaterial.SetColor("_Highlight", k_LineMaterialHighlightColor);
                    m_LineMaterial.SetColor("_Base", k_LineMaterialBaseColor);
                    m_DrawHeightHandles = true;
                }
            }

            // While the vertex count may not change, the triangle winding might. So unfortunately we can't take
            // advantage of the `vertexCountChanged = false` optimization here.
            ProBuilderEditor.Refresh();
        }
        protected void Apply(Matrix4x4 delta)
        {
#if APPLY_POSITION_TO_SPACE_GIZMO
            m_CurrentDelta.SetColumn(3, delta.GetColumn(3));
#endif

            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)
                    {
                        positions[index] = worldToLocal.MultiplyPoint3x4(
                            postApplyMatrix.MultiplyPoint3x4(
                                delta.MultiplyPoint3x4(preApplyMatrix.MultiplyPoint3x4(origins[index]))));
                    }
                }

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

            ProBuilderEditor.Refresh(false);
        }
示例#25
0
        public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, ScenePickerPreferences scenePickerPreferences)
        {
            var pickingOptions = new PickerOptions()
            {
                depthTest      = scenePickerPreferences.cullMode == CullingMode.Back,
                rectSelectMode = scenePickerPreferences.rectSelectMode
            };

            UndoUtility.RecordSelection("Drag Select");
            bool isAppendModifier = EditorHandleUtility.IsAppendModifier(Event.current.modifiers);

            if (!isAppendModifier)
            {
                MeshSelection.ClearElementSelection();
            }

            bool elementsInDragRect = false;

            switch (selectionMode)
            {
            case SelectMode.Vertex:
            case SelectMode.TextureVertex:
            {
                Dictionary <ProBuilderMesh, HashSet <int> > selected = SelectionPicker.PickVerticesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    var            mesh          = kvp.Key;
                    SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal;
                    HashSet <int>  common;

                    if (isAppendModifier)
                    {
                        common = mesh.GetSharedVertexHandles(mesh.selectedIndexesInternal);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            common.UnionWith(kvp.Value);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            common.RemoveWhere(x => kvp.Value.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            common.SymmetricExceptWith(kvp.Value);
                        }
                    }
                    else
                    {
                        common = kvp.Value;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    mesh.SetSelectedVertices(common.SelectMany(x => sharedIndexes[x]));
                }

                break;
            }

            case SelectMode.Face:
            case SelectMode.TextureFace:
            {
                Dictionary <ProBuilderMesh, HashSet <Face> > selected = SelectionPicker.PickFacesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    HashSet <Face> current;

                    if (isAppendModifier)
                    {
                        current = new HashSet <Face>(kvp.Key.selectedFacesInternal);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            current.UnionWith(kvp.Value);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            current.RemoveWhere(x => kvp.Value.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            current.SymmetricExceptWith(kvp.Value);
                        }
                    }
                    else
                    {
                        current = kvp.Value;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    kvp.Key.SetSelectedFaces(current);
                }

                break;
            }

            case SelectMode.Edge:
            case SelectMode.TextureEdge:
            {
                var selected = SelectionPicker.PickEdgesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    ProBuilderMesh        mesh          = kvp.Key;
                    Dictionary <int, int> common        = mesh.sharedVertexLookup;
                    HashSet <EdgeLookup>  selectedEdges = EdgeLookup.GetEdgeLookupHashSet(kvp.Value, common);
                    HashSet <EdgeLookup>  current;

                    if (isAppendModifier)
                    {
                        current = EdgeLookup.GetEdgeLookupHashSet(mesh.selectedEdges, common);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            current.UnionWith(selectedEdges);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            current.RemoveWhere(x => selectedEdges.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            current.SymmetricExceptWith(selectedEdges);
                        }
                    }
                    else
                    {
                        current = selectedEdges;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    mesh.SetSelectedEdges(current.Select(x => x.local));
                }

                break;
            }
            }

            // if nothing was selected in the drag rect, clear the object selection too
            if (!elementsInDragRect && !isAppendModifier)
            {
                MeshSelection.ClearElementAndObjectSelection();
            }

            ProBuilderEditor.Refresh();
            SceneView.RepaintAll();
        }
        void OnGUI()
        {
            GUILayout.BeginHorizontal(EditorStyles.toolbar);

            GUILayout.FlexibleSpace();

            GUIStyle style = m_WorldSpace ? EditorStyles.toolbarButton : UI.EditorGUIUtility.GetOnStyle(EditorStyles.toolbarButton);

            if (GUILayout.Button(m_WorldSpace ? "World Space" : "Model Space", style))
            {
                m_WorldSpace = !m_WorldSpace;
            }

            GUILayout.EndHorizontal();

            if (m_Selection == null || m_Selection.Count < 1 || !m_Selection.Any(x => x.Key.selectedVertexCount > 0))
            {
                GUILayout.FlexibleSpace();
                GUILayout.Label("Select a ProBuilder Mesh", UI.EditorGUIUtility.CenteredGreyMiniLabel);
                GUILayout.FlexibleSpace();
                return;
            }

            Event e = Event.current;

            if (m_IsActive)
            {
                if (e.type == EventType.Ignore ||
                    e.type == EventType.MouseUp)
                {
                    OnVertexMovementFinish();
                }
            }

            m_Scroll = EditorGUILayout.BeginScrollView(m_Scroll);

            foreach (var kvp in m_Selection)
            {
                ProBuilderMesh        mesh = kvp.Key;
                VertexEditorSelection sel  = kvp.Value;

                bool open = sel.isVisible;

                EditorGUI.BeginChangeCheck();
                open = EditorGUILayout.Foldout(open, mesh.name);
                if (EditorGUI.EndChangeCheck())
                {
                    sel.isVisible = open;
                }

                if (open)
                {
                    int index = 0;

                    bool wasWideMode = EditorGUIUtility.wideMode;
                    EditorGUIUtility.wideMode = true;
                    Color     background = GUI.backgroundColor;
                    Transform transform  = mesh.transform;

                    foreach (int u in sel.common)
                    {
                        GUI.backgroundColor = index % 2 == 0 ? s_EvenColor : s_OddColor;
                        GUILayout.BeginHorizontal(UI.EditorGUIUtility.solidBackgroundStyle);
                        GUI.backgroundColor = background;

                        GUILayout.Label(u.ToString(), GUILayout.MinWidth(32), GUILayout.MaxWidth(32));

                        Vector3 v = mesh.positionsInternal[mesh.sharedVerticesInternal[u][0]];

                        if (m_WorldSpace)
                        {
                            v = transform.TransformPoint(v);
                        }

                        EditorGUI.BeginChangeCheck();

                        v = EditorGUILayout.Vector3Field("", v);

                        if (EditorGUI.EndChangeCheck())
                        {
                            if (!m_IsActive)
                            {
                                OnVertexMovementBegin(mesh);
                            }

                            UndoUtility.RecordObject(mesh, "Set Vertex Postion");

                            mesh.SetSharedVertexPosition(u, m_WorldSpace ? transform.InverseTransformPoint(v) : v);

                            if (ProBuilderEditor.instance != null)
                            {
                                mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]);
                                mesh.Refresh(RefreshMask.Normals);
                                mesh.mesh.RecalculateBounds();
                                ProBuilderEditor.Refresh();
                            }
                        }
                        index++;
                        GUILayout.EndHorizontal();
                    }

                    GUI.backgroundColor       = background;
                    EditorGUIUtility.wideMode = wasWideMode;
                }
            }

            EditorGUILayout.EndScrollView();
        }
 internal static void RefreshSelectionAfterComponentReset(ProBuilderMesh mesh)
 {
     ProBuilderEditor.Refresh(true);
 }
        public void DrawShapeParametersGUI(DrawShapeTool tool = null)
        {
            if (target == null || serializedObject == null)
            {
                return;
            }

            serializedObject.Update();

            var foldoutEnabled = tool == null ? s_foldoutEnabled : DrawShapeTool.s_SettingsEnabled.value;

            foldoutEnabled = EditorGUILayout.Foldout(foldoutEnabled, m_ShapePropertyLabel, true);

            if (tool == null)
            {
                s_foldoutEnabled = foldoutEnabled;
            }
            else
            {
                DrawShapeTool.s_SettingsEnabled.value = foldoutEnabled;
            }

            if (foldoutEnabled)
            {
                EditorGUI.indentLevel++;

                EditorGUI.BeginChangeCheck();
                m_ActiveShapeIndex = HasMultipleShapeTypes
                    ? -1
                    : Mathf.Max(-1, Array.IndexOf(EditorShapeUtility.availableShapeTypes, m_CurrentShapeType));
                m_ActiveShapeIndex = EditorGUILayout.Popup(m_ActiveShapeIndex, EditorShapeUtility.shapeTypes);

                if (EditorGUI.EndChangeCheck())
                {
                    var type = EditorShapeUtility.availableShapeTypes[m_ActiveShapeIndex];
                    foreach (var comp in targets)
                    {
                        ShapeComponent shapeComponent = ((ShapeComponent)comp);
                        Shape          shape          = shapeComponent.shape;
                        if (shape.GetType() != type)
                        {
                            if (tool != null)
                            {
                                DrawShapeTool.s_ActiveShapeIndex.value = m_ActiveShapeIndex;
                            }
                            UndoUtility.RecordComponents <Transform, ProBuilderMesh, ShapeComponent>(shapeComponent.GetComponents(typeof(Component)), "Change Shape");
                            shapeComponent.SetShape(EditorShapeUtility.CreateShape(type), shapeComponent.pivotLocation);
                            ProBuilderEditor.Refresh();
                        }
                    }
                }

                if (tool)
                {
                    EditorGUILayout.PropertyField(m_ShapePivotProperty, k_ShapePivotLabel);
                }

                EditorGUILayout.PropertyField(m_ShapeSizeXProperty, k_ShapeSizeXLabel);
                if (HasMultipleShapeTypes || (m_CurrentShapeType != typeof(Plane) && m_CurrentShapeType != typeof(Sprite)))
                {
                    EditorGUILayout.PropertyField(m_ShapeSizeYProperty, k_ShapeSizeYLabel);
                }
                EditorGUILayout.PropertyField(m_ShapeSizeZProperty, k_ShapeSizeZLabel);

                EditorGUI.indentLevel--;
            }

            if (!HasMultipleShapeTypes)
            {
                EditorGUILayout.PropertyField(m_ShapeProperty, new GUIContent("Shape Properties"), true);
            }

            if (serializedObject.ApplyModifiedProperties())
            {
                foreach (var comp in targets)
                {
                    var shapeComponent = comp as ShapeComponent;
                    if (shapeComponent.isEditable)
                    {
                        UndoUtility.RecordComponents <Transform, ProBuilderMesh, ShapeComponent>(shapeComponent.GetComponents(typeof(Component)), "Resize Shape");
                        shapeComponent.UpdateComponent();
                        if (tool != null)
                        {
                            tool.SetBounds(shapeComponent.size);
                            DrawShapeTool.SaveShapeParams(shapeComponent);
                        }
                        ProBuilderEditor.Refresh();
                    }
                }
            }

            GUI.enabled = true;
        }
        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 (EditorSnapping.snapMode == SnapMode.World && !m_SnapAsGroup)
                        {
                            if (snapAxisConstraint && m_ActiveAxesWorld.active == 1)
                            {
                                var wp = postApplyMatrix.MultiplyPoint3x4(preApplyMatrix.MultiplyPoint3x4(origins[index]));

                                var snap = ProBuilderSnapping.SnapValueOnRay(
                                    new Ray(wp, m_RawHandleDelta),
                                    translationMagnitude,
                                    GetSnapValueForAxis(m_ActiveAxesWorld),
                                    m_ActiveAxesWorld);

                                positions[index] = worldToLocal.MultiplyPoint3x4(snap);
                            }
                            else
                            {
                                var wp   = postApplyMatrix.MultiplyPoint3x4(translation + preApplyMatrix.MultiplyPoint3x4(origins[index]));
                                var snap = ProBuilderSnapping.Snap(wp, snapValue);
                                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);
        }
        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());
        }