using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; using TriLibCore; using TriLibCore.SFB; using UnityEngine; using UnityEngine.Networking; using ZXL.Helper; namespace ZXL.Manager { class AssetManager : Manager { private Dictionary> assets; private AssetConfigCas cas; private Camera renderCamera; RenderTexture renderTexture; Texture2D capturedImage; private GameObject object_M; /// /// 上传模型成功的回调 /// public Action addItemAction; /// /// 初始化成功的回调 /// public Action initAction; public override void OnAwake() { base.OnAwake(); assets = new Dictionary>(); assets.Add(AssetTag.公司.ToString(), new Dictionary()); assets.Add(AssetTag.个人.ToString(), new Dictionary()); assets.Add(AssetTag.项目.ToString(), new Dictionary()); if (File.Exists(ZConst.AssetConfigPath)) { var text = File.ReadAllText(ZConst.AssetConfigPath); cas = JsonConvert.DeserializeObject(text); } if (cas == null) { cas = new AssetConfigCas(); cas.AssetConfigCa = new Dictionary>(); cas.AssetConfigCa.Add("公司", new Dictionary()); cas.AssetConfigCa.Add("个人", new Dictionary()); cas.AssetConfigCa.Add("项目", new Dictionary()); } object_M = new GameObject("object_M"); object_M.SetActive(false); StartCoroutine(Init()); } public void SetCamera(Camera camera) { renderCamera = camera; // renderTexture = new RenderTexture(renderCamera.pixelWidth, renderCamera.pixelHeight, 24); renderTexture = renderCamera.targetTexture; } #region Config (完成) /// /// init config /// /// /// IEnumerator Init() { foreach (var dic in cas.AssetConfigCa.Values) { foreach (var ca in dic.Values) { var context = AssetLoader.LoadModelFromFile(ca.AssetPath, null, null, OnProgress, null, object_M); while (true) { if (context.LoadingProgress >= 1) break; yield return null; } context.WrapperGameObject.name = ca.Name; var sprite = LoadSprite(ca.SpritePath); var assetInfo = new AssetInfo() { Name = ca.Name, GameObject = context.WrapperGameObject, Sprite = sprite, AssetTag = ca.AssetTag, Config = ca }; if (assets.TryGetValue(ca.AssetTag, out Dictionary infos)) { infos.Add(ca.Name, assetInfo); Debug.Log($"init add {ca.Name} !"); } } } initAction?.Invoke(); void OnProgress(AssetLoaderContext arg1, float arg2) { } } /// /// update config asset data /// private void UpdateAssetData() { var s = JsonConvert.SerializeObject(cas); if (!File.Exists(ZConst.AssetConfigPath)) File.CreateText(ZConst.AssetConfigPath).Dispose(); File.WriteAllText(ZConst.AssetConfigPath, s); } /// /// add config item /// /// /// /// /// void AddConfig(AssetConfigCa configCa) { cas.AssetConfigCa[configCa.AssetTag].Add(configCa.Name, configCa); UpdateAssetData(); } void DeleteConfig(string assetTag, string configName) { cas.AssetConfigCa[assetTag].Remove(configName); UpdateAssetData(); } #endregion #region AssetInfo #region 上传(完成) /// /// upload and load to scene /// /// /// /// /// public void PushAsset(string title, GameObject wrapperGameObject, AssetTag assetTag, Action callback = null) { StartCoroutine(PushModel_I(title, wrapperGameObject, assetTag, callback)); } IEnumerator PushModel_I(string title, GameObject wrapperGameObject, AssetTag assetTag, Action callback = null) { string exten = ""; var paths = StandaloneFileBrowser.OpenFilePanel(title ?? "Open File", "", exten, false); if (paths.Count == 0) { Debug.Log("Selected file: " + paths[0].Name); yield break; } else { var strings = paths[0].Name.Split("/"); var name = strings[strings.Length - 1]; string savePathWithName; switch (assetTag) { case AssetTag.公司: savePathWithName = $"{ZConst.AssetRootPath_GS}/{name}"; break; case AssetTag.个人: savePathWithName = $"{ZConst.AssetRootPath_GR}/{name}"; break; case AssetTag.项目: savePathWithName = $"{ZConst.AssetRootPath_XM}/{name}"; break; default: throw new ArgumentOutOfRangeException(nameof(assetTag), assetTag, null); } tempFilePath = savePathWithName; if (File.Exists(savePathWithName)) { File.Delete(savePathWithName); } UnityWebRequest request = UnityWebRequest.Get(paths[0].Name); request.SendWebRequest(); while (true) { if (request.isDone) { byte[] results = request.downloadHandler.data; // 通过模型数据写入本地 FileInfo file = new FileInfo(savePathWithName); if (file.Directory != null) file.Directory.Create(); Stream sw; sw = file.Create(); sw.Write(results, 0, results.Length); sw.Close(); sw.Dispose(); break; } else if (request.isNetworkError) { Debug.Log("Download Error:" + request.error); break; } yield return new WaitForSeconds(Time.deltaTime); } GameObject obj = null; bool isTrue = false; var loadModelFromFile = AssetLoader.LoadModelFromFile(savePathWithName, null, null, OnProgress, null, wrapperGameObject); while (!isTrue) { Debug.Log(loadModelFromFile.LoadingProgress); yield return null; } obj = loadModelFromFile.RootGameObject; obj.transform.SetWithChildLayer(LayerMask.NameToLayer("PushModel")); tempGameObject = obj; var split = name.Split(".")[0]; callback?.Invoke(split, savePathWithName, obj); yield break; void OnProgress(AssetLoaderContext arg1, float arg2) { if (arg2.Equals(1f) || arg1.RootGameObject!=null) { isTrue = true; } } } } string tempFilePath; GameObject tempGameObject; public void CancelAsset() { if (File.Exists(tempFilePath)) File.Delete(tempFilePath); GameObject.Destroy(tempGameObject); tempFilePath = null; tempGameObject = null; } #endregion #region 搜索 #endregion #region 删除(完成) public void DeleteAssets(AssetInfo info) { if (assets.TryGetValue(info.AssetTag, out var value)) { DeleteConfig(info.AssetTag, info.Name); value.Remove(info.Name); //TODO: is with delete asset ? var directoryInfo = new FileInfo(info.Config.AssetPath).Directory; directoryInfo?.Parent?.Delete(true); } } #endregion #region 重命名 (完成) public void RenameAsset(string assetTag, AssetInfo info, string newName) { string cstr = info.Name; info.Name = newName; var config = info.Config; if (config == null) throw new NullReferenceException(); config.Name = newName; var asset = FileHelper.RenameFile(config.AssetPath, newName); config.AssetPath = asset; asset = FileHelper.RenameFile(config.SpritePath, newName); config.SpritePath = asset; cas.AssetConfigCa[assetTag][cstr] = config; assets[assetTag][cstr] = info; UpdateAssetData(); } #endregion #region 拷贝 (完成) public void CopyAsset(string assetTag, AssetInfo info) { string cstr = info.Name; var configAssetPath = info.Config.AssetPath; FileHelper.CopyFile(configAssetPath); assets[assetTag][cstr] = info; cas.AssetConfigCa[assetTag][cstr] = info.Config; UpdateAssetData(); } #endregion #region 移动 public void MoveAsset(string oldPath, string newPath) { FileHelper.MoveDirectoryWithFiles(oldPath, newPath); } #endregion #region 筛选 #endregion #region Icon /// /// 更新图标 /// /// /// /// /// /// public void AddItemAndGenIcon(string fileName, string assetPathWithName, AssetTag assetTag, GameObject go) { var pngPath = Path.Combine(ZConst.AssetCacheIcon, fileName) + ".jpg"; var sprite = JT(pngPath); var tagStr = assetTag.ToString(); AssetConfigCa ca = new AssetConfigCa(); ca.Name = fileName; ca.AssetPath = assetPathWithName; ca.SpritePath = pngPath; ca.AssetTag = tagStr; var assetInfo = new AssetInfo() { Name = fileName, Sprite = sprite, GameObject = go, AssetTag = tagStr, Config = ca }; if (assets.TryGetValue(tagStr, out var value)) { if (value.TryAdd(fileName, assetInfo)) { AddConfig(ca); addItemAction?.Invoke(assetInfo); } value[fileName] = assetInfo; } } Sprite JT(string assetPathWithName) { // 创建一个 Texture2D 用来存储相机捕捉的画面 capturedImage = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false); // 从 RenderTexture 中读取像素数据到 Texture2D RenderTexture.active = renderTexture; capturedImage.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); capturedImage.Apply(); // 重置 RenderTexture 的激活状态 RenderTexture.active = null; // 此时 capturedImage 就包含了当前帧的画面,你可以进行保存或者其他操作 // 示例:保存为 PNG 文件 byte[] bytes = capturedImage.EncodeToJPG(); new FileInfo(assetPathWithName).Directory?.Create(); if (File.Exists(assetPathWithName)) File.Delete(assetPathWithName); System.IO.File.WriteAllBytes(assetPathWithName, bytes); // 清理资源 Destroy(capturedImage); var sprite = LoadSprite(assetPathWithName); return sprite; } Sprite LoadSprite(string assetPathWithName) { var bytes = File.ReadAllBytes(assetPathWithName); Texture2D texture2D = new Texture2D(10, 10); texture2D.LoadImage(bytes); Sprite sp = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), Vector2.zero); return sp; } #endregion #endregion public List GetAssets(AssetTag assetTag) { if (assets.TryGetValue(assetTag.ToString(), out var value)) { return value.Values.ToList(); } return null; } } [System.Serializable] public class AssetInfo { public string Name; public GameObject GameObject; public Sprite Sprite; public string AssetTag; public AssetConfigCa Config = new AssetConfigCa(); } [System.Serializable] public class AssetConfigCas { /// /// the first str is tag , /// the second str is fileName , /// no double names allowed /// public Dictionary> AssetConfigCa = new Dictionary>(); } [System.Serializable] public class AssetConfigCa { public string Name; public string AssetPath; public string SpritePath; public string AssetTag; } public enum AssetTag { 公司, 个人, 项目, } }