public static Dictionary <ProBuilderMesh, HashSet <int> > PickVerticesInRect( Camera cam, Rect rect, Rect uiRootRect, IList <ProBuilderMesh> selectable, PickerOptions options, float pixelsPerPoint = 1f) { if (options.depthTest) { return(PBSelectionPickerRenderer.PickVerticesInRect( cam, rect, selectable, true, (int)(uiRootRect.width / pixelsPerPoint), (int)(uiRootRect.height / pixelsPerPoint))); } // while the selectionpicker render path supports no depth test picking, it's usually faster to skip // the render. also avoids issues with vertex billboards obscuring one another. var selected = new Dictionary <ProBuilderMesh, HashSet <int> >(); foreach (var pb in selectable) { if (!pb.selectable) { continue; } IList <SharedVertex> sharedIndexes = pb.sharedVertices; HashSet <int> inRect = new HashSet <int>(); IList <Vector3> positions = pb.positions; var trs = pb.transform; float pixelHeight = uiRootRect.height; for (int n = 0; n < sharedIndexes.Count; n++) { Vector3 v = trs.TransformPoint(positions[sharedIndexes[n][0]]); Vector3 p = cam.WorldToScreenPoint(v); if (p.z < cam.nearClipPlane) { continue; } p.x /= pixelsPerPoint; p.y = (pixelHeight - p.y) / pixelsPerPoint; if (rect.Contains(p)) { inRect.Add(n); } } selected.Add(pb, inRect); } return(selected); }
public static Dictionary <ProBuilderMesh, HashSet <Face> > PickFaces(Camera camera, Rect rect, Rect uiRect, GameObject[] gameObjects, bool depthTest) { try { if (depthTest) { return(PBSelectionPickerRenderer.PickFacesInRect(camera, rect, gameObjects.Select(g => g.GetComponent <ProBuilderMesh>()).Where(pbm => pbm != null).ToArray(), Mathf.RoundToInt(uiRect.width), Mathf.RoundToInt(uiRect.height))); } return(SelectionPicker.PickFacesInRect(camera, rect, gameObjects.Select(g => g.GetComponent <ProBuilderMesh>()).Where(pbm => pbm != null).ToArray(), new PickerOptions { rectSelectMode = RectSelectMode.Partial, depthTest = false }, 1)); } catch (System.Exception e) { Debug.LogError(e); return(new Dictionary <ProBuilderMesh, HashSet <Face> >()); } }
public static Dictionary <ProBuilderMesh, HashSet <Edge> > PickEdgesInRect( Camera cam, Rect rect, Rect uiRootRect, IList <ProBuilderMesh> selectable, PickerOptions options, float pixelsPerPoint = 1f) { if (options.depthTest && options.rectSelectMode == RectSelectMode.Partial) { return(PBSelectionPickerRenderer.PickEdgesInRect( cam, rect, selectable, true, (int)(uiRootRect.width / pixelsPerPoint), (int)(uiRootRect.height / pixelsPerPoint))); } var selected = new Dictionary <ProBuilderMesh, HashSet <Edge> >(); foreach (var pb in selectable) { if (!pb.selectable) { continue; } Transform trs = pb.transform; var selectedEdges = new HashSet <Edge>(); IList <Face> faces = pb.faces; IList <Vector3> positions = pb.positions; for (int i = 0, fc = pb.faceCount; i < fc; i++) { var edges = faces[i].edges; for (int n = 0, ec = edges.Count; n < ec; n++) { var edge = edges[n]; var posA = trs.TransformPoint(positions[edge.a]); var posB = trs.TransformPoint(positions[edge.b]); Vector3 a = ScreenToGuiPoint(uiRootRect, cam.WorldToScreenPoint(posA), pixelsPerPoint); Vector3 b = ScreenToGuiPoint(uiRootRect, cam.WorldToScreenPoint(posB), pixelsPerPoint); switch (options.rectSelectMode) { case RectSelectMode.Complete: { // if either of the positions are clipped by the camera we cannot possibly select both, skip it if ((a.z < cam.nearClipPlane || b.z < cam.nearClipPlane)) { continue; } if (rect.Contains(a) && rect.Contains(b)) { if (!options.depthTest || !PBUtility.PointIsOccluded(cam, pb, (posA + posB) * .5f)) { selectedEdges.Add(edge); } } break; } case RectSelectMode.Partial: { // partial + depth test is covered earlier if (RectIntersectsLineSegment(rect, a, b)) { selectedEdges.Add(edge); } break; } } } } selected.Add(pb, selectedEdges); } return(selected); }