private static void PickProBuilderElementsNonAlloc(List <ProbeHit> hits, List <ProBuilderMesh> meshes, SceneView sceneView, Vector2 guiPosition) { var screenPosition = HandleUtility.GUIPointToScreenPixelCoordinate(guiPosition); var worldPosition = sceneView.camera.ScreenToWorldPoint(screenPosition); var pickRadius = PeekPlugin.Configuration.probeProBuilderRadius; var pickerOptions = PickerOptions.Default; pickerOptions.depthTest = PeekPlugin.Configuration.probeProBuilderDepthTest; var pickRect = new Rect ( guiPosition.x - pickRadius, guiPosition.y - pickRadius, 2 * pickRadius, 2 * pickRadius ); var verticesByMeshes = SelectionPicker.PickVerticesInRect(sceneView.camera, pickRect, meshes, pickerOptions, EditorGUIUtility.pixelsPerPoint); var edgesByMeshes = SelectionPicker.PickEdgesInRect(sceneView.camera, pickRect, meshes, pickerOptions, EditorGUIUtility.pixelsPerPoint); var facesByMeshes = SelectionPicker.PickFacesInRect(sceneView.camera, pickRect, meshes, pickerOptions, EditorGUIUtility.pixelsPerPoint); foreach (var verticesByMesh in verticesByMeshes) { var mesh = verticesByMesh.Key; var gameObject = mesh.gameObject; var vertices = verticesByMesh.Value; var meshVertices = mesh.GetVertices(); var sharedVertices = mesh.sharedVertices; foreach (var vertexIndex in vertices) { var hit = new ProbeHit(gameObject); var vertex = meshVertices[vertexIndex]; var sharedVertex = sharedVertices[vertexIndex]; var sharedVertexIndex = sharedVertex[0]; hit.point = vertex.position; hit.distance = Vector3.Distance(vertex.position, worldPosition); hit.label = $"{mesh.name}: Vertex {vertexIndex}"; hit.icon = PeekProBuilderIntegration.Icons.vertex; hit.groupOrder = 1; hit.selectHandler = (add) => { Selection.activeGameObject = gameObject; ProBuilderEditor.selectMode = SelectMode.Vertex; Undo.RecordObject(mesh, "Selection Change"); if (add) { mesh.SetSelectedVertices(mesh.selectedVertices.Concat(sharedVertex)); } else { mesh.SetSelectedVertices(sharedVertex); } PeekProBuilderIntegration.UpdateSelection(); }; hit.focusHandler = () => ProBuilderHighlight(new SceneSelection(mesh, sharedVertexIndex)); hit.lostFocusHandler = ClearProBuilderHighlight; hits.Add(hit); } } foreach (var edgesByMesh in edgesByMeshes) { var mesh = edgesByMesh.Key; var gameObject = mesh.gameObject; var edges = edgesByMesh.Value; var meshVertices = mesh.GetVertices(); var sharedVertices = mesh.sharedVertices; var visited = HashSetPool <(int, int)> .New(); foreach (var edge in edges) { var hit = new ProbeHit(gameObject); var vertexA = meshVertices[edge.a]; var vertexB = meshVertices[edge.b]; var center = (vertexA.position + vertexB.position) / 2; var sharedVertexIndexA = -1; var sharedVertexIndexB = -1; for (var currentSharedIndex = 0; currentSharedIndex < sharedVertices.Count; currentSharedIndex++) { var sharedVertex = sharedVertices[currentSharedIndex]; if (sharedVertex.Contains(edge.a)) { sharedVertexIndexA = currentSharedIndex; } if (sharedVertex.Contains(edge.b)) { sharedVertexIndexB = currentSharedIndex; } } var sharedVertexIndexMin = Mathf.Min(sharedVertexIndexA, sharedVertexIndexB); var sharedVertexIndexMax = Mathf.Max(sharedVertexIndexA, sharedVertexIndexB); if (visited.Contains((sharedVertexIndexMin, sharedVertexIndexMax))) { continue; } hit.point = center; hit.distance = Vector3.Distance(center, worldPosition); hit.label = $"{mesh.name}: Edge [{sharedVertexIndexMin}, {sharedVertexIndexMax}]"; hit.icon = PeekProBuilderIntegration.Icons.edge; hit.groupOrder = 2; hit.selectHandler = (add) => { Selection.activeGameObject = gameObject; ProBuilderEditor.selectMode = SelectMode.Edge; Undo.RecordObject(mesh, "Selection Change"); if (add) { mesh.SetSelectedEdges(mesh.selectedEdges.Append(edge)); } else { mesh.SetSelectedEdges(edge.Yield()); } PeekProBuilderIntegration.UpdateSelection(); }; hit.focusHandler = () => ProBuilderHighlight(new SceneSelection(mesh, edge)); hit.lostFocusHandler = ClearProBuilderHighlight; hits.Add(hit); visited.Add((sharedVertexIndexMin, sharedVertexIndexMax)); } visited.Free(); } foreach (var facesByMesh in facesByMeshes) { var mesh = facesByMesh.Key; var gameObject = mesh.gameObject; var faces = facesByMesh.Value; var meshVertices = mesh.GetVertices(); var meshFaces = mesh.faces; foreach (var face in faces) { var faceIndex = meshFaces.IndexOf(face); var hit = new ProbeHit(gameObject); var center = Vector3.zero; foreach (var vertexIndex in face.distinctIndexes) { var vertex = meshVertices[vertexIndex]; center += vertex.position; } center /= face.distinctIndexes.Count; hit.point = center; hit.distance = Vector3.Distance(center, worldPosition); hit.label = $"{mesh.name}: Face {faceIndex}"; hit.icon = PeekProBuilderIntegration.Icons.face; hit.groupOrder = 3; hit.selectHandler = (add) => { Selection.activeGameObject = gameObject; ProBuilderEditor.selectMode = SelectMode.Face; Undo.RecordObject(mesh, "Selection Change"); if (add) { mesh.SetSelectedFaces(mesh.GetSelectedFaces().Append(face)); } else { mesh.SetSelectedFaces(null); mesh.SetSelectedFaces(face.Yield()); } PeekProBuilderIntegration.UpdateSelection(); }; hit.focusHandler = () => ProBuilderHighlight(new SceneSelection(mesh, face)); hit.lostFocusHandler = ClearProBuilderHighlight; hits.Add(hit); } } }
internal static void OnSceneGUI(SceneView sceneView) { if (!PeekPlugin.Configuration.enableProbe) { return; } Profiler.BeginSample("Peek." + nameof(Probe)); try { ProgramHighlight(sceneView); #if PROBUILDER_4_OR_NEWER PeekProBuilderIntegration.DrawHighlight(proBuilderHighlight); #endif var shortcut = PeekPlugin.Configuration.probeShortcut; // Make sure not to conflict with right-click pan shortcut.mouseShortcut.checkRelease = true; shortcut.mouseShortcut.requireStaticRelease = true; if (shortcut.Check(e) && !SceneViewIntegration.used) { var hits = ListPool <ProbeHit> .New(); try { PickAllNonAlloc(hits, ProbeFilter.@default, sceneView, e.mousePosition, PeekPlugin.Configuration.probeLimit); if (hits.Count > 0) { var add = e.shift; var activatorPosition = new Rect(e.mousePosition, Vector2.zero); activatorPosition.width = 220; activatorPosition = LudiqGUIUtility.GUIToScreenRect(activatorPosition); // Note: Had to make FuzzyWindow use OnMouseUp for select here instead // of OnMouseDown because otherwise escaping the default RectSelection // behaviour with the event order and DefaultControl ID's was... hell. LudiqGUI.FuzzyDropdown ( activatorPosition, new ProbeOptionTree(hits), null, (_hit) => { add |= e?.shift ?? false; var hit = (ProbeHit)_hit; hit.Select(add); } ); FuzzyWindow.instance.Focus(); GUIUtility.hotControl = 0; // Escape the default RectSelection control e.Use(); } } finally { hits.Free(); } } } catch (Exception ex) { Debug.LogException(ex); } Profiler.EndSample(); }
internal static void OnSceneGUI(SceneView sceneView) { if (!PeekPlugin.Configuration.enableProbe) { return; } Profiler.BeginSample("Peek." + nameof(Probe)); try { ProgramHighlight(sceneView); #if PROBUILDER_4_OR_NEWER PeekProBuilderIntegration.DrawHighlight(proBuilderHighlight); #endif if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Alpha0) { Selection.activeGameObject = sceneView.camera.gameObject; } if (e.IsContextMouseButton() && !e.alt && !e.CtrlOrCmd() && !SceneViewIntegration.used) { if (e.type == EventType.MouseDown) { pressPosition = e.mousePosition; } else if (e.type == EventType.MouseUp) { if (pressPosition.HasValue) { var pressDistance = Vector2.Distance(e.mousePosition, pressPosition.Value); if (pressDistance <= 1) { var hits = ListPool <ProbeHit> .New(); try { PickAllNonAlloc(hits, ProbeFilter.@default, sceneView, e.mousePosition, PeekPlugin.Configuration.probeLimit); if (hits.Count > 0) { var add = e.shift; var activatorPosition = new Rect(e.mousePosition, Vector2.zero); activatorPosition.width = 220; activatorPosition = LudiqGUIUtility.GUIToScreenRect(activatorPosition); // Note: Had to make FuzzyWindow use OnMouseUp for select here instead // of OnMouseDown because otherwise escaping the default RectSelection // behaviour with the event order and DefaultControl ID's was... hell. LudiqGUI.FuzzyDropdown ( activatorPosition, new ProbeOptionTree(hits), null, (_hit) => { add |= e?.shift ?? false; var hit = (ProbeHit)_hit; hit.Select(add); } ); FuzzyWindow.instance.Focus(); GUIUtility.hotControl = 0; // Escape the default RectSelection control e.Use(); } } finally { hits.Free(); } } pressPosition = null; } } } } catch (Exception ex) { Debug.LogException(ex); } Profiler.EndSample(); }