#nullable enable using System; using System.IO; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Video; [CreateAssetMenu(fileName = "VideoAsset", menuName = "VideoAsset", order = 1)] public class VideoAsset : ScriptableObject { public static bool? halfResOverride = null; private static readonly string rootPath = "gs://monde-en-carton.appspot.com/Videos/"; private static readonly string halfResSuffix = "_halfres.mp4"; public string? storageUrl; public bool isHalfRes = false; [SerializeField] private bool forceDownload = false; [SerializeField] private bool useDownloadUrl = false; public VideoClip? videoClip; [SerializeField] private string? localVideoPath; [SerializeField] private string? downloadUrl; [SerializeField] private bool loaded = false; public bool Loaded => loaded; [SerializeField] private bool loading = false; public bool Loading => loading; public string errorMessage = ""; public bool NeedDownloading => forceDownload || useDownloadUrl || (videoClip == null && storageUrl != null && !File.Exists(GetLocalVideoPath())); public int PlayCount => VideoPlayManager.GetPlayCount(this); public void Init() { loaded = false; loading = false; localVideoPath = null; #if UNITY_WEBGL videoClip = null; // Reset videoClip for WebGL builds to exclude from build useDownloadUrl = true; // Use download URL for WebGL builds #endif GetLocalVideoPath(); } public void FinishLoading() { loading = false; loaded = true; } public string StorageUrl => storageUrl != null ? (isHalfRes ? storageUrl.Replace(".mp4", halfResSuffix) : storageUrl) : throw new Exception("No storage URL provided"); public void SetLocalVideoPath(string path) { localVideoPath = path; } public void SetDownloadUrl(string url) { downloadUrl = url; FinishLoading(); } public string GetLocalVideoPath() { if (storageUrl == null) throw new Exception("No storage URL provided"); string targetStorageUrl = storageUrl; if (halfResOverride ?? isHalfRes) targetStorageUrl = storageUrl.Replace(".mp4", halfResSuffix); localVideoPath = Path.Join(Application.persistentDataPath, "Videos", targetStorageUrl.Replace(rootPath, "")); return localVideoPath; } public void Prepare(Action? progressCallBack = null) { if (!NeedDownloading) { Debug.Log($"Video {name} does not need downloading."); FinishLoading(); return; } if (!forceDownload && videoClip != null) { Debug.Log("Video clip in memory."); FinishLoading(); return; } DownloadVideo(progressCallBack); } public void Play(VideoPlayer videoPlayer) { if (videoClip != null) { videoPlayer.source = VideoSource.Url; videoPlayer.clip = videoClip; } else if (useDownloadUrl && downloadUrl != null) { videoPlayer.source = VideoSource.Url; videoPlayer.url = downloadUrl; } #if !UNITY_WEBGL else if (storageUrl != null && localVideoPath != null) { videoPlayer.source = VideoSource.Url; videoPlayer.url = localVideoPath; } #endif else { Debug.LogError("No video clip or storage URL provided"); return; } } private void SetError(string error) { errorMessage = error; loading = false; } public void DownloadVideo(Action? progressCallBack = null) { if (storageUrl == null) throw new Exception("No video clip or storage URL provided"); localVideoPath = GetLocalVideoPath(); loading = true; string targetStorageUrl = storageUrl; if (halfResOverride ?? isHalfRes) targetStorageUrl = storageUrl.Replace(".mp4", halfResSuffix); if (!useDownloadUrl) { if (File.Exists(localVideoPath)) { Debug.Log("File already exists."); FinishLoading(); return; } else { string directoryPath = Path.GetDirectoryName(localVideoPath); Directory.CreateDirectory(directoryPath); } } #if UNITY_WEBGL && !UNITY_EDITOR FirebaseFileDownloader.DownloadFileFirebaseWeb(targetStorageUrl); #else if (useDownloadUrl) FirebaseFileDownloader.DownloadFileDownloadUrl(targetStorageUrl, SetDownloadUrl, SetError); else FirebaseFileDownloader.DownloadFileFirebaseVanilla(targetStorageUrl, localVideoPath, progressCallBack, FinishLoading, SetError); #endif } #if UNITY_EDITOR public void DownloadVideoInEditor() { DownloadVideo(); } #endif }