1+ using System ;
2+ using System . IO ;
3+ using System . Linq ;
4+ using System . Threading ;
5+ using UnityEditor ;
6+ using UnityEngine ;
7+ using UnityEngine . Networking ;
8+
9+ namespace Loom . Client . Unity . Editor . Internal {
10+ [ InitializeOnLoad ]
11+ internal static class LoomSdkBootstrapper {
12+ static LoomSdkBootstrapper ( ) {
13+ EditorApplication . delayCall += ( ) => {
14+ if ( IsLoomSdkImported ( ) )
15+ return ;
16+
17+ bool result = EditorUtility . DisplayDialog (
18+ "Loom SDK - Installation" ,
19+ "Loom SDK is required in this project, but is not present.\n \n " +
20+ "Download and install Loom SDK now?" ,
21+ "Download and install" ,
22+ "Cancel"
23+ ) ;
24+
25+ if ( ! result )
26+ return ;
27+
28+ DownloadAndImportSdkPackage ( ) ;
29+ } ;
30+ }
31+
32+ [ MenuItem ( "Tools/Loom SDK/Install SDK" , true ) ]
33+ public static bool InstallValidate ( ) {
34+ return ! IsLoomSdkImported ( ) ;
35+ }
36+
37+ [ MenuItem ( "Tools/Loom SDK/Install SDK" ) ]
38+ public static void Install ( ) {
39+ if ( IsLoomSdkImported ( ) )
40+ return ;
41+
42+ DownloadAndImportSdkPackage ( ) ;
43+ }
44+
45+ [ MenuItem ( "Tools/Loom SDK/Update SDK" , true ) ]
46+ public static bool UpdateValidate ( ) {
47+ return IsLoomSdkImported ( ) ;
48+ }
49+
50+ [ MenuItem ( "Tools/Loom SDK/Update SDK" ) ]
51+ public static void Update ( ) {
52+ DownloadAndImportSdkPackage ( ) ;
53+ }
54+
55+ private static bool IsLoomSdkImported ( ) {
56+ string [ ] loomSdkAsmDef = AssetDatabase . FindAssets ( "t:AssemblyDefinitionAsset LoomSDK" ) ;
57+ if ( loomSdkAsmDef . Length > 0 )
58+ return true ;
59+
60+ return false ;
61+ }
62+
63+ private static void DownloadAndImportSdkPackage ( ) {
64+ string tempPackageDownloadPath = FileUtil . GetUniqueTempPathInProject ( ) + ".unitypackage" ;
65+ try {
66+ // Fetch release
67+ UnityWebRequest request = UnityWebRequest . Get ( "https://api.github.com/repos/loomnetwork/unity3d-sdk/releases/latest" ) ;
68+ request . timeout = 10 ;
69+ ExecuteSendWebRequestSync ( request , ( requestAsyncOperation ) =>
70+ ! EditorUtility . DisplayCancelableProgressBar (
71+ "Downloading Latest Loom SDK Package" ,
72+ "Fetching package info..." ,
73+ requestAsyncOperation . progress
74+ ) ) ;
75+
76+ string text = request . downloadHandler . text ;
77+ GitHubReleaseItem gitHubRelease = JsonUtility . FromJson < GitHubReleaseItem > ( text ) ;
78+ if ( gitHubRelease . assets . Length == 0 )
79+ throw new Exception ( "No Loom SDK releases found" ) ;
80+
81+ GitHubReleaseItem . Asset unityPackageAsset =
82+ gitHubRelease . assets
83+ . FirstOrDefault ( asset => asset . name . EndsWith ( ".unitypackage" ) ) ;
84+ if ( unityPackageAsset == null )
85+ throw new Exception ( "No Loom SDK releases with .unitypackage found" ) ;
86+
87+ // Download the package
88+ request = UnityWebRequest . Get ( unityPackageAsset . browser_download_url ) ;
89+ request . timeout = 10 ;
90+ DownloadHandlerFile downloadHandlerFile = new DownloadHandlerFile ( tempPackageDownloadPath ) ;
91+ downloadHandlerFile . removeFileOnAbort = true ;
92+ request . downloadHandler = downloadHandlerFile ;
93+ ExecuteSendWebRequestSync ( request , ( requestAsyncOperation ) =>
94+ ! EditorUtility . DisplayCancelableProgressBar (
95+ "Downloading Latest Loom SDK Package" ,
96+ String . Format (
97+ "Downloading package... {0} MB/{1} MB" ,
98+ Math . Round ( requestAsyncOperation . webRequest . downloadedBytes / 1000f / 1000f , 2 ) ,
99+ Math . Round ( ( double ) Convert . ToUInt32 ( requestAsyncOperation . webRequest . GetResponseHeader ( "Content-Length" ) ) / 1000f / 1000f , 2 )
100+ ) ,
101+ requestAsyncOperation . progress
102+ ) ) ;
103+
104+ AssetDatabase . ImportPackage ( tempPackageDownloadPath , false ) ;
105+ } catch ( OperationCanceledException ) {
106+ // Ignored
107+ } finally {
108+ EditorUtility . ClearProgressBar ( ) ;
109+ if ( File . Exists ( tempPackageDownloadPath ) ) {
110+ try {
111+ File . Delete ( tempPackageDownloadPath ) ;
112+ } catch {
113+ // Ignored
114+ }
115+ }
116+ }
117+ }
118+
119+ private static void ExecuteSendWebRequestSync ( UnityWebRequest request , Func < UnityWebRequestAsyncOperation , bool > onUpdate ) {
120+ UnityWebRequestAsyncOperation requestAsyncOperation = request . SendWebRequest ( ) ;
121+ while ( ! requestAsyncOperation . isDone ) {
122+ if ( ! onUpdate ( requestAsyncOperation ) ) {
123+ request . Abort ( ) ;
124+ throw new OperationCanceledException ( ) ;
125+ }
126+
127+ Thread . Sleep ( 50 ) ;
128+ }
129+
130+ if ( request . isNetworkError )
131+ throw new Exception ( $ "Network error while getting { request . url } ") ;
132+
133+ if ( request . isHttpError )
134+ throw new Exception ( $ "HTTP error { request . responseCode } while getting { request . url } ") ;
135+ }
136+
137+ #pragma warning disable 0649
138+ [ Serializable ]
139+ private class GitHubReleaseResponse {
140+ public GitHubReleaseItem [ ] items ;
141+ }
142+
143+ [ Serializable ]
144+ private class GitHubReleaseItem {
145+ public string url ;
146+ public Asset [ ] assets = new Asset [ 0 ] ;
147+
148+ [ Serializable ]
149+ public class Asset {
150+ public string name ;
151+ public string browser_download_url ;
152+ }
153+ }
154+ #pragma warning restore 0649
155+ }
156+ }
0 commit comments