#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);
}
}
}
}
}
}