#pragma warning disable 184 using System; using System.IO; using ICSharpCode.SharpZipLib.Zip; using TriLibCore.Mappers; using TriLibCore.Utils; using UnityEngine; namespace TriLibCore { /// /// Represents a class used to load all the models inside a Zip file. /// public static class MultipleAssetLoaderZip { /// Loads all models from the given Zip file Stream asynchronously. /// The Zip file Stream. /// The Method to call on the Main Thread when any Model is loaded but resources may still pending. /// The Method to call on the Main Thread when any Model and resources are loaded. /// The Method to call when any Model loading progress changes. /// The Method to call on the Main Thread when any error occurs. /// The Game Object that will be the parent of the loaded Game Objects. Can be null. /// The options to use when loading the Models. /// The Custom Data that will be passed along the Context. /// The Models inside the Zip file extension. If null TriLib will try to find a suitable model format inside the Zip file. /// Turn on this field to avoid loading the models immediately and chain the Tasks. /// The method to call on the parallel Thread before the Unity objects are created. public static void LoadAllModelsFromZipStream( Stream stream, Action onLoad, Action onMaterialsLoad, Action onProgress, Action onError = null, GameObject wrapperGameObject = null, AssetLoaderOptions assetLoaderOptions = null, object customContextData = null, string fileExtension = null, bool haltTask = false, Action onPreLoad = null ) { if (assetLoaderOptions == null) { assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(); } SetupModelLoading(assetLoaderOptions); LoadModelsInternal(onLoad, onMaterialsLoad, onProgress, onError, wrapperGameObject, assetLoaderOptions, customContextData, fileExtension, haltTask, onPreLoad, stream); } /// Loads all models from the given Zip file path asynchronously. /// The Zip file path. /// The Method to call on the Main Thread when any Model is loaded but resources may still pending. /// The Method to call on the Main Thread when any Model and resources are loaded. /// The Method to call when any Model loading progress changes. /// The Method to call on the Main Thread when any error occurs. /// The Game Object that will be the parent of the loaded Game Objects. Can be null. /// The options to use when loading the Models. /// The Custom Data that will be passed along the Context. /// The Models inside the Zip file extension. If null TriLib will try to find a suitable model format inside the Zip file. /// Turn on this field to avoid loading the models immediately and chain the Tasks. /// The method to call on the parallel Thread before the Unity objects are created. public static void LoadAllModelsFromZipFile( string path, Action onLoad, Action onMaterialsLoad, Action onProgress, Action onError = null, GameObject wrapperGameObject = null, AssetLoaderOptions assetLoaderOptions = null, object customContextData = null, string fileExtension = null, bool haltTask = false, Action onPreLoad = null ) { if (!File.Exists(path)) { throw new Exception("File not found"); } var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); SetupModelLoading(assetLoaderOptions); LoadModelsInternal(onLoad, onMaterialsLoad, onProgress, onError, wrapperGameObject, assetLoaderOptions, customContextData, fileExtension, haltTask, onPreLoad, stream); } private static void SetupModelLoading(AssetLoaderOptions assetLoaderOptions) { if (assetLoaderOptions == null) { assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(); } if (!ArrayUtils.ContainsType(assetLoaderOptions.TextureMappers)) { assetLoaderOptions.TextureMappers = new TextureMapper[] { ScriptableObject.CreateInstance() }; } if (!(assetLoaderOptions.ExternalDataMapper is ZipFileExternalDataMapper)) { assetLoaderOptions.ExternalDataMapper = ScriptableObject.CreateInstance(); } } private static void LoadModelsInternal(Action onLoad, Action onMaterialsLoad, Action onProgress, Action onError, GameObject wrapperGameObject, AssetLoaderOptions assetLoaderOptions, object customContextData, string fileExtension, bool haltTask, Action onPreLoad, Stream stream) { var validExtensions = Readers.Extensions; var zipFile = new ZipFile(stream); foreach (ZipEntry zipEntry in zipFile) { if (!zipEntry.IsFile) { continue; } Stream memoryStream = null; var checkingFileExtension = FileUtils.GetFileExtension(zipEntry.Name, false); if (fileExtension != null && checkingFileExtension == fileExtension) { memoryStream = AssetLoaderZip.ZipFileEntryToStream(out fileExtension, zipEntry, zipFile); } else if (validExtensions.Contains(checkingFileExtension)) { memoryStream = AssetLoaderZip.ZipFileEntryToStream(out fileExtension, zipEntry, zipFile); } var customDataDic = (object)CustomDataHelper.CreateCustomDataDictionaryWithData(new ZipLoadCustomContextData { ZipFile = zipFile, Stream = stream, //CustomData = customContextData, OnError = onError, OnMaterialsLoad = onMaterialsLoad }); if (customContextData != null) { CustomDataHelper.SetCustomData(ref customDataDic, customContextData); } if (memoryStream != null) { AssetLoader.LoadModelFromStream( memoryStream, zipEntry.Name, fileExtension, onLoad, OnMaterialsLoad, onProgress, OnError, wrapperGameObject, assetLoaderOptions, customDataDic, haltTask, onPreLoad, true); } } if (assetLoaderOptions.CloseStreamAutomatically) { stream.Close(); } } //Todo: make the AssetLoaderZip method public and use that instead private static void OnMaterialsLoad(AssetLoaderContext assetLoaderContext) { var zipLoadCustomContextData = CustomDataHelper.GetCustomData(assetLoaderContext.CustomData); if (zipLoadCustomContextData != null) { if (zipLoadCustomContextData.OnMaterialsLoad != null) { zipLoadCustomContextData.OnMaterialsLoad(assetLoaderContext); } } } //Todo: make the AssetLoaderZip method public and use that instead private static void OnError(IContextualizedError contextualizedError) { if (contextualizedError?.GetContext() is AssetLoaderContext assetLoaderContext) { var zipLoadCustomContextData = CustomDataHelper.GetCustomData(assetLoaderContext.CustomData); if (zipLoadCustomContextData != null) { if (zipLoadCustomContextData.Stream != null) { zipLoadCustomContextData.Stream.Close(); } if (zipLoadCustomContextData.OnError != null) { zipLoadCustomContextData.OnError.Invoke(contextualizedError); } } } } } }