using UnityEngine; using System.Collections.Generic; using System.Collections; using System.Threading.Tasks; using System.Linq; using System; using Unity.VisualScripting; public static class VideoPlayManager { public static Dictionary PlayCounts = new(); public static int TotalVideoPlays { get { int total = 0; foreach (var video in PlayCounts) { total += video.Value; } return total; } } public static void RegisterPlay(VideoAsset videoAsset) { if (PlayCounts.ContainsKey(videoAsset)) { PlayCounts[videoAsset]++; } else { PlayCounts[videoAsset] = 1; } } public static void Reset() { PlayCounts = new Dictionary(); } public static int GetPlayCount(VideoAsset videoAsset) { if (PlayCounts.ContainsKey(videoAsset)) { return PlayCounts[videoAsset]; } return 0; } } public class VideoDownloader : MonoBehaviour { [SerializeField] private List videoAssets; public List VideoAssets => videoAssets; [SerializeField] private int downloadsInParallel = 4; // Number of parallel downloads // private List videosToDownload = new(); private System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); [SerializeField] private bool downloadInParallel = false; private void Start() { videoAssets.ForEach(video => { video.Init(); }); StartCoroutine(DownloadVideos()); onStartDownload += () => { CanvasManager.singleton.loadingScreen.Show(videosToDownload.Count); Debug.Log($"Downloading {videosToDownload.Count} videos to {Application.persistentDataPath} {(downloadInParallel ? "in parallel" : "sequentially")}"); stopwatch.Start(); }; onDownloadComplete += () => { stopwatch.Stop(); Debug.Log($"Downloaded {videosToDownload.Count} videos in {stopwatch.Elapsed.TotalSeconds} seconds."); CanvasManager.singleton.loadingScreen.Hide(); }; ProgressCallBack += (int downloaded, int total) => { CanvasManager.singleton.loadingScreen.ProgressCallback(downloaded, total); }; } [SerializeField] private List videosToDownload = new(); private void ComputeVideosToDownload() { videosToDownload = videoAssets .Where(video => video.NeedDownloading).ToList(); } public int NewVideosToDownloadCount => videosToDownload.Count; public void ReDownloadVideos() { StartCoroutine(DownloadVideos()); } public Action onStartDownload; public Action onDownloadComplete; private IEnumerator DownloadVideos() { ComputeVideosToDownload(); yield return new WaitForSeconds(0.5f); if (videosToDownload.Count == 0) { Debug.Log("No videos to download!"); CanvasManager.singleton.loadingScreen.Hide(); yield break; } //CanvasManager.singleton.loadingScreen.Show(videosToDownload.Count); onStartDownload?.Invoke(); yield return downloadInParallel ? DownloadVideosParallel() : DownloadVideosSeq(); onDownloadComplete?.Invoke(); } public Dictionary PlayCounts = new(); public void RegisterPlayVideo(VideoAsset videoAsset) { if (PlayCounts.ContainsKey(videoAsset)) { PlayCounts[videoAsset]++; } else { PlayCounts[videoAsset] = 1; } } private IEnumerator DownloadVideosParallel() { // Start the downloads in parallel List downloadTasks = new List(); int i = 0; for (i = 0; i < downloadsInParallel && i < videosToDownload.Count; i++) downloadTasks.Add(DownloadVideoTask(videosToDownload[i])); int downloaded = 0; // Monitor progress and add new downloads as previous ones complete while (i - downloadTasks.Count < videosToDownload.Count) { for (int j = 0; j < downloadTasks.Count; j++) { if (downloadTasks[j].IsCompleted) { downloaded++; Debug.Log($"Downloaded {downloaded}/{videosToDownload.Count} videos."); ProgressCallBack.Invoke(downloaded, videosToDownload.Count); // Start the next video download if available if (i < videosToDownload.Count) { downloadTasks[j] = DownloadVideoTask(videosToDownload[i]); i++; } } } // Remove completed tasks downloadTasks.RemoveAll(task => task.IsCompleted); yield return new WaitForSeconds(0.3f); // Wait a bit before checking again } } private async Task DownloadVideoTask(VideoAsset videoAsset) { videoAsset.Prepare(); while (videoAsset.Loading) { await Task.Yield(); await Task.Delay(500); } } private IEnumerator DownloadVideosSeq() { int i = 0; // Process each video download sequentially while (i < videosToDownload.Count) { Debug.Log($"Starting download for video {i + 1}/{videosToDownload.Count}"); // Wait for the current video to be downloaded yield return DownloadVideoSeq(videosToDownload[i]); Debug.Log($"Downloaded video {i + 1}/{videosToDownload.Count}"); i++; ProgressCallBack.Invoke(i, videosToDownload.Count); } } public Action ProgressCallBack { get; set; } private IEnumerator DownloadVideoSeq(VideoAsset videoAsset) { videoAsset.Prepare(); // Wait until the video is fully loaded while (videoAsset.Loading) yield return null; // Wait until next frame } public void FirebaseStorageWebCallback(string response) { FirebaseFileDownloader.DownloadFileCallback(response); } public void FirebaseStorageWebFallback(string response) { FirebaseFileDownloader.DownloadFileFallback(response); } }