public override void SetSelection(MeshSelection selection) { m_vertexSelection.Clear(); m_selection.Clear(); foreach (KeyValuePair <ProBuilderMesh, IList <int> > kvp in selection.SelectedIndices) { m_vertexSelection.Add(kvp.Key, kvp.Value); } }
public override void SetSelection(MeshSelection selection) { m_edgeSelection.Clear(); m_selection.Clear(); foreach (KeyValuePair <ProBuilderMesh, IList <Edge> > kvp in selection.SelectedEdges) { m_edgeSelection.Add(kvp.Key, kvp.Value); } }
public static float PickVertex(Camera camera, Vector3 mousePosition, float maxDistance, GameObject pickedObject, IEnumerable <ProBuilderMesh> meshes, bool depthTest, ref SceneSelection selection) { // selection.Clear(); m_nearestVertices.Clear(); maxDistance = maxDistance * maxDistance; if (pickedObject != null) { ProBuilderMesh mesh = pickedObject.GetComponent <ProBuilderMesh>(); if (mesh != null) { GetNearestVertices(camera, mesh, mousePosition, m_nearestVertices, maxDistance, 1.0f); } } foreach (ProBuilderMesh mesh in meshes) { if (!mesh.selectable) { continue; } GetNearestVertices(camera, mesh, mousePosition, m_nearestVertices, maxDistance, 1.0f); } m_nearestVertices.Sort((x, y) => x.screenDistance.CompareTo(y.screenDistance)); ProBuilderMesh selectedMesh = selection.mesh; int selectedVertex = selection.vertex; selection.Clear(); int startIndex = 0; for (int i = 0; i < m_nearestVertices.Count; i++) { VertexPickerEntry pickerEntry = m_nearestVertices[i]; if (pickerEntry.mesh == selectedMesh && pickerEntry.vertex == selectedVertex) { startIndex = i + 1; startIndex %= m_nearestVertices.Count; } } for (int i = startIndex; i < m_nearestVertices.Count; i++) { if (!depthTest || !PointIsOccluded(camera, m_nearestVertices[i].mesh, m_nearestVertices[i].worldPosition)) { selection.gameObject = m_nearestVertices[i].mesh.gameObject; selection.mesh = m_nearestVertices[i].mesh; selection.vertex = m_nearestVertices[i].vertex; return(Mathf.Sqrt(m_nearestVertices[i].screenDistance)); } } return(Mathf.Infinity); }
public override void SetSelection(MeshSelection selection) { m_vertexSelection.Clear(); m_selection.Clear(); if (selection != null) { selection = selection.ToVertices(false); foreach (KeyValuePair <GameObject, IList <int> > kvp in selection.SelectedIndices) { PBMesh pbMesh = kvp.Key.GetComponent <PBMesh>(); if (pbMesh.IsMarkedAsDestroyed) { continue; } m_vertexSelection.Add(kvp.Key.GetComponent <ProBuilderMesh>(), kvp.Value); } } }
static float VertexRaycast(Vector3 mousePosition, ScenePickerPreferences pickerOptions, bool allowUnselected, SceneSelection selection) { Camera cam = SceneView.lastActiveSceneView.camera; selection.Clear(); s_NearestVertices.Clear(); selection.gameObject = HandleUtility.PickGameObject(mousePosition, false); float maxDistance = ScenePickerPreferences.maxPointerDistance * ScenePickerPreferences.maxPointerDistance; ProBuilderMesh hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; if (allowUnselected && selection.gameObject != null) { if (hoveredMesh != null && hoveredMesh.selectable && !MeshSelection.Contains(hoveredMesh)) { GetNearestVertices(hoveredMesh, mousePosition, s_NearestVertices, maxDistance, 1); } } if (selection.mesh == null) { foreach (var mesh in MeshSelection.topInternal) { if (!mesh.selectable) { continue; } GetNearestVertices(mesh, mousePosition, s_NearestVertices, maxDistance, hoveredMesh == mesh || hoveredMesh == null ? 1.0f : ScenePickerPreferences.offPointerMultiplier); } } s_NearestVertices.Sort((x, y) => x.screenDistance.CompareTo(y.screenDistance)); for (int i = 0; i < s_NearestVertices.Count; i++) { if (!UnityEngine.ProBuilder.HandleUtility.PointIsOccluded(cam, s_NearestVertices[i].mesh, s_NearestVertices[i].worldPosition)) { selection.gameObject = s_NearestVertices[i].mesh.gameObject; selection.mesh = s_NearestVertices[i].mesh; selection.SetSingleVertex(s_NearestVertices[i].vertex); return(Mathf.Sqrt(s_NearestVertices[i].screenDistance)); } } return(Mathf.Infinity); }
public override MeshSelection ClearSelection() { MeshSelection selection = new MeshSelection(); foreach (ProBuilderMesh mesh in m_edgeSelection.Meshes) { selection.UnselectedEdges.Add(mesh, m_edgeSelection.GetEdges(mesh).ToArray()); } m_edgeSelection.Clear(); m_selection.Clear(); if (selection.UnselectedEdges.Count > 0) { return(selection); } return(null); }
public static float PickVertex(Camera camera, Vector3 mousePosition, float maxDistance, Transform transform, IList <Vector3> positions, ref SceneSelection selection) { selection.Clear(); m_nearestVertices.Clear(); maxDistance = maxDistance * maxDistance; GetNearestVertices(camera, transform, positions, mousePosition, m_nearestVertices, maxDistance, 1.0f); m_nearestVertices.Sort((x, y) => x.screenDistance.CompareTo(y.screenDistance)); for (int i = 0; i < m_nearestVertices.Count;) { //selection.gameObject = m_nearestVertices[i].mesh.gameObject; //selection.mesh = m_nearestVertices[i].mesh; selection.vertex = m_nearestVertices[i].vertex; return(Mathf.Sqrt(m_nearestVertices[i].screenDistance)); } return(Mathf.Infinity); }
public static float PickEdge(Camera camera, Vector3 mousePosition, float maxDistance, GameObject pickedObject, IEnumerable <ProBuilderMesh> meshes, ref SceneSelection selection) { selection.Clear(); selection.gameObject = pickedObject; ProBuilderMesh hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; float bestDistance = maxDistance; float unselectedBestDistance = maxDistance; //bool hoveredIsInSelection = meshes.Contains(hoveredMesh); //const bool allowUnselected = true; //if (hoveredMesh != null && (allowUnselected || hoveredIsInSelection)) if (hoveredMesh != null) { EdgeAndDistance tup = GetNearestEdgeOnMesh(camera, hoveredMesh, mousePosition); if (tup.edge.IsValid() && tup.distance < maxDistance) { selection.gameObject = hoveredMesh.gameObject; selection.mesh = hoveredMesh; selection.edge = tup.edge; unselectedBestDistance = tup.distance; // if it's in the selection, it automatically wins as best. if not, treat this is a fallback. //if (hoveredIsInSelection) { return(tup.distance); } } } foreach (ProBuilderMesh mesh in meshes) { Transform trs = mesh.transform; IList <Vector3> positions = mesh.positions; m_edges.Clear(); //When the pointer is over another object, apply a modifier to the distance to prefer picking the object hovered over the currently selected //var distMultiplier = (hoveredMesh == mesh || hoveredMesh == null) ? 1.0f : pickerPrefs.offPointerMultiplier; const float distMultiplier = 1.0f; foreach (Face face in mesh.faces) { foreach (Edge edge in face.edges) { int x = edge.a; int y = edge.b; float d = DistanceToLine(camera, mousePosition, trs.TransformPoint(positions[x]), trs.TransformPoint(positions[y])); d *= distMultiplier; if (d == bestDistance) { m_edges.Add(new Edge(x, y)); } else if (d < bestDistance) { m_edges.Clear(); m_edges.Add(new Edge(x, y)); selection.gameObject = mesh.gameObject; selection.mesh = mesh; selection.edge = new Edge(x, y); bestDistance = d; } } } //If more than 1 edge is closest, the closest is one of the vertex. //Get closest edge to the camera. if (m_edges.Count > 1) { selection.edge = GetClosestEdgeToCamera(camera, mousePosition, positions, m_edges); } } if (selection.gameObject != null) { if (bestDistance < maxDistance) { return(bestDistance); } return(Mathf.Infinity);// unselectedBestDistance; } return(Mathf.Infinity); }
static float EdgeRaycast(Vector3 mousePosition, ScenePickerPreferences pickerPrefs, bool allowUnselected, SceneSelection selection) { selection.Clear(); selection.gameObject = UHandleUtility.PickGameObject(mousePosition, false); var hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; float bestDistance = pickerPrefs.maxPointerDistance; float unselectedBestDistance = bestDistance; bool hoveredIsInSelection = MeshSelection.topInternal.Contains(hoveredMesh); if (hoveredMesh != null && (allowUnselected || hoveredIsInSelection)) { var tup = GetNearestEdgeOnMesh(hoveredMesh, mousePosition); if (tup.edge.IsValid() && tup.distance < pickerPrefs.maxPointerDistance) { selection.gameObject = hoveredMesh.gameObject; selection.mesh = hoveredMesh; selection.edge = tup.edge; unselectedBestDistance = tup.distance; // if it's in the selection, it automatically wins as best. if not, treat this is a fallback. if (hoveredIsInSelection) { return(tup.distance); } } } foreach (var mesh in MeshSelection.topInternal) { var trs = mesh.transform; var positions = mesh.positionsInternal; foreach (var face in mesh.facesInternal) { foreach (var edge in face.edges) { int x = edge.a; int y = edge.b; float d = UHandleUtility.DistanceToLine( trs.TransformPoint(positions[x]), trs.TransformPoint(positions[y])); if (d < bestDistance) { selection.gameObject = mesh.gameObject; selection.mesh = mesh; selection.edge = new Edge(x, y); bestDistance = d; } } } } if (selection.gameObject != null) { if (bestDistance < pickerPrefs.maxPointerDistance) { return(bestDistance); } return(unselectedBestDistance); } return(Mathf.Infinity); }
static float VertexRaycast(Vector3 mousePosition, ScenePickerPreferences pickerOptions, bool allowUnselected, SceneSelection selection) { Camera cam = SceneView.lastActiveSceneView.camera; selection.Clear(); s_NearestVertices.Clear(); selection.gameObject = HandleUtility.PickGameObject(mousePosition, false); float maxDistance = pickerOptions.maxPointerDistance * pickerOptions.maxPointerDistance; if (allowUnselected && selection.gameObject != null) { var mesh = selection.gameObject.GetComponent <ProBuilderMesh>(); if (mesh != null && mesh.selectable && !MeshSelection.Contains(mesh)) { var matches = GetNearestVertices(mesh, mousePosition, s_NearestVertices, maxDistance); for (int i = 0; i < matches; i++) { // Append `maxDistance` so that selected meshes are favored s_NearestVertices[i] = new VertexPickerEntry() { mesh = s_NearestVertices[i].mesh, vertex = s_NearestVertices[i].vertex, screenDistance = s_NearestVertices[i].screenDistance + maxDistance, worldPosition = s_NearestVertices[i].worldPosition }; } } } if (selection.mesh == null) { foreach (var mesh in MeshSelection.topInternal) { if (!mesh.selectable) { continue; } GetNearestVertices(mesh, mousePosition, s_NearestVertices, maxDistance); } } s_NearestVertices.Sort((x, y) => x.screenDistance.CompareTo(y.screenDistance)); for (int i = 0; i < s_NearestVertices.Count; i++) { if (!UnityEngine.ProBuilder.HandleUtility.PointIsOccluded(cam, s_NearestVertices[i].mesh, s_NearestVertices[i].worldPosition)) { selection.gameObject = s_NearestVertices[i].mesh.gameObject; selection.mesh = s_NearestVertices[i].mesh; selection.vertex = s_NearestVertices[i].vertex; // If mesh was unselected, remove the distance modifier if (s_NearestVertices[i].screenDistance > maxDistance) { return(Mathf.Sqrt(s_NearestVertices[i].screenDistance - maxDistance)); } return(Mathf.Sqrt(s_NearestVertices[i].screenDistance)); } } return(Mathf.Infinity); }
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); }
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; } } } } }
/// <summary> /// Get the nearest <see cref="Edge"/> to a screen position. /// </summary> /// <returns> /// Distance is returned as the screen distance to mesh, not edge. /// </returns> static float EdgeRaycast(Vector3 mousePosition, ScenePickerPreferences pickerPrefs, bool allowUnselected, SceneSelection selection) { selection.Clear(); selection.gameObject = UHandleUtility.PickGameObject(mousePosition, false); var hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; float bestDistance = Mathf.Infinity; bool hoveredIsInSelection = MeshSelection.topInternal.Contains(hoveredMesh); if (hoveredMesh != null && (allowUnselected || hoveredIsInSelection)) { var tup = GetNearestEdgeOnMesh(hoveredMesh, mousePosition); if (tup.edge.IsValid()) { selection.gameObject = hoveredMesh.gameObject; selection.mesh = hoveredMesh; selection.SetSingleEdge(tup.edge); bestDistance = tup.distance; // If the nearest edge was acquired by a raycast, then the distance to mesh is 0f. if (hoveredIsInSelection) { return(tup.distance); } } } foreach (var mesh in MeshSelection.topInternal) { var trs = mesh.transform; var positions = mesh.positionsInternal; s_EdgeBuffer.Clear(); // When the pointer is over another object, apply a modifier to the distance to prefer picking the // object hovered over the currently selected var distMultiplier = (hoveredMesh == mesh || hoveredMesh == null) ? 1.0f : ScenePickerPreferences.offPointerMultiplier; foreach (var face in mesh.facesInternal) { foreach (var edge in face.edges) { int x = edge.a; int y = edge.b; float d = UHandleUtility.DistanceToLine( trs.TransformPoint(positions[x]), trs.TransformPoint(positions[y])); d *= distMultiplier; // best distance isn't set to maxPointerDistance because we want to preserve an unselected // gameobject over a selected gameobject with an out of bounds edge. if (d > ScenePickerPreferences.maxPointerDistance) { continue; } // account for stacked edges if (Mathf.Approximately(d, bestDistance)) { s_EdgeBuffer.Add(new Edge(x, y)); } else if (d < bestDistance) { s_EdgeBuffer.Clear(); s_EdgeBuffer.Add(new Edge(x, y)); selection.gameObject = mesh.gameObject; selection.mesh = mesh; selection.SetSingleEdge(new Edge(x, y)); bestDistance = d; } } } // If more than 1 edge is closest, the closest is one of the vertex. // Get closest edge to the camera. if (s_EdgeBuffer.Count > 1) { selection.SetSingleEdge(GetClosestEdgeToCamera(positions, s_EdgeBuffer)); } } return(selection.gameObject != null ? bestDistance : Mathf.Infinity); }
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); }
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; } } } } }
static float EdgeRaycast(Vector3 mousePosition, ScenePickerPreferences pickerPrefs, bool allowUnselected, SceneSelection selection) { selection.Clear(); selection.gameObject = UHandleUtility.PickGameObject(mousePosition, false); var hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; float bestDistance = pickerPrefs.maxPointerDistance; float unselectedBestDistance = bestDistance; bool hoveredIsInSelection = MeshSelection.topInternal.Contains(hoveredMesh); if (hoveredMesh != null && (allowUnselected || hoveredIsInSelection)) { var tup = GetNearestEdgeOnMesh(hoveredMesh, mousePosition); if (tup.edge.IsValid() && tup.distance < pickerPrefs.maxPointerDistance) { selection.gameObject = hoveredMesh.gameObject; selection.mesh = hoveredMesh; selection.edge = tup.edge; unselectedBestDistance = tup.distance; // if it's in the selection, it automatically wins as best. if not, treat this is a fallback. if (hoveredIsInSelection) { return(tup.distance); } } } foreach (var mesh in MeshSelection.topInternal) { var trs = mesh.transform; var positions = mesh.positionsInternal; s_EdgeBuffer.Clear(); //When the pointer is over another object, apply a modifier to the distance to prefer picking the object hovered over the currently selected var distMultiplier = (hoveredMesh == mesh || hoveredMesh == null) ? 1.0f : pickerPrefs.offPointerMultiplier; foreach (var face in mesh.facesInternal) { foreach (var edge in face.edges) { int x = edge.a; int y = edge.b; float d = UHandleUtility.DistanceToLine( trs.TransformPoint(positions[x]), trs.TransformPoint(positions[y])); d *= distMultiplier; if (d == bestDistance) { s_EdgeBuffer.Add(new Edge(x, y)); } else if (d < bestDistance) { s_EdgeBuffer.Clear(); s_EdgeBuffer.Add(new Edge(x, y)); selection.gameObject = mesh.gameObject; selection.mesh = mesh; selection.edge = new Edge(x, y); bestDistance = d; } } } //If more than 1 edge is closest, the closest is one of the vertex. //Get closest edge to the camera. if (s_EdgeBuffer.Count > 1) { selection.edge = GetClosestEdgeToCamera(positions, s_EdgeBuffer); } } if (selection.gameObject != null) { if (bestDistance < pickerPrefs.maxPointerDistance) { return(bestDistance); } return(unselectedBestDistance); } return(Mathf.Infinity); }
public static float PickEdge(Camera camera, Vector3 mousePosition, float maxDistance, GameObject pickedObject, IEnumerable <ProBuilderMesh> meshes, bool depthTest, ref SceneSelection selection) { selection.Clear(); selection.gameObject = pickedObject; ProBuilderMesh hoveredMesh = selection.gameObject != null?selection.gameObject.GetComponent <ProBuilderMesh>() : null; float bestDistance = maxDistance; float unselectedBestDistance = maxDistance; if (hoveredMesh != null) { EdgeAndDistance tup = GetNearestEdgeOnMesh(camera, hoveredMesh, mousePosition); if (tup.edge.IsValid() && tup.distance < maxDistance) { selection.gameObject = hoveredMesh.gameObject; selection.mesh = hoveredMesh; selection.edge = tup.edge; unselectedBestDistance = tup.distance; // if it's in the selection, it automatically wins as best. if not, treat this is a fallback. //if (hoveredIsInSelection) { return(tup.distance); } } } ProBuilderMesh pickedMesh = pickedObject != null?pickedObject.GetComponent <ProBuilderMesh>() : null; HashSet <ProBuilderMesh> hs = new HashSet <ProBuilderMesh>(); foreach (ProBuilderMesh mesh in meshes) { if (!hs.Contains(mesh)) { hs.Add(mesh); } } if (pickedMesh != null && !hs.Contains(pickedMesh)) { hs.Add(pickedMesh); } foreach (ProBuilderMesh mesh in hs) { Transform trs = mesh.transform; IList <Vector3> positions = mesh.positions; m_edges.Clear(); const float distMultiplier = 1.0f; foreach (Face face in mesh.faces) { foreach (Edge edge in face.edges) { int x = edge.a; int y = edge.b; Vector3 projectedPoint; Vector3 p0 = trs.TransformPoint(positions[x]); Vector3 p1 = trs.TransformPoint(positions[y]); float d = MathHelper.DistanceToLine(camera, mousePosition, p0, p1, out projectedPoint); if (depthTest) { Ray ray = camera.ScreenPointToRay(projectedPoint); Vector3 cpl0; Vector3 cpl1; if (MathHelper.ClosestPointsOnTwoLines(out cpl0, out cpl1, ray.origin, ray.direction, p0, p1 - p0)) { if (PointIsOccluded(camera, mesh, cpl1)) { continue; } } } d *= distMultiplier; if (d == bestDistance) { m_edges.Add(new Edge(x, y)); } else if (d < bestDistance) { m_edges.Clear(); m_edges.Add(new Edge(x, y)); selection.gameObject = mesh.gameObject; selection.mesh = mesh; selection.edge = new Edge(x, y); bestDistance = d; } } } //If more than 1 edge is closest, the closest is one of the vertex. //Get closest edge to the camera. if (m_edges.Count > 1) { selection.edge = GetClosestEdgeToCamera(camera, mousePosition, positions, m_edges); } } if (selection.gameObject != null) { if (bestDistance < maxDistance) { return(bestDistance); } return(Mathf.Infinity);// unselectedBestDistance; } return(Mathf.Infinity); }