MultipleAssetLoaderZip.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #pragma warning disable 184
  2. using System;
  3. using System.IO;
  4. using ICSharpCode.SharpZipLib.Zip;
  5. using TriLibCore.Mappers;
  6. using TriLibCore.Utils;
  7. using UnityEngine;
  8. namespace TriLibCore
  9. {
  10. /// <summary>
  11. /// Represents a class used to load all the models inside a Zip file.
  12. /// </summary>
  13. public static class MultipleAssetLoaderZip
  14. {
  15. /// <summary>Loads all models from the given Zip file Stream asynchronously.</summary>
  16. /// <param name="stream">The Zip file Stream.</param>
  17. /// <param name="onLoad">The Method to call on the Main Thread when any Model is loaded but resources may still pending.</param>
  18. /// <param name="onMaterialsLoad">The Method to call on the Main Thread when any Model and resources are loaded.</param>
  19. /// <param name="onProgress">The Method to call when any Model loading progress changes.</param>
  20. /// <param name="onError">The Method to call on the Main Thread when any error occurs.</param>
  21. /// <param name="wrapperGameObject">The Game Object that will be the parent of the loaded Game Objects. Can be null.</param>
  22. /// <param name="assetLoaderOptions">The options to use when loading the Models.</param>
  23. /// <param name="customContextData">The Custom Data that will be passed along the Context.</param>
  24. /// <param name="fileExtension">The Models inside the Zip file extension. If <c>null</c> TriLib will try to find a suitable model format inside the Zip file.</param>
  25. /// <param name="haltTask">Turn on this field to avoid loading the models immediately and chain the Tasks.</param>
  26. /// <param name="onPreLoad">The method to call on the parallel Thread before the Unity objects are created.</param>
  27. public static void LoadAllModelsFromZipStream(
  28. Stream stream,
  29. Action<AssetLoaderContext> onLoad,
  30. Action<AssetLoaderContext> onMaterialsLoad,
  31. Action<AssetLoaderContext, float> onProgress,
  32. Action<IContextualizedError> onError = null,
  33. GameObject wrapperGameObject = null,
  34. AssetLoaderOptions assetLoaderOptions = null,
  35. object customContextData = null,
  36. string fileExtension = null,
  37. bool haltTask = false,
  38. Action<AssetLoaderContext> onPreLoad = null
  39. )
  40. {
  41. if (assetLoaderOptions == null)
  42. {
  43. assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
  44. }
  45. SetupModelLoading(assetLoaderOptions);
  46. LoadModelsInternal(onLoad, onMaterialsLoad, onProgress, onError, wrapperGameObject, assetLoaderOptions, customContextData, fileExtension, haltTask, onPreLoad, stream);
  47. }
  48. /// <summary>Loads all models from the given Zip file path asynchronously.</summary>
  49. /// <param name="path">The Zip file path.</param>
  50. /// <param name="onLoad">The Method to call on the Main Thread when any Model is loaded but resources may still pending.</param>
  51. /// <param name="onMaterialsLoad">The Method to call on the Main Thread when any Model and resources are loaded.</param>
  52. /// <param name="onProgress">The Method to call when any Model loading progress changes.</param>
  53. /// <param name="onError">The Method to call on the Main Thread when any error occurs.</param>
  54. /// <param name="wrapperGameObject">The Game Object that will be the parent of the loaded Game Objects. Can be null.</param>
  55. /// <param name="assetLoaderOptions">The options to use when loading the Models.</param>
  56. /// <param name="customContextData">The Custom Data that will be passed along the Context.</param>
  57. /// <param name="fileExtension">The Models inside the Zip file extension. If <c>null</c> TriLib will try to find a suitable model format inside the Zip file.</param>
  58. /// <param name="haltTask">Turn on this field to avoid loading the models immediately and chain the Tasks.</param>
  59. /// <param name="onPreLoad">The method to call on the parallel Thread before the Unity objects are created.</param>
  60. public static void LoadAllModelsFromZipFile(
  61. string path,
  62. Action<AssetLoaderContext> onLoad,
  63. Action<AssetLoaderContext> onMaterialsLoad,
  64. Action<AssetLoaderContext, float> onProgress,
  65. Action<IContextualizedError> onError = null,
  66. GameObject wrapperGameObject = null,
  67. AssetLoaderOptions assetLoaderOptions = null,
  68. object customContextData = null,
  69. string fileExtension = null,
  70. bool haltTask = false,
  71. Action<AssetLoaderContext> onPreLoad = null
  72. )
  73. {
  74. if (!File.Exists(path))
  75. {
  76. throw new Exception("File not found");
  77. }
  78. var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
  79. SetupModelLoading(assetLoaderOptions);
  80. LoadModelsInternal(onLoad, onMaterialsLoad, onProgress, onError, wrapperGameObject, assetLoaderOptions, customContextData, fileExtension, haltTask, onPreLoad, stream);
  81. }
  82. private static void SetupModelLoading(AssetLoaderOptions assetLoaderOptions)
  83. {
  84. if (assetLoaderOptions == null)
  85. {
  86. assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
  87. }
  88. if (!ArrayUtils.ContainsType<ZipFileTextureMapper>(assetLoaderOptions.TextureMappers))
  89. {
  90. assetLoaderOptions.TextureMappers = new TextureMapper[] { ScriptableObject.CreateInstance<ZipFileTextureMapper>() };
  91. }
  92. if (!(assetLoaderOptions.ExternalDataMapper is ZipFileExternalDataMapper))
  93. {
  94. assetLoaderOptions.ExternalDataMapper = ScriptableObject.CreateInstance<ZipFileExternalDataMapper>();
  95. }
  96. }
  97. private static void LoadModelsInternal(Action<AssetLoaderContext> onLoad,
  98. Action<AssetLoaderContext> onMaterialsLoad,
  99. Action<AssetLoaderContext, float> onProgress,
  100. Action<IContextualizedError> onError,
  101. GameObject wrapperGameObject,
  102. AssetLoaderOptions assetLoaderOptions,
  103. object customContextData,
  104. string fileExtension,
  105. bool haltTask,
  106. Action<AssetLoaderContext> onPreLoad,
  107. Stream stream)
  108. {
  109. var validExtensions = Readers.Extensions;
  110. var zipFile = new ZipFile(stream);
  111. foreach (ZipEntry zipEntry in zipFile)
  112. {
  113. if (!zipEntry.IsFile)
  114. {
  115. continue;
  116. }
  117. Stream memoryStream = null;
  118. var checkingFileExtension = FileUtils.GetFileExtension(zipEntry.Name, false);
  119. if (fileExtension != null && checkingFileExtension == fileExtension)
  120. {
  121. memoryStream = AssetLoaderZip.ZipFileEntryToStream(out fileExtension, zipEntry, zipFile);
  122. }
  123. else if (validExtensions.Contains(checkingFileExtension))
  124. {
  125. memoryStream = AssetLoaderZip.ZipFileEntryToStream(out fileExtension, zipEntry, zipFile);
  126. }
  127. var customDataDic = (object)CustomDataHelper.CreateCustomDataDictionaryWithData(new ZipLoadCustomContextData
  128. {
  129. ZipFile = zipFile,
  130. Stream = stream,
  131. //CustomData = customContextData,
  132. OnError = onError,
  133. OnMaterialsLoad = onMaterialsLoad
  134. });
  135. if (customContextData != null)
  136. {
  137. CustomDataHelper.SetCustomData(ref customDataDic, customContextData);
  138. }
  139. if (memoryStream != null)
  140. {
  141. AssetLoader.LoadModelFromStream(
  142. memoryStream,
  143. zipEntry.Name,
  144. fileExtension,
  145. onLoad,
  146. OnMaterialsLoad,
  147. onProgress,
  148. OnError,
  149. wrapperGameObject,
  150. assetLoaderOptions,
  151. customDataDic,
  152. haltTask,
  153. onPreLoad,
  154. true);
  155. }
  156. }
  157. if (assetLoaderOptions.CloseStreamAutomatically)
  158. {
  159. stream.Close();
  160. }
  161. }
  162. //Todo: make the AssetLoaderZip method public and use that instead
  163. private static void OnMaterialsLoad(AssetLoaderContext assetLoaderContext)
  164. {
  165. var zipLoadCustomContextData = CustomDataHelper.GetCustomData<ZipLoadCustomContextData>(assetLoaderContext.CustomData);
  166. if (zipLoadCustomContextData != null)
  167. {
  168. if (zipLoadCustomContextData.OnMaterialsLoad != null)
  169. {
  170. zipLoadCustomContextData.OnMaterialsLoad(assetLoaderContext);
  171. }
  172. }
  173. }
  174. //Todo: make the AssetLoaderZip method public and use that instead
  175. private static void OnError(IContextualizedError contextualizedError)
  176. {
  177. if (contextualizedError?.GetContext() is AssetLoaderContext assetLoaderContext)
  178. {
  179. var zipLoadCustomContextData = CustomDataHelper.GetCustomData<ZipLoadCustomContextData>(assetLoaderContext.CustomData);
  180. if (zipLoadCustomContextData != null)
  181. {
  182. if (zipLoadCustomContextData.Stream != null)
  183. {
  184. zipLoadCustomContextData.Stream.Close();
  185. }
  186. if (zipLoadCustomContextData.OnError != null)
  187. {
  188. zipLoadCustomContextData.OnError.Invoke(contextualizedError);
  189. }
  190. }
  191. }
  192. }
  193. }
  194. }