2023-02-07 18:35:16 +08:00

215 lines
5.7 KiB
C#

using Assets.Core;
using Assets.Scenes.Ride.Scripts;
using Assets.Scripts.Apis.Models;
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// 异步线程更新ui工具类
/// </summary>
public class Loom : MonoBehaviour
{
public static int maxThreads = 8;
static int numThreads;
private static Loom _current;
public static Loom Current
{
get
{
Initialize();
return _current;
}
}
//####去除Awake
// void Awake()
// {
// _current = this;
// initialized = true;
// }
static bool initialized;
//####作为初始化方法自己调用,可在初始化场景调用一次即可
public static void Initialize()
{
if (!initialized)
{
if (!Application.isPlaying)
return;
initialized = true;
GameObject g = new GameObject("Loom");
//####永不销毁
DontDestroyOnLoad(g);
_current = g.AddComponent<Loom>();
MapUDPService.Init();
MapUDPService.Send(0, App.CurrentUser.Id, new double[] { -1d, -1d }, competitionId: 0);
}
}
private List<Action> _actions = new List<Action>();
public struct DelayedQueueItem
{
public float time;
public Action action;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
if (Current != null)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
}
else
{
if (Current != null)
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
}
public static Thread RunAsync(Action a)
{
Initialize();
while (numThreads >= maxThreads)
{
Thread.Sleep(1);
}
Interlocked.Increment(ref numThreads);
ThreadPool.QueueUserWorkItem(RunAction, a);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
}
finally
{
Interlocked.Decrement(ref numThreads);
}
}
void OnDisable()
{
if (_current == this)
{
_current = null;
}
}
List<Action> _currentActions = new List<Action>();
// Update is called once per frame
void Update()
{
lock (_actions)
{
_currentActions.Clear();
_currentActions.AddRange(_actions);
_actions.Clear();
}
foreach (var a in _currentActions)
{
a();
}
lock (_delayed)
{
_currentDelayed.Clear();
_currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
foreach (var item in _currentDelayed)
_delayed.Remove(item);
}
foreach (var delayed in _currentDelayed)
{
delayed.action();
}
}
public static void Dispose()
{
if (_current != null)
{
initialized = false;
DestroyImmediate(_current.gameObject);
_current = null;
}
}
public static Dictionary<string, DownloadInfo> DownloadStack = new Dictionary<string, DownloadInfo>();
public static async Task DownloadLoadARDataAndVideo(MapRoute route,IProgress<float> progress)
{
DownloadStack.Add(route.FileName, new DownloadInfo(route.FileName,route.Name,0, route.Url));
var path = PFConstants.VideoFolder;
var localPath = PFConstants.ARFolder;
var arDataPath = route.ARConfig;
var videoRoute = route.VideoRoute;
var cancelToken = new CancellationTokenSource();
var dataPath = $"{localPath}/{route.Id}";
Helper.CreateDirectoryIfNotExsit(dataPath);
Helper.CreateDirectoryIfNotExsit(dataPath);
await Loom.DownloadToFileAsync(arDataPath, $"{dataPath}/{route.Id}.json");
await Loom.DownloadToFileAsync(videoRoute, $"{dataPath}/route-{route.Id}.json");
await Loom.DownloadToFileAsync(route.Url, $"{path}/{route.FileName}", progress, cancelToken);
}
/// <summary>
/// 下载文件到本地(持续存入磁盘减少内存占用)
/// </summary>
/// <param name="downloadUrl">文件连接</param>
/// <param name="fullPath">本地文件全路径</param>
/// <param name="progress">下载进度</param>
public static async UniTask<UnityWebRequest> DownloadToFileAsync(string downloadUrl, string fullPath, IProgress<float> progress = null, CancellationTokenSource cancellation = default(CancellationTokenSource))
{
var dh = new DownloadHandlerFile(fullPath)
{
removeFileOnAbort = true
};
var request = UnityWebRequest.Get(downloadUrl);
request.method = UnityWebRequest.kHttpVerbGET;
request.downloadHandler = dh;
return await request.SendWebRequest().ToUniTask(progress, PlayerLoopTiming.Update, (cancellation?.Token ?? default(CancellationToken)));
}
}