@@ -11,45 +11,122 @@ namespace Microsoft.MixedReality.Toolkit.Utilities.Editor
11
11
[ InitializeOnLoad ]
12
12
static class OnLoadUtilities
13
13
{
14
- private const string SessionStateKey = "StandardAssetsOnLoadUtilitiesSessionStateKey" ;
15
-
16
14
private const string ShaderSentinelGuid = "05852dd420bb9ec4cb7318bfa529d37c" ;
17
15
private const string ShaderSentinelFile = "MRTK.Shaders.sentinel" ;
18
16
19
17
private const string ShaderImportDestination = "MRTK/Shaders" ;
20
18
19
+ private const string IgnoreFileName = "IgnoreUpdateCheck.sentinel" ;
20
+
21
21
static OnLoadUtilities ( )
22
22
{
23
- // This InitializeOnLoad handler only runs once at editor launch in order to adjust for Unity version
24
- // differences. These don't need to (and should not be) run on an ongoing basis. This uses the
25
- // volatile SessionState which is clear when Unity launches to ensure that this only runs the
26
- // expensive work (file system i/o) once.
27
- if ( ! SessionState . GetBool ( SessionStateKey , false ) )
28
- {
29
- SessionState . SetBool ( SessionStateKey , true ) ;
30
- EnsureShaders ( ) ;
31
- }
23
+ EnsureShaders ( false ) ;
24
+ }
25
+
26
+ /// <summary>
27
+ /// Checks for updated shaders and bypasses the ignore update check.
28
+ /// </summary>
29
+ [ MenuItem ( "Mixed Reality Toolkit/Utilities/Check for Shader Updates" ) ]
30
+ private static void CheckForShaderUpdates ( )
31
+ {
32
+ EnsureShaders ( true ) ;
32
33
}
33
34
34
35
/// <summary>
35
36
/// Ensures that MRTK shader files are present in a writable location. To support the
36
37
/// Universal Render Pipeline, shader modifications must be persisted.
37
38
/// </summary>
38
- private static void EnsureShaders ( )
39
+ /// <param name="bypassIgnore">Causes the shader update code to disregard the ignore file.</param>
40
+ private static void EnsureShaders ( bool bypassIgnore )
39
41
{
40
- if ( ! AssetsContainsShaders ( ) )
42
+ DirectoryInfo packageShaderFolder = FindShaderFolderInPackage ( ) ;
43
+
44
+ if ( bypassIgnore )
45
+ {
46
+ // The customer is manually checking for updates, delete the ignore file
47
+ string sentinelPath = AssetDatabase . GUIDToAssetPath ( ShaderSentinelGuid ) ;
48
+ if ( ! string . IsNullOrWhiteSpace ( sentinelPath ) )
49
+ {
50
+ FileInfo ignoreFile = new FileInfo ( Path . Combine ( new FileInfo ( sentinelPath ) . Directory . FullName , IgnoreFileName ) ) ;
51
+ if ( ignoreFile . Exists )
52
+ {
53
+ ignoreFile . Delete ( ) ;
54
+ }
55
+ ignoreFile . Refresh ( ) ;
56
+ }
57
+ }
58
+
59
+ if ( ! AssetsContainsShaders ( packageShaderFolder ) )
41
60
{
42
- ImportShaderFiles ( ) ;
61
+ ImportShaderFiles ( packageShaderFolder ) ;
43
62
}
44
63
}
45
64
46
65
/// <summary>
47
66
/// Checks to see if the Assets or Packages (if embedded) folder trees contains the MRTK shaders.
48
67
/// </summary>
49
68
/// <returns>True if the shader sentinel file is found, otherwise false.</returns>
50
- private static bool AssetsContainsShaders ( )
69
+ private static bool AssetsContainsShaders ( DirectoryInfo packageShaderFolder )
51
70
{
52
- return ! string . IsNullOrWhiteSpace ( AssetDatabase . GUIDToAssetPath ( ShaderSentinelGuid ) ) ;
71
+ string sentinelPath = AssetDatabase . GUIDToAssetPath ( ShaderSentinelGuid ) ;
72
+
73
+ // If we do not find the sentinel, we need to import the shaders.
74
+ if ( string . IsNullOrWhiteSpace ( sentinelPath ) )
75
+ {
76
+ return false ;
77
+ }
78
+
79
+ // Getting here indicates that the project's Assets folder contains the shader sentinel.
80
+
81
+ // Check for the "ignore this check" file, if present we do NOT import
82
+ FileInfo ignoreFile = new FileInfo ( Path . Combine ( new FileInfo ( sentinelPath ) . Directory . FullName , IgnoreFileName ) ) ;
83
+ if ( ignoreFile . Exists )
84
+ {
85
+ return true ;
86
+ }
87
+
88
+ // If the package shader folder does not exist, there is nothing for us to do.
89
+ if ( ( packageShaderFolder == null ) || ! packageShaderFolder . Exists )
90
+ {
91
+ return true ;
92
+ }
93
+
94
+ // Get the versions of the sentinel files,
95
+ int packageVer = ReadSentinelVersion ( Path . Combine ( packageShaderFolder . FullName , ShaderSentinelFile ) ) ;
96
+ int assetVer = ReadSentinelVersion ( sentinelPath ) ;
97
+
98
+ // No need to copy if the versions are the same.
99
+ if ( packageVer == assetVer )
100
+ {
101
+ return true ;
102
+ }
103
+
104
+ string message = ( packageVer < assetVer ) ?
105
+ "The MRTK shaders older than those in your project, do you wish to overwrite the existing shaders?" :
106
+ "Updated MRTK shaders are available, do you wish to overwrite the existing shaders?" ;
107
+
108
+ int dialogResponse = EditorUtility . DisplayDialogComplex (
109
+ "Mixed Reality Toolkit Standard Assets" ,
110
+ message +
111
+ "\n \n NOTE: Overwriting will lose any customizations and may require reconfiguring the render pipeline." ,
112
+ "Yes" , // returns 0
113
+ "Ignore" , // returns 1 - placed in the cancel slot to force the button order as Yes, No, Ignore
114
+ "No" ) ; // returns 2
115
+
116
+ if ( dialogResponse == 1 )
117
+ {
118
+ // Write an "ignore this check" file to prevent future prompting
119
+ if ( ! ignoreFile . Directory . Exists )
120
+ {
121
+ ignoreFile . Directory . Create ( ) ;
122
+ }
123
+ ignoreFile . Create ( ) ;
124
+ }
125
+ ignoreFile . Refresh ( ) ;
126
+
127
+ // Return the inverse of the dialog result. Result of true means we want to overwrite, this method returns false
128
+ // to cause an overwrite.
129
+ return ( dialogResponse != 0 ) ;
53
130
}
54
131
55
132
/// <summary>
@@ -85,10 +162,9 @@ private static DirectoryInfo FindShaderFolderInPackage()
85
162
/// <summary>
86
163
/// Copies the shader files from the package cache to the Assets folder tree.
87
164
/// </summary>
88
- private static void ImportShaderFiles ( )
165
+ private static void ImportShaderFiles ( DirectoryInfo packageShaderFolder )
89
166
{
90
- DirectoryInfo source = FindShaderFolderInPackage ( ) ;
91
- if ( source == null )
167
+ if ( packageShaderFolder == null )
92
168
{
93
169
Debug . LogError ( "Unable to locate the shader source folder in the package" ) ;
94
170
return ;
@@ -100,11 +176,43 @@ private static void ImportShaderFiles()
100
176
destination . Create ( ) ;
101
177
}
102
178
103
- FileInfo [ ] sourceFiles = source . GetFiles ( ) ;
179
+ FileInfo [ ] sourceFiles = packageShaderFolder . GetFiles ( ) ;
104
180
foreach ( FileInfo fi in sourceFiles )
105
181
{
106
- fi . CopyTo ( Path . Combine ( destination . FullName , fi . Name ) ) ;
182
+ fi . CopyTo ( Path . Combine ( destination . FullName , fi . Name ) , true ) ;
183
+ }
184
+ }
185
+
186
+ /// <summary>
187
+ /// Reads the version number out of the shader
188
+ /// </summary>
189
+ /// <param name="sentinelPath">The path to the sentinel file.</param>
190
+ /// <returns>The version number found in the file, or -1.</returns>
191
+ private static int ReadSentinelVersion ( string sentinelPath )
192
+ {
193
+ using ( FileStream fs = new FileStream ( sentinelPath , FileMode . Open , FileAccess . Read ) )
194
+ {
195
+ using ( StreamReader reader = new StreamReader ( fs ) )
196
+ {
197
+ const string token = "ver:" ;
198
+
199
+ while ( ! reader . EndOfStream )
200
+ {
201
+ string line = reader . ReadLine ( ) ;
202
+ if ( line . StartsWith ( token ) )
203
+ {
204
+ line = line . Substring ( token . Length ) . Trim ( ) ;
205
+ if ( ! int . TryParse ( line , out int ver ) )
206
+ {
207
+ break ;
208
+ }
209
+ return ver ;
210
+ }
211
+ }
212
+ }
107
213
}
214
+
215
+ return - 1 ;
108
216
}
109
217
}
110
218
}
0 commit comments