using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using UnityEngine; using UnityEngine.Networking; public class ModelViewerDownloader { public static string UrlBase = ""; public static string SaveLocation = "/idbfs/ModelViewer/"; public static ModelViewerDownloader Instance; public bool SyncRequired; public ModelViewerDownloader() : this(UrlBase, "/idbfs/ModelViewer/") { } public ModelViewerDownloader(string baseUrl, string saveLocation) { UrlBase = baseUrl; SaveLocation = saveLocation; ModelViewerMain.GetInstance().StartCoroutine(Loop()); } public class DownloadTask { public string Name; public bool Redownload = false; public bool Finished = false; public bool Success = false; public int Priority = 0; public string ResultText; public byte[] ResultBytes; public System.Action OnDownloadSuccess; public DownloadTask(string name, int priority, bool redownload) { Name = name; Priority = priority; Redownload = redownload; } } private static List _downloadRunning = new List(); private static List _downloadQueue = new List(); public IEnumerator Loop() { float lastSync = 5; while (true) { if(_downloadQueue.Count > 0) { _downloadRunning.AddRange(_downloadQueue); _downloadRunning = _downloadRunning.OrderByDescending(d=>d.Priority).ToList(); _downloadQueue.Clear(); } if(_downloadRunning.Count > 0) { var fileToDownload = _downloadRunning[0]; _downloadRunning.RemoveAt(0); yield return DownloadFile(fileToDownload); if(!_downloadRunning.Any() && !_downloadQueue.Any()) { SyncRequired = true; lastSync = 0; } } if(SyncRequired) { lastSync += Time.deltaTime; if(lastSync >= 5) { CommitChanges(); } } yield return 0; } } public static IEnumerator WaitForDownload(string name, int priority = 0, bool redownload = false, System.Action lines = null, System.Action bytes = null, System.Action text = null, System.Action onDownloadSuccess = null) { var task = _downloadQueue.Concat(_downloadRunning).FirstOrDefault(t => t.Name == name); if(task == null) { task = new DownloadTask(name, priority, redownload); task.OnDownloadSuccess = onDownloadSuccess; _downloadQueue.Add(task); } while (!task.Finished) { yield return 0; } lines?.Invoke(task.ResultText.Split('\n').Select(s => s.Trim()).ToArray()); bytes?.Invoke(task.ResultBytes); text?.Invoke(task.ResultText); } private IEnumerator DownloadFile(DownloadTask task) { #if UNITY_WEBGL && !UNITY_EDITOR string fileSavePath = $"{SaveLocation}{task.Name}"; #else string fileSavePath = Application.persistentDataPath + " /" + task.Name; #endif if (!task.Redownload && LoadFromIdbfs(fileSavePath, out var data)) { //Debug.Log("Loaded from " + fileSavePath); task.Success = true; task.ResultText = Encoding.UTF8.GetString(data); task.ResultBytes = data; task.Finished = true; yield break; } string url = UrlBase + task.Name + (task.Redownload ? "?time=" + DateTime.Now.Ticks.ToString() : ""); //var downloadPanel = KFKViewerUI.Instance.DownloadPanel; //Msg.Log(url); using (var www = UnityWebRequest.Get(url)) { //downloadPanel.gameObject.SetActive(true); var operation = www.SendWebRequest(); do { //downloadPanel.SetStatus(task.Name, www.downloadProgress); yield return null; } while (!operation.isDone); if (www.result != UnityWebRequest.Result.Success) { Error.Log(Color.red, www.error); task.Success = false; task.ResultText = ""; task.ResultBytes = new byte[0]; } else { SaveToIdbfs(fileSavePath, www.downloadHandler.data); task.OnDownloadSuccess?.Invoke(); task.Success = true; task.ResultText = www.downloadHandler.text; task.ResultBytes = www.downloadHandler.data; } } //downloadPanel.SetStatus(task.Name, 0); //downloadPanel.gameObject.SetActive(false); task.Finished = true; } public static bool LoadFromIdbfs(string name, out byte[] data) { if(File.Exists(name)) { data = File.ReadAllBytes(name); return true; } else { data = null; return false; } } public static void SaveToIdbfs(string path, byte[] data) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, data); //Debug.Log("Saved " + path); } private static void CommitChanges() { Instance.SyncRequired = false; Debug.Log("Database Updated"); #if UNITY_WEBGL && !UNITY_EDITOR SyncFiles(); #endif } [DllImport("__Internal")] private static extern void SyncFiles(); }