@@ -20,8 +20,9 @@ public class USGEngine : AssetPostprocessor
20
20
public static bool IgnoreOverwriteSettingByAttribute = false ;
21
21
22
22
23
- const string EDITOR_PREFS_LENGTH = "__STMG_USG__TARGET_LENGTH" ;
24
- const string EDITOR_PREFS_PREFIX = "__STMG_USG__TARGET_" ;
23
+ const string EDITOR_PREFS_PREFIX = "__STMG_USG__" ;
24
+ const string EDITOR_PREFS_TARGET = EDITOR_PREFS_PREFIX + "TARGET_" ;
25
+ const string EDITOR_PREFS_LENGTH = EDITOR_PREFS_PREFIX + "TARGET_LENGTH" ;
25
26
const int BUFFER_LENGTH = 61_440 ;
26
27
const int BUFFER_MAX_CHAR_LENGTH = BUFFER_LENGTH / 3 ; // worst case of UTF-8
27
28
const string GENERATOR_PREFIX = "." ;
@@ -67,13 +68,14 @@ static void OnPostprocessAllAssets(
67
68
// menu command but OnPostprocessAllAssets event doesn't work as expected.
68
69
// (script runs with static field cleared even though .Clear() is only in ProcessingFiles().
69
70
// it's weird that event happens and asset paths retrieved but hashset items gone.)
71
+ // --> https://docs.unity3d.com/2021.3/Documentation/Manual/DomainReloading.html
70
72
// NOTE: Use EditorPrefs as a temporary storage.
71
73
var nPaths = 0 ;
72
74
for ( int i = 0 ; i < importedAssets . Length ; i ++ )
73
75
{
74
76
if ( ! IsAppropriateTarget ( importedAssets [ i ] ) ) continue ;
75
- EditorPrefs . SetString ( EDITOR_PREFS_PREFIX + nPaths ++ , importedAssets [ i ] ) ;
76
- Debug . Log ( $ "[USG]: Saved into EditorPrefs: { importedAssets [ i ] } " ) ;
77
+ if ( s_pathsToSkipNextImportEvent . Remove ( importedAssets [ i ] ) ) continue ;
78
+ EditorPrefs . SetString ( EDITOR_PREFS_TARGET + nPaths ++ , importedAssets [ i ] ) ;
77
79
}
78
80
EditorPrefs . SetInt ( EDITOR_PREFS_LENGTH , nPaths ) ;
79
81
@@ -85,7 +87,10 @@ static void OnPostprocessAllAssets(
85
87
}
86
88
87
89
90
+ readonly static HashSet < string > s_pathsToSkipNextImportEvent = new ( ) ;
91
+
88
92
readonly static HashSet < string > s_updatedGeneratorNames = new ( ) ;
93
+ readonly static HashSet < string > s_processedFiles = new ( ) ;
89
94
static void ProcessingFiles ( )
90
95
{
91
96
bool somethingUpdated = false ;
@@ -94,14 +99,16 @@ static void ProcessingFiles()
94
99
EditorPrefs . DeleteKey ( EDITOR_PREFS_LENGTH ) ;
95
100
for ( int i = 0 ; i < nPaths ; i ++ )
96
101
{
97
- var key = EDITOR_PREFS_PREFIX + i ;
102
+ var key = EDITOR_PREFS_TARGET + i ;
98
103
//if (!EditorPrefs.HasKey(key)) continue;
99
104
100
105
var path = EditorPrefs . GetString ( key ) ;
101
106
EditorPrefs . DeleteKey ( key ) ;
102
107
103
108
if ( ProcessFile ( path ) )
104
109
somethingUpdated = true ;
110
+
111
+ s_processedFiles . Add ( path ) ;
105
112
}
106
113
107
114
// TODO: more efficient way to process related targets
@@ -115,7 +122,7 @@ static void ProcessingFiles()
115
122
continue ;
116
123
117
124
var path = USGUtility . GetAssetPathByName ( info . TargetClass . Name ) ;
118
- if ( path != null && IsAppropriateTarget ( path ) )
125
+ if ( path != null && s_processedFiles . Add ( path ) && IsAppropriateTarget ( path ) )
119
126
{
120
127
IgnoreOverwriteSettingByAttribute = overwriteEnabledByCaller
121
128
|| info . Attribute . OverwriteIfFileExists ;
@@ -129,6 +136,7 @@ static void ProcessingFiles()
129
136
AssetDatabase . Refresh ( ) ;
130
137
131
138
s_updatedGeneratorNames . Clear ( ) ;
139
+ s_processedFiles . Clear ( ) ;
132
140
133
141
IgnoreOverwriteSettingByAttribute = false ; // always turn it off.
134
142
}
@@ -146,10 +154,16 @@ public static bool ProcessFile(string assetsRelPath)
146
154
147
155
if ( ! s_typeNameToInfo . ContainsKey ( clsName ) )
148
156
{
149
- if ( ! clsName . EndsWith ( GENERATOR_EXT ) )
157
+ // NOTE: When generated code has error, removing error code and save will invoke
158
+ // import event and error code will be re-generated again.
159
+ // (delaying code generation won't solve this behaviour...? disable anyway)
160
+ if ( ! IgnoreOverwriteSettingByAttribute )
150
161
return false ;
151
162
152
163
// try find generator
164
+ if ( ! clsName . EndsWith ( GENERATOR_EXT ) )
165
+ return false ;
166
+
153
167
clsName = Path . GetFileNameWithoutExtension ( clsName ) ;
154
168
clsName = Path . GetExtension ( clsName ) ;
155
169
@@ -164,9 +178,10 @@ public static bool ProcessFile(string assetsRelPath)
164
178
var info = s_typeNameToInfo [ clsName ] ;
165
179
if ( info == null ) return false ;
166
180
167
- // TODO: more streamlined.
168
181
if ( info . TargetClass == null )
169
182
{
183
+ // NOTE: this list contains referenced only generator names that used to perform
184
+ // code generation on referencing classes.
170
185
s_updatedGeneratorNames . Add ( clsName ) ;
171
186
return false ;
172
187
}
@@ -215,12 +230,17 @@ public static bool ProcessFile(string assetsRelPath)
215
230
return false ;
216
231
217
232
// NOTE: overwrite check must be done after Emit() due to allowing output path modification.
218
- // TODO: code generation happens but file is not written. any way to skip code generation?
219
- if ( File . Exists ( context . OutputPath ) &&
220
- ( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
221
- )
233
+ // TODO: code generation happens but file is not written when overwrite is disabled.
234
+ // any way to skip code generation?
235
+ if ( File . Exists ( context . OutputPath ) )
222
236
{
223
- return false ;
237
+ if ( ! info . Attribute . OverwriteIfFileExists && ! IgnoreOverwriteSettingByAttribute )
238
+ return false ;
239
+ }
240
+ else
241
+ {
242
+ // used to prevent import event happens on newly generated file.
243
+ s_pathsToSkipNextImportEvent . Add ( context . OutputPath ) ;
224
244
}
225
245
226
246
@@ -303,6 +323,7 @@ static void CollectTargets()
303
323
*/
304
324
305
325
326
+ // OPTIMIZE: ReflectionOnlyGetType() can be used??
306
327
var infos = AppDomain . CurrentDomain . GetAssemblies ( )
307
328
. Where ( static x =>
308
329
{
0 commit comments