66using System . Collections . Generic ;
77using System . Linq ;
88using System . Reflection ;
9+ using System . Runtime . CompilerServices ;
910using UnityObject = UnityEngine . Object ;
1011
1112namespace JLChnToZ . EditorExtensions . UInspectorPlus {
@@ -106,7 +107,7 @@ public void Call() {
106107 }
107108 try {
108109 thrownException = null ;
109- var requestData = Array . ConvertAll ( parameters , d => d . Value ) ;
110+ var requestData = Array . ConvertAll ( parameters , d => d ? . Value ) ;
110111 object returnData ;
111112 switch ( mode ) {
112113 case MethodMode . Constructor :
@@ -129,9 +130,13 @@ public void Call() {
129130 OnClose = OnClose ,
130131 } ;
131132 break ;
132- case MethodMode . Method :
133133 default :
134- returnData = ( member as MethodInfo ) . Invoke ( component , requestData ) ;
134+ var thisType = component ;
135+ if ( mode == MethodMode . ExtensionMethod ) {
136+ requestData [ 0 ] = component ;
137+ thisType = null ;
138+ }
139+ returnData = ( member as MethodInfo ) . Invoke ( thisType , requestData ) ;
135140 result = ( member as MethodInfo ) . ReturnType == typeof ( void ) ?
136141 null :
137142 new MethodPropertyDrawer (
@@ -143,6 +148,7 @@ public void Call() {
143148 break ;
144149 }
145150 for ( int i = 0 , l = Math . Min ( parameters . Length , requestData . Length ) ; i < l ; i ++ ) {
151+ if ( parameters [ i ] == null ) continue ;
146152 parameters [ i ] . Value = requestData [ i ] ;
147153 if ( parameters [ i ] . ReferenceMode )
148154 Helper . AssignValue ( parameters [ i ] . RefFieldInfo , parameters [ i ] . Component , requestData [ i ] ) ;
@@ -167,7 +173,7 @@ public void Draw() {
167173 }
168174 if ( mode != MethodMode . Indexer || result == null )
169175 EditorGUILayout . Space ( ) ;
170- if ( mode == MethodMode . Constructor ||
176+ if ( mode == MethodMode . Constructor || mode == MethodMode . ExtensionMethod ||
171177 ( mode == MethodMode . Method && ( component != null || ! selectedMember . IsInstanceMember ( ) ) ) ||
172178 ( mode == MethodMode . Indexer && component != null && result == null ) ) {
173179 if ( GUI . changed ) {
@@ -177,6 +183,7 @@ public void Draw() {
177183 showMethodSelector . target = true ;
178184 } else
179185 showMethodSelector . target = false ;
186+ EditorGUILayout . BeginVertical ( GUI . skin . box ) ;
180187 if ( EditorGUILayout . BeginFadeGroup ( showMethodSelector . faded ) )
181188 DrawComponent ( ) ;
182189 EditorGUILayout . EndFadeGroup ( ) ;
@@ -190,6 +197,7 @@ public void Draw() {
190197 }
191198 if ( execButton )
192199 DrawExecButton ( ) ;
200+ EditorGUILayout . EndVertical ( ) ;
193201 }
194202 }
195203
@@ -215,7 +223,7 @@ public void ShowSearchPopup() => SearchWindowProvider.OpenSearchWindow(methodNam
215223 public void Dispose ( ) {
216224 if ( parameters != null )
217225 foreach ( var parameter in parameters )
218- parameter . Dispose ( ) ;
226+ parameter ? . Dispose ( ) ;
219227 result ? . Dispose ( ) ;
220228 }
221229
@@ -242,6 +250,7 @@ private void AddComponentMethod(object target, Type type = null) {
242250 if ( target == null ) AddConstructors ( type , flag | BindingFlags . Instance ) ;
243251 AddIndexers ( type , target , flag ) ;
244252 AddMethods ( type , target , flag ) ;
253+ AddExtensionMethods ( type , target ) ;
245254 }
246255
247256 private void AddMethods ( Type type , BindingFlags flag ) => methods . AddRange (
@@ -282,6 +291,23 @@ where FilterMemberInfo(m)
282291 }
283292 ) ;
284293
294+ private void AddExtensionMethods ( Type type , object target ) => methods . AddRange (
295+ from a in AppDomain . CurrentDomain . GetAssemblies ( )
296+ where a . IsDefined ( typeof ( ExtensionAttribute ) , false )
297+ from t in a . GetTypes ( )
298+ where t . IsSealed && ! t . IsGenericType && ! t . IsNested &&
299+ t . IsDefined ( typeof ( ExtensionAttribute ) , false )
300+ from m in t . GetMethods ( BindingFlags . Static | BindingFlags . Public )
301+ where FilterMemberInfo ( m ) &&
302+ m . IsDefined ( typeof ( ExtensionAttribute ) , false ) &&
303+ ( m . GetParameters ( ) . FirstOrDefault ( ) ? . ParameterType . IsAssignableFrom ( type ) ) . GetValueOrDefault ( false )
304+ select new ComponentMethod {
305+ member = m ,
306+ target = target ,
307+ mode = MethodMode . ExtensionMethod ,
308+ }
309+ ) ;
310+
285311 private void InitComponentMethods ( bool resetIndex = true ) {
286312 methods . Clear ( ) ;
287313 methodNames . Clear ( ) ;
@@ -340,19 +366,15 @@ private string GetMethodNameFormatted(ComponentMethod m) {
340366 case MethodMode . Indexer :
341367 name = null ;
342368 break ;
343- case MethodMode . Constructor :
344- case MethodMode . Method :
345369 default :
346- name = m . member . GetMemberName ( ) . Replace ( '_' , ' ' ) ;
370+ name = m . member . GetMemberName ( isExtensionMethod : m . mode == MethodMode . ExtensionMethod ) . Replace ( '_' , ' ' ) ;
347371 break ;
348372 }
349373 switch ( m . mode ) {
350374 case MethodMode . Indexer :
351375 parameters = ( m . member as PropertyInfo ) . GetIndexParameters ( ) ;
352376 formatStr = "[{1}]" ;
353377 break ;
354- case MethodMode . Constructor :
355- case MethodMode . Method :
356378 default :
357379 parameters = ( m . member as MethodBase ) . GetParameters ( ) ;
358380 formatStr = "{0} ({1})" ;
@@ -372,7 +394,6 @@ private void InitMethodParams() {
372394 parameterInfo = ( selectedMember as PropertyInfo ) . GetIndexParameters ( ) ;
373395 paramsFolded = parameterInfo . Length > 0 ;
374396 break ;
375- case MethodMode . Method :
376397 default :
377398 component = methods [ selectedMethodIndex ] . target ;
378399 break ;
@@ -381,8 +402,44 @@ private void InitMethodParams() {
381402 resolvedMember = null ;
382403 if ( selectedMember is MethodBase methodBase ) {
383404 parameterInfo = methodBase . GetParameters ( ) ;
384- if ( methodBase is MethodInfo method && method . ContainsGenericParameters )
385- typeResolver = new TypeResolverGUI ( method ) ;
405+ if ( methodBase is MethodInfo method && method . ContainsGenericParameters ) {
406+ if ( mode == MethodMode . ExtensionMethod ) {
407+ var parameters = method . GetParameters ( ) ;
408+ var genericArgs = method . GetGenericArguments ( ) ;
409+ if ( parameters . Length > 0 ) {
410+ var firstParam = parameters [ 0 ] . ParameterType ;
411+ if ( firstParam . IsGenericMethodParameter ) {
412+ genericArgs [ firstParam . GenericParameterPosition ] = targetType ;
413+ method = method . MakeGenericMethod ( genericArgs ) ;
414+ } else if ( firstParam . ContainsGenericParameters ) {
415+ var firstParamResolvedGenericArgs = firstParam . GetGenericArguments ( ) ;
416+ var type = targetType ;
417+ Type [ ] resolvedGenericArgs = null ;
418+ var genericDefinitionType = firstParam . GetGenericTypeDefinition ( ) ;
419+ while ( type != null ) {
420+ if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == genericDefinitionType ) {
421+ resolvedGenericArgs = type . GetGenericArguments ( ) ;
422+ break ;
423+ }
424+ type = type . BaseType ;
425+ }
426+ if ( resolvedGenericArgs == null )
427+ foreach ( var interfaceType in targetType . GetInterfaces ( ) )
428+ if ( interfaceType . IsGenericType && interfaceType . GetGenericTypeDefinition ( ) == genericDefinitionType ) {
429+ resolvedGenericArgs = interfaceType . GetGenericArguments ( ) ;
430+ break ;
431+ }
432+ if ( resolvedGenericArgs != null )
433+ for ( int i = 0 ; i < genericArgs . Length ; i ++ )
434+ if ( firstParamResolvedGenericArgs [ i ] . IsGenericParameter )
435+ genericArgs [ i ] = resolvedGenericArgs [ firstParamResolvedGenericArgs [ i ] . GenericParameterPosition ] ;
436+ method = method . MakeGenericMethod ( genericArgs ) ;
437+ }
438+ }
439+ }
440+ if ( method . ContainsGenericParameters )
441+ typeResolver = new TypeResolverGUI ( method ) ;
442+ }
386443 paramsFolded = parameterInfo . Length > 0 ;
387444 }
388445 CreateDrawers ( ) ;
@@ -395,7 +452,7 @@ private void CreateDrawers() {
395452 foreach ( var entry in parameters )
396453 entry ? . Dispose ( ) ;
397454 parameters = new MethodPropertyDrawer [ parameterInfo . Length ] ;
398- for ( int i = 0 ; i < parameterInfo . Length ; i ++ ) {
455+ for ( int i = mode == MethodMode . ExtensionMethod ? 1 : 0 ; i < parameterInfo . Length ; i ++ ) {
399456 var info = parameterInfo [ i ] ;
400457 parameters [ i ] = new MethodPropertyDrawer ( info , privateFields , obsolete ) ;
401458 parameters [ i ] . OnRequireRedraw += RequireRedraw ;
@@ -405,7 +462,7 @@ private void CreateDrawers() {
405462 private void DrawComponent ( ) {
406463 if ( OnClose != null )
407464 EditorGUILayout . BeginHorizontal ( ) ;
408- EditorGUILayout . PrefixLabel ( mode . ToString ( ) ) ;
465+ EditorGUILayout . PrefixLabel ( ObjectNames . NicifyVariableName ( mode . ToString ( ) ) ) ;
409466 if ( GUILayout . Button ( selectedMethodIndex < 0 ? GUIContent . none : methodNames [ selectedMethodIndex + 1 ] . content , EditorStyles . popup ) )
410467 ShowSearchPopup ( ) ;
411468 if ( OnClose != null ) {
@@ -434,7 +491,6 @@ private void DrawMethod() {
434491 case MethodMode . Indexer :
435492 paramsFolded = EditorGUILayout . Foldout ( paramsFolded , $ "Indexer ({ parameters . Length } )") ;
436493 break ;
437- case MethodMode . Method :
438494 default :
439495 paramsFolded = EditorGUILayout . Foldout ( paramsFolded , $ "{ selectedMember . Name } ({ parameters . Length } )") ;
440496 break ;
@@ -460,10 +516,10 @@ private void DrawMethod() {
460516 }
461517 if ( mode != MethodMode . Indexer && component == null && selectedMember . IsInstanceMember ( ) )
462518 EditorGUILayout . HelpBox ( "Method requires an exists instance." , MessageType . Warning ) ;
463- if ( parameterInfo . Length == 0 )
519+ if ( parameterInfo . Length == ( mode == MethodMode . ExtensionMethod ? 1 : 0 ) )
464520 EditorGUILayout . HelpBox ( "There is no parameters required for this method." , MessageType . Info ) ;
465521 foreach ( var drawer in parameters )
466- drawer . Draw ( ) ;
522+ drawer ? . Draw ( ) ;
467523 EditorGUILayout . EndVertical ( ) ;
468524 EditorGUI . indentLevel -- ;
469525 }
@@ -502,7 +558,6 @@ private void DrawExecButton() {
502558 if ( result != null ) return ;
503559 execute = GUILayout . Button ( "Create Property" ) ;
504560 break ;
505- case MethodMode . Method :
506561 default :
507562 execute = GUILayout . Button ( $ "Execute { selectedMember . Name } ") ;
508563 break ;
0 commit comments