@@ -40,6 +40,7 @@ public class AppveyorBuild
4040[ InitializeOnLoad ]
4141public class MLAPIEditor : EditorWindow
4242{
43+ private const string API_URL = "https://api.github.com/repos/MidLevel/MLAPI/releases" ;
4344 private GithubRelease [ ] releases = new GithubRelease [ 0 ] ;
4445 private bool [ ] foldoutStatus = new bool [ 0 ] ;
4546 private string currentVersion
@@ -68,6 +69,7 @@ private long lastUpdated
6869 private bool isFetching = false ;
6970 private bool isParsing = false ;
7071 private bool canRefetch => ! ( isFetching || isParsing ) ;
72+ private string statusMessage ;
7173
7274 private int tab ;
7375
@@ -80,7 +82,7 @@ public static void ShowWindow()
8082 Vector2 scrollPos = Vector2 . zero ;
8183 private void OnGUI ( )
8284 {
83- GUILayout . BeginArea ( new Rect ( 5 , 0 , position . width - 5 , position . height - 60 ) ) ;
85+ GUILayout . BeginArea ( new Rect ( 5 , 0 , position . width - 5 , position . height - ( 40 + ( ( string . IsNullOrEmpty ( statusMessage ) ? 0 : 20 ) + ( canRefetch ? 20 : 0 ) ) ) ) ) ;
8486 scrollPos = GUILayout . BeginScrollView ( scrollPos ) ;
8587 tab = GUILayout . Toolbar ( tab , new string [ ] { "GitHub" , "Commits" } ) ;
8688 if ( tab == 0 )
@@ -120,7 +122,7 @@ private void OnGUI()
120122 EditorGUILayout . LabelField ( "Release date: " + DateTime . Parse ( DateTime . Parse ( releases [ i ] . published_at ) . ToString ( ) ) , EditorStyles . miniBoldLabel ) ;
121123
122124 if ( currentVersion != releases [ i ] . tag_name && GUILayout . Button ( "Install" ) )
123- InstallRelease ( i ) ;
125+ EditorCoroutine . Start ( InstallRelease ( i ) ) ;
124126
125127 EditorGUI . indentLevel -- ;
126128 }
@@ -129,19 +131,20 @@ private void OnGUI()
129131 }
130132 else if ( tab == 1 )
131133 {
132- EditorGUILayout . LabelField ( "Not yet implemented. The rest API for AppVeyor is proper garbage and is needed to grab the artifact download URLs" , EditorStyles . wordWrappedLabel ) ;
134+ EditorGUILayout . LabelField ( "Not yet implemented. The rest API for AppVeyor is proper garbage and is needed to grab the artifact download URLs" , EditorStyles . wordWrappedMiniLabel ) ;
133135 }
134136 GUILayout . EndScrollView ( ) ;
135137 GUILayout . EndArea ( ) ;
136138
137- GUILayout . BeginArea ( new Rect ( 5 , position . height - 60 , position . width - 5 , 60 ) ) ;
139+ GUILayout . BeginArea ( new Rect ( 5 , position . height - ( 40 + ( ( string . IsNullOrEmpty ( statusMessage ) ? 0 : 20 ) + ( canRefetch ? 20 : 0 ) ) ) , position . width - 5 , ( 60 + ( ( string . IsNullOrEmpty ( statusMessage ) ? 0 : 20 ) + ( canRefetch ? 20 : 0 ) ) ) ) ) ;
138140
139141 string lastUpdatedString = lastUpdated == 0 ? "Never" : new DateTime ( lastUpdated ) . ToShortTimeString ( ) ;
140142 GUILayout . Label ( "Last checked: " + lastUpdatedString , EditorStyles . centeredGreyMiniLabel ) ;
141143
142- string fetchButton = isFetching ? "Fetching..." : isParsing ? "Parsing..." : "Fetch releases" ;
143- if ( GUILayout . Button ( fetchButton ) && canRefetch )
144+ if ( canRefetch && GUILayout . Button ( "Fetch releases" ) )
144145 EditorCoroutine . Start ( GetReleases ( ) ) ;
146+ if ( ! string . IsNullOrEmpty ( statusMessage ) )
147+ GUILayout . Label ( statusMessage , EditorStyles . centeredGreyMiniLabel ) ;
145148 if ( GUILayout . Button ( "Reset defaults" ) )
146149 {
147150 releases = new GithubRelease [ 0 ] ;
@@ -158,93 +161,147 @@ private void OnGUI()
158161 Repaint ( ) ;
159162 }
160163
161- private void InstallRelease ( int index )
164+ private IEnumerator InstallRelease ( int index )
162165 {
166+ statusMessage = "Cleaning lib folder" ;
167+ yield return null ;
168+
169+ if ( Directory . Exists ( Application . dataPath + "/MLAPI/Lib/" ) )
170+ Directory . Delete ( Application . dataPath + "/MLAPI/Lib/" , true ) ;
171+
172+ Directory . CreateDirectory ( Application . dataPath + "/MLAPI/Lib/" ) ;
173+
174+ bool downloadFail = false ;
163175 for ( int i = 0 ; i < releases [ index ] . assets . Length ; i ++ )
164176 {
165177 WWW www = new WWW ( releases [ index ] . assets [ i ] . browser_download_url ) ;
166178 while ( ! www . isDone && string . IsNullOrEmpty ( www . error ) )
167179 {
168- EditorGUI . ProgressBar ( new Rect ( 5 , position . height - 60 , position . width , 20 ) , www . progress , "Installing " + i + "/" + releases [ index ] . assets . Length ) ;
180+ statusMessage = "Downloading " + releases [ index ] . assets [ i ] . name + "(" + ( i + 1 ) + "/" + releases [ index ] . assets . Length + ") " + www . progress + "%" ;
181+ yield return null ;
169182 }
170183
171- if ( ! Directory . Exists ( Application . dataPath + "/MLAPI/Lib/" ) )
172- Directory . CreateDirectory ( Application . dataPath + "/MLAPI/Lib/" ) ;
184+ if ( ! string . IsNullOrEmpty ( www . error ) )
185+ {
186+ //Some kind of error
187+ downloadFail = true ;
188+ statusMessage = "Failed to download asset " + releases [ index ] . assets [ i ] . name + ". Error: " + www . error ;
189+ double startTime = EditorApplication . timeSinceStartup ;
190+ //Basically = yield return new WaitForSeconds(5);
191+ while ( EditorApplication . timeSinceStartup - startTime <= 5f )
192+ yield return null ;
193+ statusMessage = "" ;
194+ }
195+ else
196+ {
197+ statusMessage = "Writing " + releases [ index ] . assets [ i ] . name + " to disk" ;
198+ yield return null ;
199+
200+ File . WriteAllBytes ( Application . dataPath + "/MLAPI/Lib/" + releases [ index ] . assets [ i ] . name , www . bytes ) ;
173201
174- File . WriteAllBytes ( Application . dataPath + "/MLAPI/Lib/" + releases [ index ] . assets [ i ] . name , www . bytes ) ;
202+ if ( releases [ index ] . assets [ i ] . name . EndsWith ( ".unitypackage" ) )
203+ {
204+ statusMessage = "Installing " + releases [ index ] . assets [ i ] . name ;
205+ yield return null ;
206+ AssetDatabase . ImportPackage ( Application . dataPath + "/MLAPI/Lib/" + releases [ index ] . assets [ i ] . name , false ) ;
207+ }
175208
176- if ( releases [ index ] . assets [ i ] . name . EndsWith ( ".unitypackage" ) )
177- AssetDatabase . ImportPackage ( Application . dataPath + "/MLAPI/Lib/" + releases [ index ] . assets [ i ] . name , false ) ;
209+ yield return null ;
210+ }
178211 }
179212
180- currentVersion = releases [ index ] . tag_name ;
213+ yield return null ;
214+ statusMessage = "" ;
215+ if ( ! downloadFail )
216+ currentVersion = releases [ index ] . tag_name ; //Only set this if there was no fail. This is to allow them to still retry the download
181217 AssetDatabase . Refresh ( ) ;
182218 }
183219
184220
185- IEnumerator GetReleases ( )
221+ private IEnumerator GetReleases ( )
186222 {
187223 lastUpdated = DateTime . Now . Ticks ;
188224
189- WWW www = new WWW ( "https://api.github.com/repos/TwoTenPvP/MLAPI/releases" ) ;
225+ WWW www = new WWW ( API_URL ) ;
190226 isFetching = true ;
191227 while ( ! www . isDone && string . IsNullOrEmpty ( www . error ) )
192228 {
229+ statusMessage = "Fetching releases " + www . progress + "%" ;
193230 yield return null ;
194231 }
195- isFetching = false ;
196- isParsing = true ;
197- string json = www . text ;
198-
199- //This makes it from a json array to the individual objects in the array.
200- //The JSON serializer cant take arrays. We have to split it up outselves.
201- List < string > releasesJson = new List < string > ( ) ;
202- int depth = 0 ;
203- StringBuilder builder = new StringBuilder ( ) ;
204- for ( int i = 1 ; i < json . Length - 1 ; i ++ )
205- {
206- if ( json [ i ] == '[' )
207- depth ++ ;
208- else if ( json [ i ] == ']' )
209- depth -- ;
210- else if ( json [ i ] == '{' )
211- depth ++ ;
212- else if ( json [ i ] == '}' )
213- depth -- ;
214-
215- if ( ( depth == 0 && json [ i ] != ',' ) || depth > 0 )
216- builder . Append ( json [ i ] ) ;
217-
218- if ( depth == 0 && json [ i ] == ',' )
219- {
220- releasesJson . Add ( builder . ToString ( ) ) ;
221- builder . Length = 0 ;
222- }
223232
224- //Parse in smaller batches
225- if ( i % ( json . Length / 30 ) == 0 )
226- {
233+ if ( ! string . IsNullOrEmpty ( www . error ) )
234+ {
235+ //Some kind of error
236+ statusMessage = "Failed to fetch releases. Error: " + www . error ;
237+ double startTime = EditorApplication . timeSinceStartup ;
238+ //Basically = yield return new WaitForSeconds(5);
239+ while ( EditorApplication . timeSinceStartup - startTime <= 5f )
227240 yield return null ;
228- }
241+ statusMessage = "" ;
229242 }
243+ else
244+ {
245+ isFetching = false ;
246+ isParsing = true ;
247+ string json = www . text ;
248+
249+ //This makes it from a json array to the individual objects in the array.
250+ //The JSON serializer cant take arrays. We have to split it up outselves.
251+ List < string > releasesJson = new List < string > ( ) ;
252+ int depth = 0 ;
253+ StringBuilder builder = new StringBuilder ( ) ;
254+ for ( int i = 1 ; i < json . Length - 1 ; i ++ )
255+ {
256+ if ( json [ i ] == '[' )
257+ depth ++ ;
258+ else if ( json [ i ] == ']' )
259+ depth -- ;
260+ else if ( json [ i ] == '{' )
261+ depth ++ ;
262+ else if ( json [ i ] == '}' )
263+ depth -- ;
264+
265+ if ( ( depth == 0 && json [ i ] != ',' ) || depth > 0 )
266+ builder . Append ( json [ i ] ) ;
267+
268+ if ( depth == 0 && json [ i ] == ',' )
269+ {
270+ releasesJson . Add ( builder . ToString ( ) ) ;
271+ builder . Length = 0 ;
272+ }
230273
231- releases = new GithubRelease [ releasesJson . Count ] ;
232- foldoutStatus = new bool [ releasesJson . Count ] ;
274+ //Parse in smaller batches
275+ if ( i % ( json . Length / 100 ) == 0 )
276+ {
277+ statusMessage = "Splitting JSON " + ( i / ( float ) json . Length ) * 100f + "%" ;
278+ yield return null ;
279+ }
233280
234- for ( int i = 0 ; i < releasesJson . Count ; i ++ )
235- {
236- releases [ i ] = JsonUtility . FromJson < GithubRelease > ( releasesJson [ i ] ) ;
237- if ( i == 0 )
238- foldoutStatus [ i ] = true ;
239- else
240- foldoutStatus [ i ] = false ;
281+ statusMessage = "" ;
282+ }
241283
242- if ( i % ( releasesJson . Count / 30f ) == 0 )
284+ releases = new GithubRelease [ releasesJson . Count ] ;
285+ foldoutStatus = new bool [ releasesJson . Count ] ;
286+
287+ for ( int i = 0 ; i < releasesJson . Count ; i ++ )
243288 {
244- yield return null ;
289+ releases [ i ] = JsonUtility . FromJson < GithubRelease > ( releasesJson [ i ] ) ;
290+ if ( i == 0 )
291+ foldoutStatus [ i ] = true ;
292+ else
293+ foldoutStatus [ i ] = false ;
294+
295+ if ( i % ( releasesJson . Count / 30f ) == 0 )
296+ {
297+ yield return null ;
298+ statusMessage = "Parsing JSON " + ( i / ( float ) releasesJson . Count ) * 100f + "%" ;
299+ }
245300 }
301+
302+ statusMessage = "" ;
303+ isParsing = false ;
246304 }
247- isParsing = false ;
248305 }
249306
250307 public class EditorCoroutine
0 commit comments