SD-20250415ABSO\Administrator 321e38cb79 冠军框架迁移
2025-04-18 19:18:15 +08:00

857 lines
25 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Security.Policy;
using System;
using UnityEngine.Networking;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using TEngine;
using WebP;
public class AsyncImageDownload : MonoBehaviour
{
private Dictionary<int, Sprite> sprites = new Dictionary<int, Sprite>();
public Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();
private Sprite myWXPic;
private static AsyncImageDownload _instance = null;
public static AsyncImageDownload GetInstance() { return Instance; }
public static AsyncImageDownload Instance
{
get
{
if (_instance == null)
{
GameObject obj = new GameObject("AsyncImageDownload");
_instance = obj.AddComponent<AsyncImageDownload>();
DontDestroyOnLoad(obj);
_instance.Init();
}
return _instance;
}
}
public void CleanMemory()
{
this.sprites.Clear();
this.textures.Clear();
}
public bool Init()
{
if (!Directory.Exists(Application.persistentDataPath + "/ImageCache/"))
{
Directory.CreateDirectory(Application.persistentDataPath + "/ImageCache/");
}
myWXPic = null;
return true;
}
public static string GetBigMd5(string str)
{
string cl = str;
string pwd = "";
var md5 = MD5.Create();
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
for (int i = 0; i < s.Length; i++)
{
pwd = pwd + s[i].ToString("X2");
}
return pwd;
}
public async Task SetAsyncImage(string url, RawImage image)
{
// 神秘人头像不缓存
if (url == "smr")
{
GameModule.Resource.LoadAsset<Texture2D>("smr", (tex) =>
{
if (image != null)
{
image.texture = tex;
}
});
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
if (image != null)
{
image.texture = textures[id];
}
return;
}
if (!File.Exists(path + id))
{
await DownloadImageRaw(id, url, image);
}
else
{
await LoadLocalImageRaw(id, url, image);
}
}
public async Task SetAsyncImage(string url, SpriteRenderer spriteRenderer)
{
// Check if the URL is for a special case
if (url == "smr")
{
GameModule.Resource.LoadAsset<Texture2D>("smr", (tex) =>
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
});
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
if (spriteRenderer != null)
{
var tex = textures[id];
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
return;
}
if (!File.Exists(path + id))
{
await DownloadImageSprite(id, url, spriteRenderer);
}
else
{
await LoadLocalImageSprite(id, url, spriteRenderer);
}
}
public async Task SetAsyncImage(string url, Image image)
{
// Check if the URL is for a special case
if (url == "smr")
{
GameModule.Resource.LoadAsset<Texture2D>("smr", (tex) =>
{
if (image != null)
{
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
image.sprite = sprite;
}
});
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
if (image != null)
{
var tex = textures[id];
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
sprite.name = id; // 设置Sprite的名称
image.sprite = sprite;
}
return;
}
if (!File.Exists(GetFilePath(id)))
{
await DownloadImageForImage(id, url, image);
}
else
{
await LoadLocalImageForImage(id, url, image);
}
}
//int index,Action<int,Texture2D> act
IEnumerator DownloadImageRaw2(string id, string url, RawImage image, int index, Action<int, string, Texture2D> act)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
{
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
//Debug.LogError(url+" "+www.result);
act?.Invoke(index, url, null);
}
else
{
Texture2D tex2d = DownloadHandlerTexture.GetContent(www); //www.texture;
if (tex2d != null)
{
if (image != null)
{
image.texture = tex2d;
}
textures[id] = tex2d;
//将图片保存至缓存路径
byte[] pngData = tex2d.EncodeToPNG();//将材质压缩成byte流
File.WriteAllBytes(path + id, pngData);
}
act?.Invoke(index, url, tex2d);
}
}
}
private async Task DownloadImageRaw(string id, string url, RawImage image)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
if (www.result != UnityWebRequest.Result.Success)
{
if (image != null)
{
image.texture = null;
}
}
else
{
byte[] data = www.downloadHandler.data;
// 在解码前获取图片尺寸
var (originalWidth, originalHeight) = GetImageSize(data);
// 计算限制大小后的尺寸
var (targetWidth, targetHeight) = CalculateTargetSize(originalWidth, originalHeight, 100, 100);
// Debug.Log($"Image size before decode: {originalWidth}x{originalHeight}, target size: {targetWidth}x{targetHeight} from URL: {url}");
Texture2D tex2d = null;
if (IsWebP(data))
{
tex2d = DecodeWebP(data, targetWidth, targetHeight);
}
else
{
tex2d = new Texture2D(targetWidth, targetHeight);
tex2d.LoadImage(data);
}
if (tex2d != null)
{
if (image != null)
{
image.texture = tex2d;
}
if (!textures.ContainsKey(id))
{
textures[id] = tex2d;
}
byte[] pngData = tex2d.EncodeToPNG();
File.WriteAllBytes(path + id, pngData);
}
else
{
if (image != null)
{
image.texture = null;
}
}
}
}
}
// 计算目标尺寸,保持宽高比并限制最大尺寸
private (int width, int height) CalculateTargetSize(int originalWidth, int originalHeight, int maxWidth, int maxHeight)
{
if (originalWidth <= 0 || originalHeight <= 0)
return (2, 2); // 默认最小尺寸
if (originalWidth <= maxWidth && originalHeight <= maxHeight)
return (originalWidth, originalHeight); // 如果原始尺寸已经在限制范围内,直接使用
float ratio = Mathf.Min(
maxWidth / (float)originalWidth,
maxHeight / (float)originalHeight
);
int targetWidth = Mathf.Max(2, Mathf.RoundToInt(originalWidth * ratio));
int targetHeight = Mathf.Max(2, Mathf.RoundToInt(originalHeight * ratio));
return (targetWidth, targetHeight);
}
// 检查是否是WebP格式
private bool IsWebP(byte[] data)
{
if (data.Length < 12) return false;
// WebP文件头标识"RIFF" + 4字节 + "WEBP"
return data[0] == 'R' && data[1] == 'I' && data[2] == 'F' && data[3] == 'F'
&& data[8] == 'W' && data[9] == 'E' && data[10] == 'B' && data[11] == 'P';
}
// 使用SimpleWebP解码WebP图片
private Texture2D DecodeWebP(byte[] data, int width, int height)
{
try
{
// 使用SimpleWebP插件解码
// Texture2D texture = SimpleWebP.Load(data);
// var texutre = Texture2DExt.CreateTexture2DFromWebP(data,false,false,(e)=>{});
Texture2D texture = new Texture2D(width, height);
texture.LoadWebP(data, out Error error);
return texture;
}
catch (Exception e)
{
Debug.LogError($"WebP decode error: {e.Message}");
return null;
}
}
// 这里有很大的GC隐患概率卡顿的问题在这
IEnumerator LoadLocalImageRaw2(string id, string url, RawImage image, int index, Action<int, string, Texture2D> act)
{
string filePath = "file:///" + path + id;
//Debug.LogError(filePath);
//WWW www = new WWW(filePath);
//yield return www;
//Texture2D texture = www.texture;
//textures[id] = texture;
////image.texture = texture;
//act?.Invoke(index, url, texture);
//www.Dispose();
//string filePath = path + url.GetHashCode();
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
yield return www.SendWebRequest();
Texture2D texture = DownloadHandlerTexture.GetContent(www);
textures[id] = texture;
//image.texture = texture;
act?.Invoke(index, url, texture);
}
}
// 这里有很大的GC隐患概率卡顿的问题在这
private async Task LoadLocalImageRaw(string id, string url, RawImage image)
{
string filePath = "file:///" + path + id;
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (!textures.ContainsKey(id))
{
textures[id] = texture;
}
if (image != null)
{
image.texture = texture;
}
}
}
public string path
{
get
{
//pc,ios //android :jar:file//
return Application.persistentDataPath + "/ImageCache/";
}
}
public async Task PreCacheImage(string url)
{
// 神秘人头像不缓存
if (url == "smr")
{
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
// 图像已经缓存,无需再次下载
return;
}
if (!File.Exists(path + id))
{
await DownloadImageRaw(id, url, null);
}
else
{
await LoadLocalImageRaw(id, url, null);
}
}
private (int width, int height) GetImageSize(byte[] data)
{
if (IsWebP(data))
{
return GetWebPSize(data);
}
else if (IsPNG(data))
{
return GetPNGSize(data);
}
else if (IsJPG(data))
{
return GetJPGSize(data);
}
return (0, 0);
}
private bool IsPNG(byte[] data)
{
if (data.Length < 8) return false;
return data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47;
}
private (int width, int height) GetPNGSize(byte[] data)
{
if (data.Length < 24) return (0, 0);
int width = (data[16] << 24) | (data[17] << 16) | (data[18] << 8) | data[19];
int height = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
return (width, height);
}
private bool IsJPG(byte[] data)
{
if (data.Length < 2) return false;
return data[0] == 0xFF && data[1] == 0xD8;
}
private (int width, int height) GetJPGSize(byte[] data)
{
int pos = 2;
while (pos < data.Length - 2)
{
if (data[pos] != 0xFF) return (0, 0);
if (data[pos + 1] == 0xC0 || data[pos + 1] == 0xC2)
{
int height = (data[pos + 5] << 8) | data[pos + 6];
int width = (data[pos + 7] << 8) | data[pos + 8];
return (width, height);
}
pos += 2 + ((data[pos + 2] << 8) | data[pos + 3]);
}
return (0, 0);
}
private (int width, int height) GetWebPSize(byte[] data)
{
if (data.Length < 30) return (0, 0);
// WebP VP8
if (data[12] == 'V' && data[13] == 'P' && data[14] == '8')
{
int width = (data[26] | (data[27] << 8)) & 0x3FFF;
int height = (data[28] | (data[29] << 8)) & 0x3FFF;
return (width, height);
}
return (0, 0);
}
private async Task DownloadImageSprite(string id, string url, SpriteRenderer spriteRenderer)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
if (www.result != UnityWebRequest.Result.Success)
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = null;
}
}
else
{
byte[] data = www.downloadHandler.data;
Texture2D tex2d = new Texture2D(2, 2);
tex2d.LoadImage(data);
if (tex2d != null)
{
if (spriteRenderer != null)
{
var sprite = Sprite.Create(tex2d, new Rect(0, 0, tex2d.width, tex2d.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
if (!textures.ContainsKey(id))
{
textures[id] = tex2d;
}
byte[] pngData = tex2d.EncodeToPNG();
File.WriteAllBytes(path + id, pngData);
}
else
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = null;
}
}
}
}
}
private async Task LoadLocalImageSprite(string id, string url, SpriteRenderer spriteRenderer)
{
string filePath = "file:///" + path + id;
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (!textures.ContainsKey(id))
{
textures[id] = texture;
}
if (spriteRenderer != null)
{
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
}
}
public void SetSyncImage(string url, RawImage image)
{
if (url == "smr")
{
GameModule.Resource.LoadAsset<Texture2D>("smr", (tex) =>
{
if (image != null)
{
image.texture = tex;
}
});
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
if (image != null)
{
image.texture = textures[id];
}
return;
}
if (!File.Exists(path + id))
{
DownloadImageRawSync(id, url, image);
}
else
{
LoadLocalImageRawSync(id, url, image);
}
}
private void DownloadImageRawSync(string id, string url, RawImage image)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
while (!www.isDone) { }
if (www.result != UnityWebRequest.Result.Success)
{
if (image != null)
{
image.texture = null;
}
}
else
{
byte[] data = www.downloadHandler.data;
Texture2D tex2d = new Texture2D(2, 2);
tex2d.LoadImage(data);
if (tex2d != null)
{
if (image != null)
{
image.texture = tex2d;
}
if (!textures.ContainsKey(id))
{
textures[id] = tex2d;
}
byte[] pngData = tex2d.EncodeToPNG();
File.WriteAllBytes(path + id, pngData);
}
else
{
if (image != null)
{
image.texture = null;
}
}
}
}
}
private void LoadLocalImageRawSync(string id, string url, RawImage image)
{
string filePath = "file:///" + path + id;
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
www.SendWebRequest();
while (!www.isDone) { }
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (!textures.ContainsKey(id))
{
textures[id] = texture;
}
if (image != null)
{
image.texture = texture;
}
}
}
public void SetSyncImage(string url, SpriteRenderer spriteRenderer)
{
if (url == "smr")
{
GameModule.Resource.LoadAsset<Texture2D>("smr", (tex) =>
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
});
return;
}
var id = GetBigMd5(url);
if (textures.ContainsKey(id))
{
if (spriteRenderer != null)
{
var tex = textures[id];
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
return;
}
if (!File.Exists(path + id))
{
DownloadImageSpriteSync(id, url, spriteRenderer);
}
else
{
LoadLocalImageSpriteSync(id, url, spriteRenderer);
}
}
private void DownloadImageSpriteSync(string id, string url, SpriteRenderer spriteRenderer)
{
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
while (!www.isDone) { }
if (www.result != UnityWebRequest.Result.Success)
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = null;
}
}
else
{
byte[] data = www.downloadHandler.data;
Texture2D tex2d = new Texture2D(2, 2);
tex2d.LoadImage(data);
if (tex2d != null)
{
if (spriteRenderer != null)
{
var sprite = Sprite.Create(tex2d, new Rect(0, 0, tex2d.width, tex2d.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
if (!textures.ContainsKey(id))
{
textures[id] = tex2d;
}
byte[] pngData = tex2d.EncodeToPNG();
File.WriteAllBytes(path + id, pngData);
}
else
{
if (spriteRenderer != null)
{
spriteRenderer.sprite = null;
}
}
}
}
}
private void LoadLocalImageSpriteSync(string id, string url, SpriteRenderer spriteRenderer)
{
string filePath = "file:///" + path + id;
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
www.SendWebRequest();
while (!www.isDone) { }
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (!textures.ContainsKey(id))
{
textures[id] = texture;
}
if (spriteRenderer != null)
{
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
sprite.name = id;
spriteRenderer.sprite = sprite;
}
}
}
private async Task DownloadImageForImage(string id, string url, Image image)
{
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
if (www.result != UnityWebRequest.Result.Success)
{
if (image != null)
{
image.sprite = null;
}
}
else
{
byte[] data = www.downloadHandler.data;
Texture2D tex2d = new Texture2D(2, 2);
tex2d.LoadImage(data);
if (tex2d != null)
{
if (image != null)
{
var sprite = Sprite.Create(tex2d, new Rect(0, 0, tex2d.width, tex2d.height), new Vector2(0.5f, 0.5f));
sprite.name = id; // 设置Sprite的名称
image.sprite = sprite;
}
if (!textures.ContainsKey(id))
{
textures[id] = tex2d;
}
byte[] pngData = tex2d.EncodeToPNG();
File.WriteAllBytes(GetFilePath(id), pngData);
}
else
{
if (image != null)
{
image.sprite = null;
}
}
}
}
}
private async Task LoadLocalImageForImage(string id, string url, Image image)
{
string filePath = "file:///" + GetFilePath(id);
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(filePath))
{
var asyncOp = www.SendWebRequest();
while (!asyncOp.isDone)
{
await Task.Yield();
}
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (!textures.ContainsKey(id))
{
textures[id] = texture;
}
if (image != null)
{
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
sprite.name = id; // 设置Sprite的名称
image.sprite = sprite;
}
}
}
private string GetFilePath(string id)
{
return path + id;
}
}