#if UNITY_WEBGL using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using UnityEngine; using XericLibrary.Runtime.MacroLibrary; using XericLibrary.Runtime.Type; using XericLibrary.Runtime.Type.Base; namespace XericLibrary.Runtime.MacroLibrary { /// /// Web 平台文件句柄。 /// public class WebGLHandle : MacroFile.CrossPlatformFileHandle { public override string PlatformName => "WebGL"; public static WebGLHandle handle = new WebGLHandle(); public static float GlobalTimeout = 10f; public float Timeout = -1f; private float timeout => Timeout >= 0 ? Timeout : GlobalTimeout; public WebGLHandle() : base(RuntimePlatform.WebGLPlayer) { if (handle == null) handle = this; } #if XERIC_WEBGL_DOWNLOAD [DllImport("__Internal")] private static extern void Download(string base64str, string fileName); #endif #if XERIC_WEBGL_FILEBROWSER [DllImport("__Internal")] private static extern void OpenFileDialog(string gameObjectName, string callbackMethodName); [DllImport("__Internal")] private static extern void OpenFileDialogBinary(string gameObjectName, string callbackMethodName); #endif #if XERIC_WEBGL_JSBRIDGE /// /// 从 JS 端发送消息到 Unity(对应 xeric-jsbridge.js 中的 SendToUnity) /// public static void SendToUnity(string gameObject, string method, string message) { #if UNITY_WEBGL && !UNITY_EDITOR SendMessageToUnity(gameObject, method, message); #else // Editor 回退:尝试直接查找并调用 var go = GameObject.Find(gameObject); if (go != null) go.SendMessage(method, message, SendMessageOptions.DontRequireReceiver); #endif } [DllImport("__Internal")] private static extern void SendMessageToUnity(string gameObject, string method, string message); /// /// 通知 JS 端 Canvas 获得焦点(Unity 可捕获输入) /// public static void NotifyCanvasFocus() { // JS 端 OnCanvasFocus() 会反向调用 Unity.SendMessage } /// /// 通知 JS 端 Canvas 失去焦点(前端可处理输入) /// public static void NotifyCanvasBlur() { // JS 端 OnCanvasBlur() 会反向调用 Unity.SendMessage } #endif public override bool ReadTextFromFile(string absolutePathname, out string content) { var waitFlag = false; var result = string.Empty; SingleMonoBase.GlobalInstance.DirectlyLoadFile(absolutePathname, s => result = s, s => { XericLogger.CCError($"WebGl文件同步加载失败:{s}"); }, () => { waitFlag = true; }); // 等待文件加载完成 while (!waitFlag) { // 让出控制权,避免完全阻塞 Debug.LogWarning("不建议在WebGl端使用同步文件读取方式,当前已让渡主线程控制权"); Thread.Sleep(0); } content = result; return waitFlag; } #if XERIC_WEBGL_DOWNLOAD public override bool WriteTextIntoFile(string absolutePathname, string content) { try { Download(content, absolutePathname); return true; } catch (Exception e) { Debug.LogError($"无法下载文件{absolutePathname}:{e.Message}"); return false; } } #endif public override async Task AsyncReadTextFromFile(string absolutePathname, Action complete, Action loadError) { var waitFlag = false; var result = false; SingleMonoBase.GlobalInstance.DirectlyLoadFile(absolutePathname, s => { result = true; complete?.Invoke(s); }, loadError, () => { waitFlag = true; }); await MacroAsync.WaitUntil(() => waitFlag, () => "WebGl文件读取失败", timeout); return result; } #if XERIC_WEBGL_DOWNLOAD public override async Task AsyncWriteTextIntoFile(string absolutePathname, string content, Action complete, Action loadError) { await Task.Yield(); if (WriteTextIntoFile(absolutePathname, content)) { complete?.Invoke(); } else { loadError?.Invoke("WebGL文件写入失败"); XericLogger.CCError("WebGL文件写入失败"); } await Task.CompletedTask; return false; } #endif public override string CombinePath(string pathA, string pathB) { try { if (!pathA.EndsWith("/")) // 确保路径以斜杠结尾 pathA += "/"; var uri = new Uri(new Uri(pathA, UriKind.Absolute), new Uri(pathB, UriKind.RelativeOrAbsolute)); /* 不能使用uri自己的 * 比如 uri.IsAbsoluteUri ? uri.AbsolutePath : uri.LocalPath; * 在这种情况时: * http://192.168.0.39:8080/DGJ/StreamingAssets/ + UriConfig.json * 结果是 => /DGJ/StreamingAssets/UriConfig.json 用是AbsolutePath * 所以要么直接A + B * 要么直接Tostring。 */ Debug.Log($"Web路径拼接处理结果浏览:{pathA}\n{pathB}\n{uri}\n"); return uri.ToString(); } catch (UriFormatException ex) { // 处理URI格式错误 XericLogger.CCError($"Web路径拼接失败: {ex.Message}"); return string.Empty; } } } } #endif