1024 lines
36 KiB
C#
1024 lines
36 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
|
||
using FairyGUI;
|
||
using SGModule.Common;
|
||
using SGModule.NetKit;
|
||
using ZooMatch;
|
||
using UnityEngine;
|
||
using UnityEngine.Events;
|
||
using UnityEngine.Networking;
|
||
using UnityEngine.Video;
|
||
using Object = UnityEngine.Object;
|
||
|
||
public class TextureHelper
|
||
{
|
||
public static void GetNTexture(string path, string name, UnityAction<NTexture> action)
|
||
{
|
||
if (!nTexturesDic.TryGetValue(path + name, out var spr))
|
||
try
|
||
{
|
||
LoadKit.Instance.LoadSprite(path, name, sprite =>
|
||
{
|
||
if (sprite != null)
|
||
{
|
||
spr = new NTexture(sprite);
|
||
action?.Invoke(spr);
|
||
nTexturesDic.TryAdd(path + name, spr);
|
||
}
|
||
});
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
else
|
||
action?.Invoke(spr);
|
||
}
|
||
|
||
|
||
public static void GetItemIcon(int itemId, UnityAction<NTexture> action = null)
|
||
{
|
||
var itemIconPath = "Atlas.Item";
|
||
var name = itemId.ToString();
|
||
if (!true)
|
||
if (itemId is 101 or 111)
|
||
name = "102";
|
||
|
||
if (itemId is 102 or 106) name += "_normal";
|
||
|
||
GetNTexture(itemIconPath, name, action);
|
||
}
|
||
|
||
|
||
public static IEnumerator GetGalleryFromNet(int imageID, Action<bool> action = null)
|
||
{
|
||
if (imageID == 0)
|
||
{
|
||
action?.Invoke(true);
|
||
}
|
||
else
|
||
{
|
||
var picInfoUrl = $"{LoginKit.Instance.LoginModel.CdnURL}gallery/{imageID}.jpg";
|
||
yield return GetTextureFromNet("Gallery", imageID, picInfoUrl, action);
|
||
}
|
||
}
|
||
|
||
public static string GetBankIconUrl(string icon_name)
|
||
{
|
||
return string.Format("ui://G002_main/{0}", icon_name);
|
||
}
|
||
|
||
public static void GetGalleryLocal(int imageID, Action<NTexture> action)
|
||
{
|
||
if (!galleryNTexturesDic.TryGetValue(imageID, out var spr))
|
||
{
|
||
var path = $"Gallery/{imageID}";
|
||
var asset = Resources.Load($"Atlas/{path}");
|
||
if (asset)
|
||
{
|
||
}
|
||
else
|
||
{
|
||
CrazyAsyKit.StartCoroutine(GetGalleryFromNet(imageID, isSuccess =>
|
||
{
|
||
if (isSuccess)
|
||
CrazyAsyKit.StartCoroutine(GetLocalTexture($"{path}.jpg", texture =>
|
||
{
|
||
if (texture == null)
|
||
{
|
||
action?.Invoke(null);
|
||
|
||
return;
|
||
}
|
||
|
||
var spr1 = new NTexture(texture);
|
||
galleryNTexturesDic.TryAdd(imageID, spr1);
|
||
action?.Invoke(spr1);
|
||
}));
|
||
else
|
||
action?.Invoke(null);
|
||
}));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
action?.Invoke(spr);
|
||
}
|
||
}
|
||
|
||
#region 缓存
|
||
|
||
private static readonly Dictionary<string, NTexture> nTexturesDic = new();
|
||
private static readonly Dictionary<int, NTexture> avatarNTexturesDic = new();
|
||
private static readonly Dictionary<int, NTexture> galleryNTexturesDic = new();
|
||
|
||
#endregion
|
||
|
||
#region 加载Texture
|
||
|
||
private static IEnumerator GetLocalTexture(string imagePath, Action<Texture> action)
|
||
{
|
||
var file = $"{Application.persistentDataPath}/{imagePath}";
|
||
var fileInfo = new FileInfo(file);
|
||
if (!fileInfo.Exists)
|
||
{
|
||
action?.Invoke(null);
|
||
yield break;
|
||
}
|
||
|
||
var avatarPath = $"file://{file}";
|
||
var uwr = UnityWebRequestTexture.GetTexture(avatarPath);
|
||
yield return uwr.SendWebRequest();
|
||
if (uwr.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError)
|
||
{
|
||
action?.Invoke(null);
|
||
yield break;
|
||
}
|
||
|
||
var texture2D = DownloadHandlerTexture.GetContent(uwr);
|
||
|
||
action?.Invoke(texture2D);
|
||
}
|
||
|
||
private class DownloadTask
|
||
{
|
||
public Action<NTexture> Callback;
|
||
public string FileName;
|
||
public string Folder;
|
||
public GLoader Loader;
|
||
public string LocalFolder;
|
||
public bool IsGameBg;
|
||
|
||
}
|
||
|
||
public static string imgUrl = "";
|
||
|
||
// 普通队列
|
||
private static readonly Queue<DownloadTask> normalQueue = new();
|
||
|
||
private static Coroutine normalCoroutine;
|
||
|
||
// 优先队列
|
||
private static readonly Queue<DownloadTask> priorityQueue = new();
|
||
private static Coroutine priorityCoroutine;
|
||
|
||
|
||
// ====================== 并发配置 ======================
|
||
private static int maxPriorityConcurrent = 3; // ✅ 可配置最大并发数
|
||
private static int priorityRunning = 0; // 当前正在运行的任务数
|
||
|
||
#region 材质池
|
||
|
||
private static class MaterialPool
|
||
{
|
||
private static readonly Stack<Material> blurMats = new();
|
||
private static readonly Stack<Material> normalMats = new();
|
||
|
||
public static Material GetBlur()
|
||
{
|
||
if (blurMats.Count > 0) return blurMats.Pop();
|
||
var shader = Resources.Load<Shader>("ZooMatchAssets/Shader/Blur");
|
||
if (!shader) return null;
|
||
return new Material(shader);
|
||
}
|
||
|
||
public static Material GetNormal()
|
||
{
|
||
if (normalMats.Count > 0) return normalMats.Pop();
|
||
var shader = Resources.Load<Shader>("ZooMatchAssets/Shader/FairyGUI/FairyGUI-Image");
|
||
if (!shader) return null;
|
||
return new Material(shader);
|
||
}
|
||
|
||
public static void Return(Material mat)
|
||
{
|
||
if (!mat) return;
|
||
var name = mat.shader.name;
|
||
if (name.Contains("Blur")) blurMats.Push(mat);
|
||
else normalMats.Push(mat);
|
||
}
|
||
|
||
public static void Clear()
|
||
{
|
||
foreach (var mat in blurMats) Object.Destroy(mat);
|
||
blurMats.Clear();
|
||
foreach (var mat in normalMats) Object.Destroy(mat);
|
||
normalMats.Clear();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 图片加载接口
|
||
|
||
public static string getResPath()
|
||
{
|
||
// 删除旧资源
|
||
if (!DataMgr.curResVersion.Value.IsNullOrWhiteSpace() && DataMgr.curResVersion.Value != ConfigSystem.GetConfigResVersion())
|
||
{
|
||
var oldFolder = Path.Combine(Application.persistentDataPath, DataMgr.curResVersion.Value);
|
||
if (Directory.Exists(oldFolder))
|
||
{
|
||
Directory.Delete(oldFolder, true);
|
||
}
|
||
DataMgr.curResVersion.Value = ConfigSystem.GetConfigResVersion();
|
||
}
|
||
else if (DataMgr.curResVersion.Value.IsNullOrWhiteSpace())
|
||
{
|
||
DataMgr.curResVersion.Value = ConfigSystem.GetConfigResVersion();
|
||
}
|
||
|
||
if (ConfigSystem.GetConfigResVersion().IsNullOrWhiteSpace())
|
||
{
|
||
Debug.LogError("获取资源路径失败");
|
||
return Application.persistentDataPath;
|
||
}
|
||
|
||
string curFolder = Path.Combine(Application.persistentDataPath, ConfigSystem.GetConfigResVersion());
|
||
return curFolder;
|
||
}
|
||
|
||
public static void SetImgLoader(GLoader loader, string fileName, Action<NTexture> callback,
|
||
string folder, string localFolder, bool priority = true, bool isLoad = false, bool isGameBg = false)
|
||
{
|
||
var localPath = Path.Combine(getResPath(), localFolder, fileName + ".jpg");
|
||
if (File.Exists(localPath))
|
||
{
|
||
Debug.Log($"[SetImgLoader] 本地存在,直接加载 {fileName}");
|
||
CrazyAsyKit.StartCoroutine(LoadTexture(fileName, loader, callback, localFolder, isGameBg));
|
||
return;
|
||
}
|
||
|
||
if (isLoad)
|
||
{
|
||
Debug.Log($"[SetImgLoader] 兼容老逻辑,直接加载 {fileName}");
|
||
return;
|
||
}
|
||
|
||
var task = new DownloadTask
|
||
{
|
||
Loader = loader,
|
||
FileName = fileName,
|
||
Folder = folder,
|
||
Callback = callback,
|
||
LocalFolder = localFolder,
|
||
IsGameBg = isGameBg
|
||
|
||
};
|
||
|
||
if (priority)
|
||
EnqueuePriorityTask(task, isBatch: false); // 👈 单任务标记
|
||
else
|
||
EnqueueNormalTask(loader, fileName, callback, folder, localFolder);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 批量加载任务(优先队列,串行)
|
||
/// </summary>
|
||
public static void SetImgLoaders(
|
||
List<(GLoader loader, string fileName, Action<NTexture> callback, string folder, string localFolder)> tasks)
|
||
{
|
||
Debug.Log($"[BatchSetImgLoader] 收到 {tasks.Count} 个任务");
|
||
|
||
// 清空旧任务(批量任务才清空)
|
||
if (priorityCoroutine != null)
|
||
{
|
||
CrazyAsyKit.StopCoroutine(priorityCoroutine);
|
||
priorityCoroutine = null;
|
||
}
|
||
|
||
priorityQueue.Clear();
|
||
|
||
foreach (var task in tasks)
|
||
{
|
||
var downloadTask = new DownloadTask
|
||
{
|
||
Loader = task.loader,
|
||
FileName = task.fileName,
|
||
Folder = task.folder,
|
||
Callback = task.callback,
|
||
LocalFolder = task.localFolder,
|
||
IsGameBg = false
|
||
|
||
};
|
||
|
||
EnqueuePriorityTask(downloadTask, isBatch: true); // 👈 批量标记
|
||
}
|
||
|
||
if (priorityCoroutine == null)
|
||
priorityCoroutine = CrazyAsyKit.StartCoroutine(ProcessPriorityQueue());
|
||
}
|
||
|
||
|
||
private static void EnqueuePriorityTask(DownloadTask task, bool isBatch)
|
||
{
|
||
// 去重:如果已在队列中就跳过
|
||
foreach (var queued in priorityQueue)
|
||
{
|
||
if (queued.FileName == task.FileName)
|
||
{
|
||
Debug.Log($"[PriorityQueue] 跳过重复任务 {task.FileName}");
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (isBatch)
|
||
Debug.Log($"[PriorityQueue] 批量添加任务 {task.FileName}");
|
||
else
|
||
Debug.Log($"[PriorityQueue] 单任务添加 {task.FileName}");
|
||
|
||
priorityQueue.Enqueue(task);
|
||
|
||
if (priorityCoroutine == null)
|
||
priorityCoroutine = CrazyAsyKit.StartCoroutine(ProcessPriorityQueue());
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region 普通队列逻辑
|
||
|
||
private static void EnqueueNormalTask(GLoader loader, string fileName, Action<NTexture> callback, string folder, string localFolder)
|
||
{
|
||
normalQueue.Enqueue(new DownloadTask
|
||
{
|
||
Loader = loader,
|
||
FileName = fileName,
|
||
Folder = folder,
|
||
Callback = callback,
|
||
LocalFolder = localFolder
|
||
});
|
||
|
||
if (normalCoroutine == null)
|
||
normalCoroutine = CrazyAsyKit.StartCoroutine(ProcessNormalQueue());
|
||
}
|
||
|
||
private static IEnumerator ProcessNormalQueue()
|
||
{
|
||
while (normalQueue.Count > 0)
|
||
{
|
||
var task = normalQueue.Dequeue();
|
||
yield return DownloadCoroutine(task);
|
||
}
|
||
|
||
normalCoroutine = null;
|
||
}
|
||
|
||
private static IEnumerator ProcessPriorityQueue()
|
||
{
|
||
while (priorityQueue.Count > 0 || priorityRunning > 0)
|
||
{
|
||
// 如果没达到最大并发,就从队列里拉一个任务出来
|
||
while (priorityRunning < maxPriorityConcurrent && priorityQueue.Count > 0)
|
||
{
|
||
var task = priorityQueue.Dequeue();
|
||
priorityRunning++;
|
||
Debug.Log($"[PriorityQueue] 开始下载 {task.FileName}");
|
||
|
||
// 启动一个子协程跑下载
|
||
CrazyAsyKit.StartCoroutine(RunPriorityTask(task));
|
||
}
|
||
|
||
yield return null; // 每帧检查一次
|
||
}
|
||
|
||
priorityCoroutine = null;
|
||
Debug.Log("[PriorityQueue] 批量任务完成");
|
||
}
|
||
|
||
|
||
private static IEnumerator RunPriorityTask(DownloadTask task)
|
||
{
|
||
yield return DownloadCoroutine(task);
|
||
|
||
priorityRunning--;
|
||
Debug.Log($"[PriorityQueue] 完成 {task.FileName}");
|
||
}
|
||
|
||
private static IEnumerator DownloadCoroutine(DownloadTask task)
|
||
{
|
||
var localPath = Path.Combine(getResPath(), task.LocalFolder, task.FileName + ".jpg");
|
||
|
||
var tempPath = localPath + ".tmp";
|
||
var url = imgUrl + task.Folder + task.FileName + ".jpg";
|
||
Debug.Log($"[Download] 下载 tempPath=0== {tempPath} \n url==={url}");
|
||
if (File.Exists(localPath))
|
||
{
|
||
// Debug.Log($"[SetImgLoader] 本地存在,直接加载 {task.FileName}");
|
||
yield return LoadTexture(task.FileName, task.Loader, task.Callback, task.LocalFolder, task.IsGameBg);
|
||
yield break;
|
||
}
|
||
|
||
// ⚠️ 确保遗留的临时文件被清理掉
|
||
Debug.Log($"[Download] tempPath=1== {tempPath}");
|
||
if (File.Exists(tempPath))
|
||
{
|
||
Debug.Log($"[Download] 删除遗留临时文件 {tempPath}");
|
||
File.Delete(tempPath);
|
||
}
|
||
|
||
// 确保目录存在
|
||
string tempDir = Path.GetDirectoryName(tempPath);
|
||
if (!Directory.Exists(tempDir))
|
||
{
|
||
Directory.CreateDirectory(tempDir);
|
||
}
|
||
|
||
var attempt = 0;
|
||
while (attempt < 3)
|
||
{
|
||
Debug.Log($"[Download] 正在下载 {task.FileName} 次数:{attempt}");
|
||
Debug.Log(url);
|
||
attempt++;
|
||
using (var www = UnityWebRequest.Get(url))
|
||
{
|
||
yield return www.SendWebRequest();
|
||
if (www.result == UnityWebRequest.Result.Success)
|
||
{
|
||
try
|
||
{
|
||
Debug.Log($"[Download] 下载成功,保存临时文件 {tempPath}");
|
||
File.WriteAllBytes(tempPath, www.downloadHandler.data);
|
||
|
||
if (File.Exists(localPath)) File.Delete(localPath);
|
||
|
||
File.Move(tempPath, localPath);
|
||
// 解密文件
|
||
// Debug.Log($"[Download] 开始解密文件 {task.FileName}");
|
||
// Rescrypt.DecryptFile(tempPath, localPath, ConfigManager.GameConfig.packageName);
|
||
// Debug.Log($"[Download] 解密完成,保存路径:{localPath}");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[Download] 解密或保存失败:{e}");
|
||
yield break;
|
||
}
|
||
|
||
if (task.Loader != null)
|
||
yield return LoadTexture(task.FileName, task.Loader, task.Callback, task.LocalFolder, task.IsGameBg);
|
||
yield break;
|
||
}
|
||
|
||
yield return new WaitForSeconds(1f);
|
||
}
|
||
}
|
||
|
||
task.Callback?.Invoke(null);
|
||
}
|
||
|
||
public static IEnumerator LoadTexture(string fileName, GLoader loader, Action<NTexture> callback = null,
|
||
string folder = "", bool isGameBg = false)
|
||
{
|
||
string encryptedPath = Path.Combine(getResPath(), folder, fileName + ".jpg");
|
||
|
||
if (!File.Exists(encryptedPath))
|
||
{
|
||
Debug.LogWarning($"[LoadEncryptedTexture] 加密文件不存在: {encryptedPath}");
|
||
callback?.Invoke(null);
|
||
yield break;
|
||
}
|
||
|
||
Debug.Log($"[LoadEncryptedTexture] 开始加载加密图片: {fileName}");
|
||
|
||
Debug.Log($"[LoadTexture] 开始加载本地图片 {fileName}");
|
||
using (var www = UnityWebRequestTexture.GetTexture("file://" + GetDecryptedImagePath(fileName, folder)))
|
||
{
|
||
yield return www.SendWebRequest();
|
||
if (www.result == UnityWebRequest.Result.Success)
|
||
{
|
||
var tex = DownloadHandlerTexture.GetContent(www);
|
||
var nTex = new NTexture(tex) { destroyMethod = DestroyMethod.Destroy };
|
||
|
||
tex.name = fileName;
|
||
if (loader != null && loader.texture != null)
|
||
{
|
||
loader.texture.Dispose(); // 释放 GPU 资源
|
||
loader.texture = null; // 断开引用
|
||
}
|
||
|
||
if (loader != null && !loader.isDisposed)
|
||
{
|
||
loader.texture = nTex;
|
||
// Debug.Log($"[LoadTexture] 图片已设置到 Loader {fileName}");
|
||
callback?.Invoke(nTex);
|
||
}
|
||
else
|
||
{
|
||
// Debug.Log($"[LoadTexture] Loader 不存在或已销毁 {fileName}");
|
||
}
|
||
|
||
//设置游戏背景时,传的是UGUI的,不传loader
|
||
if (isGameBg)
|
||
{
|
||
callback?.Invoke(nTex);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"[LoadTexture] 加载失败 {www.error}");
|
||
callback?.Invoke(null);
|
||
}
|
||
}
|
||
|
||
if (loader != null && !loader.isDisposed)
|
||
loader.visible = true;
|
||
}
|
||
|
||
public static string GetDecryptedImagePath(string fileName, string localFolder)
|
||
{
|
||
string tempPath = Path.Combine(Application.temporaryCachePath, FolderNames.GameCache, localFolder, fileName + "_temp.jpg");
|
||
Debug.Log($"获取解密路径: {tempPath}");
|
||
|
||
if (!File.Exists(tempPath))
|
||
{
|
||
Debug.Log($"!!!!!!!!!!!!临时文件不存在: {fileName}");
|
||
// 确保目录存在
|
||
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
||
|
||
string encPath = Path.Combine(getResPath(), localFolder, fileName + ".jpg");
|
||
Debug.Log(encPath);
|
||
if (!File.Exists(encPath)) return null;
|
||
Debug.Log($"!!!!!!!!!!!!写入一张: {fileName}");
|
||
byte[] decryptedBytes = Rescrypt.DecryptFileToBytes(encPath);
|
||
File.WriteAllBytes(tempPath, decryptedBytes);
|
||
}
|
||
return tempPath;
|
||
}
|
||
public static IEnumerator WriteTempBeforeOpenCoroutine_()
|
||
{
|
||
System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||
|
||
var levelUnlocks = ConfigSystem.GetLevelUnlockConfig();
|
||
var FreeImageLibrary_ = ConfigSystem.GetFreeImageConfig();
|
||
var ADImageLibrary_ = ConfigSystem.GetADImageConfig();
|
||
var SpecialImageLibrary_ = ConfigSystem.GetSpecialImageConfig();
|
||
var VIPImageLibrary_ = ConfigSystem.GetVIPImageConfig();
|
||
for (int i = 0; i < GameHelper.GetCommonModel().MultiModal - 1; i++)
|
||
{
|
||
GetDecryptedImagePath(levelUnlocks[i].Name, FolderNames.AlbumName);
|
||
yield return null;
|
||
}
|
||
var LevelUnlockListNew = DataMgr.LevelUnlockListNew.Value;
|
||
for (int i = 0; i < LevelUnlockListNew.Count; i++)
|
||
{
|
||
switch (LevelUnlockListNew[i].type)
|
||
{
|
||
case 0:
|
||
GetDecryptedImagePath(FreeImageLibrary_[LevelUnlockListNew[i].config_index].Name, FolderNames.AlbumName);
|
||
break;
|
||
case 1:
|
||
GetDecryptedImagePath(ADImageLibrary_[LevelUnlockListNew[i].config_index].Name, FolderNames.AlbumName);
|
||
break;
|
||
case 2:
|
||
GetDecryptedImagePath(SpecialImageLibrary_[LevelUnlockListNew[i].config_index].Name, FolderNames.AlbumName);
|
||
break;
|
||
case 3:
|
||
GetDecryptedImagePath(VIPImageLibrary_[LevelUnlockListNew[i].config_index].Name, FolderNames.AlbumName);
|
||
break;
|
||
}
|
||
yield return null;
|
||
}
|
||
// Debug.Log("ppppppppppppppppppppp" + Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName));
|
||
// Debug.Log("ppppppppppppppppppppp" + File.Exists(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName)));
|
||
// if (Directory.Exists(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName)))
|
||
// {
|
||
// int write_num_max = 10;
|
||
// int write_num = 0;
|
||
// if (UIManager.Instance.IsExistUI(UIConst.LiveUI)) write_num_max = 999;
|
||
// Debug.Log("ppppppppppppppppppppp");
|
||
// string[] files = Directory.GetFiles(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName), "*.mp4");
|
||
// foreach (var file in files)
|
||
// {
|
||
// Debug.Log("ppppppppppppppppppppp" + file);
|
||
// var fileName = Path.GetFileNameWithoutExtension(file);
|
||
// var localPath = Path.Combine(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName), fileName + ".mp4");
|
||
// byte[] decryptedBytes = Rescrypt.DecryptFileToBytes(localPath);
|
||
// string encPath = Path.Combine(Application.temporaryCachePath, FolderNames.GameCache, FolderNames.VideoName, fileName + ".mp4");
|
||
// Directory.CreateDirectory(Path.GetDirectoryName(encPath));
|
||
// File.WriteAllBytes(encPath, decryptedBytes);
|
||
// write_num++;
|
||
// if (write_num > write_num_max) break;
|
||
// yield return null;
|
||
// }
|
||
// }
|
||
stopwatch.Stop();
|
||
SuperApplication.WriteTempBefore = null;
|
||
UnityEngine.Debug.Log($"WriteTempBeforeOpen 协程执行耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
|
||
}
|
||
// public static IEnumerator WriteTempBeforeOpenCoroutine_test()
|
||
// {
|
||
// System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||
|
||
// var levelUnlocks = ConfigSystem.GetLevelUnlockConfig();
|
||
|
||
// for (int i = 0; i < 500; i++)
|
||
// {
|
||
// GetDecryptedImagePath(levelUnlocks[i].Name, FolderNames.AlbumName);
|
||
|
||
// // 每隔 N 次让出一帧,避免卡顿(可调节)
|
||
// yield return null;
|
||
// }
|
||
|
||
// stopwatch.Stop();
|
||
// SuperApplication.WriteTempBefore = null;
|
||
// UnityEngine.Debug.Log($"WriteTempBeforeOpen 协程执行耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
|
||
// }
|
||
public static IEnumerator WriteTempBeforeOpenCoroutine_test()
|
||
{
|
||
System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||
if (File.Exists(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName)))
|
||
{
|
||
var files = Directory.GetFiles(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName), "*.mp4");
|
||
foreach (var file in files)
|
||
{
|
||
var fileName = Path.GetFileNameWithoutExtension(file);
|
||
var localPath = Path.Combine(Path.Combine(TextureHelper.getResPath(), FolderNames.VideoName), fileName + ".mp4");
|
||
byte[] decryptedBytes = Rescrypt.DecryptFileToBytes(localPath);
|
||
string encPath = Path.Combine(Application.temporaryCachePath, FolderNames.GameCache, FolderNames.VideoName, fileName + ".mp4");
|
||
Directory.CreateDirectory(Path.GetDirectoryName(encPath));
|
||
File.WriteAllBytes(encPath, decryptedBytes);
|
||
yield return null;
|
||
}
|
||
}
|
||
stopwatch.Stop();
|
||
|
||
UnityEngine.Debug.Log($"WriteTempBeforeOpen 协程执行耗时: {stopwatch.ElapsedMilliseconds} 毫秒");
|
||
}
|
||
#endregion
|
||
|
||
|
||
private static IEnumerator WaitForReady(VideoPlayer player, Action onReady)
|
||
{
|
||
while (!player.isPrepared)
|
||
yield return null;
|
||
|
||
onReady?.Invoke();
|
||
}
|
||
|
||
public static void SaveImageToAlbum(string fileName, string encryptedFolder, Action onSuccess = null)
|
||
{
|
||
try
|
||
{
|
||
// 加密图片路径
|
||
string encryptedPath = Path.Combine(getResPath(), encryptedFolder, fileName + ".jpg");
|
||
|
||
if (!File.Exists(encryptedPath))
|
||
{
|
||
Debug.LogWarning($"加密图片不存在: {encryptedPath}");
|
||
return;
|
||
}
|
||
|
||
// 解密为字节数组
|
||
byte[] decryptedBytes = Rescrypt.DecryptFileToBytes(encryptedPath);
|
||
|
||
// 写入临时路径(系统可访问)
|
||
string tempPath = Path.Combine(Application.temporaryCachePath, fileName + "_temp.jpg");
|
||
File.WriteAllBytes(tempPath, decryptedBytes);
|
||
|
||
// 保存到系统相册
|
||
NativeGallery.SaveImageToGallery(tempPath, "MyAlbum", fileName + ".jpg", (bool success, string path) =>
|
||
{
|
||
if (success)
|
||
{
|
||
GameHelper.ShowTips("save_successed",true);
|
||
onSuccess?.Invoke();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("保存到相册失败");
|
||
}
|
||
|
||
// 可选:清理临时文件
|
||
if (File.Exists(tempPath))
|
||
File.Delete(tempPath);
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"保存加密图片到相册失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
public static void SaveVideoToAlbum(string fileName, Action onSuccess = null)
|
||
{
|
||
try
|
||
{
|
||
string localPath = Path.Combine(getResPath(), FolderNames.VideoName, fileName + ".mp4");
|
||
File.SetCreationTime(localPath, DateTime.Now);
|
||
File.SetCreationTimeUtc(localPath, DateTime.Now);
|
||
File.SetLastWriteTime(localPath, DateTime.Now);
|
||
File.SetLastWriteTimeUtc(localPath, DateTime.Now);
|
||
// CrazyAsyKit.StartCoroutine(GetSaveVideo(fileName, (isSuccess) =>
|
||
// {
|
||
|
||
// }));
|
||
NativeGallery.SaveVideoToGallery(localPath, "MyAlbum", "my_video.mp4", (bool success, string path) =>
|
||
{
|
||
if (success)
|
||
{
|
||
GameHelper.ShowTips("save_successed",true);
|
||
onSuccess?.Invoke();
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"保存加密视频到相册失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public static void SetVideoLoader(VideoPlayer player, GLoader loader, string fileName,
|
||
Action<VideoPlayer> action = null, bool play = true)
|
||
{
|
||
VideoLoadScheduler.EnqueueLoad(player, fileName, loader, videoPlayer =>
|
||
{
|
||
Debug.Log("[绑定播放器 EnqueueLoad]=========1=== ");
|
||
if (videoPlayer != null)
|
||
{
|
||
Debug.Log("视频加载成功!");
|
||
action?.Invoke(videoPlayer);
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("视频加载失败!");
|
||
VideoPlayerPool.Instance.ReturnPlayer(player);
|
||
action?.Invoke(null);
|
||
}
|
||
}, play);
|
||
}
|
||
|
||
public static void SetImageMosaic(GLoader loader, int num = 80)
|
||
{
|
||
var shader = Resources.Load<Shader>("ZooMatchAssets/Shader/Mosaic");
|
||
if (shader == null)
|
||
{
|
||
Debug.LogError("找不到 Shader:Custom/Mosaic。请确保 shader 名称正确并已包含到构建中。");
|
||
return;
|
||
}
|
||
|
||
var material = new Material(shader);
|
||
material.SetFloat("_BlockSize", num); // 假设你 shader 中的 blockSize 参数是这个
|
||
loader.material = material;
|
||
}
|
||
|
||
#region 材质处理
|
||
|
||
public static void SetImageBlur(GLoader loader)
|
||
{
|
||
if (loader == null || loader.isDisposed || loader.texture == null || loader.material.name == "Custom/Blur") return;
|
||
if (loader.material != null) MaterialPool.Return(loader.material);
|
||
loader.material = MaterialPool.GetBlur();
|
||
}
|
||
|
||
public static void CancelImageBlur(GLoader loader)
|
||
{
|
||
if (loader == null || loader.isDisposed || loader.texture == null || loader.material.name != "Custom/Blur") return;
|
||
|
||
if (loader.material != null) MaterialPool.Return(loader.material);
|
||
loader.material = MaterialPool.GetNormal();
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 彻底清理材质池(切场景/退出游戏时调用)
|
||
/// </summary>
|
||
public static void ClearMaterialPool()
|
||
{
|
||
MaterialPool.Clear();
|
||
}
|
||
|
||
public static void setGamebg(string fileName)
|
||
{
|
||
|
||
// 调用统一的 SetImgLoader,不需要再自己写下载逻辑
|
||
SetImgLoader(null, fileName, nTex =>
|
||
{
|
||
if (nTex != null && nTex.nativeTexture != null)
|
||
{
|
||
Debug.Log("背景图片加载成功!");
|
||
|
||
var tex2D = nTex.nativeTexture as Texture2D;
|
||
if (tex2D == null)
|
||
{
|
||
Debug.LogError("NTexture 转换失败!");
|
||
return;
|
||
}
|
||
tex2D.name = fileName;
|
||
// 创建 Sprite
|
||
var sprite = Sprite.Create(
|
||
tex2D,
|
||
new Rect(0, 0, tex2D.width, tex2D.height),
|
||
new Vector2(0.5f, 0.5f)
|
||
);
|
||
|
||
var spriteRenderer = GameObject.Find("game_bg").GetComponent<SpriteRenderer>();
|
||
if (spriteRenderer.sprite != null)
|
||
{
|
||
// 记录旧的 Sprite 和 Texture2D
|
||
var oldSprite = spriteRenderer.sprite;
|
||
var oldTex = oldSprite != null ? oldSprite.texture : null;
|
||
|
||
// 替换为 null,断开引用
|
||
spriteRenderer.sprite = null;
|
||
|
||
// 只销毁运行时创建的资源
|
||
if (oldSprite != null && oldSprite.hideFlags == HideFlags.None)
|
||
{
|
||
UnityEngine.Object.Destroy(oldSprite);
|
||
}
|
||
if (oldTex != null && oldTex.hideFlags == HideFlags.None)
|
||
{
|
||
UnityEngine.Object.Destroy(oldTex);
|
||
}
|
||
|
||
}
|
||
|
||
spriteRenderer.sprite = sprite;
|
||
|
||
var currentWidth = spriteRenderer.sprite.bounds.size.x;
|
||
var scaleFactor = 64f / currentWidth;
|
||
|
||
// 等比缩放
|
||
spriteRenderer.transform.localScale = new Vector3(scaleFactor, scaleFactor, 1);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("背景图片加载失败!");
|
||
}
|
||
}, "LevelAlbums/", FolderNames.AlbumName, true, false, true); // ✅ 背景一般是立刻需要的,走优先下载
|
||
}
|
||
|
||
|
||
public static void GetCardIcon(bool isLogo = false, UnityAction<NTexture> action = null)
|
||
{
|
||
var cardIconPath = "logo_default";
|
||
// var paymentTypeVo = GameHelper.GetPaymentTypeVO();
|
||
// if (isLogo)
|
||
// {
|
||
// cardIconPath = paymentTypeVo.logo_id;
|
||
// }
|
||
// else
|
||
// {
|
||
// cardIconPath = paymentTypeVo.card_name;
|
||
// }
|
||
|
||
|
||
GetNTexture("Atlas.Pay", cardIconPath, action);
|
||
}
|
||
|
||
private static IEnumerator GetTextureFromNet(string type, int imgId, string imgUrl, Action<bool> action = null)
|
||
{
|
||
var imagePath = $"{CommonHelper.GetAppSavePath()}/{type}/{imgId}.jpg";
|
||
var fileInfo = new FileInfo(imagePath);
|
||
if (fileInfo.Exists)
|
||
{
|
||
action?.Invoke(true);
|
||
yield break;
|
||
}
|
||
|
||
var avatarRequest = UnityWebRequest.Get(imgUrl);
|
||
yield return avatarRequest.SendWebRequest();
|
||
if (avatarRequest.result == UnityWebRequest.Result.ConnectionError ||
|
||
avatarRequest.result == UnityWebRequest.Result.ProtocolError)
|
||
{
|
||
action?.Invoke(false);
|
||
}
|
||
else
|
||
{
|
||
var avatarData = avatarRequest.downloadHandler.data;
|
||
var dirPath = Path.GetDirectoryName(imagePath);
|
||
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
|
||
|
||
if (fileInfo.Exists)
|
||
yield break;
|
||
Stream stream = fileInfo.Create();
|
||
stream.Write(avatarData, 0, avatarData.Length);
|
||
stream.Close();
|
||
stream.Dispose();
|
||
action?.Invoke(true);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 头像相关
|
||
|
||
public static void SetAvatarToLoader(int avatarId, GLoader _GLoader, bool IsNeedDefAvatar = true)
|
||
{
|
||
if (!avatarNTexturesDic.TryGetValue(avatarId, out var spr))
|
||
try
|
||
{
|
||
Sprite sprite = null;
|
||
if (avatarId == 0)
|
||
{
|
||
if (!PlayerPrefsKit.ReadBool("IsLogin"))
|
||
{
|
||
avatarId = 1;
|
||
SetAvatarToLoader(avatarId, _GLoader);
|
||
return;
|
||
}
|
||
|
||
if (PlayerPrefsKit.ReadString("AvatarUrl").IsNullOrWhiteSpace())
|
||
{
|
||
_GLoader.url = "ui://pmf3wbjicxrg4";
|
||
return;
|
||
}
|
||
|
||
GetSelfFaceBookAvatar(texture =>
|
||
{
|
||
if (_GLoader != null)
|
||
{
|
||
if (texture != null)
|
||
_GLoader.texture = texture;
|
||
else
|
||
_GLoader.url = "ui://pmf3wbjicxrg4";
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (avatarId > 100)
|
||
{
|
||
if (IsNeedDefAvatar) _GLoader.url = "ui://pmf3wbjicxrg4";
|
||
|
||
GetFaceBookAvatar(avatarId, e =>
|
||
{
|
||
if (_GLoader != null)
|
||
{
|
||
if (e == null)
|
||
_GLoader.url = "ui://pmf3wbjicxrg4";
|
||
else
|
||
_GLoader.texture = e;
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
LoadKit.Instance.LoadSprite("Atlas.Avatar", avatarId.ToString(), spr =>
|
||
{
|
||
sprite = spr;
|
||
var spr1 = new NTexture(sprite);
|
||
_GLoader.texture = spr1;
|
||
avatarNTexturesDic.Add(avatarId, spr1);
|
||
});
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
else
|
||
_GLoader.texture = spr;
|
||
}
|
||
|
||
|
||
private static IEnumerator GetAvatarLocal(int avatarId, Action<Texture> action)
|
||
{
|
||
yield return GetLocalTexture($"Avatar/{avatarId}.jpg", action);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region FaceBook头像相关
|
||
|
||
public static void GetFaceBookAvatar(int avatarId, Action<NTexture> action)
|
||
{
|
||
if (!avatarNTexturesDic.TryGetValue(avatarId, out var spr))
|
||
HallManager.Instance.StartCoroutine(GetAvatarLocal(avatarId, texture =>
|
||
{
|
||
if (texture == null)
|
||
{
|
||
action?.Invoke(null);
|
||
return;
|
||
}
|
||
|
||
spr = new NTexture(texture);
|
||
if (avatarNTexturesDic.ContainsKey(avatarId)) avatarNTexturesDic.Add(avatarId, spr);
|
||
|
||
action?.Invoke(spr);
|
||
}));
|
||
else
|
||
action?.Invoke(spr);
|
||
}
|
||
|
||
|
||
public static void GetSelfFaceBookAvatar(Action<NTexture> action)
|
||
{
|
||
if (!avatarNTexturesDic.TryGetValue(0, out var spr))
|
||
{
|
||
}
|
||
else
|
||
{
|
||
action?.Invoke(spr);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
} |