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); }