SkinDownloadManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Object = UnityEngine.Object;
  6. public class SkinDownloadManager : MonoBehaviour
  7. {
  8. public Shader ShaderAtlas;
  9. #region Unity Singleton
  10. private static SkinDownloadManager _instance;
  11. public static SkinDownloadManager Instance
  12. {
  13. get
  14. {
  15. if (_instance == null)
  16. {
  17. _instance = FindObjectOfType(typeof(SkinDownloadManager)) as SkinDownloadManager;
  18. if (_instance == null)
  19. {
  20. AVDebug.LogError(string.Format("No gameObject with {0} component exists. Make sure to create a gameObject with {0} component", new System.Diagnostics.StackFrame().GetMethod().DeclaringType));
  21. }
  22. }
  23. return _instance;
  24. }
  25. }
  26. void Awake()
  27. {
  28. Caching.CleanCache();
  29. if (_instance != null && _instance != this)
  30. {
  31. AVDebug.LogWarning(string.Format("{0} Instance already exists on another gameObject. Destroying this gameObject {1}", this.GetType().Name, gameObject.name));
  32. Destroy(gameObject);
  33. return;
  34. }
  35. _instance = this;
  36. DontDestroyOnLoad(gameObject);
  37. //DownloadBundleDevice.Extract();
  38. //Debug.LogError("Awake");
  39. }
  40. #endregion
  41. public ScreenBase applyingSkinProgressIndicator;
  42. public Transform sceneryAnchor;
  43. List<Object> _loadedObjects = new List<Object>();
  44. const int NUM_OF_SUB_PARTS = 1;
  45. //int _subPartsDownloadedSoFar;
  46. bool _downloadInProgress;
  47. public const int BUNDLES_VERSION = 3; //TODO not sure how to use this value properly yet
  48. List<string> _queuedSkinsForDownload = new List<string>();
  49. bool _isSkinBeingAppliedAtLaunch = true;
  50. public void DownloadSkin(string skinId)
  51. {
  52. _queuedSkinsForDownload.Add(skinId);
  53. if (!_downloadInProgress)
  54. {
  55. StartCoroutine(ProcessQueueCoroutine());
  56. }
  57. }
  58. IEnumerator ProcessQueueCoroutine()
  59. {
  60. while (_queuedSkinsForDownload.Count > 0)
  61. {
  62. string skinId = _queuedSkinsForDownload[0];
  63. _queuedSkinsForDownload.RemoveAt(0);
  64. yield return StartCoroutine(DownloadSkinCoroutine(skinId));
  65. }
  66. }
  67. IEnumerator DownloadSkinCoroutine(string skinId)
  68. {
  69. Debug.Log("DownloadSkinCoroutine " + skinId);
  70. //_subPartsDownloadedSoFar = 0;
  71. _downloadInProgress = true;
  72. yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, "Backgrounds"));
  73. //If the previous sub part failed, the downloadInProgress would have been set to false
  74. if (_downloadInProgress)
  75. {
  76. yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, GetAtlasNameAccordingToResolution()));
  77. }
  78. //If the previous sub part failed, the downloadInProgress would have been set to false
  79. if (_downloadInProgress)
  80. {
  81. yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, "Scenery"));
  82. }
  83. if (_downloadInProgress)
  84. {
  85. //All subparts are available and in cache
  86. NotificationCenter.Post(NotificationType.SkinDownloadCompleted, skinId);
  87. _downloadInProgress = false;
  88. }
  89. }
  90. IEnumerator DownloadAndCacheCoroutine(string skinId, string subPart)
  91. {
  92. //string url = GetSubPartURL(skinId, subPart);
  93. //AVDebug.Log("Loading asset bundle from "+url);
  94. // Wait for the Caching system to be ready
  95. while (!Caching.ready)
  96. {
  97. yield return null;
  98. }
  99. NotificationCenter.Post(NotificationType.SkinDownloadProgress, new object[] { skinId, 1 });
  100. // Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
  101. //#if UNITY_EDITOR
  102. // using (WWW www = new WWW(url)) //don't use caching in editor
  103. //#else
  104. // using (WWW www = WWW.LoadFromCacheOrDownload (url, BUNDLES_VERSION))
  105. //#endif
  106. // {
  107. // while (!www.isDone)
  108. // {
  109. // float skinDownloadProgress = (_subPartsDownloadedSoFar/NUM_OF_SUB_PARTS) + (www.progress / NUM_OF_SUB_PARTS);
  110. // NotificationCenter.Post(NotificationType.SkinDownloadProgress, new object[] {skinId, skinDownloadProgress});
  111. // yield return null;
  112. // }
  113. // if (www.error != null)
  114. // {
  115. // AVDebug.LogError("WWW download had an error:" + www.error);
  116. // _downloadInProgress = false;
  117. // NotificationCenter.Post (NotificationType.SkinDownloadFailed, skinId);
  118. // } else
  119. // {
  120. // AVDebug.Log ("Asset bundle downloaded "+url);
  121. // }
  122. // ++_subPartsDownloadedSoFar;
  123. // // Frees the memory from the web stream
  124. // www.Dispose ();
  125. // }
  126. }
  127. public static string GetSubPartPath(string skinId, string subPart)
  128. {
  129. string filename = skinId + "_" + subPart;// + ".unity3d";
  130. #if UNITY_EDITOR || UNITY_ANDROID
  131. filename = "Android/" + filename;
  132. #else
  133. filename = "iPhone/" + filename;
  134. #endif
  135. return filename;
  136. //AssetBundle.CreateFromMemory()
  137. //#if !UNITY_WEBPLAYER
  138. // if (skinId == "default")
  139. // {
  140. // string url = Application.persistentDataPath + "/" + AssetBundleUtils.GetBuildTargetPrefix() + "/" + filename;
  141. //#if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID
  142. // url = "file:///" + url; //On Android we there is some jar:file// prefix automatically by Application.streamingAssetsPath
  143. //#endif
  144. // Debug.Log("GetSubPartURL " + url);
  145. // return url;
  146. // }
  147. // else
  148. //#endif
  149. // {
  150. // Debug.Log("AssetBundleUtils.GetAssetBundlesURL() filename " + AssetBundleUtils.GetAssetBundlesURL() + "/" + filename);
  151. // return AssetBundleUtils.GetAssetBundlesURL() + "/" + filename;
  152. // }
  153. }
  154. public static string GetSubPartURL(string skinId, string subPart)
  155. {
  156. string filename = skinId+"_"+subPart+".unity3d";
  157. #if !UNITY_WEBPLAYER
  158. if (skinId == "default")
  159. {
  160. string url = Application.persistentDataPath+"/"+AssetBundleUtils.GetBuildTargetPrefix()+"/"+filename;
  161. #if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID
  162. url = "file:///"+url; //On Android we there is some jar:file// prefix automatically by Application.streamingAssetsPath
  163. #endif
  164. Debug.Log("GetSubPartURL " + url);
  165. return url;
  166. } else
  167. #endif
  168. {
  169. Debug.Log("AssetBundleUtils.GetAssetBundlesURL() filename " + AssetBundleUtils.GetAssetBundlesURL() + "/" + filename);
  170. return AssetBundleUtils.GetAssetBundlesURL() + "/"+filename;
  171. }
  172. }
  173. public void ApplyCachedSkin(string skinId)
  174. {
  175. Debug.Log("Applying skin "+skinId);
  176. StartCoroutine(ApplyCachedSkinCoroutine(skinId));
  177. }
  178. IEnumerator ApplyCachedSkinCoroutine(string skinId)
  179. {
  180. if (!_isSkinBeingAppliedAtLaunch)
  181. {
  182. if(applyingSkinProgressIndicator!=null)
  183. applyingSkinProgressIndicator.Show();
  184. yield return new WaitForSeconds(0.5f);
  185. }
  186. yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, "background", "ApplyBackgroundsCoroutine"));
  187. NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 0.33f);
  188. yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, GetAtlasNameAccordingToResolution(), "ApplyAtlasCoroutine"));
  189. NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 0.66f);
  190. yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, "scenery", "ApplySceneryCoroutine"));
  191. NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 1f);
  192. if (!_isSkinBeingAppliedAtLaunch)
  193. {
  194. if(applyingSkinProgressIndicator!= null)
  195. applyingSkinProgressIndicator.Hide();
  196. } else
  197. {
  198. _isSkinBeingAppliedAtLaunch = false;
  199. }
  200. NotificationCenter.Post(NotificationType.SkinApplied);
  201. System.GC.Collect();
  202. Resources.UnloadUnusedAssets();
  203. }
  204. IEnumerator ApplyCachedSkinSubPartCoroutine(string skinId, string subPart, string onCompleteCoroutineName)
  205. {
  206. var path = GetSubPartPath(skinId, subPart);
  207. Debug.Log("Path " + path);
  208. var asynk = AssetBundle.LoadFromMemoryAsync(Resources.Load<TextAsset>(path).bytes);
  209. yield return asynk;
  210. yield return StartCoroutine(onCompleteCoroutineName, asynk.assetBundle);
  211. // string url = GetSubPartURL(skinId, subPart);
  212. // AVDebug.Log("Loading cached asset bundle from "+url);
  213. // // Wait for the Caching system to be ready
  214. // while (!Caching.ready)
  215. // {
  216. // yield return null;
  217. // }
  218. // Debug.LogWarning(url);
  219. //#if UNITY_EDITOR
  220. // using (WWW www = new WWW(url)) //don't use caching in editor
  221. //#else
  222. // using (WWW www = WWW.LoadFromCacheOrDownload (url, BUNDLES_VERSION))
  223. //#endif
  224. // {
  225. // yield return www;
  226. // if (www.error != null)
  227. // {
  228. // Debug.LogError(www.error);
  229. // //AVDebug.LogError("WWW cached download for "+url+" had an error:" + www.error);
  230. // }
  231. // else
  232. // {
  233. // //AVDebug.Log("Successfully downloaded asset bundle from "+url);
  234. // Debug.LogWarning(www.url);
  235. // yield return StartCoroutine(onCompleteCoroutineName, www);
  236. // }
  237. // // Frees the memory from the web stream
  238. // www.Dispose();
  239. // }
  240. }
  241. IEnumerator ApplyBackgroundsCoroutine(AssetBundle www)
  242. {
  243. //Clear anything from the previous loaded asset bundle
  244. foreach (Object loadedObj in _loadedObjects)
  245. {
  246. AVDebug.Log ("Destroying "+loadedObj);
  247. DestroyImmediate(loadedObj, true);
  248. }
  249. _loadedObjects.Clear();
  250. //Debug.Log(www.url);
  251. AssetBundle bundle = www;//.assetBundle;
  252. // Load the object asynchronously
  253. Texture2D[] textures = new Texture2D[3];
  254. for (int i = 0; i < 3; i++)
  255. {
  256. AssetBundleRequest request = bundle.LoadAssetAsync("texture" + i, typeof(Texture2D));
  257. // Wait for completion
  258. yield return request;
  259. // Get the reference to the loaded object
  260. Texture2D texture = (Texture2D)request.asset;
  261. AVDebug.Log ("texture "+texture.name+" width "+texture.width);
  262. textures[i] = texture;
  263. _loadedObjects.Add(texture);
  264. }
  265. NotificationCenter.Post(NotificationType.ApplySkinBackgrounds, textures);
  266. // Unload the AssetBundles compressed contents to conserve memory
  267. bundle.Unload (false);
  268. }
  269. IEnumerator ApplyAtlasCoroutine(AssetBundle www)
  270. {
  271. AssetBundle bundle = www;//.assetBundle;
  272. /* foreach (var VARIABLE in bundle.GetAllAssetNames())
  273. {
  274. Debug.Log(VARIABLE);
  275. }*/
  276. //Debug.Log(www.url);
  277. string resolutionSuffix = GetSuffixAccordingToResolution();
  278. // Load the objects asynchronously
  279. AtlasBundle atlasBundle = new AtlasBundle();
  280. AssetBundleRequest request = bundle.LoadAssetAsync("GameAtlas" + resolutionSuffix, typeof(Texture2D));
  281. yield return request;
  282. atlasBundle.atlasSheet = request.asset as Texture2D;
  283. _loadedObjects.Add(atlasBundle.atlasSheet);
  284. var name = ("GameAtlas" + resolutionSuffix);//.ToLower();
  285. //Debug.Log(name);
  286. request = bundle.LoadAssetAsync(name, typeof(GameObject));
  287. //Debug.Log(request.asset);
  288. yield return request;
  289. try
  290. {
  291. //Debug.Log(request.asset.name);
  292. /*for (int i = 0; i < request.asset; i++)
  293. {
  294. Debug.Log(request.allAssets[i].name);
  295. }*/
  296. //Debug.Log(request.asset);
  297. atlasBundle.atlasPrefab = ((GameObject)request.asset).GetComponent<UIAtlas>();
  298. atlasBundle.atlasPrefab.spriteMaterial.shader = ShaderAtlas;
  299. }
  300. catch (Exception)
  301. {
  302. throw;
  303. }
  304. //Debug.Log(((GameObject)request.asset).GetComponent<UIAtlas>());
  305. _loadedObjects.Add(atlasBundle.atlasPrefab);
  306. request = bundle.LoadAssetAsync("ButtonFont" + resolutionSuffix, typeof(GameObject));
  307. yield return request;
  308. atlasBundle.buttonFontPrefab = ((GameObject)request.asset).GetComponent<UIFont>();
  309. atlasBundle.buttonFontPrefab.atlas = atlasBundle.atlasPrefab;
  310. _loadedObjects.Add(atlasBundle.buttonFontPrefab);
  311. request = bundle.LoadAssetAsync("ScoreFont" + resolutionSuffix, typeof(GameObject));
  312. yield return request;
  313. atlasBundle.scoreFontPrefab = ((GameObject)request.asset).GetComponent<UIFont>();
  314. _loadedObjects.Add(atlasBundle.scoreFontPrefab);
  315. request = bundle.LoadAssetAsync("TextFont" + resolutionSuffix, typeof(GameObject));
  316. yield return request;
  317. atlasBundle.textFontPrefab = ((GameObject)request.asset).GetComponent<UIFont>();
  318. _loadedObjects.Add(atlasBundle.textFontPrefab);
  319. NotificationCenter.Post(NotificationType.ApplyAtlasBundle, atlasBundle);
  320. // Unload the AssetBundles compressed contents to conserve memory
  321. bundle.Unload (false);
  322. }
  323. IEnumerator ApplySceneryCoroutine(AssetBundle www)
  324. {
  325. AssetBundle bundle = www;//.assetBundle;
  326. Debug.Log(www.ToString());
  327. AssetBundleRequest request = bundle.LoadAssetAsync("Scenery", typeof(GameObject));
  328. GameObject sceneryPrefab = (GameObject)request.asset;
  329. _loadedObjects.Add(sceneryPrefab);
  330. Destroy(GameObject.Find("Scenery"));
  331. GameObject scenery = (GameObject)Instantiate(sceneryPrefab);
  332. scenery.name = "Scenery";
  333. scenery.SetActive(true);
  334. // Unload the AssetBundles compressed contents to conserve memory
  335. bundle.Unload (false);
  336. yield return request;
  337. }
  338. public static string GetAtlasNameAccordingToResolution()
  339. {
  340. return GetSuffixAccordingToResolution();
  341. }
  342. public static string GetSuffixAccordingToResolution()
  343. {
  344. if (ResolutionSwitchController.IsSHD)
  345. {
  346. return "SHD";
  347. } else
  348. if (ResolutionSwitchController.IsHD)
  349. {
  350. return "HD";
  351. } else
  352. //if (ResolutionSwitchController.IsSD)
  353. {
  354. return "SD";
  355. }
  356. }
  357. }