using System; using UnityEngine; using System.Collections; using System.Collections.Generic; using Object = UnityEngine.Object; public class SkinDownloadManager : MonoBehaviour { public Shader ShaderAtlas; #region Unity Singleton private static SkinDownloadManager _instance; public static SkinDownloadManager Instance { get { if (_instance == null) { _instance = FindObjectOfType(typeof(SkinDownloadManager)) as SkinDownloadManager; if (_instance == null) { 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)); } } return _instance; } } void Awake() { Caching.CleanCache(); if (_instance != null && _instance != this) { AVDebug.LogWarning(string.Format("{0} Instance already exists on another gameObject. Destroying this gameObject {1}", this.GetType().Name, gameObject.name)); Destroy(gameObject); return; } _instance = this; DontDestroyOnLoad(gameObject); //DownloadBundleDevice.Extract(); //Debug.LogError("Awake"); } #endregion public ScreenBase applyingSkinProgressIndicator; public Transform sceneryAnchor; List _loadedObjects = new List(); const int NUM_OF_SUB_PARTS = 1; //int _subPartsDownloadedSoFar; bool _downloadInProgress; public const int BUNDLES_VERSION = 3; //TODO not sure how to use this value properly yet List _queuedSkinsForDownload = new List(); bool _isSkinBeingAppliedAtLaunch = true; public void DownloadSkin(string skinId) { _queuedSkinsForDownload.Add(skinId); if (!_downloadInProgress) { StartCoroutine(ProcessQueueCoroutine()); } } IEnumerator ProcessQueueCoroutine() { while (_queuedSkinsForDownload.Count > 0) { string skinId = _queuedSkinsForDownload[0]; _queuedSkinsForDownload.RemoveAt(0); yield return StartCoroutine(DownloadSkinCoroutine(skinId)); } } IEnumerator DownloadSkinCoroutine(string skinId) { Debug.Log("DownloadSkinCoroutine " + skinId); //_subPartsDownloadedSoFar = 0; _downloadInProgress = true; yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, "Backgrounds")); //If the previous sub part failed, the downloadInProgress would have been set to false if (_downloadInProgress) { yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, GetAtlasNameAccordingToResolution())); } //If the previous sub part failed, the downloadInProgress would have been set to false if (_downloadInProgress) { yield return StartCoroutine(DownloadAndCacheCoroutine(skinId, "Scenery")); } if (_downloadInProgress) { //All subparts are available and in cache NotificationCenter.Post(NotificationType.SkinDownloadCompleted, skinId); _downloadInProgress = false; } } IEnumerator DownloadAndCacheCoroutine(string skinId, string subPart) { //string url = GetSubPartURL(skinId, subPart); //AVDebug.Log("Loading asset bundle from "+url); // Wait for the Caching system to be ready while (!Caching.ready) { yield return null; } NotificationCenter.Post(NotificationType.SkinDownloadProgress, new object[] { skinId, 1 }); // Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache //#if UNITY_EDITOR // using (WWW www = new WWW(url)) //don't use caching in editor //#else // using (WWW www = WWW.LoadFromCacheOrDownload (url, BUNDLES_VERSION)) //#endif // { // while (!www.isDone) // { // float skinDownloadProgress = (_subPartsDownloadedSoFar/NUM_OF_SUB_PARTS) + (www.progress / NUM_OF_SUB_PARTS); // NotificationCenter.Post(NotificationType.SkinDownloadProgress, new object[] {skinId, skinDownloadProgress}); // yield return null; // } // if (www.error != null) // { // AVDebug.LogError("WWW download had an error:" + www.error); // _downloadInProgress = false; // NotificationCenter.Post (NotificationType.SkinDownloadFailed, skinId); // } else // { // AVDebug.Log ("Asset bundle downloaded "+url); // } // ++_subPartsDownloadedSoFar; // // Frees the memory from the web stream // www.Dispose (); // } } public static string GetSubPartPath(string skinId, string subPart) { string filename = skinId + "_" + subPart;// + ".unity3d"; #if UNITY_EDITOR || UNITY_ANDROID filename = "Android/" + filename; #else filename = "iPhone/" + filename; #endif return filename; //AssetBundle.CreateFromMemory() //#if !UNITY_WEBPLAYER // if (skinId == "default") // { // string url = Application.persistentDataPath + "/" + AssetBundleUtils.GetBuildTargetPrefix() + "/" + filename; //#if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID // url = "file:///" + url; //On Android we there is some jar:file// prefix automatically by Application.streamingAssetsPath //#endif // Debug.Log("GetSubPartURL " + url); // return url; // } // else //#endif // { // Debug.Log("AssetBundleUtils.GetAssetBundlesURL() filename " + AssetBundleUtils.GetAssetBundlesURL() + "/" + filename); // return AssetBundleUtils.GetAssetBundlesURL() + "/" + filename; // } } public static string GetSubPartURL(string skinId, string subPart) { string filename = skinId+"_"+subPart+".unity3d"; #if !UNITY_WEBPLAYER if (skinId == "default") { string url = Application.persistentDataPath+"/"+AssetBundleUtils.GetBuildTargetPrefix()+"/"+filename; #if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID url = "file:///"+url; //On Android we there is some jar:file// prefix automatically by Application.streamingAssetsPath #endif Debug.Log("GetSubPartURL " + url); return url; } else #endif { Debug.Log("AssetBundleUtils.GetAssetBundlesURL() filename " + AssetBundleUtils.GetAssetBundlesURL() + "/" + filename); return AssetBundleUtils.GetAssetBundlesURL() + "/"+filename; } } public void ApplyCachedSkin(string skinId) { Debug.Log("Applying skin "+skinId); StartCoroutine(ApplyCachedSkinCoroutine(skinId)); } IEnumerator ApplyCachedSkinCoroutine(string skinId) { if (!_isSkinBeingAppliedAtLaunch) { if(applyingSkinProgressIndicator!=null) applyingSkinProgressIndicator.Show(); yield return new WaitForSeconds(0.5f); } yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, "background", "ApplyBackgroundsCoroutine")); NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 0.33f); yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, GetAtlasNameAccordingToResolution(), "ApplyAtlasCoroutine")); NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 0.66f); yield return StartCoroutine(ApplyCachedSkinSubPartCoroutine(skinId, "scenery", "ApplySceneryCoroutine")); NotificationCenter.Post(NotificationType.ApplyingSkinProgress, 1f); if (!_isSkinBeingAppliedAtLaunch) { if(applyingSkinProgressIndicator!= null) applyingSkinProgressIndicator.Hide(); } else { _isSkinBeingAppliedAtLaunch = false; } NotificationCenter.Post(NotificationType.SkinApplied); System.GC.Collect(); Resources.UnloadUnusedAssets(); } IEnumerator ApplyCachedSkinSubPartCoroutine(string skinId, string subPart, string onCompleteCoroutineName) { var path = GetSubPartPath(skinId, subPart); Debug.Log("Path " + path); var asynk = AssetBundle.LoadFromMemoryAsync(Resources.Load(path).bytes); yield return asynk; yield return StartCoroutine(onCompleteCoroutineName, asynk.assetBundle); // string url = GetSubPartURL(skinId, subPart); // AVDebug.Log("Loading cached asset bundle from "+url); // // Wait for the Caching system to be ready // while (!Caching.ready) // { // yield return null; // } // Debug.LogWarning(url); //#if UNITY_EDITOR // using (WWW www = new WWW(url)) //don't use caching in editor //#else // using (WWW www = WWW.LoadFromCacheOrDownload (url, BUNDLES_VERSION)) //#endif // { // yield return www; // if (www.error != null) // { // Debug.LogError(www.error); // //AVDebug.LogError("WWW cached download for "+url+" had an error:" + www.error); // } // else // { // //AVDebug.Log("Successfully downloaded asset bundle from "+url); // Debug.LogWarning(www.url); // yield return StartCoroutine(onCompleteCoroutineName, www); // } // // Frees the memory from the web stream // www.Dispose(); // } } IEnumerator ApplyBackgroundsCoroutine(AssetBundle www) { //Clear anything from the previous loaded asset bundle foreach (Object loadedObj in _loadedObjects) { AVDebug.Log ("Destroying "+loadedObj); DestroyImmediate(loadedObj, true); } _loadedObjects.Clear(); //Debug.Log(www.url); AssetBundle bundle = www;//.assetBundle; // Load the object asynchronously Texture2D[] textures = new Texture2D[3]; for (int i = 0; i < 3; i++) { AssetBundleRequest request = bundle.LoadAssetAsync("texture" + i, typeof(Texture2D)); // Wait for completion yield return request; // Get the reference to the loaded object Texture2D texture = (Texture2D)request.asset; AVDebug.Log ("texture "+texture.name+" width "+texture.width); textures[i] = texture; _loadedObjects.Add(texture); } NotificationCenter.Post(NotificationType.ApplySkinBackgrounds, textures); // Unload the AssetBundles compressed contents to conserve memory bundle.Unload (false); } IEnumerator ApplyAtlasCoroutine(AssetBundle www) { AssetBundle bundle = www;//.assetBundle; /* foreach (var VARIABLE in bundle.GetAllAssetNames()) { Debug.Log(VARIABLE); }*/ //Debug.Log(www.url); string resolutionSuffix = GetSuffixAccordingToResolution(); // Load the objects asynchronously AtlasBundle atlasBundle = new AtlasBundle(); AssetBundleRequest request = bundle.LoadAssetAsync("GameAtlas" + resolutionSuffix, typeof(Texture2D)); yield return request; atlasBundle.atlasSheet = request.asset as Texture2D; _loadedObjects.Add(atlasBundle.atlasSheet); var name = ("GameAtlas" + resolutionSuffix);//.ToLower(); //Debug.Log(name); request = bundle.LoadAssetAsync(name, typeof(GameObject)); //Debug.Log(request.asset); yield return request; try { //Debug.Log(request.asset.name); /*for (int i = 0; i < request.asset; i++) { Debug.Log(request.allAssets[i].name); }*/ //Debug.Log(request.asset); atlasBundle.atlasPrefab = ((GameObject)request.asset).GetComponent(); atlasBundle.atlasPrefab.spriteMaterial.shader = ShaderAtlas; } catch (Exception) { throw; } //Debug.Log(((GameObject)request.asset).GetComponent()); _loadedObjects.Add(atlasBundle.atlasPrefab); request = bundle.LoadAssetAsync("ButtonFont" + resolutionSuffix, typeof(GameObject)); yield return request; atlasBundle.buttonFontPrefab = ((GameObject)request.asset).GetComponent(); atlasBundle.buttonFontPrefab.atlas = atlasBundle.atlasPrefab; _loadedObjects.Add(atlasBundle.buttonFontPrefab); request = bundle.LoadAssetAsync("ScoreFont" + resolutionSuffix, typeof(GameObject)); yield return request; atlasBundle.scoreFontPrefab = ((GameObject)request.asset).GetComponent(); _loadedObjects.Add(atlasBundle.scoreFontPrefab); request = bundle.LoadAssetAsync("TextFont" + resolutionSuffix, typeof(GameObject)); yield return request; atlasBundle.textFontPrefab = ((GameObject)request.asset).GetComponent(); _loadedObjects.Add(atlasBundle.textFontPrefab); NotificationCenter.Post(NotificationType.ApplyAtlasBundle, atlasBundle); // Unload the AssetBundles compressed contents to conserve memory bundle.Unload (false); } IEnumerator ApplySceneryCoroutine(AssetBundle www) { AssetBundle bundle = www;//.assetBundle; Debug.Log(www.ToString()); AssetBundleRequest request = bundle.LoadAssetAsync("Scenery", typeof(GameObject)); GameObject sceneryPrefab = (GameObject)request.asset; _loadedObjects.Add(sceneryPrefab); Destroy(GameObject.Find("Scenery")); GameObject scenery = (GameObject)Instantiate(sceneryPrefab); scenery.name = "Scenery"; scenery.SetActive(true); // Unload the AssetBundles compressed contents to conserve memory bundle.Unload (false); yield return request; } public static string GetAtlasNameAccordingToResolution() { return GetSuffixAccordingToResolution(); } public static string GetSuffixAccordingToResolution() { if (ResolutionSwitchController.IsSHD) { return "SHD"; } else if (ResolutionSwitchController.IsHD) { return "HD"; } else //if (ResolutionSwitchController.IsSD) { return "SD"; } } }