@@ -60,36 +60,38 @@ void OnPreprocessAsset()
6060 static void OnPostprocessAllAssets (
6161 string [ ] importedAssets , string [ ] deletedAssets , string [ ] movedAssets , string [ ] movedFromAssetPaths )
6262 {
63+ // NOTE: Do NOT handle deleted assets because Unity tracking changes perfectly.
64+ // Even if delete file while Unity shutted down, asset deletion event happens on next Unity launch.
65+ // As a result, delete/import event loops infinitely and file cannot be deleted.
6366 for ( int i = 0 ; i < importedAssets . Length ; i ++ )
6467 {
6568 AddAppropriateTarget ( importedAssets [ i ] ) ;
6669 }
6770
68- // NOTE: Do NOT handle deleted assets because Unity tracking changes perfectly.
69- // Even if delete file while Unity shutted down, asset deletion event happens on next Unity launch.
70- // As a result, delete/import event loops infinitely and file cannot be deleted.
7171 if ( s_processingJobQueued ) return ;
7272 s_processingJobQueued = true ;
7373
74- // NOTE: need to stack jobs. nesting delayCall's causes error.
75- EditorApplication . delayCall += static ( ) =>
74+ // TODO: Unity sometimes reloads updated scripts by Visual Studio in background automatically.
75+ // In this situation, code generation will be done with script data right before saving.
76+ // It cannot be solved on C#, simply restart Unity.
77+ // Using [DidReloadScripts] or EditorApplication.delayCall, It works fine with Reimport
78+ // menu command but OnPostprocessAllAssets event doesn't work as expected.
79+ // (script runs with static field cleared even though .Clear() is only in ProcessingFiles())
80+ ////EditorApplication.delayCall += () =>
7681 {
7782 ProcessingFiles ( ) ;
78- s_updatedGeneratorJob ? . Invoke ( ) ;
79- s_updatedGeneratorJob = null ;
80-
81- IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
82- s_processingJobQueued = false ;
8383 } ;
8484 }
8585
86- static Action s_updatedGeneratorJob = null ;
86+
8787 readonly static HashSet < string > s_updatedGeneratorNames = new ( ) ;
8888 static void ProcessingFiles ( )
8989 {
90+ bool somethingUpdated = false ;
9091 foreach ( string path in s_targetFilePaths )
9192 {
92- ProcessFile ( path ) ;
93+ if ( ProcessFile ( path ) )
94+ somethingUpdated = true ;
9395 }
9496
9597 // TODO: more efficient way to process related targets
@@ -100,19 +102,30 @@ static void ProcessingFiles()
100102 if ( info . TargetClass == null ) continue ;
101103 if ( info . Attribute . GeneratorClass ? . Name != generatorName ) continue ;
102104
103- s_updatedGeneratorJob += ( ) => USGUtility . ForceGenerate ( info . TargetClass . Name , false ) ;
105+ var path = USGUtility . GetScriptFileByName ( info . TargetClass . Name ) ;
106+ if ( path != null )
107+ {
108+ IgnoreOverwriteSettingByAttribute = true ;
109+ if ( ProcessFile ( path ) )
110+ somethingUpdated = true ;
111+ }
104112 }
105113 }
106- s_updatedGeneratorNames . Clear ( ) ;
107114
108- if ( s_targetFilePaths . Count ( ) > 0 ) AssetDatabase . Refresh ( ) ;
115+ if ( somethingUpdated )
116+ AssetDatabase . Refresh ( ) ;
109117 s_targetFilePaths . Clear ( ) ;
118+ s_updatedGeneratorNames . Clear ( ) ;
119+
120+ IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
121+ s_processingJobQueued = false ;
110122 }
111123
112124
113125 ///<summary>This method respects "OverwriteIfFileExists" attribute setting.</summary>
114126 ///<param name="assetsRelPath">Path need to be started with "Assets/"</param>
115- public static void ProcessFile ( string assetsRelPath )
127+ ///<returns>true if file is written</returns>
128+ public static bool ProcessFile ( string assetsRelPath )
116129 {
117130 if ( ! File . Exists ( assetsRelPath ) ) throw new FileNotFoundException ( assetsRelPath ) ;
118131
@@ -122,35 +135,35 @@ public static void ProcessFile(string assetsRelPath)
122135 if ( ! s_typeNameToInfo . ContainsKey ( clsName ) )
123136 {
124137 if ( ! clsName . EndsWith ( GENERATOR_EXT ) )
125- return ;
138+ return false ;
126139
127140 // try find generator
128141 clsName = Path . GetFileNameWithoutExtension ( clsName ) ;
129142 clsName = Path . GetExtension ( clsName ) ;
130143
131- if ( clsName . Length == 0 ) return ;
144+ if ( clsName . Length == 0 ) return false ;
132145 clsName = clsName . Substring ( 1 ) ;
133146
134147 if ( ! s_typeNameToInfo . ContainsKey ( clsName ) )
135- return ;
148+ return false ;
136149 }
137150
138151
139152 var info = s_typeNameToInfo [ clsName ] ;
140- if ( info == null ) return ;
153+ if ( info == null ) return false ;
141154
142155 // TODO: more streamlined.
143156 if ( info . TargetClass == null )
144157 {
145158 s_updatedGeneratorNames . Add ( clsName ) ;
146- return ;
159+ return false ;
147160 }
148161
149162
150163 if ( ! TryBuildOutputFileName ( info ) )
151164 {
152165 Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
153- return ;
166+ return false ;
154167 }
155168
156169 var generatorCls = info . Attribute . GeneratorClass ?? info . TargetClass ;
@@ -187,25 +200,25 @@ public static void ProcessFile(string assetsRelPath)
187200 }
188201
189202 if ( ! isSaveFile || sb == null || string . IsNullOrWhiteSpace ( context . OutputPath ) )
190- return ;
203+ return false ;
204+
191205
192206
193- //file check
194207 var outputDir = Path . GetDirectoryName ( context . OutputPath ) ;
195208 if ( ! Directory . Exists ( outputDir ) ) Directory . CreateDirectory ( outputDir ) ;
196209
197-
198210 if ( File . Exists ( context . OutputPath ) &&
199211 ( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
200212 )
201213 {
202- return ;
214+ return false ;
203215 }
204216
205217
206218 File . WriteAllText ( context . OutputPath , sb . ToString ( ) ) ;
207219 Debug . Log ( $ "[{ nameof ( UnitySourceGenerator ) } ] Generated: { context . OutputPath } ") ;
208220
221+ return true ;
209222 }
210223
211224
0 commit comments