@@ -684,31 +684,35 @@ static float EdgeRaycast(Vector3 mousePosition, ScenePickerPreferences pickerPre
684684 int x = edge . a ;
685685 int y = edge . b ;
686686
687- float d = UHandleUtility . DistanceToLine (
688- trs . TransformPoint ( positions [ x ] ) ,
689- trs . TransformPoint ( positions [ y ] ) ) ;
687+ Vector3 worldPosA = trs . TransformPoint ( positions [ x ] ) ;
688+ Vector3 worldPosB = trs . TransformPoint ( positions [ y ] ) ;
690689
691- d *= distMultiplier ;
690+ if ( ProcessEdgePoints ( Camera . current , worldPosA , worldPosB , out Vector3 guiPointA , out Vector3 guiPointB ) )
691+ {
692+ // Calculate distance from the mouse position to the line
693+ float d = HandleUtility . DistancePointLine ( mousePosition , guiPointA , guiPointB ) ;
694+ d *= distMultiplier ;
692695
693- // best distance isn't set to maxPointerDistance because we want to preserve an unselected
694- // gameobject over a selected gameobject with an out of bounds edge.
695- if ( d > ScenePickerPreferences . maxPointerDistance )
696- continue ;
696+ // best distance isn't set to maxPointerDistance because we want to preserve an unselected
697+ // gameobject over a selected gameobject with an out of bounds edge.
698+ if ( d > ScenePickerPreferences . maxPointerDistance )
699+ continue ;
697700
698- // account for stacked edges
699- if ( Mathf . Approximately ( d , bestDistance ) )
700- {
701- s_EdgeBuffer . Add ( new Edge ( x , y ) ) ;
702- }
703- else if ( d < bestDistance )
704- {
705- s_EdgeBuffer . Clear ( ) ;
706- s_EdgeBuffer . Add ( new Edge ( x , y ) ) ;
701+ // account for stacked edges
702+ if ( Mathf . Approximately ( d , bestDistance ) )
703+ {
704+ s_EdgeBuffer . Add ( new Edge ( x , y ) ) ;
705+ }
706+ else if ( d < bestDistance )
707+ {
708+ s_EdgeBuffer . Clear ( ) ;
709+ s_EdgeBuffer . Add ( new Edge ( x , y ) ) ;
707710
708- selection . gameObject = mesh . gameObject ;
709- selection . mesh = mesh ;
710- selection . SetSingleEdge ( new Edge ( x , y ) ) ;
711- bestDistance = d ;
711+ selection . gameObject = mesh . gameObject ;
712+ selection . mesh = mesh ;
713+ selection . SetSingleEdge ( new Edge ( x , y ) ) ;
714+ bestDistance = d ;
715+ }
712716 }
713717 }
714718 }
@@ -722,6 +726,20 @@ static float EdgeRaycast(Vector3 mousePosition, ScenePickerPreferences pickerPre
722726 return selection . gameObject != null ? bestDistance : Mathf . Infinity ;
723727 }
724728
729+
730+ /// <summary>
731+ /// Function to clip a point to the near plane.
732+ /// </summary>
733+ /// <param name="pointBehind"> the point behind the plane</param>
734+ /// <param name="pointInFront"> the point in front of te plane</param>
735+ /// <param name="nearPlaneZ"> the camera near plane z</param>
736+ /// <returns>The intersection point between the line and the near plane</returns>
737+ static Vector3 ClipPointToNearPlane ( Vector3 pointBehind , Vector3 pointInFront , float nearPlaneZ )
738+ {
739+ float t = ( nearPlaneZ - pointBehind . z ) / ( pointInFront . z - pointBehind . z ) ;
740+ return pointBehind + t * ( pointInFront - pointBehind ) ;
741+ }
742+
725743 static Edge GetClosestEdgeToCamera ( Vector3 [ ] positions , IEnumerable < Edge > edges )
726744 {
727745 var camPos = SceneView . lastActiveSceneView . camera . transform . position ;
@@ -813,12 +831,71 @@ static EdgeAndDistance GetNearestEdgeOnMesh(ProBuilderMesh mesh, Vector3 mousePo
813831 }
814832
815833 if ( res . edge . IsValid ( ) )
816- res . distance = UHandleUtility . DistanceToLine (
817- mesh . transform . TransformPoint ( v [ res . edge . a ] ) ,
818- mesh . transform . TransformPoint ( v [ res . edge . b ] ) ) ;
834+ {
835+ Vector3 worldPosA = mesh . transform . TransformPoint ( v [ res . edge . a ] ) ;
836+ Vector3 worldPosB = mesh . transform . TransformPoint ( v [ res . edge . b ] ) ;
837+
838+ if ( ProcessEdgePoints ( Camera . current , worldPosA , worldPosB , out Vector3 guiPointA , out Vector3 guiPointB ) )
839+ {
840+ // Calculate distance from the mouse position to the line
841+ res . distance = HandleUtility . DistancePointLine ( mousePosition , guiPointA , guiPointB ) ;
842+ }
843+ else
844+ {
845+ // If both points are behind the camera, skip this edge
846+ res . distance = Mathf . Infinity ;
847+ }
848+ }
819849 }
820850
821851 return res ;
822852 }
853+
854+ static bool ProcessEdgePoints ( Camera camera , Vector3 worldPosA , Vector3 worldPosB , out Vector3 guiPointA , out Vector3 guiPointB )
855+ {
856+ guiPointA = Vector3 . zero ;
857+ guiPointB = Vector3 . zero ;
858+
859+ // Check if the points are in front of the camera
860+ bool pointAInFront = Vector3 . Dot ( camera . transform . forward , worldPosA - camera . transform . position ) > 0 ;
861+ bool pointBInFront = Vector3 . Dot ( camera . transform . forward , worldPosB - camera . transform . position ) > 0 ;
862+
863+ // If both points are behind the camera, skip this edge
864+ if ( ! pointAInFront && ! pointBInFront )
865+ {
866+ return false ;
867+ }
868+
869+ // Check if either point is behind the camera
870+ if ( ! pointAInFront || ! pointBInFront )
871+ {
872+ // Clip points against the near plane
873+ Vector3 cameraSpacePointA = camera . transform . InverseTransformPoint ( worldPosA ) ;
874+ Vector3 cameraSpacePointB = camera . transform . InverseTransformPoint ( worldPosB ) ;
875+
876+ float nearPlaneZ = camera . nearClipPlane ;
877+
878+ if ( cameraSpacePointA . z < nearPlaneZ )
879+ {
880+ cameraSpacePointA = ClipPointToNearPlane ( cameraSpacePointA , cameraSpacePointB , nearPlaneZ ) ;
881+ }
882+
883+ if ( cameraSpacePointB . z < nearPlaneZ )
884+ {
885+ cameraSpacePointB = ClipPointToNearPlane ( cameraSpacePointB , cameraSpacePointA , nearPlaneZ ) ;
886+ }
887+
888+ // Transform clipped points back to screen space
889+ guiPointA = HandleUtility . WorldToGUIPoint ( camera . transform . TransformPoint ( cameraSpacePointA ) ) ;
890+ guiPointB = HandleUtility . WorldToGUIPoint ( camera . transform . TransformPoint ( cameraSpacePointB ) ) ;
891+ }
892+ else // Both points are in front of the camera
893+ {
894+ guiPointA = HandleUtility . WorldToGUIPoint ( worldPosA ) ;
895+ guiPointB = HandleUtility . WorldToGUIPoint ( worldPosB ) ;
896+ }
897+
898+ return true ;
899+ }
823900 }
824901}
0 commit comments