public static void DoMouseHover(SceneSelection selection) { if (selection.faces.Count == 0) { return; } var mesh = selection.mesh; var face = selection.faces[0]; var activeFace = mesh.GetActiveFace(); if (activeFace == null || activeFace == face) { return; } var faces = mesh.facesInternal; var pathFaces = SelectPathFaces.GetPath(mesh, Array.IndexOf <Face>(faces, activeFace), Array.IndexOf <Face>(faces, face)); if (pathFaces != null) { foreach (var path in pathFaces) { selection.faces.Add(faces[path]); } } }
public static void DrawHighlight(SceneSelection highlight) { if (Event.current.type == EventType.Repaint && highlight != null) { UnityEditorProBuilderDynamic.EditorMeshHandles.DrawSceneSelection(highlight); } }
public static void DrawHighlight(SceneSelection highlight) { if (Event.current.type == EventType.Repaint && highlight != null) { #if PROBUILDER_4_4_OR_NEWER UnityEditorProBuilderDynamic.EditorHandleDrawing.DrawSceneSelection(highlight); #else UnityEditorProBuilderDynamic.EditorMeshHandles.DrawSceneSelection(highlight); #endif } }
public static void OpenSceneSelection() { var lastScene = Instance.currentScene; var selection = new SceneSelection(); selection.Load(); Instance.currentScene = selection; Instance.sceneSelection = selection; SceneManager.LoadSceneAsync("Scenes/SceneSelection"); CloseScene(lastScene); }
public static void DrawSceneSelection(SceneSelection selection) { var mesh = selection.mesh; if (mesh == null) { return; } var positions = mesh.positionsInternal; // Draw nearest edge if (selection.face != null) { using (new TriangleDrawingScope(s_PreselectionColor)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); var face = selection.face; var ind = face.indexes; for (int i = 0, c = ind.Count; i < c; i += 3) { GL.Vertex(positions[ind[i]]); GL.Vertex(positions[ind[i + 1]]); GL.Vertex(positions[ind[i + 2]]); } } } else if (selection.edge != Edge.Empty) { using (var drawingScope = new LineDrawingScope(s_PreselectionColor, -1f, CompareFunction.Always)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); drawingScope.DrawLine(positions[selection.edge.a], positions[selection.edge.b]); } } else if (selection.vertex > -1) { using (var drawingScope = new PointDrawingScope(s_PreselectionColor, CompareFunction.Always) { matrix = mesh.transform.localToWorldMatrix }) { drawingScope.Draw(positions[selection.vertex]); } } }
void DrawSceneSelectionInternal(SceneSelection selection) { var mesh = selection.mesh; if (mesh == null) { return; } var positions = mesh.positionsInternal; // Draw nearest edge if (selection.face != null) { using (new TriangleDrawingScope(preselectionColor)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); var face = selection.face; var ind = face.indexes; for (int i = 0, c = ind.Count; i < c; i += 3) { GL.Vertex(positions[ind[i]]); GL.Vertex(positions[ind[i + 1]]); GL.Vertex(positions[ind[i + 2]]); } } } else if (selection.edge != Edge.Empty) { using (var drawingScope = new LineDrawingScope(preselectionColor, -1f, CompareFunction.Always)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); drawingScope.DrawLine(positions[selection.edge.a], positions[selection.edge.b]); } } else if (selection.vertex > -1) { var size = dotCapSize; using (new Handles.DrawingScope(preselectionColor, mesh.transform.localToWorldMatrix)) { var pos = positions[selection.vertex]; Handles.DotHandleCap(-1, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * size, Event.current.type); } } }
// Get the object & mesh selection that the mouse is currently nearest. // A ProBuilderMesh is returned because double click actions need to know what the last selected pb_Object was. // If deepClickOffset is specified, the object + deepClickOffset in the deep select stack will be returned (instead of next). internal static float MouseRayHitTest( Vector3 mousePosition, SelectMode selectionMode, ScenePickerPreferences pickerOptions, SceneSelection selection, bool allowUnselected = false) { if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { return(EdgeRaycast(mousePosition, pickerOptions, allowUnselected, selection)); } if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) { return(VertexRaycast(mousePosition, pickerOptions, allowUnselected, selection)); } return(FaceRaycast(mousePosition, pickerOptions, allowUnselected, selection, 0, true)); }
public bool Click(Camera camera, Vector3 pointer) { if (!m_isEditing) { return(false); } SceneSelection selection = new SceneSelection(); float result = PBUtility.PickVertex(camera, pointer, 20, m_selection.Transform, m_selection.Positions, ref selection); if (result != Mathf.Infinity) { if (m_selection.Positions.Count >= 3) { m_selection.Unselect(); m_selection.Select(selection.vertex); return(true); } } else { if (Stage == 0) { Ray ray = camera.ScreenPointToRay(pointer); float enter; Plane plane = new Plane(m_selection.transform.up, m_selection.transform.position); if (plane.Raycast(ray, out enter)) { Vector3 position = ray.GetPoint(enter); position = m_selection.Transform.InverseTransformPoint(position); m_selection.Add(position); m_positions.Add(position); } m_target.CreateShapeFromPolygon(m_selection.Positions, 0.001f, false); } } return(false); }
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); }
/// <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); }
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); }
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 void ClearProBuilderHighlight() { highlight = null; proBuilderHighlight = null; SceneView.RepaintAll(); }
public static void ProBuilderHighlight(SceneSelection selection) { highlight = selection.gameObject; proBuilderHighlight = selection; SceneView.RepaintAll(); }
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); }
public static float PickVertex(Camera camera, Vector3 mousePosition, float maxDistance, GameObject pickedObject, IEnumerable <ProBuilderMesh> meshes, 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)); for (int i = 0; i < m_nearestVertices.Count; i++) { if (!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 static void DrawSceneSelection(SceneSelection selection) { Get().DrawSceneSelectionInternal(selection); }
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); }