public static ProbeHit[] PickAll(ProbeFilter filter, SceneView sceneView, Vector2 guiPosition, int limit = DefaultLimit) { var results = new List <ProbeHit>(); PickAllNonAlloc(results, filter, sceneView, guiPosition, limit); return(results.ToArray()); }
public static ProbeHit?Pick(ProbeFilter filter, SceneView sceneView, Vector2 guiPosition, out Vector3 point) { var results = ListPool <ProbeHit> .New(); try { PickAllNonAlloc(results, filter, sceneView, guiPosition); foreach (var result in results) { if (result.point.HasValue) { point = result.point.Value; return(result); } } point = DefaultPoint(sceneView, guiPosition); return(null); } finally { results.Free(); } }
public static void PickAllNonAlloc(List <ProbeHit> hits, ProbeFilter filter, SceneView sceneView, Vector2 guiPosition, int limit = DefaultLimit) { var screenPosition = HandleUtility.GUIPointToScreenPixelCoordinate(guiPosition); var ray3D = HandleUtility.GUIPointToWorldRay(guiPosition); var worldPosition = sceneView.camera.ScreenToWorldPoint(screenPosition); var layerMask = PeekPlugin.Configuration.probeLayerMask; var raycastHits = ArrayPool <RaycastHit> .New(limit); var overlapHits = ArrayPool <Collider2D> .New(limit); var handleHits = HashSetPool <GameObject> .New(); var ancestorHits = HashSetPool <ProbeHit> .New(); #if PROBUILDER_4_OR_NEWER var proBuilderHits = ListPool <ProbeHit> .New(); #endif var gameObjectHits = DictionaryPool <GameObject, ProbeHit> .New(); try { // Raycast (3D) if (filter.raycast) { var raycastHitCount = Physics.RaycastNonAlloc(ray3D, raycastHits, Mathf.Infinity, layerMask); for (var i = 0; i < raycastHitCount; i++) { var raycastHit = raycastHits[i]; #if UNITY_2019_2_OR_NEWER if (SceneVisibilityManager.instance.IsHidden(raycastHit.transform.gameObject)) { continue; } #endif var gameObject = raycastHit.transform.gameObject; if (!gameObjectHits.TryGetValue(gameObject, out var hit)) { hit = new ProbeHit(gameObject); } hit.point = raycastHit.point; hit.distance = raycastHit.distance; gameObjectHits[gameObject] = hit; } } // Overlap (2D) if (filter.overlap) { var overlapHitCount = Physics2D.OverlapPointNonAlloc(worldPosition, overlapHits, layerMask); for (var i = 0; i < overlapHitCount; i++) { var overlapHit = overlapHits[i]; #if UNITY_2019_2_OR_NEWER if (SceneVisibilityManager.instance.IsHidden(overlapHit.transform.gameObject)) { continue; } #endif var gameObject = overlapHit.transform.gameObject; if (!gameObjectHits.TryGetValue(gameObject, out var hit)) { hit = new ProbeHit(gameObject); } hit.distance = hit.distance ?? Vector3.Distance(overlapHit.transform.position, worldPosition); gameObjectHits[gameObject] = hit; } } // Handles (Editor Default) if (filter.handles && canPickHandles) { PickAllHandlesNonAlloc(handleHits, guiPosition, limit); foreach (var handleHit in handleHits) { var gameObject = handleHit; if (!gameObjectHits.TryGetValue(gameObject, out var hit)) { hit = new ProbeHit(gameObject); } hit.distance = hit.distance ?? Vector3.Distance(handleHit.transform.position, worldPosition); gameObjectHits[gameObject] = hit; } } // Ancestors foreach (var gameObjectHit in gameObjectHits) { var gameObject = gameObjectHit.Key; var hit = gameObjectHit.Value; var parent = gameObject.transform.parent; int depth = 0; while (parent != null) { var parentGameObject = parent.gameObject; var parentHit = new ProbeHit(parentGameObject); parentHit.groupGameObject = gameObject; parentHit.distance = hit.distance ?? Vector3.Distance(parentHit.transform.position, worldPosition); parentHit.groupOrder = 1000 + depth; ancestorHits.Add(parentHit); parent = parent.parent; depth++; } } #if PROBUILDER_4_OR_NEWER // ProBuilder if (filter.proBuilder && ProBuilderEditor.instance != null) { var proBuilderMeshes = ListPool <ProBuilderMesh> .New(); try { foreach (var gameObjectHit in gameObjectHits.Values) { var proBuilderMesh = gameObjectHit.gameObject.GetComponent <ProBuilderMesh>(); if (proBuilderMesh != null) { proBuilderMeshes.Add(proBuilderMesh); } } PickProBuilderElementsNonAlloc(proBuilderHits, proBuilderMeshes, sceneView, guiPosition); } finally { proBuilderMeshes.Free(); } } #endif // Prepare final hits hits.Clear(); // Add hits foreach (var gameObjectHit in gameObjectHits.Values) { hits.Add(gameObjectHit); } foreach (var ancestorHit in ancestorHits) { hits.Add(ancestorHit); } #if PROBUILDER_4_OR_NEWER foreach (var proBuilderHit in proBuilderHits) { hits.Add(proBuilderHit); } #endif // Sort by distance hits.Sort(compareHits); } finally { raycastHits.Free(); overlapHits.Free(); handleHits.Free(); ancestorHits.Free(); #if PROBUILDER_4_OR_NEWER proBuilderHits.Free(); #endif gameObjectHits.Free(); } }