@@ -60,36 +60,38 @@ void OnPreprocessAsset()
60
60
static void OnPostprocessAllAssets (
61
61
string [ ] importedAssets , string [ ] deletedAssets , string [ ] movedAssets , string [ ] movedFromAssetPaths )
62
62
{
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.
63
66
for ( int i = 0 ; i < importedAssets . Length ; i ++ )
64
67
{
65
68
AddAppropriateTarget ( importedAssets [ i ] ) ;
66
69
}
67
70
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.
71
71
if ( s_processingJobQueued ) return ;
72
72
s_processingJobQueued = true ;
73
73
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 += () =>
76
81
{
77
82
ProcessingFiles ( ) ;
78
- s_updatedGeneratorJob ? . Invoke ( ) ;
79
- s_updatedGeneratorJob = null ;
80
-
81
- IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
82
- s_processingJobQueued = false ;
83
83
} ;
84
84
}
85
85
86
- static Action s_updatedGeneratorJob = null ;
86
+
87
87
readonly static HashSet < string > s_updatedGeneratorNames = new ( ) ;
88
88
static void ProcessingFiles ( )
89
89
{
90
+ bool somethingUpdated = false ;
90
91
foreach ( string path in s_targetFilePaths )
91
92
{
92
- ProcessFile ( path ) ;
93
+ if ( ProcessFile ( path ) )
94
+ somethingUpdated = true ;
93
95
}
94
96
95
97
// TODO: more efficient way to process related targets
@@ -100,19 +102,30 @@ static void ProcessingFiles()
100
102
if ( info . TargetClass == null ) continue ;
101
103
if ( info . Attribute . GeneratorClass ? . Name != generatorName ) continue ;
102
104
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
+ }
104
112
}
105
113
}
106
- s_updatedGeneratorNames . Clear ( ) ;
107
114
108
- if ( s_targetFilePaths . Count ( ) > 0 ) AssetDatabase . Refresh ( ) ;
115
+ if ( somethingUpdated )
116
+ AssetDatabase . Refresh ( ) ;
109
117
s_targetFilePaths . Clear ( ) ;
118
+ s_updatedGeneratorNames . Clear ( ) ;
119
+
120
+ IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
121
+ s_processingJobQueued = false ;
110
122
}
111
123
112
124
113
125
///<summary>This method respects "OverwriteIfFileExists" attribute setting.</summary>
114
126
///<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 )
116
129
{
117
130
if ( ! File . Exists ( assetsRelPath ) ) throw new FileNotFoundException ( assetsRelPath ) ;
118
131
@@ -122,35 +135,35 @@ public static void ProcessFile(string assetsRelPath)
122
135
if ( ! s_typeNameToInfo . ContainsKey ( clsName ) )
123
136
{
124
137
if ( ! clsName . EndsWith ( GENERATOR_EXT ) )
125
- return ;
138
+ return false ;
126
139
127
140
// try find generator
128
141
clsName = Path . GetFileNameWithoutExtension ( clsName ) ;
129
142
clsName = Path . GetExtension ( clsName ) ;
130
143
131
- if ( clsName . Length == 0 ) return ;
144
+ if ( clsName . Length == 0 ) return false ;
132
145
clsName = clsName . Substring ( 1 ) ;
133
146
134
147
if ( ! s_typeNameToInfo . ContainsKey ( clsName ) )
135
- return ;
148
+ return false ;
136
149
}
137
150
138
151
139
152
var info = s_typeNameToInfo [ clsName ] ;
140
- if ( info == null ) return ;
153
+ if ( info == null ) return false ;
141
154
142
155
// TODO: more streamlined.
143
156
if ( info . TargetClass == null )
144
157
{
145
158
s_updatedGeneratorNames . Add ( clsName ) ;
146
- return ;
159
+ return false ;
147
160
}
148
161
149
162
150
163
if ( ! TryBuildOutputFileName ( info ) )
151
164
{
152
165
Debug . LogError ( $ "[{ nameof ( UnitySourceGenerator ) } ] Output file name is invalid: { info . OutputFileName } ") ;
153
- return ;
166
+ return false ;
154
167
}
155
168
156
169
var generatorCls = info . Attribute . GeneratorClass ?? info . TargetClass ;
@@ -187,25 +200,25 @@ public static void ProcessFile(string assetsRelPath)
187
200
}
188
201
189
202
if ( ! isSaveFile || sb == null || string . IsNullOrWhiteSpace ( context . OutputPath ) )
190
- return ;
203
+ return false ;
204
+
191
205
192
206
193
- //file check
194
207
var outputDir = Path . GetDirectoryName ( context . OutputPath ) ;
195
208
if ( ! Directory . Exists ( outputDir ) ) Directory . CreateDirectory ( outputDir ) ;
196
209
197
-
198
210
if ( File . Exists ( context . OutputPath ) &&
199
211
( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
200
212
)
201
213
{
202
- return ;
214
+ return false ;
203
215
}
204
216
205
217
206
218
File . WriteAllText ( context . OutputPath , sb . ToString ( ) ) ;
207
219
Debug . Log ( $ "[{ nameof ( UnitySourceGenerator ) } ] Generated: { context . OutputPath } ") ;
208
220
221
+ return true ;
209
222
}
210
223
211
224
0 commit comments