@@ -15,7 +15,7 @@ namespace SatorImaging.UnitySourceGenerator
15
15
{
16
16
public class USGEngine : AssetPostprocessor
17
17
{
18
- ///<summary>This will be disabled after import event automatically.</summary>
18
+ ///<summary>This will be disabled after Unity Editor import event automatically.</summary>
19
19
public static bool IgnoreOverwriteSettingByAttribute = false ;
20
20
21
21
@@ -71,22 +71,42 @@ static void OnPostprocessAllAssets(
71
71
if ( s_processingJobQueued ) return ;
72
72
s_processingJobQueued = true ;
73
73
74
- AssetDatabase . Refresh ( ) ; // load updated generator class script before event
75
- EditorApplication . delayCall += ProcessingFiles ;
74
+ // NOTE: need to stack jobs. nesting delayCall's causes error.
75
+ EditorApplication . delayCall += static ( ) =>
76
+ {
77
+ ProcessingFiles ( ) ;
78
+ s_updatedGeneratorJob ? . Invoke ( ) ;
79
+ s_updatedGeneratorJob = null ;
80
+
81
+ IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
82
+ s_processingJobQueued = false ;
83
+ } ;
76
84
}
77
85
86
+ static Action s_updatedGeneratorJob = null ;
87
+ readonly static HashSet < string > s_updatedGeneratorNames = new ( ) ;
78
88
static void ProcessingFiles ( )
79
89
{
80
90
foreach ( string path in s_targetFilePaths )
81
91
{
82
92
ProcessFile ( path ) ;
83
93
}
84
94
95
+ // TODO: more efficient way to process related targets
96
+ foreach ( var generatorName in s_updatedGeneratorNames )
97
+ {
98
+ foreach ( var info in s_typeNameToInfo . Values )
99
+ {
100
+ if ( info . TargetClass == null ) continue ;
101
+ if ( info . Attribute . GeneratorClass ? . Name != generatorName ) continue ;
102
+
103
+ s_updatedGeneratorJob += ( ) => USGUtility . ForceGenerate ( info . TargetClass . Name , false ) ;
104
+ }
105
+ }
106
+ s_updatedGeneratorNames . Clear ( ) ;
107
+
85
108
if ( s_targetFilePaths . Count ( ) > 0 ) AssetDatabase . Refresh ( ) ;
86
109
s_targetFilePaths . Clear ( ) ;
87
-
88
- IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
89
- s_processingJobQueued = false ;
90
110
}
91
111
92
112
@@ -119,6 +139,22 @@ public static void ProcessFile(string assetsRelPath)
119
139
var info = s_typeNameToInfo [ clsName ] ;
120
140
if ( info == null ) return ;
121
141
142
+ // TODO: more streamlined.
143
+ if ( info . TargetClass == null )
144
+ {
145
+ s_updatedGeneratorNames . Add ( clsName ) ;
146
+ return ;
147
+ }
148
+
149
+
150
+ if ( ! TryBuildOutputFileName ( info ) )
151
+ {
152
+ Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
153
+ return ;
154
+ }
155
+
156
+ var generatorCls = info . Attribute . GeneratorClass ?? info . TargetClass ;
157
+
122
158
123
159
// build path
124
160
string outputPath = Path . Combine ( s_projectDirPath , Path . GetDirectoryName ( assetsRelPath ) ) . Replace ( '\\ ' , '/' ) ;
@@ -129,14 +165,15 @@ public static void ProcessFile(string assetsRelPath)
129
165
130
166
var context = new USGContext
131
167
{
168
+ TargetClass = info . TargetClass ,
132
169
AssetPath = assetsRelPath . Replace ( '\\ ' , '/' ) ,
133
170
OutputPath = outputPath . Replace ( '\\ ' , '/' ) ,
134
171
} ;
135
172
136
173
137
174
// do it.
138
175
var sb = new StringBuilder ( ) ;
139
- sb . AppendLine ( $ "// <auto-generated>{ info . Type . Name } </auto-generated>") ;
176
+ sb . AppendLine ( $ "// <auto-generated>{ generatorCls . Name } </auto-generated>") ;
140
177
141
178
var isSaveFile = false ;
142
179
try
@@ -145,7 +182,7 @@ public static void ProcessFile(string assetsRelPath)
145
182
}
146
183
catch
147
184
{
148
- Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Unhandled Error on Emit(): { info . Type } ") ;
185
+ Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Unhandled Error on Emit(): { generatorCls } ") ;
149
186
throw ;
150
187
}
151
188
@@ -159,7 +196,7 @@ public static void ProcessFile(string assetsRelPath)
159
196
160
197
161
198
if ( File . Exists ( context . OutputPath ) &&
162
- ( ! info . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
199
+ ( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
163
200
)
164
201
{
165
202
return ;
@@ -183,14 +220,14 @@ public static void ProcessFile(string assetsRelPath)
183
220
184
221
class CachedTypeInfo
185
222
{
186
- public Type Type ;
187
-
188
- //from attribute
189
- public bool OverwriteIfFileExists ;
223
+ // TODO: more streamlined.
224
+ ///<summary>null if generator that only referenced from other classes.</summary>
225
+ public Type TargetClass ;
226
+ public UnitySourceGeneratorAttribute Attribute ;
190
227
191
- //from method
192
- public MethodInfo EmitMethod ;
193
228
public string OutputFileName ;
229
+ public MethodInfo EmitMethod ;
230
+ public MethodInfo OutputFileNameMethod ;
194
231
}
195
232
196
233
@@ -246,8 +283,8 @@ static void CollectTargets()
246
283
var attr = t . GetCustomAttribute < UnitySourceGeneratorAttribute > ( false ) ;
247
284
return new CachedTypeInfo
248
285
{
249
- Type = t ,
250
- OverwriteIfFileExists = attr . OverwriteIfFileExists ,
286
+ TargetClass = t ,
287
+ Attribute = attr ,
251
288
} ;
252
289
} )
253
290
;
@@ -258,48 +295,67 @@ static void CollectTargets()
258
295
{
259
296
//Debug.Log($"[{nameof(UnitySourceGenerator)}] Processing...: {info.ClassName}");
260
297
261
- var outputMethod = info . Type . GetMethod ( "OutputFileName" , METHOD_FLAGS , null , Type . EmptyTypes , null ) ;
262
- var emitMethod = info . Type . GetMethod ( "Emit" , METHOD_FLAGS , null , new Type [ ] { typeof ( USGContext ) , typeof ( StringBuilder ) } , null ) ;
298
+ var generatorCls = info . Attribute . GeneratorClass ?? info . TargetClass ;
299
+ var outputMethod = generatorCls . GetMethod ( "OutputFileName" , METHOD_FLAGS , null , Type . EmptyTypes , null ) ;
300
+ var emitMethod = generatorCls . GetMethod ( "Emit" , METHOD_FLAGS , null , new Type [ ] { typeof ( USGContext ) , typeof ( StringBuilder ) } , null ) ;
263
301
264
302
if ( outputMethod == null || emitMethod == null )
265
303
{
266
- Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Required static method(s) not found: { info . Type } ") ;
304
+ Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Required static method(s) not found: { generatorCls } ") ;
267
305
continue ;
268
306
}
269
307
270
-
271
308
info . EmitMethod = emitMethod ;
309
+ info . OutputFileNameMethod = outputMethod ;
272
310
273
311
//filename??
274
- info . OutputFileName = ( string ) outputMethod . Invoke ( null , null ) ;
275
- if ( string . IsNullOrWhiteSpace ( info . OutputFileName ) )
312
+ if ( ! TryBuildOutputFileName ( info ) )
276
313
{
277
314
Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
278
315
continue ;
279
316
}
280
317
281
318
282
- //build filename
283
- string fileName = Path . GetFileNameWithoutExtension ( info . OutputFileName ) ;
284
- string fileExt = Path . GetExtension ( info . OutputFileName ) ;
285
- string outputFileName = fileName + GENERATOR_PREFIX + info . Type . Name + GENERATOR_EXT + fileExt ;
319
+ s_typeNameToInfo . TryAdd ( info . TargetClass . Name , info ) ;
320
+ if ( generatorCls != info . TargetClass )
321
+ {
322
+ // TODO: more streamlined.
323
+ //Debug.Log($"[USG] Generator found: {generatorCls.Name}");
286
324
287
- info . OutputFileName = outputFileName ;
325
+ var genInfo = new CachedTypeInfo
326
+ {
327
+ TargetClass = null ,
328
+ OutputFileName = null ,
329
+ EmitMethod = null ,
330
+ OutputFileNameMethod = null ,
331
+ Attribute = info . Attribute ,
332
+ } ;
288
333
289
- //once again
290
- if ( string . IsNullOrWhiteSpace ( info . OutputFileName ) )
291
- {
292
- Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
293
- continue ;
334
+ s_typeNameToInfo . TryAdd ( generatorCls . Name , genInfo ) ;
294
335
}
295
336
296
- s_typeNameToInfo . TryAdd ( info . Type . Name , info ) ;
297
-
298
337
299
338
} //foreach
300
339
}
301
340
302
341
342
+ static bool TryBuildOutputFileName ( CachedTypeInfo info )
343
+ {
344
+ info . OutputFileName = ( string ) info . OutputFileNameMethod ? . Invoke ( null , null ) ;
345
+ if ( string . IsNullOrWhiteSpace ( info . OutputFileName ) )
346
+ return false ;
347
+
348
+ string fileName = Path . GetFileNameWithoutExtension ( info . OutputFileName ) ;
349
+ string fileExt = Path . GetExtension ( info . OutputFileName ) ;
350
+ info . OutputFileName = fileName + GENERATOR_PREFIX + info . TargetClass . Name ;
351
+ if ( info . Attribute . GeneratorClass != null )
352
+ info . OutputFileName += GENERATOR_PREFIX + info . Attribute . GeneratorClass . Name ;
353
+ info . OutputFileName += GENERATOR_EXT + fileExt ;
354
+
355
+ return true ;
356
+ }
357
+
358
+
303
359
}
304
360
}
305
361
#endif
0 commit comments