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(); }
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); }
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(); }
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(); }
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(); }
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); } }
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); }
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(); } }
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(); }
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(); }
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); }
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()); }