protected override void DoToolGUI() { if (showHandleInfo && isEditing) { DrawDeltaInfo("Scale: " + m_Scale.ToString("0.00")); } if (!isEditing) { m_Scale = Vector3.one; } EditorGUI.BeginChangeCheck(); var size = HandleUtility.GetHandleSize(m_HandlePosition); EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(m_HandlePosition, m_HandleRotation, Vector3.one); m_Scale = Handles.ScaleHandle(m_Scale, Vector3.zero, Quaternion.identity, size); EditorHandleUtility.PopMatrix(); if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Scale Selection"); } Apply(Matrix4x4.Scale(m_Scale)); } }
void SetupInputPlane(Vector2 mousePosition) { plane = EditorHandleUtility.FindBestPlane(mousePosition); var planeNormal = plane.normal; var planeCenter = plane.normal * -plane.distance; // if hit point on plane is cardinal axis and on grid, snap to grid. if (Math.IsCardinalAxis(planeNormal)) { const float epsilon = .00001f; bool offGrid = false; Vector3 snapVal = EditorSnapping.activeMoveSnapValue; Vector3 center = Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal), planeCenter); for (int i = 0; i < 3; i++) { offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon; } polygon.isOnGrid = !offGrid; } else { polygon.isOnGrid = false; } }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { base.DoTool(handlePosition, handleRotation); if (!isEditing) { m_Scale = Vector3.one; } EditorGUI.BeginChangeCheck(); var size = HandleUtility.GetHandleSize(handlePosition); EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); m_Scale = Handles.ScaleHandle(m_Scale, Vector3.zero, Quaternion.identity, size); EditorHandleUtility.PopMatrix(); if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Scale Selection"); } Apply(Matrix4x4.Scale(m_Scale)); } }
void SetupInputPlane(Vector2 mousePosition) { m_Plane = EditorHandleUtility.FindBestPlane(mousePosition); if (ProGridsInterface.SnapEnabled()) { m_Plane.SetNormalAndPosition( m_Plane.normal, ProGridsInterface.ProGridsSnap(m_Plane.normal * -m_Plane.distance)); } var planeNormal = m_Plane.normal; var planeCenter = m_Plane.normal * -m_Plane.distance; // if hit point on plane is cardinal axis and on grid, snap to grid. if (Math.IsCardinalAxis(planeNormal)) { const float epsilon = .00001f; float snapVal = Mathf.Abs(ProGridsInterface.SnapValue()); float rem = Mathf.Abs(snapVal - (Vector3.Scale(planeNormal, planeCenter).magnitude % snapVal)); polygon.isOnGrid = (rem < epsilon || Mathf.Abs(snapVal - rem) < epsilon); } else { polygon.isOnGrid = false; } }
public override void OnToolGUI(EditorWindow window) { SceneViewOverlay.Window(k_ShapeTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle); var evt = Event.current; if (EditorHandleUtility.SceneViewInUse(evt)) { return; } m_ControlID = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(m_ControlID); m_CurrentState = m_CurrentState.DoState(evt); }
public override void OnToolGUI(EditorWindow window) { SceneViewOverlay.Window(k_ShapeTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle); var evt = Event.current; if (EditorHandleUtility.SceneViewInUse(evt)) { return; } m_ControlID = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(m_ControlID); if (GUIUtility.hotControl == 0) { EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.ArrowPlus); } m_CurrentState = m_CurrentState.DoState(evt); }
void DoPointPlacement() { Event evt = Event.current; EventType eventType = evt.type; if (m_PlacingPoint) { Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (eventType == EventType.MouseDrag) { float hitDistance = Mathf.Infinity; if (plane.Raycast(ray, out hitDistance)) { evt.Use(); polygon.m_Points[m_SelectedIndex] = GetPointInLocalSpace(ray.GetPoint(hitDistance)); RebuildPolyShapeMesh(false); SceneView.RepaintAll(); } } if (eventType == EventType.MouseUp || eventType == EventType.Ignore || eventType == EventType.KeyDown || eventType == EventType.KeyUp) { evt.Use(); m_PlacingPoint = false; m_SelectedIndex = -1; SceneView.RepaintAll(); } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path) { if (eventType == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId) { if (polygon.m_Points.Count < 1) { SetupInputPlane(evt.mousePosition); } float hitDistance = Mathf.Infinity; Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (plane.Raycast(ray, out hitDistance)) { UndoUtility.RecordObject(polygon, "Add Polygon Shape Point"); Vector3 hit = ray.GetPoint(hitDistance); if (polygon.m_Points.Count < 1) { // this monstrosity exists so that grid and incremental snap work when possible, and // incremental is enabled when grid is not available. polygon.transform.position = m_Polygon.isOnGrid ? EditorSnapping.MoveSnap(hit) : EditorSnapping.snapMode == SnapMode.Relative ? ProBuilderSnapping.Snap(hit, EditorSnapping.incrementalSnapMoveValue) : hit; Vector3 cameraFacingPlaneNormal = plane.normal; if (Vector3.Dot(cameraFacingPlaneNormal, SceneView.lastActiveSceneView.camera.transform.forward) > 0f) { cameraFacingPlaneNormal *= -1; } polygon.transform.rotation = Quaternion.LookRotation(cameraFacingPlaneNormal) * Quaternion.Euler(new Vector3(90f, 0f, 0f)); } Vector3 point = GetPointInLocalSpace(hit); if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point)) { m_NextMouseUpAdvancesMode = true; return; } polygon.m_Points.Add(point); m_PlacingPoint = true; m_SelectedIndex = polygon.m_Points.Count - 1; RebuildPolyShapeMesh(polygon); evt.Use(); } } else { float hitDistance = Mathf.Infinity; Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (plane.Raycast(ray, out hitDistance)) { Vector3 hit = ray.GetPoint(hitDistance); m_CurrentPosition = GetPointInLocalSpace(hit); } } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit) { if (polygon.m_Points.Count < 3) { SetPolyEditMode(PolyShape.PolyEditMode.Path); return; } if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl) { // point insertion Vector2 mouse = evt.mousePosition; Ray ray = HandleUtility.GUIPointToWorldRay(mouse); float hitDistance = Mathf.Infinity; if (plane.Raycast(ray, out hitDistance)) { Vector3 hit = ray.GetPoint(hitDistance); Vector3 point = GetPointInLocalSpace(hit); int polyCount = polygon.m_Points.Count; float distToLineInGUI; int index; Vector3 pInGUI = EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distToLineInGUI, true, polygon.transform); Vector3 aToPoint = point - polygon.m_Points[index - 1]; Vector3 aToB = polygon.m_Points[index % polyCount] - polygon.m_Points[index - 1]; float ratio = Vector3.Dot(aToPoint, aToB.normalized) / aToB.magnitude; Vector3 wp = Vector3.Lerp(polygon.m_Points[index - 1], polygon.m_Points[index % polyCount], ratio); wp = polygon.transform.TransformPoint(wp); Vector2 aInGUI = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index - 1])); Vector2 bInGUI = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polyCount])); float distanceToVertex = Mathf.Min(Vector2.Distance(mouse, aInGUI), Vector2.Distance(mouse, bInGUI)); if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distToLineInGUI < PreferenceKeys.k_MaxPointDistanceFromControl) { m_MouseCursor = MouseCursor.ArrowPlus; if (evt.type == EventType.Repaint) { Handles.color = Color.green; Handles.DotHandleCap(-1, wp, Quaternion.identity, HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type); } if (evt.type == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId) { evt.Use(); UndoUtility.RecordObject(polygon, "Insert Point"); polygon.m_Points.Insert(index, point); m_SelectedIndex = index; m_PlacingPoint = true; RebuildPolyShapeMesh(true); OnBeginVertexMovement(); } Handles.color = Color.white; } if (evt.type != EventType.Repaint) { SceneView.RepaintAll(); } } } } }
/// <summary> /// Main GUI update for the tool, calls every secondary methods to place points, update lines and compute the cut /// </summary> /// <param name="window">current window calling the tool : SceneView</param> public override void OnToolGUI(EditorWindow window) { Event evt = Event.current; SceneViewOverlay.Window(m_OverlayTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle); if (polygon == null) { return; } if (polygon.polyEditMode == PolyShape.PolyEditMode.None) { return; } // used when finishing a loop by clicking the first created point if (m_NextMouseUpAdvancesMode && evt.type == EventType.MouseUp) { evt.Use(); m_NextMouseUpAdvancesMode = false; if (SceneCameraIsAlignedWithPolyUp()) { SetPolyEditMode(PolyShape.PolyEditMode.Edit); } else { SetPolyEditMode(PolyShape.PolyEditMode.Height); } } if (m_IsModifyingVertices && ( evt.type == EventType.MouseUp || evt.type == EventType.Ignore || evt.type == EventType.KeyDown || evt.type == EventType.KeyUp)) { OnFinishVertexMovement(); } if (evt.type == EventType.KeyDown) { HandleKeyEvent(evt); } //The user can press a key to exit editing mode, //leading to null polygon at this point if (polygon == null) { return; } if (EditorHandleUtility.SceneViewInUse(evt)) { return; } m_ControlId = GUIUtility.GetControlID(FocusType.Passive); if (evt.type == EventType.Layout) { HandleUtility.AddDefaultControl(m_ControlId); } if (polygon.polyEditMode == PolyShape.PolyEditMode.Path && !m_PlacingPoint) { m_MouseCursor = MouseCursor.ArrowPlus; } else if ((GUIUtility.hotControl != 0) || m_PlacingPoint) { m_MouseCursor = MouseCursor.MoveArrow; } else { m_MouseCursor = MouseCursor.Arrow; } if (evt.type == EventType.MouseMove) { SceneView.RepaintAll(); } DoPointPlacement(); DoExistingPointsGUI(); if (evt.type == EventType.Repaint) { DoExistingLinesGUI(); Rect sceneViewRect = window.position; sceneViewRect.x = 0; sceneViewRect.y = 0; SceneView.AddCursorRect(sceneViewRect, m_MouseCursor); } }
static float FaceRaycast(Vector3 mousePosition, ScenePickerPreferences pickerOptions, bool allowUnselected, SceneSelection selection, int deepClickOffset = 0, bool isPreview = true) { GameObject pickedGo = null; ProBuilderMesh pickedPb = null; Face pickedFace = null; int newHash = 0; // If any event modifiers are engaged don't cycle the deep click EventModifiers em = Event.current.modifiers; if (isPreview || em != EventModifiers.None) { EditorHandleUtility.GetHovered(mousePosition, s_OverlappingGameObjects); } else { EditorHandleUtility.GetAllOverlapping(mousePosition, s_OverlappingGameObjects); } selection.Clear(); float distance = Mathf.Infinity; for (int i = 0, next = 0, pickedCount = s_OverlappingGameObjects.Count; i < pickedCount; i++) { var go = s_OverlappingGameObjects[i]; var mesh = go.GetComponent <ProBuilderMesh>(); Face face = null; if (mesh != null && (allowUnselected || MeshSelection.topInternal.Contains(mesh))) { Ray ray = UHandleUtility.GUIPointToWorldRay(mousePosition); RaycastHit hit; if (UnityEngine.ProBuilder.HandleUtility.FaceRaycast(ray, mesh, out hit, Mathf.Infinity, pickerOptions.cullMode)) { face = mesh.facesInternal[hit.face]; distance = Vector2.SqrMagnitude(((Vector2)mousePosition) - HandleUtility.WorldToGUIPoint(mesh.transform.TransformPoint(hit.point))); } } // pb_Face doesn't define GetHashCode, meaning it falls to object.GetHashCode (reference comparison) int hash = face == null?go.GetHashCode() : face.GetHashCode(); if (s_DeepSelectionPrevious == hash) { next = (i + (1 + deepClickOffset)) % pickedCount; } if (next == i) { pickedGo = go; pickedPb = mesh; pickedFace = face; newHash = hash; // a prior hash was matched, this is the next. if // it's just the first iteration don't break (but do // set the default). if (next != 0) { break; } } } if (!isPreview) { s_DeepSelectionPrevious = newHash; } if (pickedGo != null) { Event.current.Use(); if (pickedPb != null) { if (pickedPb.selectable) { selection.gameObject = pickedGo; selection.mesh = pickedPb; selection.face = pickedFace; return(Mathf.Sqrt(distance)); } } // If clicked off a pb_Object but onto another gameobject, set the selection // and dip out. selection.gameObject = pickedGo; return(Mathf.Sqrt(distance)); } return(distance); }
public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences) { bool appendModifier = EditorHandleUtility.IsAppendModifier(evt.modifiers); if (!appendModifier) { MeshSelection.SetSelection((GameObject)null); } float pickedElementDistance = Mathf.Infinity; if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); } else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) { pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); } else { pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, true, s_Selection, evt.clickCount > 1 ? -1 : 0, false); } evt.Use(); if (pickedElementDistance > pickerPreferences.maxPointerDistance) { if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject)) { MeshSelection.RemoveFromSelection(s_Selection.gameObject); } else { MeshSelection.AddToSelection(s_Selection.gameObject); } return(null); } MeshSelection.AddToSelection(s_Selection.gameObject); if (s_Selection.mesh != null) { var mesh = s_Selection.mesh; if (s_Selection.face != null) { // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts) MaterialEditor matEditor = MaterialEditor.instance; if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, s_Selection.face)) { return(null); } UVEditor uvEditor = UVEditor.instance; if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, s_Selection.face)) { return(null); } var faces = mesh.faces as Face[] ?? mesh.faces.ToArray(); var ind = Array.IndexOf <Face>(faces, s_Selection.face); var sel = mesh.selectedFaceIndexes.IndexOf(ind); UndoUtility.RecordSelection(mesh, "Select Face"); if (sel > -1) { mesh.RemoveFromFaceSelectionAtIndex(sel); } else { mesh.AddToFaceSelection(ind); } } else if (s_Selection.edge != Edge.Empty) { int ind = mesh.IndexOf(mesh.selectedEdges, s_Selection.edge); UndoUtility.RecordSelection(mesh, "Select Edge"); if (ind > -1) { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind)); } else { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(s_Selection.edge)); } } else if (s_Selection.vertex > -1) { int ind = Array.IndexOf(mesh.selectedIndexesInternal, s_Selection.vertex); UndoUtility.RecordSelection(mesh, "Select Vertex"); if (ind > -1) { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.RemoveAt(ind)); } else { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(s_Selection.vertex)); } } return(mesh); } return(null); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Position = Vector3.zero; } EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); EditorGUI.BeginChangeCheck(); Handles.color = Color.blue; m_Position = Handles.Slider2D(m_Position, Vector3.forward, Vector3.right, Vector3.up, HandleUtility.GetHandleSize(m_Position) * .2f, Handles.RectangleHandleCap, 0f, false); Handles.color = Color.green; m_Position = Handles.Slider(m_Position, Vector3.up); Handles.color = Color.red; m_Position = Handles.Slider(m_Position, Vector3.right); Handles.color = Color.white; if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Translate Textures"); } if (relativeSnapEnabled) { m_Position.x = Snapping.SnapValue(m_Position.x, relativeSnapX); m_Position.y = Snapping.SnapValue(m_Position.y, relativeSnapY); } else if (progridsSnapEnabled) { m_Position.x = Snapping.SnapValue(m_Position.x, progridsSnapValue); m_Position.y = Snapping.SnapValue(m_Position.y, progridsSnapValue); } // invert `y` because to users it's confusing that "up" in UV space visually moves the texture down var delta = new Vector4(m_Position.x, -m_Position.y, 0f, 0f); foreach (var mesh in elementSelection) { if (!(mesh is MeshAndTextures)) { continue; } delta *= 1f / mesh.mesh.transform.lossyScale.magnitude; var origins = ((MeshAndTextures)mesh).origins; var positions = ((MeshAndTextures)mesh).textures; foreach (var group in mesh.elementGroups) { foreach (var index in group.indices) { positions[index] = origins[index] + delta; } } mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); } } EditorHandleUtility.PopMatrix(); }
void OnSceneGUI() { if (polygon.polyEditMode == PolyShape.PolyEditMode.None) { return; } if (polygon == null || Tools.current != Tool.None) { SetPolyEditMode(PolyShape.PolyEditMode.None); return; } if (m_LineMaterial != null) { m_LineMaterial.SetPass(0); Graphics.DrawMeshNow(m_LineMesh, polygon.transform.localToWorldMatrix, 0); } Event evt = Event.current; // used when finishing a loop by clicking the first created point if (m_NextMouseUpAdvancesMode && evt.type == EventType.MouseUp) { evt.Use(); m_NextMouseUpAdvancesMode = false; if (SceneCameraIsAlignedWithPolyUp()) { SetPolyEditMode(PolyShape.PolyEditMode.Edit); } else { SetPolyEditMode(PolyShape.PolyEditMode.Height); } } if (m_IsModifyingVertices && ( evt.type == EventType.MouseUp || evt.type == EventType.Ignore || evt.type == EventType.KeyDown || evt.type == EventType.KeyUp)) { OnFinishVertexMovement(); } DoExistingPointsGUI(); if (evt.type == EventType.KeyDown) { HandleKeyEvent(evt); } if (EditorHandleUtility.SceneViewInUse(evt)) { return; } int controlID = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(controlID); DoPointPlacement(); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Scale.x = 1f; m_Scale.y = 1f; m_UniformScale = 1f; } EditorGUI.BeginChangeCheck(); var size = HandleUtility.GetHandleSize(handlePosition); EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); var snap = relativeSnapEnabled ? relativeSnapScale : progridsSnapEnabled ? progridsSnapValue : 0f; Handles.color = Color.red; m_Scale.x = Handles.ScaleSlider(m_Scale.x, Vector3.zero, Vector3.right, Quaternion.identity, size, snap); Handles.color = Color.green; m_Scale.y = Handles.ScaleSlider(m_Scale.y, Vector3.zero, Vector3.up, Quaternion.identity, size, snap); Handles.color = Color.blue; m_UniformScale = Handles.ScaleValueHandle(m_UniformScale, Vector3.zero, Quaternion.identity, size, Handles.CubeHandleCap, snap); EditorHandleUtility.PopMatrix(); if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Scale Textures"); } var delta = m_Scale * m_UniformScale; delta.x = 1f / delta.x; delta.y = 1f / delta.y; foreach (var mesh in elementSelection) { if (!(mesh is MeshAndTextures)) { continue; } var mat = (MeshAndTextures)mesh; var origins = mat.origins; var positions = mat.textures; foreach (var group in mesh.elementGroups) { foreach (var index in group.indices) { positions[index] = mat.postApplyMatrix.MultiplyPoint( Vector2.Scale(mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), delta)); } } mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); } } }
void OnSceneGUI() { Event e = Event.current; bool eventHasBeenUsed = false; if (m_IsMoving) { if (e.type == EventType.Ignore || e.type == EventType.MouseUp) { eventHasBeenUsed = true; OnFinishVertexModification(); } } bool sceneViewInUse = EditorHandleUtility.SceneViewInUse(e); if (e.type == EventType.KeyDown) { if (e.keyCode == KeyCode.Backspace && m_currentHandle > -1 && m_currentHandle < m_Points.Count) { UndoUtility.RecordObject(m_Target, "Delete Bezier Point"); m_Points.RemoveAt(m_currentHandle); UpdateMesh(true); } else if (e.keyCode == KeyCode.Escape) { SetIsEditing(false); } } int count = m_Points.Count; Matrix4x4 handleMatrix = Handles.matrix; Handles.matrix = m_Target.transform.localToWorldMatrix; EditorGUI.BeginChangeCheck(); for (int index = 0; index < count; index++) { if (index < count - 1 || m_CloseLoop) { Handles.DrawBezier(m_Points[index].position, m_Points[(index + 1) % count].position, m_Points[index].tangentOut, m_Points[(index + 1) % count].tangentIn, Color.green, EditorGUIUtility.whiteTexture, 1f); } if (!m_IsEditing) { continue; } // If the index is selected show the full transform gizmo, otherwise use free move handles if (m_currentHandle == index) { BezierPoint point = m_Points[index]; if (!m_currentHandle.isTangent) { Vector3 prev = point.position; prev = Handles.PositionHandle(prev, Quaternion.identity); if (!Math.Approx3(prev, point.position)) { if (!m_IsMoving) { OnBeginVertexModification(); } prev = EditorSnapping.MoveSnap(prev); Vector3 dir = prev - point.position; point.position = prev; point.tangentIn += dir; point.tangentOut += dir; } // rotation int prev_index = index > 0 ? index - 1 : (m_CloseLoop ? count - 1 : -1); int next_index = index < count - 1 ? index + 1 : (m_CloseLoop ? 0 : -1); Vector3 rd = BezierPoint.GetLookDirection(m_Points, index, prev_index, next_index); Quaternion look = Quaternion.LookRotation(rd); float size = HandleUtility.GetHandleSize(point.position); Matrix4x4 pm = Handles.matrix; Handles.matrix = pm * Matrix4x4.TRS(point.position, look, Vector3.one); point.rotation = Handles.Disc(point.rotation, Vector3.zero, Vector3.forward, size, false, 0f); Handles.matrix = pm; } else { Handles.color = bezierTangentHandleColor; if (m_currentHandle.tangent == BezierTangentDirection.In && (m_CloseLoop || index > 0)) { EditorGUI.BeginChangeCheck(); point.tangentIn = Handles.PositionHandle(point.tangentIn, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentIn = EditorSnapping.MoveSnap(point.tangentIn); point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode); } Handles.color = Color.blue; Handles.DrawLine(m_Points[index].position, m_Points[index].tangentIn); } if (m_currentHandle.tangent == BezierTangentDirection.Out && (m_CloseLoop || index < count - 1)) { EditorGUI.BeginChangeCheck(); point.tangentOut = Handles.PositionHandle(point.tangentOut, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentOut = EditorSnapping.MoveSnap(point.tangentOut); point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode); } Handles.color = Color.red; Handles.DrawLine(m_Points[index].position, m_Points[index].tangentOut); } } m_Points[index] = point; } } if (!m_IsEditing) { return; } EventType eventType = e.type; if (!eventHasBeenUsed) { eventHasBeenUsed = eventType == EventType.Used; } for (int index = 0; index < count; index++) { Vector3 prev; BezierPoint point = m_Points[index]; // Position Handle float size = HandleUtility.GetHandleSize(point.position) * k_HandleSize; Handles.color = bezierPositionHandleColor; if (m_currentHandle == index && !m_currentHandle.isTangent) { Handles.DotHandleCap(0, point.position, Quaternion.identity, size, e.type); } else { prev = point.position; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle = (BezierHandle)index; Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.position)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.SetPosition(EditorSnapping.MoveSnap(prev)); } } // Tangent handles Handles.color = bezierTangentHandleColor; // Tangent In Handle if (m_CloseLoop || index > 0) { size = HandleUtility.GetHandleSize(point.tangentIn) * k_HandleSize; Handles.DrawLine(point.position, point.tangentIn); if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.In) { Handles.DotHandleCap(0, point.tangentIn, Quaternion.identity, size, e.type); } else { prev = point.tangentIn; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.In); Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.tangentIn)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentIn = EditorSnapping.MoveSnap(prev); point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode); } } } // Tangent Out if (m_CloseLoop || index < count - 1) { size = HandleUtility.GetHandleSize(point.tangentOut) * k_HandleSize; Handles.DrawLine(point.position, point.tangentOut); if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.Out) { Handles.DotHandleCap(0, point.tangentOut, Quaternion.identity, size, e.type); } else { prev = point.tangentOut; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.Out); Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.tangentOut)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentOut = EditorSnapping.MoveSnap(prev); point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode); } } } m_Points[index] = point; } // Do control point insertion if (!eventHasBeenUsed && m_ControlPoints != null && m_ControlPoints.Count > 1) { int index = -1; float distanceToLine; Vector3 p = EditorHandleUtility.ClosestPointToPolyLine(m_ControlPoints, out index, out distanceToLine, false, null); if (!IsHoveringHandlePoint(e.mousePosition) && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl) { Handles.color = Color.green; Handles.DotHandleCap(-1, p, Quaternion.identity, HandleUtility.GetHandleSize(p) * .05f, e.type); Handles.color = Color.white; if (!eventHasBeenUsed && eventType == EventType.MouseDown && e.button == 0) { UndoUtility.RecordObject(m_Target, "Add Point"); Vector3 dir = m_ControlPoints[(index + 1) % m_ControlPoints.Count] - m_ControlPoints[index]; m_Points.Insert((index / m_Columns) + 1, new BezierPoint(p, p - dir, p + dir, Quaternion.identity)); UpdateMesh(true); e.Use(); } SceneView.RepaintAll(); } } if (e.type == EventType.MouseUp && !sceneViewInUse) { m_currentHandle.SetIndex(-1); } Handles.matrix = handleMatrix; if (EditorGUI.EndChangeCheck()) { UpdateMesh(false); } }
public override ShapeState DoState(Event evt) { if (evt.type == EventType.KeyDown) { switch (evt.keyCode) { case KeyCode.Escape: ToolManager.RestorePreviousTool(); break; } } if (tool.m_LastShapeCreated != null) { EditShapeTool.DoEditingHandles(tool.m_LastShapeCreated, true); } if (evt.isMouse && HandleUtility.nearestControl == tool.controlID) { var res = EditorHandleUtility.FindBestPlaneAndBitangent(evt.mousePosition); Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); float hit; if (res.item1.Raycast(ray, out hit)) { //Plane init tool.m_Plane = res.item1; tool.m_PlaneForward = res.item2; tool.m_PlaneRight = Vector3.Cross(tool.m_Plane.normal, tool.m_PlaneForward); var planeNormal = tool.m_Plane.normal; var planeCenter = tool.m_Plane.normal * -tool.m_Plane.distance; // if hit point on plane is cardinal axis and on grid, snap to grid. if (Math.IsCardinalAxis(planeNormal)) { const float epsilon = .00001f; bool offGrid = false; Vector3 snapVal = EditorSnapping.activeMoveSnapValue; Vector3 center = Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal), planeCenter); for (int i = 0; i < 3; i++) { offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon; } tool.m_IsOnGrid = !offGrid; } else { tool.m_IsOnGrid = false; } m_HitPosition = tool.GetPoint(ray.GetPoint(hit)); //Click has been done => Define a plane for the tool if (evt.type == EventType.MouseDown) { //BB init tool.m_BB_Origin = m_HitPosition; tool.m_BB_HeightCorner = tool.m_BB_Origin; tool.m_BB_OppositeCorner = tool.m_BB_Origin; return(NextState()); } } else { m_HitPosition = Vector3.negativeInfinity; } } if (GUIUtility.hotControl == 0 && evt.shift && !(evt.control || evt.command)) { tool.DuplicatePreview(m_HitPosition); } else if (tool.m_DuplicateGO != null) { Object.DestroyImmediate(tool.m_DuplicateGO); } // Repaint to visualize the placement preview dot if (evt.type == EventType.MouseMove && HandleUtility.nearestControl == tool.controlID) { HandleUtility.Repaint(); } if (evt.type == EventType.Repaint) { if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == tool.controlID) { using (new Handles.DrawingScope(EditorHandleDrawing.vertexSelectedColor)) { Handles.DotHandleCap(-1, m_HitPosition, Quaternion.identity, HandleUtility.GetHandleSize(m_HitPosition) * 0.05f, EventType.Repaint); } } if (GUIUtility.hotControl == 0 && evt.shift && !(evt.control || evt.command)) { tool.DrawBoundingBox(false); } } return(this); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Position = Vector3.zero; } EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); EditorGUI.BeginChangeCheck(); Handles.color = Color.blue; m_Position = Handles.Slider2D(m_Position, Vector3.forward, Vector3.right, Vector3.up, HandleUtility.GetHandleSize(m_Position) * .2f, Handles.RectangleHandleCap, 0f, false); Handles.color = Color.green; m_Position = Handles.Slider(m_Position, Vector3.up); Handles.color = Color.red; m_Position = Handles.Slider(m_Position, Vector3.right); Handles.color = Color.white; if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Translate Textures"); } if (relativeSnapEnabled) { m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, relativeSnapX); m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, relativeSnapY); } else if (progridsSnapEnabled) { m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, progridsSnapValue); m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, progridsSnapValue); } // invert `y` because to users it's confusing that "up" in UV space visually moves the texture down var delta = new Vector4(m_Position.x, -m_Position.y, 0f, 0f); foreach (var value in elementSelection) { var selection = value as TranslateTextureSelection; if (selection == null) { continue; } // Account for object scale delta *= k_Vector3Magnitude / selection.mesh.transform.lossyScale.magnitude; var origins = selection.origins; var positions = selection.textures; // Translating faces is treated as a special case because we want the textures in scene to visually // match the movement of the translation handle. When UVs are scaled, they have the appearance of // moving faster or slower (even though they are translating the correct distances). To avoid this, // we cache the UV scale of each face and modify the translation delta accordingly. This isn't perfect, // as it will not be able to find the scale for sheared or otherwise distorted face UVs. However, for // most cases it maps quite well. if (ProBuilderEditor.selectMode == SelectMode.TextureFace) { foreach (var face in selection.faceAndScale) { var faceDelta = new Vector4(delta.x / face.item2.x, delta.y / face.item2.y, 0f, 0f); foreach (var index in face.item1.distinctIndexes) { positions[index] = origins[index] + faceDelta; } } } else { foreach (var group in value.elementGroups) { foreach (var index in group.indices) { positions[index] = origins[index] + delta; } } } selection.mesh.mesh.SetUVs(k_TextureChannel, positions); } } EditorHandleUtility.PopMatrix(); }
void OnSceneGUI(SceneView sceneView) { SceneStyles.Init(); m_CurrentEvent = Event.current; EditorHandleDrawing.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode); DrawHandleGUI(sceneView); if (m_CurrentEvent.type == EventType.KeyDown) { // Escape isn't assignable as a shortcut if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object) { selectMode = SelectMode.Object; m_IsDragging = false; m_IsReadyForMouseDrag = false; m_CurrentEvent.Use(); } } if (selectMode == SelectMode.Object) { return; } bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(m_CurrentEvent.modifiers); // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight && selectMode.IsMeshElementMode() && (m_CurrentEvent.type == EventType.MouseMove || (m_wasSelectingPath != pathSelectionModifier && m_CurrentEvent.isKey))) { m_Hovering.CopyTo(m_HoveringPrevious); if (GUIUtility.hotControl != 0 || EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance) { m_Hovering.Clear(); } if (!m_Hovering.Equals(m_HoveringPrevious)) { if (pathSelectionModifier) { EditorSceneViewPicker.DoMouseHover(m_Hovering); } SceneView.RepaintAll(); } } m_wasSelectingPath = pathSelectionModifier; if (Tools.current == Tool.View) { return; } switch (m_CurrentEvent.type) { case EventType.ValidateCommand: case EventType.ExecuteCommand: bool execute = m_CurrentEvent.type == EventType.ExecuteCommand; switch (m_CurrentEvent.commandName) { case "SelectAll": if (execute) { SelectAll(); } m_CurrentEvent.Use(); break; case "DeselectAll": if (execute) { DeselectAll(); } m_CurrentEvent.Use(); break; case "InvertSelection": if (execute) { InvertSelection(); } m_CurrentEvent.Use(); break; } break; } if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent)) { if (m_IsDragging) { m_IsDragging = false; } if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } return; } // This prevents us from selecting other objects in the scene, // and allows for the selection of faces / vertices. m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive); if (Event.current.type == EventType.Layout) { HandleUtility.AddDefaultControl(m_DefaultControl); } if (m_CurrentEvent.type == EventType.MouseDown && HandleUtility.nearestControl == m_DefaultControl) { // double clicking object if (m_CurrentEvent.clickCount > 1) { DoubleClick(m_CurrentEvent); } m_InitialMousePosition = m_CurrentEvent.mousePosition; // readyForMouseDrag prevents a bug wherein after ending a drag an errant // MouseDrag event is sent with no corresponding MouseDown/MouseUp event. m_IsReadyForMouseDrag = true; GUIUtility.hotControl = m_DefaultControl; } if (m_CurrentEvent.type == EventType.MouseDrag && m_IsReadyForMouseDrag && GUIUtility.hotControl == m_DefaultControl) { if (!m_IsDragging && Vector2.Distance(m_CurrentEvent.mousePosition, m_InitialMousePosition) > k_MouseDragThreshold) { sceneView.Repaint(); m_IsDragging = true; } } if (m_CurrentEvent.type == EventType.Ignore) { if (m_IsDragging) { m_IsReadyForMouseDrag = false; m_IsDragging = false; EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences); } if (m_WasDoubleClick) { m_WasDoubleClick = false; } if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } } if (m_CurrentEvent.type == EventType.MouseUp && GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; if (m_WasDoubleClick) { m_WasDoubleClick = false; } else { if (!m_IsDragging) { if (UVEditor.instance) { UVEditor.instance.ResetUserPivot(); } EditorSceneViewPicker.DoMouseClick(m_CurrentEvent, selectMode, m_ScenePickerPreferences); UpdateSelection(); } else { m_IsDragging = false; m_IsReadyForMouseDrag = false; if (UVEditor.instance) { UVEditor.instance.ResetUserPivot(); } EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences); if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } } } } }
void OnSceneGUI(SceneView sceneView) { SceneStyles.Init(); m_CurrentEvent = Event.current; EditorHandleDrawing.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode); DrawHandleGUI(sceneView); if (m_CurrentEvent.type == EventType.KeyDown) { // Escape isn't assignable as a shortcut if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object) { selectMode = SelectMode.Object; m_IsDragging = false; m_IsReadyForMouseDrag = false; m_CurrentEvent.Use(); } } if (selectMode == SelectMode.Object) { return; } bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(m_CurrentEvent.modifiers); // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight && selectMode.IsMeshElementMode() && (m_CurrentEvent.type == EventType.MouseMove || (m_wasSelectingPath != pathSelectionModifier && m_CurrentEvent.isKey))) { m_Hovering.CopyTo(m_HoveringPrevious); if (GUIUtility.hotControl != 0 || EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance) { m_Hovering.Clear(); } if (!m_Hovering.Equals(m_HoveringPrevious)) { if (pathSelectionModifier) { EditorSceneViewPicker.DoMouseHover(m_Hovering); } SceneView.RepaintAll(); } } m_wasSelectingPath = pathSelectionModifier; if (Tools.current == Tool.View) { return; } switch (m_CurrentEvent.type) { case EventType.ValidateCommand: case EventType.ExecuteCommand: bool execute = m_CurrentEvent.type == EventType.ExecuteCommand; switch (m_CurrentEvent.commandName) { case "SelectAll": if (execute) { SelectAll(); } m_CurrentEvent.Use(); break; case "DeselectAll": if (execute) { DeselectAll(); } m_CurrentEvent.Use(); break; case "InvertSelection": if (execute) { InvertSelection(); } m_CurrentEvent.Use(); break; } break; } if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent)) { if (m_IsDragging) { m_IsDragging = false; } if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } return; } // This prevents us from selecting other objects in the scene, // and allows for the selection of faces / vertices. m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive); if (Event.current.type == EventType.Layout) { HandleUtility.AddDefaultControl(m_DefaultControl); } HandleMouseEvent(sceneView, m_DefaultControl); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Rotation = 0f; } EditorGUI.BeginChangeCheck(); var size = HandleUtility.GetHandleSize(handlePosition); EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); Handles.color = Color.blue; m_Euler.z = m_Rotation; m_Quaternion = Quaternion.Euler(m_Euler); m_Quaternion = Handles.Disc(m_Quaternion, Vector3.zero, Vector3.forward, size, relativeSnapEnabled, relativeSnapRotation); m_Euler = m_Quaternion.eulerAngles; m_Rotation = m_Euler.z; EditorHandleUtility.PopMatrix(); if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Rotate Textures"); } if (relativeSnapEnabled) { m_Rotation = Snapping.SnapValue(m_Rotation, relativeSnapX); } else if (progridsSnapEnabled) { m_Rotation = Snapping.SnapValue(m_Rotation, progridsSnapValue); } foreach (var mesh in elementSelection) { if (!(mesh is MeshAndTextures)) { continue; } var mat = (MeshAndTextures)mesh; var origins = mat.origins; var positions = mat.textures; foreach (var group in mat.elementGroups) { foreach (var index in group.indices) { positions[index] = mat.postApplyMatrix.MultiplyPoint( Math.RotateAroundPoint( mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), Vector2.zero, -m_Rotation)); } } mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); } } }
public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences) { bool appendModifier = EditorHandleUtility.IsAppendModifier(evt.modifiers); bool addToSelectionModifier = EditorHandleUtility.IsSelectionAddModifier(evt.modifiers); bool addOrRemoveIfPresentFromSelectionModifier = EditorHandleUtility.IsSelectionAppendOrRemoveIfPresentModifier(evt.modifiers); bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(evt.modifiers); float pickedElementDistance; if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection); } else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) { pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection); } else { pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection, evt.clickCount > 1 ? -1 : 0, false); } evt.Use(); if (!appendModifier) { if (s_Selection.mesh != null) { s_Selection.mesh.ClearSelection(); } MeshSelection.SetSelection((GameObject)null); } if (pickedElementDistance > ScenePickerPreferences.maxPointerDistance) { if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject)) { MeshSelection.RemoveFromSelection(s_Selection.gameObject); } else { MeshSelection.AddToSelection(s_Selection.gameObject); } return(null); } GameObject candidateNewActiveObject = s_Selection.gameObject; bool activeObjectSelectionChanged = Selection.gameObjects.Contains(s_Selection.gameObject) && s_Selection.gameObject != Selection.activeGameObject; if (s_Selection.mesh != null) { var mesh = s_Selection.mesh; foreach (var face in s_Selection.faces) { // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts) MaterialEditor matEditor = MaterialEditor.instance; if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, face)) { return(null); } UVEditor uvEditor = UVEditor.instance; if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, face)) { return(null); } var faces = mesh.faces as Face[] ?? mesh.faces.ToArray(); var ind = Array.IndexOf <Face>(faces, face); var sel = mesh.selectedFaceIndexes.IndexOf(ind); UndoUtility.RecordSelection(mesh, "Select Face"); if (sel > -1) { if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && face == mesh.GetActiveFace() && !activeObjectSelectionChanged)) { mesh.RemoveFromFaceSelectionAtIndex(sel); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedFaceCount == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedFaceCount > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedFaceIndicesInternal = mesh.selectedFaceIndicesInternal.Remove(ind); mesh.SetSelectedFaces(mesh.selectedFaceIndicesInternal.Add(ind)); } } else if (pathSelectionModifier && mesh.GetActiveFace() != null) { var pathFaces = SelectPathFaces.GetPath(mesh, Array.IndexOf <Face>(faces, mesh.GetActiveFace()), Array.IndexOf <Face>(faces, face)); foreach (var pathFace in pathFaces) { mesh.AddToFaceSelection(pathFace); } } else { mesh.AddToFaceSelection(ind); } } foreach (var edge in s_Selection.edges) { int ind = mesh.IndexOf(mesh.selectedEdges, edge); UndoUtility.RecordSelection(mesh, "Select Edge"); if (ind > -1) { if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && edge == mesh.GetActiveEdge() && !activeObjectSelectionChanged)) { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind)); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedEdgeCount == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedEdgeCount > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedEdgesInternal = mesh.selectedEdgesInternal.Remove(edge); mesh.SetSelectedEdges(mesh.selectedEdgesInternal.Add(edge)); } } else { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(edge)); } } foreach (var vertex in s_Selection.vertexes) { int ind = Array.IndexOf(mesh.selectedIndexesInternal, vertex); UndoUtility.RecordSelection(mesh, "Select Vertex"); if (ind > -1) { var sharedIndex = mesh.sharedVertexLookup[vertex]; var sharedVertex = mesh.sharedVerticesInternal[sharedIndex]; s_IndexBuffer.Clear(); foreach (var sVertex in sharedVertex) { var index = Array.IndexOf(mesh.selectedIndexesInternal, sVertex); if (index < 0) { continue; } s_IndexBuffer.Add(index); } s_IndexBuffer.Sort(); if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && vertex == mesh.GetActiveVertex() && !activeObjectSelectionChanged)) { mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer); mesh.SetSelectedVertices(mesh.selectedIndexesInternal); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedIndexesInternal.Length == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedIndexesInternal.Length > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer); mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex)); } } else { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex)); } } if (activeObjectSelectionChanged) { MeshSelection.MakeActiveObject(candidateNewActiveObject); } else { MeshSelection.AddToSelection(candidateNewActiveObject); } return(mesh); } return(null); }
void DoPointPlacement() { Event evt = Event.current; EventType eventType = evt.type; if (m_PlacingPoint) { Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (eventType == EventType.MouseDrag) { float hitDistance = Mathf.Infinity; if (m_Plane.Raycast(ray, out hitDistance)) { evt.Use(); polygon.m_Points[m_SelectedIndex] = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(ray.GetPoint(hitDistance)), Vector3.one); RebuildPolyShapeMesh(false); SceneView.RepaintAll(); } } if (eventType == EventType.MouseUp || eventType == EventType.Ignore || eventType == EventType.KeyDown || eventType == EventType.KeyUp) { evt.Use(); m_PlacingPoint = false; m_SelectedIndex = -1; SceneView.RepaintAll(); } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path) { if (eventType == EventType.MouseDown) { if (polygon.m_Points.Count < 1) { SetupInputPlane(evt.mousePosition); } float hitDistance = Mathf.Infinity; Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (m_Plane.Raycast(ray, out hitDistance)) { UndoUtility.RecordObject(polygon, "Add Polygon Shape Point"); Vector3 hit = ray.GetPoint(hitDistance); if (polygon.m_Points.Count < 1) { polygon.transform.position = polygon.isOnGrid ? ProGridsInterface.ProGridsSnap(hit) : hit; polygon.transform.rotation = Quaternion.LookRotation(m_Plane.normal) * Quaternion.Euler(new Vector3(90f, 0f, 0f)); } Vector3 point = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(hit), Vector3.one); if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point)) { m_NextMouseUpAdvancesMode = true; return; } polygon.m_Points.Add(point); m_PlacingPoint = true; m_SelectedIndex = polygon.m_Points.Count - 1; RebuildPolyShapeMesh(polygon); evt.Use(); } } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit) { if (polygon.m_Points.Count < 3) { SetPolyEditMode(PolyShape.PolyEditMode.Path); return; } if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl) { // point insertion int index; float distanceToLine; Vector3 p = EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distanceToLine, true, polygon.transform); Vector3 wp = polygon.transform.TransformPoint(p); Vector2 ga = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polygon.m_Points.Count])); Vector2 gb = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[(index - 1)])); Vector2 mouse = evt.mousePosition; float distanceToVertex = Mathf.Min(Vector2.Distance(mouse, ga), Vector2.Distance(mouse, gb)); if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl) { Handles.color = Color.green; Handles.DotHandleCap(-1, wp, Quaternion.identity, HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type); if (evt.type == EventType.MouseDown) { evt.Use(); UndoUtility.RecordObject(polygon, "Insert Point"); polygon.m_Points.Insert(index, p); m_SelectedIndex = index; m_PlacingPoint = true; RebuildPolyShapeMesh(true); OnBeginVertexMovement(); } Handles.color = Color.white; } } } }
void OnSceneGUI(SceneView sceneView) { #if !UNITY_2018_2_OR_NEWER if (s_ResetOnSceneGUIState != null) { s_ResetOnSceneGUIState.Invoke(sceneView, null); } #endif SceneStyles.Init(); m_CurrentEvent = Event.current; EditorMeshHandles.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode); DrawHandleGUI(sceneView); #if SHORTCUT_MANAGER // Escape isn't assignable as a shortcut if (m_CurrentEvent.type == EventType.KeyDown) { if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object) { selectMode = SelectMode.Object; m_CurrentEvent.Use(); } } #else if (m_CurrentEvent.type == EventType.MouseDown && m_CurrentEvent.button == 1) { m_IsRightMouseDown = true; } if (m_CurrentEvent.type == EventType.MouseUp && m_CurrentEvent.button == 1 || m_CurrentEvent.type == EventType.Ignore) { m_IsRightMouseDown = false; } if (!m_IsRightMouseDown && (m_CurrentEvent.type == EventType.KeyUp ? m_CurrentEvent.keyCode : KeyCode.None) != KeyCode.None) { if (ShortcutCheck(m_CurrentEvent)) { m_CurrentEvent.Use(); return; } } if (m_CurrentEvent.type == EventType.KeyDown) { if (s_Shortcuts.value.Any(x => x.Matches(m_CurrentEvent.keyCode, m_CurrentEvent.modifiers))) { m_CurrentEvent.Use(); } } #endif if (selectMode == SelectMode.Object) { return; } // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight && m_CurrentEvent.type == EventType.MouseMove && selectMode.IsMeshElementMode()) { m_Hovering.CopyTo(m_HoveringPrevious); if (GUIUtility.hotControl != 0 || EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance) { m_Hovering.Clear(); } if (!m_Hovering.Equals(m_HoveringPrevious)) { SceneView.RepaintAll(); } } if (Tools.current == Tool.View) { return; } // Overrides the toolbar transform tools if (Tools.current != Tool.None && Tools.current != m_CurrentTool) { SetTool_Internal(Tools.current); } Tools.current = Tool.None; if (selectMode.IsMeshElementMode() && MeshSelection.selectedVertexCount > 0) { var tool = GetToolForSelectMode(m_CurrentTool, s_SelectMode); if (tool != null) { tool.OnSceneGUI(m_CurrentEvent); } } if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent) || m_CurrentEvent.isKey) { m_IsDragging = false; if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } return; } // This prevents us from selecting other objects in the scene, // and allows for the selection of faces / vertices. m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(m_DefaultControl); if (m_CurrentEvent.type == EventType.MouseDown && HandleUtility.nearestControl == m_DefaultControl) { // double clicking object if (m_CurrentEvent.clickCount > 1) { DoubleClick(m_CurrentEvent); } m_InitialMousePosition = m_CurrentEvent.mousePosition; // readyForMouseDrag prevents a bug wherein after ending a drag an errant // MouseDrag event is sent with no corresponding MouseDown/MouseUp event. m_IsReadyForMouseDrag = true; GUIUtility.hotControl = m_DefaultControl; } if (m_CurrentEvent.type == EventType.MouseDrag && m_IsReadyForMouseDrag && GUIUtility.hotControl == m_DefaultControl) { if (!m_IsDragging && Vector2.Distance(m_CurrentEvent.mousePosition, m_InitialMousePosition) > k_MouseDragThreshold) { sceneView.Repaint(); m_IsDragging = true; } } if (m_CurrentEvent.type == EventType.Ignore) { if (m_IsDragging) { m_IsReadyForMouseDrag = false; m_IsDragging = false; EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences); } if (m_WasDoubleClick) { m_WasDoubleClick = false; } if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } } if (m_CurrentEvent.type == EventType.MouseUp && GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; if (m_WasDoubleClick) { m_WasDoubleClick = false; } else { if (!m_IsDragging) { if (UVEditor.instance) { UVEditor.instance.ResetUserPivot(); } EditorSceneViewPicker.DoMouseClick(m_CurrentEvent, selectMode, m_ScenePickerPreferences); UpdateSelection(); SceneView.RepaintAll(); } else { m_IsDragging = false; m_IsReadyForMouseDrag = false; if (UVEditor.instance) { UVEditor.instance.ResetUserPivot(); } EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences); if (GUIUtility.hotControl == m_DefaultControl) { GUIUtility.hotControl = 0; } } } } }
void DoExistingPointsGUI() { Transform trs = polygon.transform; int len = polygon.m_Points.Count; Vector3 up = polygon.transform.up; Vector3 right = polygon.transform.right; Vector3 forward = polygon.transform.forward; Vector3 center = Vector3.zero; Event evt = Event.current; bool used = evt.type == EventType.Used; if (!used && (evt.type == EventType.MouseDown && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers))) { m_SelectedIndex = -1; Repaint(); } if (polygon.polyEditMode == PolyShape.PolyEditMode.Height) { if (!used && evt.type == EventType.MouseUp && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers)) { evt.Use(); SetPolyEditMode(PolyShape.PolyEditMode.Edit); } bool sceneInUse = EditorHandleUtility.SceneViewInUse(evt); Ray r = HandleUtility.GUIPointToWorldRay(evt.mousePosition); Vector3 origin = polygon.transform.TransformPoint(Math.Average(polygon.m_Points)); float extrude = polygon.extrude; if (evt.type == EventType.MouseMove && !sceneInUse) { Vector3 p = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction); extrude = ProGridsInterface.ProGridsSnap(s_HeightMouseOffset + Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up))); } Vector3 extrudePoint = origin + (extrude * up); Handles.color = k_HandleColor; Handles.DotHandleCap(-1, origin, Quaternion.identity, HandleUtility.GetHandleSize(origin) * k_HandleSize, evt.type); Handles.color = k_HandleColorGreen; Handles.DrawLine(origin, extrudePoint); Handles.DotHandleCap(-1, extrudePoint, Quaternion.identity, HandleUtility.GetHandleSize(extrudePoint) * k_HandleSize, evt.type); Handles.color = Color.white; if (!sceneInUse && polygon.extrude != extrude) { OnBeginVertexMovement(); polygon.extrude = extrude; RebuildPolyShapeMesh(false); } } else { // vertex dots for (int ii = 0; ii < len; ii++) { Vector3 point = trs.TransformPoint(polygon.m_Points[ii]); center.x += point.x; center.y += point.y; center.z += point.z; float size = HandleUtility.GetHandleSize(point) * k_HandleSize; Handles.color = ii == m_SelectedIndex ? k_HandleSelectedColor : k_HandleColor; EditorGUI.BeginChangeCheck(); point = Handles.Slider2D(point, up, right, forward, size, Handles.DotHandleCap, Vector2.zero, true); if (EditorGUI.EndChangeCheck()) { UndoUtility.RecordObject(polygon, "Move Polygon Shape Point"); Vector3 snapMask = Snapping.GetSnappingMaskBasedOnNormalVector(m_Plane.normal); polygon.m_Points[ii] = ProGridsInterface.ProGridsSnap(trs.InverseTransformPoint(point), snapMask); OnBeginVertexMovement(); RebuildPolyShapeMesh(false); } // "clicked" a button if (!used && evt.type == EventType.Used) { if (ii == 0 && polygon.m_Points.Count > 2 && polygon.polyEditMode == PolyShape.PolyEditMode.Path) { m_NextMouseUpAdvancesMode = true; return; } else { used = true; m_SelectedIndex = ii; } } } Handles.color = Color.white; // height setting if (polygon.polyEditMode != PolyShape.PolyEditMode.Path && polygon.m_Points.Count > 2) { center.x /= (float)len; center.y /= (float)len; center.z /= (float)len; Vector3 extrude = center + (up * polygon.extrude); m_DistanceFromHeightHandle = Vector2.Distance(HandleUtility.WorldToGUIPoint(extrude), evt.mousePosition); EditorGUI.BeginChangeCheck(); Handles.color = k_HandleColor; Handles.DotHandleCap(-1, center, Quaternion.identity, HandleUtility.GetHandleSize(center) * k_HandleSize, evt.type); Handles.DrawLine(center, extrude); Handles.color = k_HandleColorGreen; extrude = Handles.Slider(extrude, up, HandleUtility.GetHandleSize(extrude) * k_HandleSize, Handles.DotHandleCap, 0f); Handles.color = Color.white; if (EditorGUI.EndChangeCheck()) { UndoUtility.RecordObject(polygon, "Set Polygon Shape Height"); polygon.extrude = ProGridsInterface.ProGridsSnap(Vector3.Distance(extrude, center) * Mathf.Sign(Vector3.Dot(up, extrude - center))); OnBeginVertexMovement(); RebuildPolyShapeMesh(false); } } } }
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(); }