using System; using System.Collections; using System.IO; using TriLibCore.General; using TriLibCore.Utils; using UnityEngine; using UnityEngine.Networking; namespace TriLibCore { /// Represents a class used to download Models with Coroutines used by the Asset Downloader. public class AssetDownloaderBehaviour : MonoBehaviour { /// /// Unity web request instance used on this script. /// private UnityWebRequest _unityWebRequest; /// /// Method to call when the model downloading progress changes. /// private Action _onProgress; /// /// Context used to load the model. /// private AssetLoaderContext _assetLoaderContext; /// Downloads the Model using the given Request and options. /// The Unity Web Request used to load the Model. You can use the CreateWebRequest method to create a new Unity Web Request or pass your instance. /// The Method to call on the Main Thread when the Model is loaded but resources may still pending. /// The Method to call on the Main Thread when the Model and resources are loaded. /// The Method to call when the Model loading progress changes. /// The Game Object that will be the parent of the loaded Game Object. Can be null. /// The Method to call on the Main Thread when any error occurs. /// The options to use when loading the Model. /// The Custom Data that will be passed along the Context. /// The extension of the URI Model. /// Pass true if your file is a Zip file. /// The download coroutine enumerator. public IEnumerator DownloadAsset(UnityWebRequest unityWebRequest, Action onLoad, Action onMaterialsLoad, Action onProgress, GameObject wrapperGameObject, Action onError, AssetLoaderOptions assetLoaderOptions, object customContextData, string fileExtension, bool? isZipFile = null) { _unityWebRequest = unityWebRequest; _onProgress = onProgress; yield return unityWebRequest.SendWebRequest(); try { if (unityWebRequest.responseCode < 400) { var memoryStream = new MemoryStream(_unityWebRequest.downloadHandler.data); var customDataDic = (object)CustomDataHelper.CreateCustomDataDictionaryWithData(new UriLoadCustomContextData { UnityWebRequest = _unityWebRequest }); if (customContextData != null) { CustomDataHelper.SetCustomData(ref customDataDic, customContextData); } var contentType = unityWebRequest.GetResponseHeader("Content-Type"); if (contentType != null && isZipFile == null) { isZipFile = contentType.Contains("application/zip") || contentType.Contains("application/x-zip-compressed") || contentType.Contains("multipart/x-zip"); } if (!isZipFile.GetValueOrDefault() && string.IsNullOrWhiteSpace(fileExtension)) { fileExtension = FileUtils.GetFileExtension(unityWebRequest.url); } if (isZipFile.GetValueOrDefault()) { _assetLoaderContext = AssetLoaderZip.LoadModelFromZipStream(memoryStream, onLoad, onMaterialsLoad, delegate (AssetLoaderContext assetLoaderContext, float progress) { onProgress?.Invoke(assetLoaderContext, 0.5f + progress * 0.5f); }, onError, wrapperGameObject, assetLoaderOptions, customDataDic, fileExtension); } else { _assetLoaderContext = AssetLoader.LoadModelFromStream(memoryStream, null, fileExtension, onLoad, onMaterialsLoad, delegate (AssetLoaderContext assetLoaderContext, float progress) { onProgress?.Invoke(assetLoaderContext, 0.5f + progress * 0.5f); }, onError, wrapperGameObject, assetLoaderOptions, customDataDic); } } else { var exception = new Exception($"UnityWebRequest error:{unityWebRequest.error}, code:{unityWebRequest.responseCode}"); throw exception; } } catch (Exception exception) { if (onError != null) { var contextualizedError = exception as IContextualizedError; onError(contextualizedError ?? new ContextualizedError(exception, null)); } else { throw; } } Destroy(gameObject); } /// Updates the download progress. private void Update() { _onProgress?.Invoke(_assetLoaderContext, _unityWebRequest.downloadProgress * 0.5F); } } }