@@ -15,7 +15,7 @@ namespace SatorImaging.UnitySourceGenerator
1515{
1616 public class USGEngine : AssetPostprocessor
1717 {
18- ///<summary>This will be disabled after import event automatically.</summary>
18+ ///<summary>This will be disabled after Unity Editor import event automatically.</summary>
1919 public static bool IgnoreOverwriteSettingByAttribute = false ;
2020
2121
@@ -71,22 +71,42 @@ static void OnPostprocessAllAssets(
7171 if ( s_processingJobQueued ) return ;
7272 s_processingJobQueued = true ;
7373
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+ } ;
7684 }
7785
86+ static Action s_updatedGeneratorJob = null ;
87+ readonly static HashSet < string > s_updatedGeneratorNames = new ( ) ;
7888 static void ProcessingFiles ( )
7989 {
8090 foreach ( string path in s_targetFilePaths )
8191 {
8292 ProcessFile ( path ) ;
8393 }
8494
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+
85108 if ( s_targetFilePaths . Count ( ) > 0 ) AssetDatabase . Refresh ( ) ;
86109 s_targetFilePaths . Clear ( ) ;
87-
88- IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
89- s_processingJobQueued = false ;
90110 }
91111
92112
@@ -119,6 +139,22 @@ public static void ProcessFile(string assetsRelPath)
119139 var info = s_typeNameToInfo [ clsName ] ;
120140 if ( info == null ) return ;
121141
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+
122158
123159 // build path
124160 string outputPath = Path . Combine ( s_projectDirPath , Path . GetDirectoryName ( assetsRelPath ) ) . Replace ( '\\ ' , '/' ) ;
@@ -129,14 +165,15 @@ public static void ProcessFile(string assetsRelPath)
129165
130166 var context = new USGContext
131167 {
168+ TargetClass = info . TargetClass ,
132169 AssetPath = assetsRelPath . Replace ( '\\ ' , '/' ) ,
133170 OutputPath = outputPath . Replace ( '\\ ' , '/' ) ,
134171 } ;
135172
136173
137174 // do it.
138175 var sb = new StringBuilder ( ) ;
139- sb . AppendLine ( $ "// <auto-generated>{ info . Type . Name } </auto-generated>") ;
176+ sb . AppendLine ( $ "// <auto-generated>{ generatorCls . Name } </auto-generated>") ;
140177
141178 var isSaveFile = false ;
142179 try
@@ -145,7 +182,7 @@ public static void ProcessFile(string assetsRelPath)
145182 }
146183 catch
147184 {
148- Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Unhandled Error on Emit(): { info . Type } ") ;
185+ Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Unhandled Error on Emit(): { generatorCls } ") ;
149186 throw ;
150187 }
151188
@@ -159,7 +196,7 @@ public static void ProcessFile(string assetsRelPath)
159196
160197
161198 if ( File . Exists ( context . OutputPath ) &&
162- ( ! info . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
199+ ( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
163200 )
164201 {
165202 return ;
@@ -183,14 +220,14 @@ public static void ProcessFile(string assetsRelPath)
183220
184221 class CachedTypeInfo
185222 {
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 ;
190227
191- //from method
192- public MethodInfo EmitMethod ;
193228 public string OutputFileName ;
229+ public MethodInfo EmitMethod ;
230+ public MethodInfo OutputFileNameMethod ;
194231 }
195232
196233
@@ -246,8 +283,8 @@ static void CollectTargets()
246283 var attr = t . GetCustomAttribute < UnitySourceGeneratorAttribute > ( false ) ;
247284 return new CachedTypeInfo
248285 {
249- Type = t ,
250- OverwriteIfFileExists = attr . OverwriteIfFileExists ,
286+ TargetClass = t ,
287+ Attribute = attr ,
251288 } ;
252289 } )
253290 ;
@@ -258,48 +295,67 @@ static void CollectTargets()
258295 {
259296 //Debug.Log($"[{nameof(UnitySourceGenerator)}] Processing...: {info.ClassName}");
260297
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 ) ;
263301
264302 if ( outputMethod == null || emitMethod == null )
265303 {
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 } ") ;
267305 continue ;
268306 }
269307
270-
271308 info . EmitMethod = emitMethod ;
309+ info . OutputFileNameMethod = outputMethod ;
272310
273311 //filename??
274- info . OutputFileName = ( string ) outputMethod . Invoke ( null , null ) ;
275- if ( string . IsNullOrWhiteSpace ( info . OutputFileName ) )
312+ if ( ! TryBuildOutputFileName ( info ) )
276313 {
277314 Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
278315 continue ;
279316 }
280317
281318
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}");
286324
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+ } ;
288333
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 ) ;
294335 }
295336
296- s_typeNameToInfo . TryAdd ( info . Type . Name , info ) ;
297-
298337
299338 } //foreach
300339 }
301340
302341
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+
303359 }
304360}
305361#endif
0 commit comments