9
9
namespace GraphProcessor
10
10
{
11
11
public delegate IEnumerable < PortData > CustomPortBehaviorDelegate ( List < SerializableEdge > edges ) ;
12
+ public delegate IEnumerable < PortData > CustomPortTypeBehaviorDelegate ( string fieldName , string displayName , object value ) ;
12
13
13
14
[ Serializable ]
14
15
public abstract class BaseNode
@@ -105,6 +106,9 @@ public abstract class BaseNode
105
106
[ NonSerialized ]
106
107
internal Dictionary < string , NodeFieldInformation > nodeFields = new Dictionary < string , NodeFieldInformation > ( ) ;
107
108
109
+ [ NonSerialized ]
110
+ internal Dictionary < Type , CustomPortTypeBehaviorDelegate > customPortTypeBehaviorMap = new Dictionary < Type , CustomPortTypeBehaviorDelegate > ( ) ;
111
+
108
112
[ NonSerialized ]
109
113
List < string > messages = new List < string > ( ) ;
110
114
@@ -186,12 +190,53 @@ public static BaseNode CreateFromType(Type nodeType, Vector2 position)
186
190
public void Initialize ( BaseGraph graph )
187
191
{
188
192
this . graph = graph ;
193
+ InitializeCustomPortTypeMethods ( ) ;
189
194
190
195
ExceptionToLog . Call ( ( ) => Enable ( ) ) ;
191
196
192
197
InitializePorts ( ) ;
193
198
}
194
199
200
+ void InitializeCustomPortTypeMethods ( )
201
+ {
202
+ // var methods = GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
203
+
204
+ // if (GetType().Name.Contains("Distance"))
205
+ // Debug.Log(GetType().GetMethod("GetTypeFromTextureDim", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy));
206
+
207
+ MethodInfo [ ] methods = new MethodInfo [ 0 ] ;
208
+ Type baseType = GetType ( ) ;
209
+ while ( true )
210
+ {
211
+ methods = baseType . GetMethods ( BindingFlags . NonPublic | BindingFlags . Instance ) ;
212
+ foreach ( var method in methods )
213
+ {
214
+ var typeBehaviors = method . GetCustomAttributes < CustomPortTypeBehavior > ( ) . ToArray ( ) ;
215
+
216
+ if ( typeBehaviors . Length == 0 )
217
+ continue ;
218
+
219
+ CustomPortTypeBehaviorDelegate deleg = null ;
220
+ try
221
+ {
222
+ deleg = Delegate . CreateDelegate ( typeof ( CustomPortTypeBehaviorDelegate ) , this , method ) as CustomPortTypeBehaviorDelegate ;
223
+ } catch ( Exception e )
224
+ {
225
+ Debug . LogError ( e ) ;
226
+ Debug . LogError ( $ "Cannot convert method { method } to a delegate of type { typeof ( CustomPortTypeBehaviorDelegate ) } ") ;
227
+ }
228
+
229
+ foreach ( var typeBehavior in typeBehaviors )
230
+ customPortTypeBehaviorMap [ typeBehavior . type ] = deleg ;
231
+ }
232
+
233
+ // Try to also find private methods in the base class
234
+ baseType = baseType . BaseType ;
235
+ if ( baseType == null )
236
+ break ;
237
+ }
238
+ }
239
+
195
240
/// <summary>
196
241
/// Use this function to initialize anything related to ports generation in your node
197
242
/// This will allow the node creation menu to correctly recognize ports that can be connected between nodes
@@ -202,7 +247,7 @@ public virtual void InitializePorts()
202
247
{
203
248
var nodeField = nodeFieldKP . Value ;
204
249
205
- if ( nodeField . behavior != null )
250
+ if ( HasCustomBehavior ( nodeField ) )
206
251
{
207
252
UpdatePortsForField ( nodeField . fieldName ) ;
208
253
}
@@ -262,7 +307,7 @@ public bool UpdatePortsForFieldLocal(string fieldName)
262
307
263
308
var fieldInfo = nodeFields [ fieldName ] ;
264
309
265
- if ( fieldInfo . behavior == null )
310
+ if ( ! HasCustomBehavior ( fieldInfo ) )
266
311
return false ;
267
312
268
313
List < string > finalPorts = new List < string > ( ) ;
@@ -274,7 +319,20 @@ public bool UpdatePortsForFieldLocal(string fieldName)
274
319
// Gather all edges connected to these fields:
275
320
var edges = nodePorts . SelectMany ( n => n . GetEdges ( ) ) . ToList ( ) ;
276
321
277
- foreach ( var portData in fieldInfo . behavior ( edges ) )
322
+ if ( fieldInfo . behavior != null )
323
+ {
324
+ foreach ( var portData in fieldInfo . behavior ( edges ) )
325
+ AddPortData ( portData ) ;
326
+ }
327
+ else
328
+ {
329
+ var customPortTypeBehavior = customPortTypeBehaviorMap [ fieldInfo . info . FieldType ] ;
330
+
331
+ foreach ( var portData in customPortTypeBehavior ( fieldName , fieldInfo . name , fieldInfo . info . GetValue ( this ) ) )
332
+ AddPortData ( portData ) ;
333
+ }
334
+
335
+ void AddPortData ( PortData portData )
278
336
{
279
337
var port = nodePorts . FirstOrDefault ( n => n . portData . identifier == portData . identifier ) ;
280
338
// Guard using the port identifier so we don't duplicate identifiers
@@ -335,6 +393,17 @@ public bool UpdatePortsForFieldLocal(string fieldName)
335
393
return changed ;
336
394
}
337
395
396
+ bool HasCustomBehavior ( NodeFieldInformation info )
397
+ {
398
+ if ( info . behavior != null )
399
+ return true ;
400
+
401
+ if ( customPortTypeBehaviorMap . ContainsKey ( info . info . FieldType ) )
402
+ return true ;
403
+
404
+ return false ;
405
+ }
406
+
338
407
/// <summary>
339
408
/// Update the ports related to one C# property field and all connected nodes in the graph
340
409
/// </summary>
@@ -372,7 +441,7 @@ public bool UpdatePortsForField(string fieldName)
372
441
foreach ( var edge in port . GetEdges ( ) )
373
442
{
374
443
var edgeNode = ( node . IsFieldInput ( field ) ) ? edge . outputNode : edge . inputNode ;
375
- var fieldsWithBehavior = edgeNode . nodeFields . Values . Where ( f => f . behavior != null ) . Select ( f => f . fieldName ) . ToList ( ) ;
444
+ var fieldsWithBehavior = edgeNode . nodeFields . Values . Where ( f => HasCustomBehavior ( f ) ) . Select ( f => f . fieldName ) . ToList ( ) ;
376
445
fieldsToUpdate . Push ( new PortUpdate { fieldNames = fieldsWithBehavior , node = edgeNode } ) ;
377
446
}
378
447
}
0 commit comments