11using System . Collections . Generic ;
22using System . Linq ;
33using System . Text . RegularExpressions ;
4+ using Ludiq . OdinSerializer . Utilities ;
45using UnityEditor ;
56using UnityEngine ;
67using UnityEngine . UIElements ;
@@ -21,6 +22,7 @@ private static void ShowWindow()
2122 public SerializedObject serializedObject ;
2223 public float maxDistance = 1.0f ;
2324 public LayerMask layerMask = 0x801 ;
25+ public bool useBounds ;
2426 public QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction . Ignore ;
2527
2628
@@ -55,6 +57,17 @@ private static Vector2 ParseLatLon(string text)
5557 return new Vector2 ( float . Parse ( split [ 0 ] ) , float . Parse ( split [ 1 ] ) ) ;
5658 }
5759
60+ private static float GetGroundDistance ( Vector3 origin , float maxDistance , LayerMask layerMask , QueryTriggerInteraction queryTriggerInteraction )
61+ {
62+ var hitUp = Physics . Raycast ( origin + Vector3 . up * maxDistance , Vector3 . down , out var up , maxDistance , layerMask , queryTriggerInteraction ) ;
63+ if ( hitUp ) return maxDistance - up . distance ;
64+
65+ var hitDown = Physics . Raycast ( origin , Vector3 . down , out var down , maxDistance , layerMask , queryTriggerInteraction ) ;
66+ if ( hitDown ) return - down . distance ;
67+
68+ return 0 ;
69+ }
70+
5871 private void OnGUI ( )
5972 {
6073 serializedObject . Update ( ) ;
@@ -97,18 +110,51 @@ private void OnGUI()
97110 case nameof ( queryTriggerInteraction ) :
98111 if ( GUILayout . Button ( "Snap To Ground" ) )
99112 {
100- var transforms = Selection . transforms ;
101- foreach ( var transform in transforms )
113+ try
102114 {
103- Undo . RecordObject ( transform , "Snap To Ground" ) ;
104- var hitUp = Physics . Raycast ( transform . position + Vector3 . up * maxDistance , Vector3 . down , out var up , maxDistance , layerMask , queryTriggerInteraction ) ;
105- if ( hitUp ) transform . position = up . point ;
106- else
115+ var transforms = Selection . transforms ;
116+ var i = 0 ;
117+ foreach ( var transform in transforms )
107118 {
108- var hitDown = Physics . Raycast ( transform . position , Vector3 . down , out var down , maxDistance , layerMask , queryTriggerInteraction ) ;
109- if ( hitDown ) transform . position = down . point ;
119+ EditorUtility . DisplayProgressBar ( "Snap To Ground" , transform . gameObject . name , ( float ) i ++ / transforms . Length ) ;
120+ Undo . RecordObject ( transform , "Snap To Ground" ) ;
121+
122+ var renderer = transform . GetComponent < Renderer > ( ) ;
123+ if ( useBounds && renderer )
124+ {
125+ var bounds = renderer . bounds ;
126+ var center = bounds . center ;
127+ var extents = bounds . extents ;
128+
129+ var y = center . y - extents . y ;
130+
131+ var left = center . x - extents . x ;
132+ var right = center . x + extents . x ;
133+
134+ var top = center . z + extents . z ;
135+ var bottom = center . z - extents . z ;
136+
137+ var points = new [ ] {
138+ transform . position ,
139+ center + Vector3 . Scale ( extents , new Vector3 ( 1 , - 1 , 1 ) ) ,
140+ center + Vector3 . Scale ( extents , new Vector3 ( - 1 , - 1 , 1 ) ) ,
141+ center + Vector3 . Scale ( extents , new Vector3 ( 1 , - 1 , - 1 ) ) ,
142+ center + Vector3 . Scale ( extents , new Vector3 ( - 1 , - 1 , - 1 ) ) ,
143+ } ;
144+
145+ var distance = points . Select ( origin => GetGroundDistance ( origin , maxDistance , layerMask , queryTriggerInteraction ) ) . Min ( ) ;
146+ transform . position += Vector3 . up * distance ;
147+ }
148+ else
149+ {
150+ transform . position += Vector3 . up * GetGroundDistance ( transform . position , maxDistance , layerMask , queryTriggerInteraction ) ;
151+ }
110152 }
111153 }
154+ finally
155+ {
156+ EditorUtility . ClearProgressBar ( ) ;
157+ }
112158 }
113159 EditorGUILayout . Separator ( ) ;
114160 break ;
0 commit comments