AssetViewerBase.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #pragma warning disable 649
  2. using System;
  3. using System.IO;
  4. using TriLibCore.General;
  5. using TriLibCore.Utils;
  6. using UnityEngine;
  7. using UnityEngine.Networking;
  8. using UnityEngine.UI;
  9. namespace TriLibCore.Samples
  10. {
  11. /// <summary>Represents a base class used in TriLib samples.</summary>
  12. public class AssetViewerBase : AbstractInputSystem
  13. {
  14. /// <summary>Gets the Asset Viewer Singleton instance.</summary>
  15. public static AssetViewerBase Instance { get; private set; }
  16. /// <summary>
  17. /// Model/skybox loading bar. (Used on platforms with async capabilities)
  18. /// </summary>
  19. [SerializeField]
  20. private RectTransform _loadingBar;
  21. /// <summary>
  22. /// Help box wrapper.
  23. /// </summary>
  24. [SerializeField]
  25. private GameObject _helpWrapper;
  26. /// <summary>
  27. /// Loading screen wrapper. (Used on platforms without async capabilities)
  28. /// </summary>
  29. [SerializeField]
  30. private GameObject _loadingWrapper;
  31. /// <summary>
  32. /// Model URL loading dialog.
  33. /// </summary>
  34. [SerializeField]
  35. private GameObject _modelUrlDialog;
  36. /// <summary>
  37. /// Model URL loading Input Field.
  38. /// </summary>
  39. [SerializeField]
  40. private InputField _modelUrl;
  41. /// <summary>
  42. /// Animation playback slider.
  43. /// </summary>
  44. [SerializeField]
  45. protected Slider PlaybackSlider;
  46. /// <summary>
  47. /// Animation playback time.
  48. /// </summary>
  49. [SerializeField]
  50. protected Text PlaybackTime;
  51. /// <summary>
  52. /// Animation selector.
  53. /// </summary>
  54. [SerializeField]
  55. protected Dropdown PlaybackAnimation;
  56. /// <summary>
  57. /// Play button.
  58. /// </summary>
  59. [SerializeField]
  60. protected Selectable Play;
  61. /// <summary>
  62. /// Stop button.
  63. /// </summary>
  64. [SerializeField]
  65. protected Selectable Stop;
  66. /// <summary>
  67. /// Options used in this sample.
  68. /// </summary>
  69. protected AssetLoaderOptions AssetLoaderOptions;
  70. /// <summary>
  71. /// Current camera pitch and yaw angles.
  72. /// </summary>
  73. public Vector2 CameraAngle;
  74. /// <summary>
  75. /// Loaded game object.
  76. /// </summary>
  77. public GameObject RootGameObject { get; protected set; }
  78. /// <summary>
  79. /// Mouse input multiplier.
  80. /// Higher values will make the mouse movement more sensible.
  81. /// </summary>
  82. protected const float InputMultiplierRatio = 0.1f;
  83. /// <summary>
  84. /// Maximum camera pitch and light pitch (rotation around local X-axis).
  85. /// </summary>
  86. protected const float MaxPitch = 80f;
  87. /// <summary>
  88. /// The AssetLoaderFilePicker instance created for this viewer.
  89. /// </summary>
  90. protected AssetLoaderFilePicker FilePickerAssetLoader;
  91. /// <summary>
  92. /// Holds the peak memory used to load the model.
  93. /// </summary>
  94. protected long PeakMemory;
  95. #if TRILIB_SHOW_MEMORY_USAGE
  96. /// <summary>
  97. /// Holds the peak managed memory used to load the model.
  98. /// </summary>
  99. protected long PeakManagedMemory;
  100. #endif
  101. /// <summary>
  102. /// A flag representing if the model is loading or not.
  103. /// </summary>
  104. private bool _loading;
  105. /// <summary>Updates the Camera based on mouse Input.</summary>
  106. protected void UpdateCamera()
  107. {
  108. CameraAngle.x = Mathf.Repeat(CameraAngle.x + GetAxis("Mouse X"), 360f);
  109. CameraAngle.y = Mathf.Clamp(CameraAngle.y + GetAxis("Mouse Y"), -MaxPitch, MaxPitch);
  110. }
  111. /// <summary>
  112. /// Shows the help box.
  113. /// </summary>
  114. public void ShowHelp()
  115. {
  116. _helpWrapper.SetActive(true);
  117. }
  118. /// <summary>
  119. /// Hides the help box.
  120. /// </summary>
  121. public void HideHelp()
  122. {
  123. _helpWrapper.SetActive(false);
  124. }
  125. /// <summary>
  126. /// Shows the model URL dialog.
  127. /// </summary>
  128. public void ShowModelUrlDialog()
  129. {
  130. _modelUrlDialog.SetActive(true);
  131. _modelUrl.Select();
  132. _modelUrl.ActivateInputField();
  133. }
  134. /// <summary>
  135. /// Hides the model URL dialog.
  136. /// </summary>
  137. public void HideModelUrlDialog()
  138. {
  139. _modelUrlDialog.SetActive(false);
  140. _modelUrl.text = null;
  141. }
  142. /// <summary>
  143. /// Shows the file picker for loading a model from local file-system.
  144. /// </summary>
  145. protected void LoadModelFromFile(GameObject wrapperGameObject = null, Action<AssetLoaderContext> onMaterialsLoad = null)
  146. {
  147. SetLoading(false);
  148. FilePickerAssetLoader = AssetLoaderFilePicker.Create();
  149. FilePickerAssetLoader.LoadModelFromFilePickerAsync("Select a File", OnLoad, onMaterialsLoad ?? OnMaterialsLoad, OnProgress, OnBeginLoadModel, OnError, wrapperGameObject ?? gameObject, AssetLoaderOptions);
  150. }
  151. /// <summary>
  152. /// Loads a model from a URL.
  153. /// </summary>
  154. protected void LoadModelFromURL(UnityWebRequest request, string fileExtension, GameObject wrapperGameObject = null, object customData = null, Action<AssetLoaderContext> onMaterialsLoad = null)
  155. {
  156. if (string.IsNullOrWhiteSpace(fileExtension))
  157. {
  158. throw new Exception("TriLib could not determine the given model extension.");
  159. }
  160. HideModelUrlDialog();
  161. SetLoading(true);
  162. OnBeginLoadModel(true);
  163. fileExtension = fileExtension.ToLowerInvariant();
  164. var isZipFile = fileExtension == "zip" || fileExtension == ".zip";
  165. AssetDownloader.LoadModelFromUri(request, OnLoad, onMaterialsLoad ?? OnMaterialsLoad, OnProgress, OnError, wrapperGameObject, AssetLoaderOptions, customData, isZipFile ? null : fileExtension, isZipFile);
  166. }
  167. /// <summary>
  168. /// Shows the URL selector for loading a model from network.
  169. /// </summary>
  170. protected void LoadModelFromURLWithDialogValues()
  171. {
  172. if (string.IsNullOrWhiteSpace(_modelUrl.text))
  173. {
  174. return;
  175. }
  176. var request = AssetDownloader.CreateWebRequest(_modelUrl.text.Trim());
  177. var fileExtension = FileUtils.GetFileExtension(request.uri.Segments[request.uri.Segments.Length - 1], false);
  178. try
  179. {
  180. LoadModelFromURL(request, fileExtension);
  181. }
  182. catch (Exception e)
  183. {
  184. HideModelUrlDialog();
  185. OnError(new ContextualizedError<object>(e, null));
  186. }
  187. }
  188. /// <summary>Event triggered when the user selects a file or cancels the Model selection dialog.</summary>
  189. /// <param name="hasFiles">If any file has been selected, this value is <c>true</c>, otherwise it is <c>false</c>.</param>
  190. protected virtual void OnBeginLoadModel(bool hasFiles)
  191. {
  192. if (hasFiles)
  193. {
  194. if (RootGameObject != null)
  195. {
  196. Destroy(RootGameObject);
  197. }
  198. SetLoading(true);
  199. }
  200. }
  201. /// <summary>
  202. /// Enables/disables the loading flag.
  203. /// </summary>
  204. /// <param name="value">The new loading flag.</param>
  205. protected void SetLoading(bool value)
  206. {
  207. var selectables = FindObjectsOfType<Selectable>();
  208. for (var i = 0; i < selectables.Length; i++)
  209. {
  210. var button = selectables[i];
  211. button.interactable = !value;
  212. }
  213. _loadingWrapper.gameObject.SetActive(value);
  214. _loadingBar.gameObject.SetActive(value);
  215. _loading = value;
  216. }
  217. /// <summary>
  218. /// Gets a flag indicating whether the model is loading or not.
  219. /// </summary>
  220. /// <returns>The loading flag.</returns>
  221. protected bool IsLoading()
  222. {
  223. return _loading;
  224. }
  225. /// <summary>Checks if the Dispatcher instance exists and stores this class instance as the Singleton.</summary>
  226. protected virtual void Start()
  227. {
  228. Dispatcher.CheckInstance();
  229. PasteManager.CheckInstance();
  230. Instance = this;
  231. }
  232. /// <summary>Event that is triggered when the Model loading progress changes.</summary>
  233. /// <param name="assetLoaderContext">The Asset Loader Context reference. Asset Loader Context contains the Model loading data.</param>
  234. /// <param name="value">The loading progress, ranging from 0 to 1.</param>
  235. protected virtual void OnProgress(AssetLoaderContext assetLoaderContext, float value)
  236. {
  237. _loadingBar.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width * value);
  238. }
  239. /// <summary>Event that is triggered when any error occurs.</summary>
  240. /// <param name="contextualizedError">The Contextualized Error that has occurred.</param>
  241. protected virtual void OnError(IContextualizedError contextualizedError)
  242. {
  243. Debug.LogError(contextualizedError);
  244. RootGameObject = null;
  245. SetLoading(false);
  246. }
  247. /// <summary>Event that is triggered when the Model Meshes and hierarchy are loaded.</summary>
  248. /// <param name="assetLoaderContext">The Asset Loader Context reference. Asset Loader Context contains the Model loading data.</param>
  249. protected virtual void OnLoad(AssetLoaderContext assetLoaderContext)
  250. {
  251. PeakMemory = 0;
  252. #if TRILIB_SHOW_MEMORY_USAGE
  253. PeakManagedMemory = 0;
  254. #endif
  255. }
  256. /// <summary>Event is triggered when the Model (including Textures and Materials) has been fully loaded.</summary>
  257. /// <param name="assetLoaderContext">The Asset Loader Context reference. Asset Loader Context contains the Model loading data.</param>
  258. protected virtual void OnMaterialsLoad(AssetLoaderContext assetLoaderContext)
  259. {
  260. SetLoading(false);
  261. }
  262. /// <summary>
  263. /// Plays the selected animation.
  264. /// </summary>
  265. public virtual void PlayAnimation()
  266. {
  267. }
  268. /// <summary>Stops playing the selected animation.</summary>
  269. public virtual void StopAnimation()
  270. {
  271. }
  272. /// <summary>Switches to the animation selected on the Dropdown.</summary>
  273. /// <param name="index">The selected Animation index.</param>
  274. public virtual void PlaybackAnimationChanged(int index)
  275. {
  276. }
  277. /// <summary>
  278. /// Event triggered when the animation slider value has been changed by the user.
  279. /// </summary>
  280. /// <param name="value">The Animation playback normalized position.</param>
  281. public virtual void PlaybackSliderChanged(float value)
  282. {
  283. }
  284. }
  285. }