|
@@ -0,0 +1,316 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using ET;
|
|
|
+using UnityEngine;
|
|
|
+using UnityEngine.Networking;
|
|
|
+
|
|
|
+namespace GFGGame
|
|
|
+{
|
|
|
+ public class PictureDataManager : SingletonBase<PictureDataManager>
|
|
|
+ {
|
|
|
+ //本地地址
|
|
|
+ private const string _loadUrl = "gfgpicture";
|
|
|
+
|
|
|
+ //正在操作的文件队列
|
|
|
+ private Queue<string> _queueOperateFileList = new Queue<string>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 所有照片的二进制
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<string, Texture2D> _allPicByteDic = new Dictionary<string, Texture2D>();
|
|
|
+
|
|
|
+ public async ETTask<Texture2D> GetPicNTexture(string tempUrl)
|
|
|
+ {
|
|
|
+ string fileNameKey = GetUrlFileName(tempUrl);
|
|
|
+ if (_allPicByteDic.TryGetValue(fileNameKey, out Texture2D texture2D))
|
|
|
+ {
|
|
|
+ // 可能存在
|
|
|
+ if (texture2D != null &&
|
|
|
+ texture2D.width > 0 &&
|
|
|
+ texture2D.height > 0 &&
|
|
|
+ texture2D.GetPixels().Length > 0)
|
|
|
+ {
|
|
|
+ // 检查纹理的格式是否支持
|
|
|
+ if (texture2D.format == TextureFormat.RGBA32 ||
|
|
|
+ texture2D.format == TextureFormat.RGB24)
|
|
|
+ {
|
|
|
+ // 纹理有效,可以正常显示
|
|
|
+ return texture2D; // 或者转换为 NTexture 对象
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogError("Texture format is not supported.");
|
|
|
+ // 处理不支持的纹理格式
|
|
|
+ return await DownloadOrLoadPic(tempUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogWarning("Texture is invalid or has no pixels.");
|
|
|
+ // 处理无效的纹理
|
|
|
+ return await DownloadOrLoadPic(tempUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //TODO 一定不存在, 需要去进行下载
|
|
|
+ return await DownloadOrLoadPic(tempUrl);
|
|
|
+ }
|
|
|
+
|
|
|
+ //从远端进行下载
|
|
|
+ public async ETTask<Texture2D> DownloadOrLoadPic(string tempUrl)
|
|
|
+ {
|
|
|
+ string fileName = GetUrlFileName(tempUrl);
|
|
|
+ Texture2D texture2D = await DownloadPictureAsync(tempUrl);
|
|
|
+ if (texture2D == null)
|
|
|
+ {
|
|
|
+ return GetDefaultTexture();
|
|
|
+ }
|
|
|
+
|
|
|
+ //不为null, 以协程的方式存储到内存以及, 本地
|
|
|
+
|
|
|
+ _allPicByteDic[fileName] = texture2D;
|
|
|
+ //加入队列
|
|
|
+ _queueOperateFileList.Enqueue(fileName);
|
|
|
+ SavaPicToLoad().Coroutine();
|
|
|
+
|
|
|
+ return texture2D;
|
|
|
+ }
|
|
|
+
|
|
|
+ //存储图片文件到本地,如果存在就进行删除本地或者覆盖,以当前的为最新的进行记录
|
|
|
+ public async ETTask SavaPicToLoad()
|
|
|
+ {
|
|
|
+ var tempList = _queueOperateFileList.ToList();
|
|
|
+
|
|
|
+ for (int i = 0; i < tempList.Count; i++)
|
|
|
+ {
|
|
|
+ if (_queueOperateFileList.Count == 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ string fileName = _queueOperateFileList.Dequeue();
|
|
|
+ if (string.IsNullOrEmpty(fileName))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!_allPicByteDic.TryGetValue(fileName, out Texture2D texture2D))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (texture2D == null)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取本地存储路径
|
|
|
+ string localPath = Path.Combine(Application.persistentDataPath, fileName);
|
|
|
+
|
|
|
+ // 存储图片文件到本地
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 将 Texture2D 转换为字节数组
|
|
|
+ byte[] imageData = texture2D.EncodeToPNG();
|
|
|
+
|
|
|
+ // 如果文件已经存在,则覆盖
|
|
|
+ if (File.Exists(localPath))
|
|
|
+ {
|
|
|
+ File.Delete(localPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将字节数组写入文件
|
|
|
+ File.WriteAllBytes(localPath, imageData);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Debug.LogError($"Failed to save image to local path: {ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ await ETTask.CompletedTask;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async ETTask<Texture2D> DownloadPictureAsync(string tempUrl, int count = 0)
|
|
|
+ {
|
|
|
+ string fileName = GetUrlFileName(tempUrl);
|
|
|
+
|
|
|
+ if (count >= 3)
|
|
|
+ {
|
|
|
+ PromptController.Instance.ShowFloatTextPrompt("下载失败");
|
|
|
+ ViewManager.Hide<ModalStatusView>();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(tempUrl))
|
|
|
+ {
|
|
|
+ var asyncOperation = request.SendWebRequest();
|
|
|
+
|
|
|
+ while (!asyncOperation.isDone)
|
|
|
+ {
|
|
|
+ await TimerComponent.Instance.WaitTillAsync(100); // 等待一段时间后继续检查
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request.result == UnityWebRequest.Result.ProtocolError ||
|
|
|
+ request.result == UnityWebRequest.Result.ConnectionError)
|
|
|
+ {
|
|
|
+ count += 1;
|
|
|
+ return await DownloadPictureAsync(tempUrl, count); // 递归重试
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture;
|
|
|
+ return texture;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取存储文件的完整路径
|
|
|
+ public static string GetFilePath(string fileName)
|
|
|
+ {
|
|
|
+ // 获取持久化数据路径
|
|
|
+ string persistentDataPath = Application.persistentDataPath;
|
|
|
+
|
|
|
+ // 创建“zhaoPian”文件夹路径
|
|
|
+ string folderPath = Path.Combine(persistentDataPath, _loadUrl);
|
|
|
+
|
|
|
+ // 确保文件夹存在
|
|
|
+ if (!Directory.Exists(folderPath))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(folderPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回文件的完整路径
|
|
|
+ return Path.Combine(folderPath, fileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取下载地址的文件名, 包含后缀 TODO 需要增加容错
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="url"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static string GetUrlFileName(string url)
|
|
|
+ {
|
|
|
+ // 创建一个 Uri 对象
|
|
|
+ Uri uri = new Uri(url);
|
|
|
+
|
|
|
+ // 获取 URL 的路径部分
|
|
|
+ string path = uri.AbsolutePath;
|
|
|
+
|
|
|
+ // 从路径中提取文件名
|
|
|
+ string fileName = System.IO.Path.GetFileName(path);
|
|
|
+
|
|
|
+ // // 获取不包含扩展名的文件名
|
|
|
+ // string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(fileName);
|
|
|
+
|
|
|
+ return fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+ //TODO 默认纹理, 让客户端来修改这个代码, 定义一个默认的 Texture2D
|
|
|
+ private Texture2D GetDefaultTexture()
|
|
|
+ {
|
|
|
+ // 创建一个简单的默认图片,比如纯色或空白图片
|
|
|
+ Texture2D defaultTexture = new Texture2D(2, 2);
|
|
|
+ Color[] pixels = defaultTexture.GetPixels();
|
|
|
+ for (int i = 0; i < pixels.Length; i++)
|
|
|
+ {
|
|
|
+ pixels[i] = Color.gray; // 设置为灰色的默认图片
|
|
|
+ }
|
|
|
+
|
|
|
+ defaultTexture.SetPixels(pixels);
|
|
|
+ defaultTexture.Apply();
|
|
|
+
|
|
|
+ return defaultTexture;
|
|
|
+ }
|
|
|
+
|
|
|
+ //初始化的时候根据图片保存时间, 加载最多50条到内存中
|
|
|
+ public void LoadAllImages()
|
|
|
+ {
|
|
|
+ // 获取文件夹路径
|
|
|
+ string folderPath = Path.Combine(Application.persistentDataPath, _loadUrl);
|
|
|
+
|
|
|
+ // 检查文件夹是否存在
|
|
|
+ if (Directory.Exists(folderPath))
|
|
|
+ {
|
|
|
+ // 获取所有图片文件路径(假设图片格式为.jpg和.png)
|
|
|
+ string[] imageFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly);
|
|
|
+
|
|
|
+ // 过滤出图片文件,并按修改时间排序
|
|
|
+ var imageFileInfos = imageFiles
|
|
|
+ .Where(filePath => filePath.EndsWith(".jpg") || filePath.EndsWith(".png"))
|
|
|
+ .Select(filePath => new FileInfo(filePath))
|
|
|
+ .OrderByDescending(fileInfo => fileInfo.LastWriteTime)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ int loadedCount = 0;
|
|
|
+ const int maxImagesToLoad = 50;
|
|
|
+
|
|
|
+ foreach (var fileInfo in imageFileInfos)
|
|
|
+ {
|
|
|
+ string filePath = fileInfo.FullName;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 读取图片数据
|
|
|
+ byte[] imageData = File.ReadAllBytes(filePath);
|
|
|
+
|
|
|
+ // 创建纹理并加载数据
|
|
|
+ Texture2D texture = new Texture2D(2, 2); // 创建一个2x2的空纹理
|
|
|
+ if (texture.LoadImage(imageData))
|
|
|
+ {
|
|
|
+ // 提取文件名作为字典的键
|
|
|
+ string fileName = Path.GetFileName(filePath);
|
|
|
+
|
|
|
+ // 将纹理添加到字典
|
|
|
+ _allPicByteDic[fileName] = texture;
|
|
|
+
|
|
|
+ Debug.Log($"Loaded {fileName}");
|
|
|
+
|
|
|
+ loadedCount++;
|
|
|
+
|
|
|
+ // 如果已经加载了最大数量的图片,停止加载并删除剩余较旧的图片
|
|
|
+ if (loadedCount >= maxImagesToLoad)
|
|
|
+ {
|
|
|
+ DeleteOldImages(imageFileInfos, loadedCount);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Failed to load image from {filePath}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Error processing file: {filePath}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Folder not found: {folderPath}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除较旧的图片
|
|
|
+ private void DeleteOldImages(List<FileInfo> imageFileInfos, int loadedCount)
|
|
|
+ {
|
|
|
+ // 从已经加载的图片后面开始删除
|
|
|
+ for (int i = loadedCount; i < imageFileInfos.Count; i++)
|
|
|
+ {
|
|
|
+ string filePath = imageFileInfos[i].FullName;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ File.Delete(filePath);
|
|
|
+ Debug.Log($"Deleted {filePath}");
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Failed to delete {filePath}: {ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|