#pragma warning disable 649 using System; using System.IO; using TriLibCore.General; using TriLibCore.Utils; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; namespace TriLibCore.Samples { /// Represents a base class used in TriLib samples. public class AssetViewerBase : AbstractInputSystem { /// Gets the Asset Viewer Singleton instance. public static AssetViewerBase Instance { get; private set; } /// /// Model/skybox loading bar. (Used on platforms with async capabilities) /// [SerializeField] private RectTransform _loadingBar; /// /// Help box wrapper. /// [SerializeField] private GameObject _helpWrapper; /// /// Loading screen wrapper. (Used on platforms without async capabilities) /// [SerializeField] private GameObject _loadingWrapper; /// /// Model URL loading dialog. /// [SerializeField] private GameObject _modelUrlDialog; /// /// Model URL loading Input Field. /// [SerializeField] private InputField _modelUrl; /// /// Animation playback slider. /// [SerializeField] protected Slider PlaybackSlider; /// /// Animation playback time. /// [SerializeField] protected Text PlaybackTime; /// /// Animation selector. /// [SerializeField] protected Dropdown PlaybackAnimation; /// /// Play button. /// [SerializeField] protected Selectable Play; /// /// Stop button. /// [SerializeField] protected Selectable Stop; /// /// Options used in this sample. /// protected AssetLoaderOptions AssetLoaderOptions; /// /// Current camera pitch and yaw angles. /// public Vector2 CameraAngle; /// /// Loaded game object. /// public GameObject RootGameObject { get; protected set; } /// /// Mouse input multiplier. /// Higher values will make the mouse movement more sensible. /// protected const float InputMultiplierRatio = 0.1f; /// /// Maximum camera pitch and light pitch (rotation around local X-axis). /// protected const float MaxPitch = 80f; /// /// The AssetLoaderFilePicker instance created for this viewer. /// protected AssetLoaderFilePicker FilePickerAssetLoader; /// /// Holds the peak memory used to load the model. /// protected long PeakMemory; #if TRILIB_SHOW_MEMORY_USAGE /// /// Holds the peak managed memory used to load the model. /// protected long PeakManagedMemory; #endif /// /// A flag representing if the model is loading or not. /// private bool _loading; /// Updates the Camera based on mouse Input. protected void UpdateCamera() { CameraAngle.x = Mathf.Repeat(CameraAngle.x + GetAxis("Mouse X"), 360f); CameraAngle.y = Mathf.Clamp(CameraAngle.y + GetAxis("Mouse Y"), -MaxPitch, MaxPitch); } /// /// Shows the help box. /// public void ShowHelp() { _helpWrapper.SetActive(true); } /// /// Hides the help box. /// public void HideHelp() { _helpWrapper.SetActive(false); } /// /// Shows the model URL dialog. /// public void ShowModelUrlDialog() { _modelUrlDialog.SetActive(true); _modelUrl.Select(); _modelUrl.ActivateInputField(); } /// /// Hides the model URL dialog. /// public void HideModelUrlDialog() { _modelUrlDialog.SetActive(false); _modelUrl.text = null; } /// /// Shows the file picker for loading a model from local file-system. /// protected void LoadModelFromFile(GameObject wrapperGameObject = null, Action onMaterialsLoad = null) { SetLoading(false); FilePickerAssetLoader = AssetLoaderFilePicker.Create(); FilePickerAssetLoader.LoadModelFromFilePickerAsync("Select a File", OnLoad, onMaterialsLoad ?? OnMaterialsLoad, OnProgress, OnBeginLoadModel, OnError, wrapperGameObject ?? gameObject, AssetLoaderOptions); } /// /// Loads a model from a URL. /// protected void LoadModelFromURL(UnityWebRequest request, string fileExtension, GameObject wrapperGameObject = null, object customData = null, Action onMaterialsLoad = null) { if (string.IsNullOrWhiteSpace(fileExtension)) { throw new Exception("TriLib could not determine the given model extension."); } HideModelUrlDialog(); SetLoading(true); OnBeginLoadModel(true); fileExtension = fileExtension.ToLowerInvariant(); var isZipFile = fileExtension == "zip" || fileExtension == ".zip"; AssetDownloader.LoadModelFromUri(request, OnLoad, onMaterialsLoad ?? OnMaterialsLoad, OnProgress, OnError, wrapperGameObject, AssetLoaderOptions, customData, isZipFile ? null : fileExtension, isZipFile); } /// /// Shows the URL selector for loading a model from network. /// protected void LoadModelFromURLWithDialogValues() { if (string.IsNullOrWhiteSpace(_modelUrl.text)) { return; } var request = AssetDownloader.CreateWebRequest(_modelUrl.text.Trim()); var fileExtension = FileUtils.GetFileExtension(request.uri.Segments[request.uri.Segments.Length - 1], false); try { LoadModelFromURL(request, fileExtension); } catch (Exception e) { HideModelUrlDialog(); OnError(new ContextualizedError(e, null)); } } /// Event triggered when the user selects a file or cancels the Model selection dialog. /// If any file has been selected, this value is true, otherwise it is false. protected virtual void OnBeginLoadModel(bool hasFiles) { if (hasFiles) { if (RootGameObject != null) { Destroy(RootGameObject); } SetLoading(true); } } /// /// Enables/disables the loading flag. /// /// The new loading flag. protected void SetLoading(bool value) { var selectables = FindObjectsOfType(); for (var i = 0; i < selectables.Length; i++) { var button = selectables[i]; button.interactable = !value; } _loadingWrapper.gameObject.SetActive(value); _loadingBar.gameObject.SetActive(value); _loading = value; } /// /// Gets a flag indicating whether the model is loading or not. /// /// The loading flag. protected bool IsLoading() { return _loading; } /// Checks if the Dispatcher instance exists and stores this class instance as the Singleton. protected virtual void Start() { Dispatcher.CheckInstance(); PasteManager.CheckInstance(); Instance = this; } /// Event that is triggered when the Model loading progress changes. /// The Asset Loader Context reference. Asset Loader Context contains the Model loading data. /// The loading progress, ranging from 0 to 1. protected virtual void OnProgress(AssetLoaderContext assetLoaderContext, float value) { _loadingBar.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width * value); } /// Event that is triggered when any error occurs. /// The Contextualized Error that has occurred. protected virtual void OnError(IContextualizedError contextualizedError) { Debug.LogError(contextualizedError); RootGameObject = null; SetLoading(false); } /// Event that is triggered when the Model Meshes and hierarchy are loaded. /// The Asset Loader Context reference. Asset Loader Context contains the Model loading data. protected virtual void OnLoad(AssetLoaderContext assetLoaderContext) { PeakMemory = 0; #if TRILIB_SHOW_MEMORY_USAGE PeakManagedMemory = 0; #endif } /// Event is triggered when the Model (including Textures and Materials) has been fully loaded. /// The Asset Loader Context reference. Asset Loader Context contains the Model loading data. protected virtual void OnMaterialsLoad(AssetLoaderContext assetLoaderContext) { SetLoading(false); } /// /// Plays the selected animation. /// public virtual void PlayAnimation() { } /// Stops playing the selected animation. public virtual void StopAnimation() { } /// Switches to the animation selected on the Dropdown. /// The selected Animation index. public virtual void PlaybackAnimationChanged(int index) { } /// /// Event triggered when the animation slider value has been changed by the user. /// /// The Animation playback normalized position. public virtual void PlaybackSliderChanged(float value) { } } }