@@ -42,7 +42,7 @@ public void OnGUI()
42
42
43
43
EditorGUILayout . LabelField ( "The version you are upgrading to has a greater major version. This means that there are non backwards compatibile changes. \n " +
44
44
"For more information about the MLAPI versioning, please visit SemVer.org" , warningStyle ) ;
45
- EditorGUILayout . LabelField ( "It's ALWAYS recommended to do a backup when upgrading major versions. If your project doesn't compile " +
45
+ EditorGUILayout . LabelField ( "It's ALWAYS recommended to do a backup AND reading all the breaking changes when upgrading major versions. If your project doesn't compile " +
46
46
"There is good chance serialized data will be PERMANENTLY LOST. Don't be stupid." , errorStyle ) ;
47
47
EditorGUILayout . LabelField ( "Here are the versions with breaking changes you are skipping." , EditorStyles . wordWrappedLabel ) ;
48
48
GUILayout . Space ( 5 ) ;
@@ -194,14 +194,27 @@ public class GithubRelease
194
194
public GithubAsset [ ] assets ;
195
195
}
196
196
197
+ [ Serializable ]
198
+ public class TransportArtifactDefinition
199
+ {
200
+ public TransportArtifact [ ] artifacts ;
201
+ }
202
+
197
203
[ Serializable ]
198
204
public class TransportArtifact
199
205
{
200
206
public string id ;
201
- public string description ;
202
207
public string name ;
208
+ public string description ;
203
209
public string path ;
204
210
public string credits ;
211
+ public string licence ;
212
+ public string platform_compatibility_description ;
213
+ public bool net35 ;
214
+ public bool net45 ;
215
+ public bool preferNet45 ;
216
+ public bool experimental ;
217
+ public int mlapi_major_version ;
205
218
}
206
219
207
220
[ Serializable ]
@@ -227,7 +240,8 @@ public class MLAPIEditor : EditorWindow
227
240
private const string TRANSPORT_ARTIFACT_PATH_URL = "https://api.github.com/repos/MidLevel/MLAPI.Transports/contents/artifact_paths.json" ;
228
241
private const string TRANSPORT_ARTIFACT_DOWNLOAD_URL_TEMPLATE = "https://ci.appveyor.com/api/projects/MidLevel/MLAPI-Transports/artifacts/<path>?branch=master" ;
229
242
private GithubRelease [ ] releases = new GithubRelease [ 0 ] ;
230
- private TransportArtifact [ ] transportArtifacts = new TransportArtifact [ 0 ] ;
243
+ private TransportArtifactDefinition transportArtifacts = null ;
244
+ private int [ ] transportVersionSelections = new int [ 0 ] ;
231
245
private bool [ ] releaseFoldoutStatus = new bool [ 0 ] ;
232
246
private bool [ ] transportFoldoutStatus = new bool [ 0 ] ;
233
247
@@ -361,28 +375,61 @@ private void OnGUI()
361
375
}
362
376
else if ( tab == 1 )
363
377
{
364
- if ( transportFoldoutStatus != null )
378
+ MLAPIVersion currentMLAPIVersion = MLAPIVersion . Parse ( currentVersion ) ;
379
+
380
+ if ( transportArtifacts != null && transportArtifacts . artifacts != null && transportFoldoutStatus != null )
365
381
{
366
- for ( int i = 0 ; i < transportFoldoutStatus . Length ; i ++ )
382
+ for ( int i = 0 ; i < transportArtifacts . artifacts . Length ; i ++ )
367
383
{
368
- if ( transportArtifacts [ i ] == null )
384
+ if ( transportArtifacts . artifacts [ i ] == null )
369
385
continue ;
370
386
371
- transportFoldoutStatus [ i ] = EditorGUILayout . Foldout ( transportFoldoutStatus [ i ] , transportArtifacts [ i ] . name ) ;
387
+ string transportDirectory = Path . Combine ( Path . Combine ( Path . Combine ( Application . dataPath , "MLAPI" ) , "OfficialTransports" ) , transportArtifacts . artifacts [ i ] . id ) ;
388
+ bool isInstalled = Directory . Exists ( transportDirectory ) && Directory . GetFiles ( transportDirectory ) . Length > 0 ;
389
+
390
+ transportFoldoutStatus [ i ] = EditorGUILayout . Foldout ( transportFoldoutStatus [ i ] , transportArtifacts . artifacts [ i ] . name + ( ( isInstalled ) ? " - [Installed]" : "" ) ) ;
372
391
373
392
if ( transportFoldoutStatus [ i ] )
374
393
{
375
394
EditorGUI . indentLevel ++ ;
376
395
377
- string transportDirectory = Path . Combine ( Path . Combine ( Path . Combine ( Application . dataPath , "MLAPI" ) , "OfficialTransports" ) , transportArtifacts [ i ] . id ) ;
378
-
379
396
EditorGUILayout . LabelField ( "Description" , EditorStyles . boldLabel ) ;
380
- EditorGUILayout . LabelField ( transportArtifacts [ i ] . description , EditorStyles . wordWrappedLabel ) ;
397
+ EditorGUILayout . LabelField ( transportArtifacts . artifacts [ i ] . description , EditorStyles . wordWrappedLabel ) ;
381
398
382
399
EditorGUILayout . LabelField ( "Credits" , EditorStyles . boldLabel ) ;
383
- EditorGUILayout . LabelField ( transportArtifacts [ i ] . credits , EditorStyles . wordWrappedLabel ) ;
400
+ EditorGUILayout . LabelField ( transportArtifacts . artifacts [ i ] . credits , EditorStyles . wordWrappedLabel ) ;
401
+
402
+ EditorGUILayout . LabelField ( "Platform Compatibility" , EditorStyles . boldLabel ) ;
403
+ EditorGUILayout . LabelField ( transportArtifacts . artifacts [ i ] . platform_compatibility_description , EditorStyles . wordWrappedLabel ) ;
404
+
405
+ EditorGUILayout . LabelField ( "Licence" , EditorStyles . boldLabel ) ;
406
+ EditorGUILayout . LabelField ( transportArtifacts . artifacts [ i ] . licence , EditorStyles . wordWrappedLabel ) ;
407
+
408
+ if ( currentMLAPIVersion . MAJOR != ( byte ) transportArtifacts . artifacts [ i ] . mlapi_major_version )
409
+ {
410
+ EditorGUILayout . Space ( ) ;
411
+ GUIStyle style = new GUIStyle ( EditorStyles . wordWrappedLabel ) ;
412
+ style . normal . textColor = new Color ( 1f , 0f , 0f ) ;
413
+ EditorGUILayout . LabelField ( "The MLAPI version you have installed through the installer has a different major version from the transports major version. You have version v" + currentMLAPIVersion . ToString ( ) + " while this transport targets version v" + transportArtifacts . artifacts [ i ] . mlapi_major_version + ".x.x. This means there could potentially be compatibility issues, but its not guaranteed. If you have installed the MLAPI manually and have version v" + transportArtifacts . artifacts [ i ] . mlapi_major_version + ".x.x you can ignore this message." , style ) ;
414
+ EditorGUILayout . Space ( ) ;
415
+ }
384
416
385
- if ( Directory . Exists ( transportDirectory ) && Directory . GetFiles ( transportDirectory ) . Length > 0 )
417
+ if ( transportArtifacts . artifacts [ i ] . experimental )
418
+ {
419
+ EditorGUILayout . Space ( ) ;
420
+ GUIStyle style = new GUIStyle ( EditorStyles . boldLabel ) ;
421
+ style . normal . textColor = new Color ( 1f , 0.5f , 0f ) ;
422
+ EditorGUILayout . LabelField ( "Experimental" , style ) ;
423
+ }
424
+ else
425
+ {
426
+ EditorGUILayout . Space ( ) ;
427
+ GUIStyle style = new GUIStyle ( EditorStyles . boldLabel ) ;
428
+ style . normal . textColor = new Color ( 0f , 1f , 0f ) ;
429
+ EditorGUILayout . LabelField ( "Stable" , style ) ;
430
+ }
431
+
432
+ if ( isInstalled )
386
433
{
387
434
GUIStyle boldStyle = new GUIStyle ( EditorStyles . boldLabel ) ;
388
435
boldStyle . normal . textColor = new Color ( 0.3f , 1f , 0.3f ) ;
@@ -397,6 +444,31 @@ private void OnGUI()
397
444
if ( GUILayout . Button ( "Remove" ) )
398
445
{
399
446
Directory . Delete ( transportDirectory , true ) ;
447
+
448
+ string metaFileName = transportDirectory ;
449
+
450
+ if ( metaFileName . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) ||
451
+ metaFileName . EndsWith ( Path . AltDirectorySeparatorChar . ToString ( ) ) )
452
+ {
453
+ metaFileName = metaFileName . Substring ( metaFileName . Length , metaFileName . Length - 1 ) ;
454
+ }
455
+
456
+ metaFileName += ".meta" ;
457
+
458
+ if ( File . Exists ( metaFileName ) )
459
+ {
460
+ File . Delete ( metaFileName ) ;
461
+ }
462
+
463
+ try
464
+ {
465
+ AssetDatabase . Refresh ( ) ;
466
+ }
467
+ catch ( Exception e )
468
+ {
469
+ Debug . LogError ( e . ToString ( ) ) ;
470
+ Debug . LogError ( e . GetType ( ) . FullName ) ;
471
+ }
400
472
}
401
473
}
402
474
else
@@ -421,7 +493,7 @@ private void OnGUI()
421
493
string lastUpdatedString = lastUpdated == 0 ? "Never" : new DateTime ( lastUpdated ) . ToShortTimeString ( ) ;
422
494
GUILayout . Label ( "Last checked: " + lastUpdatedString , EditorStyles . centeredGreyMiniLabel ) ;
423
495
424
- if ( canRefetch && GUILayout . Button ( "Fetch releases " ) )
496
+ if ( canRefetch && GUILayout . Button ( "Fetch All " ) )
425
497
EditorCoroutine . Start ( FetchAll ( ) ) ;
426
498
if ( ! string . IsNullOrEmpty ( statusMessage ) )
427
499
GUILayout . Label ( statusMessage , EditorStyles . centeredGreyMiniLabel ) ;
@@ -582,7 +654,16 @@ private IEnumerator InstallRelease(int index)
582
654
statusMessage = "" ;
583
655
if ( ! downloadFail )
584
656
currentVersion = releases [ index ] . tag_name ; //Only set this if there was no fail. This is to allow them to still retry the download
585
- AssetDatabase . Refresh ( ) ;
657
+
658
+ try
659
+ {
660
+ AssetDatabase . Refresh ( ) ;
661
+ }
662
+ catch ( Exception e )
663
+ {
664
+ Debug . LogError ( e . ToString ( ) ) ;
665
+ Debug . LogError ( e . GetType ( ) . FullName ) ;
666
+ }
586
667
}
587
668
showProgressBar = false ;
588
669
statusMessage = "" ;
@@ -598,27 +679,31 @@ private IEnumerator InstallTransport(int index)
598
679
statusMessage = "Cleaning transport folder" ;
599
680
yield return null ;
600
681
601
- string transportDirectory = Path . Combine ( Path . Combine ( Path . Combine ( Application . dataPath , "MLAPI" ) , "OfficialTransports" ) , transportArtifacts [ index ] . id ) ;
682
+ // Create the MLAPI directory if it doesnt exist, for example with manual installs.
683
+ if ( ! Directory . Exists ( Application . dataPath + "/MLAPI/" ) )
684
+ Directory . CreateDirectory ( Application . dataPath + "/MLAPI/" ) ;
685
+
686
+ string transportDirectory = Path . Combine ( Path . Combine ( Path . Combine ( Application . dataPath , "MLAPI" ) , "OfficialTransports" ) , transportArtifacts . artifacts [ index ] . id ) ;
602
687
603
688
if ( Directory . Exists ( transportDirectory ) )
604
689
Directory . Delete ( transportDirectory , true ) ;
605
690
606
691
Directory . CreateDirectory ( transportDirectory ) ;
607
692
608
693
609
- using ( UnityWebRequest www = UnityWebRequest . Get ( TRANSPORT_ARTIFACT_DOWNLOAD_URL_TEMPLATE . Replace ( "<path>" , transportArtifacts [ index ] . path ) ) )
694
+ using ( UnityWebRequest www = UnityWebRequest . Get ( TRANSPORT_ARTIFACT_DOWNLOAD_URL_TEMPLATE . Replace ( "<path>" , transportArtifacts . artifacts [ index ] . path ) ) )
610
695
{
611
696
www . SendWebRequest ( ) ;
612
697
while ( ! www . isDone && string . IsNullOrEmpty ( www . error ) )
613
698
{
614
- statusMessage = "Downloading " + transportArtifacts [ index ] . name + " " + www . downloadProgress + "%" ;
699
+ statusMessage = "Downloading " + transportArtifacts . artifacts [ index ] . name + " " + www . downloadProgress + "%" ;
615
700
yield return null ;
616
701
}
617
702
618
703
if ( ! string . IsNullOrEmpty ( www . error ) )
619
704
{
620
705
//Some kind of error
621
- statusMessage = "Failed to download asset " + transportArtifacts [ index ] . name + ". Error: " + www . error ;
706
+ statusMessage = "Failed to download asset " + transportArtifacts . artifacts [ index ] . name + ". Error: " + www . error ;
622
707
double startTime = EditorApplication . timeSinceStartup ;
623
708
//Basically = yield return new WaitForSeconds(5);
624
709
while ( EditorApplication . timeSinceStartup - startTime <= 5f )
@@ -627,34 +712,50 @@ private IEnumerator InstallTransport(int index)
627
712
}
628
713
else
629
714
{
630
- statusMessage = "Writing " + transportArtifacts [ index ] . name + " to disk" ;
715
+ statusMessage = "Writing " + transportArtifacts . artifacts [ index ] . name + " to disk" ;
631
716
yield return null ;
632
717
633
- File . WriteAllBytes ( Path . Combine ( transportDirectory , transportArtifacts [ index ] . path ) , www . downloadHandler . data ) ;
718
+ File . WriteAllBytes ( Path . Combine ( transportDirectory , transportArtifacts . artifacts [ index ] . path ) , www . downloadHandler . data ) ;
634
719
635
- if ( ! transportArtifacts [ index ] . path . EndsWith ( ".zip" ) )
720
+ if ( ! transportArtifacts . artifacts [ index ] . path . EndsWith ( ".zip" ) )
636
721
{
637
- // TODO: Invalid extension
722
+ Debug . LogError ( "Transport does not have a valid .zip extension. Is the editor outdated?" ) ;
638
723
}
639
724
else
640
725
{
641
- statusMessage = "Unzipping " + transportArtifacts [ index ] . name ;
726
+ statusMessage = "Unzipping " + transportArtifacts . artifacts [ index ] . name ;
642
727
643
- ZipStorer zip = ZipStorer . Open ( Path . Combine ( transportDirectory , transportArtifacts [ index ] . path ) , FileAccess . Read ) ;
728
+ ZipStorer zip = ZipStorer . Open ( Path . Combine ( transportDirectory , transportArtifacts . artifacts [ index ] . path ) , FileAccess . Read ) ;
644
729
List < ZipStorer . ZipFileEntry > dir = zip . ReadCentralDir ( ) ;
645
730
731
+ bool net35Exists = dir . Exists ( x => x . FilenameInZip . Contains ( "net35" ) ) ;
732
+ bool net45Exists = dir . Exists ( x => x . FilenameInZip . Contains ( "net45" ) ) ;
733
+
734
+ #if NET_4_6
735
+ bool supportsNet45 = true ;
736
+ #else
737
+ bool supportsNet45 = false ;
738
+ #endif
739
+
740
+ bool useNet35 = ( ! supportsNet45 || ! net45Exists || ! transportArtifacts . artifacts [ index ] . preferNet45 ) && net35Exists ;
741
+ bool useNet45 = net45Exists && supportsNet45 && ! useNet35 ;
742
+
743
+ if ( ! useNet35 && ! useNet45 )
744
+ {
745
+ Debug . LogError ( ( "Could not download transport \" " + transportArtifacts . artifacts [ index ] + "\" . There is no valid target for your platform." ) ) ;
746
+ }
747
+
646
748
foreach ( ZipStorer . ZipFileEntry entry in dir )
647
749
{
648
- if ( entry . FilenameInZip . Contains ( "net35" ) )
750
+ if ( ( useNet35 && entry . FilenameInZip . Contains ( "net35" ) ) ||
751
+ ( useNet45 && entry . FilenameInZip . Contains ( "net45" ) ) )
649
752
{
650
753
string fileName = Path . GetFileName ( entry . FilenameInZip ) ;
651
754
zip . ExtractFile ( entry , Path . Combine ( transportDirectory , fileName ) ) ;
652
755
}
653
756
}
654
757
655
758
zip . Close ( ) ;
656
-
657
- statusMessage = "" ;
658
759
}
659
760
660
761
yield return null ;
@@ -664,7 +765,16 @@ private IEnumerator InstallTransport(int index)
664
765
yield return null ;
665
766
statusMessage = "" ;
666
767
showProgressBar = false ;
667
- AssetDatabase . Refresh ( ) ;
768
+
769
+ try
770
+ {
771
+ AssetDatabase . Refresh ( ) ;
772
+ }
773
+ catch ( Exception e )
774
+ {
775
+ Debug . LogError ( e . ToString ( ) ) ;
776
+ Debug . LogError ( e . GetType ( ) . FullName ) ;
777
+ }
668
778
}
669
779
670
780
private IEnumerator FetchAll ( )
@@ -684,7 +794,9 @@ private IEnumerator FetchAll()
684
794
if ( ! string . IsNullOrEmpty ( www . error ) )
685
795
{
686
796
//Some kind of error
687
- statusMessage = "Failed to fetch releases. Error: " + www . error ;
797
+ statusMessage = "Failed to " +
798
+ "fetch rel" +
799
+ "eases. Error: " + www . error ;
688
800
double startTime = EditorApplication . timeSinceStartup ;
689
801
//Basically = yield return new WaitForSeconds(5);
690
802
while ( EditorApplication . timeSinceStartup - startTime <= 5f )
@@ -788,55 +900,23 @@ private IEnumerator FetchAll()
788
900
{
789
901
string decodedJson = Encoding . UTF8 . GetString ( Convert . FromBase64String ( githubContent . content ) ) ;
790
902
791
- //This makes it from a json array to the individual objects in the array.
792
- //The JSON serializer cant take arrays. We have to split it up outselves.
793
- List < string > transportsJson = new List < string > ( ) ;
794
- int depth = 0 ;
795
- StringBuilder builder = new StringBuilder ( ) ;
796
- for ( int i = 1 ; i < decodedJson . Length - 1 ; i ++ )
903
+ transportArtifacts = JsonUtility . FromJson < TransportArtifactDefinition > ( decodedJson ) ;
904
+
905
+ if ( transportArtifacts == null )
797
906
{
798
- if ( decodedJson [ i ] == '[' )
799
- depth ++ ;
800
- else if ( decodedJson [ i ] == ']' )
801
- depth -- ;
802
- else if ( decodedJson [ i ] == '{' )
803
- depth ++ ;
804
- else if ( decodedJson [ i ] == '}' )
805
- depth -- ;
806
-
807
- if ( ( depth == 0 && decodedJson [ i ] != ',' ) || depth > 0 )
808
- builder . Append ( decodedJson [ i ] ) ;
809
- if ( depth == 0 && ( decodedJson [ i ] == ',' || i == decodedJson . Length - 2 ) )
810
- {
811
- transportsJson . Add ( builder . ToString ( ) ) ;
812
- builder . Length = 0 ;
813
- }
814
- //Parse in smaller batches
815
- if ( i % ( decodedJson . Length / 100 ) == 0 )
816
- {
817
- statusMessage = "Splitting JSON " + ( i / ( float ) decodedJson . Length ) * 100f + "%" ;
818
- yield return null ;
819
- }
820
- statusMessage = "" ;
907
+ transportArtifacts = new TransportArtifactDefinition ( ) ;
821
908
}
822
909
823
- transportArtifacts = new TransportArtifact [ transportsJson . Count ] ;
824
- transportFoldoutStatus = new bool [ transportsJson . Count ] ;
825
- for ( int i = 0 ; i < transportsJson . Count ; i ++ )
910
+ if ( transportArtifacts . artifacts == null )
826
911
{
827
- transportArtifacts [ i ] = JsonUtility . FromJson < TransportArtifact > ( transportsJson [ i ] ) ;
828
- transportFoldoutStatus [ i ] = false ;
829
-
830
- if ( i % ( transportsJson . Count / 30f ) == 0 )
831
- {
832
- yield return null ;
833
- statusMessage = "Parsing JSON " + ( i / ( float ) transportsJson . Count ) * 100f + "%" ;
834
- }
912
+ transportArtifacts . artifacts = new TransportArtifact [ 0 ] ;
835
913
}
914
+
915
+ transportFoldoutStatus = new bool [ transportArtifacts . artifacts . Length ] ;
836
916
}
837
917
else
838
918
{
839
- // TODO: Invalid format
919
+ Debug . LogError ( "The artifact manifest had an unsupported encoding: " + githubContent . encoding + ". Supported encodings are base64" ) ;
840
920
}
841
921
842
922
0 commit comments