源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
18 KiB

  1. #if UNITY_EDITOR
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Runtime.Serialization;
  7. using LuaFramework;
  8. using LuaInterface;
  9. using UnityEngine;
  10. using UnityEngine.SceneManagement;
  11. using UnityEngine.Video;
  12. public class ResourceManagerEx : ILocalResLoader
  13. {
  14. ResourceManager mgr;
  15. FilePathRuleInfo pathRules;
  16. Dictionary<string,float> resLoadedTime;
  17. Dictionary<string,string> cachePaths;
  18. string rulePath = Application.dataPath + "/FilePathRule.json";
  19. string cacheFilePath = Application.dataPath + "/FilePathCache.txt";
  20. public void Init(ResourceManager mgr)
  21. {
  22. this.mgr = mgr;
  23. resLoadedTime = new Dictionary<string,float>();
  24. if (File.Exists(rulePath))
  25. {
  26. var infoContent = File.ReadAllText(rulePath);
  27. pathRules = JsonUtility.FromJson<FilePathRuleInfo>(infoContent);
  28. }
  29. if (AppConst.IsUseLocalPathCache)
  30. {
  31. cachePaths = new Dictionary<string,string>();
  32. if (File.Exists(cacheFilePath))
  33. {
  34. var infoContent = File.ReadAllLines(cacheFilePath);
  35. foreach (var item in infoContent)
  36. {
  37. var kvParts = item.Split(',');
  38. cachePaths.Add(kvParts[0], kvParts[1]);
  39. }
  40. }
  41. }
  42. }
  43. public void OnDestroy()
  44. {
  45. if (AppConst.IsUseLocalPathCache)
  46. {
  47. List<string> cacheList = new List<string>();
  48. foreach (var item in cachePaths)
  49. {
  50. cacheList.Add(item.Key+","+item.Value);
  51. }
  52. File.WriteAllLines(cacheFilePath, cacheList.ToArray());
  53. }
  54. }
  55. public bool Load(string abName, string[] assetNames, Type type, Action<UnityEngine.Object[]> action = null, LuaFunction func = null, uint level = 0)
  56. {
  57. if (assetNames.Length==0)
  58. return false;
  59. if (abName.EndsWith(AppConst.ExtName))
  60. abName = abName.Substring(0, abName.Length-AppConst.ExtName.Length);
  61. assetNames = HandleMultipleRes(assetNames);
  62. if (assetNames.Length > 1)
  63. {
  64. //同时加载多个文件
  65. LoadMultipleAssetsInLocal(abName, assetNames, type, action, func, level);
  66. return true;
  67. }
  68. var filePath = GetRealPath(abName, assetNames[0], type);
  69. if (filePath == "")
  70. return false;
  71. mgr.StartCoroutine(LoadAssetInLocal(filePath, abName, assetNames[0], type, action, func));
  72. return true;
  73. }
  74. IEnumerator LoadAssetInLocal(string filePath, string abName, string resName, Type type, Action<UnityEngine.Object[]> action = null, LuaFunction func = null)
  75. {
  76. //如果之前已经加载过的话就不用等到下一帧才加载成功
  77. var hasLoaded = resLoadedTime.ContainsKey(filePath.ToLowerInvariant());
  78. if (!hasLoaded)
  79. yield return new WaitForSeconds(0.01f);
  80. UnityEngine.Object res = UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, type);
  81. if (res != null)
  82. {
  83. if (resLoadedTime.ContainsKey(filePath.ToLowerInvariant()))
  84. resLoadedTime[filePath.ToLowerInvariant()] = Time.time;
  85. else
  86. resLoadedTime.Add(filePath.ToLowerInvariant(), Time.time);
  87. if (func != null)
  88. {
  89. List<UnityEngine.Object> list = new List<UnityEngine.Object>();
  90. list.Add(res);
  91. object[] args = new object[] { list.ToArray() };
  92. func.Call(args);
  93. func.Dispose();
  94. func = null;
  95. }
  96. else if (action != null)
  97. {
  98. List<UnityEngine.Object> list = new List<UnityEngine.Object>();
  99. list.Add(res);
  100. UnityEngine.Object[] args = list.ToArray();
  101. action(args);
  102. }
  103. }
  104. else
  105. {
  106. Debug.Log("ResourceManagerEx:LoadAssetInLocal Error:cannot find file:" + filePath+" ab:"+abName+" res:"+resName);
  107. }
  108. yield return null;
  109. }
  110. void LoadMultipleAssetsInLocal(string abName, string[] assetNames, Type type, Action<UnityEngine.Object[]> action = null, LuaFunction func = null, uint level = 0)
  111. {
  112. List<UnityEngine.Object> list = new List<UnityEngine.Object>();
  113. foreach (var resName in assetNames)
  114. {
  115. var filePath = GetRealPath(abName, resName, type);
  116. UnityEngine.Object res = UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, type);
  117. // Debug.Log("LoadMultipleAssetsInLocal res : "+(res!=null)+" file:"+filePath+" ab:"+abName+" res:"+resName);
  118. list.Add(res);//不管是否为null都要放进去
  119. if (res != null)
  120. {
  121. if (resLoadedTime.ContainsKey(filePath.ToLowerInvariant()))
  122. resLoadedTime[filePath.ToLowerInvariant()] = Time.time;
  123. else
  124. resLoadedTime.Add(filePath.ToLowerInvariant(), Time.time);
  125. }
  126. else
  127. {
  128. Debug.Log("ResourceManagerEx:LoadMultipleAssetsInLocal Error:cannot find file:" + filePath+" ab:"+abName+" res:"+resName);
  129. }
  130. }
  131. if (func != null)
  132. {
  133. object[] args = new object[] { list.ToArray() };
  134. func.Call(args);
  135. func.Dispose();
  136. func = null;
  137. }
  138. else if (action != null)
  139. {
  140. UnityEngine.Object[] args = list.ToArray();
  141. action(args);
  142. }
  143. }
  144. //因为传入的assetNames可能是{"1.png,2.png","3.png","4.png"},注意1和2是连在一起的,所以需要转化为单独元素的列表:{"1.png","2.png","3.png","4.png"}
  145. string[] HandleMultipleRes(string[] assetNames)
  146. {
  147. var hasMultiResInOne = false;
  148. foreach (var names in assetNames)
  149. {
  150. if (names.IndexOf(',')!=-1)
  151. {
  152. hasMultiResInOne = true;
  153. break;
  154. }
  155. }
  156. if (hasMultiResInOne)
  157. {
  158. List<string> realResList = new List<string>();
  159. foreach (var names in assetNames)
  160. {
  161. if (names.IndexOf(',')!=-1)
  162. {
  163. var parts = names.Split(',');
  164. foreach (var part in parts)
  165. {
  166. realResList.Add(part);
  167. }
  168. }
  169. else
  170. {
  171. realResList.Add(names);
  172. }
  173. }
  174. assetNames = realResList.ToArray();
  175. }
  176. return assetNames;
  177. }
  178. private static string GetIconFilePathInDeep(string path, string[] abNames, string spriteName)
  179. {
  180. if (System.IO.Directory.Exists(path))
  181. {
  182. System.IO.DirectoryInfo direction = new System.IO.DirectoryInfo(path);
  183. System.IO.DirectoryInfo[] sub_directions = direction.GetDirectories();
  184. foreach (var dir in sub_directions)
  185. {
  186. string try_dir_path = path + dir.Name + "/";
  187. string result = try_dir_path + spriteName;
  188. if (dir.Name == abNames[1])
  189. {
  190. System.IO.DirectoryInfo try_dir = new System.IO.DirectoryInfo(try_dir_path);
  191. System.IO.FileInfo[] files = try_dir.GetFiles("*", System.IO.SearchOption.AllDirectories);
  192. for (int i = 0; i < files.Length; i++)
  193. {
  194. if (files[i].Name == (spriteName))
  195. {
  196. path = files[i].FullName;
  197. return path;
  198. }
  199. }
  200. }
  201. else
  202. {
  203. result = GetIconFilePathInDeep(try_dir_path, abNames, spriteName);
  204. if (result != "")
  205. return result;
  206. }
  207. }
  208. }
  209. return "";
  210. }
  211. static List<string> NoTextureFolder = new List<string> { "alphasingle", "alphaCommon", "alphaMain" };
  212. private string GetRealPath(string abName, string resName, Type type)
  213. {
  214. string path = "";
  215. do
  216. {
  217. var cacheKey = (abName+":"+resName).ToLowerInvariant();
  218. // Debug.Log("cachePaths.ContainsKey(cacheKey) : "+cachePaths.ContainsKey(cacheKey)+" key:"+cacheKey);
  219. if (AppConst.IsUseLocalPathCache && cachePaths.ContainsKey(cacheKey))
  220. {
  221. path = cachePaths[cacheKey];
  222. break;
  223. }
  224. var dotIndex = resName.IndexOf('.');
  225. if (dotIndex != -1)
  226. resName = resName.Substring(0, dotIndex);
  227. path = SearchInUI(abName, resName);
  228. if (path != "")
  229. break;
  230. path = SearchByRules(abName, resName);
  231. if (path != "")
  232. break;
  233. path = SearchInIcon(abName, resName);
  234. if (path != "")
  235. break;
  236. if (AppConst.UseLocalResource >= 2)
  237. {
  238. //这一步将从整个项目资源目录进行搜索,会很卡的,建议发现找不到资源时在FilePathRule.json文件增加搜索规则
  239. path = SearchInAll(abName, resName, type);
  240. if (path != "")
  241. break;
  242. }
  243. } while (false);
  244. var isFileExist = File.Exists(path);
  245. // Debug.Log("load local file failed : "+"isFileExist: "+isFileExist+" abName:"+abName+" res:"+assetNames[0]+" guess file:"+filePath);
  246. if (!isFileExist)
  247. {
  248. if (AppConst.PrintLoadLocalRes >= 1)
  249. {
  250. var isPrintStack = AppConst.PrintLoadLocalRes >= 2;
  251. string printContent = "load local file failed : "+"abName:"+abName+" res:"+resName+" guess file:"+path;
  252. if (isPrintStack)
  253. printContent += new System.Diagnostics.StackTrace().ToString();
  254. Debug.Log(printContent);
  255. }
  256. path = "";
  257. }
  258. if (path.IndexOf(':')!=-1)
  259. {
  260. path = path.Replace('\\', '/');
  261. path = UnityEditor.FileUtil.GetProjectRelativePath(path);
  262. }
  263. if (AppConst.IsUseLocalPathCache)
  264. {
  265. if (File.Exists(path))
  266. {
  267. var cacheKey = (abName+":"+resName).ToLowerInvariant();
  268. // if (cachePaths.ContainsKey(cacheKey))
  269. cachePaths[cacheKey] = path;
  270. // else
  271. // cachePaths.Add(cacheKey, path);
  272. }
  273. }
  274. return path;
  275. }
  276. private string SearchByRules(string abName, string resName)
  277. {
  278. foreach (var rule in pathRules.Rules)
  279. {
  280. if (rule.Type == "StartsWith")
  281. {
  282. if (abName.StartsWith(rule.Key))
  283. {
  284. foreach (var testPath in rule.Paths)
  285. {
  286. var realPath = string.Format(testPath, resName);
  287. if (File.Exists(realPath))
  288. return realPath;
  289. }
  290. }
  291. }
  292. }
  293. return "";
  294. }
  295. private string SearchInAll(string abName, string resName, Type type)
  296. {
  297. string typeName = GetTypeName(type);
  298. string findFilter = resName;
  299. if (typeName != "")
  300. findFilter += " t:" + typeName;
  301. string[] guids = UnityEditor.AssetDatabase.FindAssets(findFilter);
  302. var retNum = guids.Length;
  303. // Debug.Log(" findFilter : "+findFilter+" retNum:"+retNum+" typeName:"+typeName);
  304. if (retNum == 1)
  305. {
  306. return UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
  307. }
  308. if (retNum > 1)
  309. {
  310. foreach (var retPathUID in guids)
  311. {
  312. var retPath = UnityEditor.AssetDatabase.GUIDToAssetPath(retPathUID);
  313. // Debug.Log(retPath+" isEndWith:"+retPath.EndsWith(resName+"."+typeName.ToLowerInvariant()));
  314. var fileSubffix = GetTypeFileSubffix(type);
  315. if (retPath.ToLowerInvariant().EndsWith((resName+fileSubffix).ToLowerInvariant()))
  316. return retPath;
  317. }
  318. }
  319. return "";
  320. }
  321. private string GetTypeName(Type type)
  322. {
  323. if (type == typeof(GameObject))
  324. return "Prefab";
  325. else if (type == typeof(Sprite))
  326. return "Sprite";
  327. else if (type == typeof(Texture))
  328. return "Texture";
  329. else if (type == typeof(Mesh))
  330. return "Mesh";
  331. else if (type == typeof(Shader))
  332. return "Shader";
  333. else if (type == typeof(Scene))
  334. return "Scene";
  335. else if (type == typeof(Font))
  336. return "Font";
  337. else if (type == typeof(Material))
  338. return "Material";
  339. else if (type == typeof(AudioClip))
  340. return "AudioClip";
  341. return "";
  342. }
  343. private string GetTypeFileSubffix(Type type)
  344. {
  345. if (type == typeof(GameObject))
  346. return ".prefab";
  347. else if (type == typeof(Sprite))
  348. return ".png";
  349. else if (type == typeof(Texture))
  350. return ".jpg";
  351. else if (type == typeof(Mesh))
  352. return ".fbx";
  353. else if (type == typeof(Shader))
  354. return ".shader";
  355. else if (type == typeof(Scene))
  356. return ".scene";
  357. else if (type == typeof(Font))
  358. return ".fnt";
  359. else if (type == typeof(Material))
  360. return ".mat";
  361. else if (type == typeof(AudioClip))
  362. return ".ogg";
  363. return "";
  364. }
  365. private string SearchInIcon(string abName, string resName)
  366. {
  367. if (abName.StartsWith("icon_"))
  368. {
  369. string[] path_fix = abName.Split('_');
  370. if (path_fix.Length >= 2)
  371. {
  372. string try_path = "Assets/LuaFramework/AssetBundleRes/iconjpg/" + resName;
  373. if (!resName.EndsWith("jpg"))
  374. try_path += ".jpg";
  375. //Debug.Log("iconjpg try_path : "+try_path);
  376. if (File.Exists(try_path))
  377. {
  378. return try_path;
  379. }
  380. else
  381. {
  382. string folder_str = path_fix[1];
  383. try_path = "Assets/LuaFramework/AssetBundleRes/icon/" + folder_str + "/" + resName;
  384. if (!resName.EndsWith(".png"))
  385. resName += ".png";
  386. //Debug.Log("icon try_path : "+try_path);
  387. if (File.Exists(try_path))
  388. {
  389. return try_path;
  390. }
  391. else
  392. {
  393. try_path = "Assets/LuaFramework/AssetBundleRes/icon/" + folder_str + "/necessaryBg/" + resName;
  394. if (!resName.EndsWith(".png"))
  395. resName += ".png";
  396. if (File.Exists(try_path))
  397. {
  398. return try_path;
  399. }
  400. else
  401. {
  402. try_path = GetIconFilePathInDeep("Assets/LuaFramework/AssetBundleRes/icon/", path_fix, resName);
  403. if (try_path != "")
  404. {
  405. if (try_path.IndexOf(':') != -1)
  406. try_path = UnityEditor.FileUtil.GetProjectRelativePath(try_path);
  407. return try_path;
  408. }
  409. }
  410. }
  411. }
  412. }
  413. }
  414. return "";
  415. }
  416. private string SearchInUI(string abName, string resName)
  417. {
  418. string path = "";
  419. bool is_no_texture_folder = false;
  420. foreach (var item in NoTextureFolder)
  421. {
  422. if (abName.StartsWith(item))
  423. {
  424. is_no_texture_folder = true;
  425. path = "Assets/LuaFramework/AssetBundleRes/ui/" + item + "/" + resName + ".png";
  426. //Debug.Log("NoTextureFolder abName:"+abName+" resName:"+resName+" path:"+path);
  427. return path;
  428. }
  429. }
  430. if (!is_no_texture_folder)
  431. {
  432. if (abName.EndsWith("_asset"))
  433. {
  434. string folder_name = abName.Substring(0, abName.Length - 6);
  435. string folder_path = "Assets/LuaFramework/AssetBundleRes/ui/" + folder_name + "/texture/";
  436. path = folder_path + resName;
  437. if (File.Exists(path + ".png"))
  438. {
  439. return path + ".png";
  440. }
  441. else if (File.Exists(path + ".jpg"))
  442. {
  443. return path + ".jpg";
  444. }
  445. else
  446. {
  447. if (Directory.Exists(folder_path))
  448. {
  449. DirectoryInfo direction = new DirectoryInfo(folder_path);
  450. FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
  451. for (int i = 0; i < files.Length; i++)
  452. {
  453. // if (files[i].Name.StartsWith(resName))
  454. if (files[i].Name == (resName+".png"))
  455. {
  456. path = files[i].FullName;
  457. return path;
  458. }
  459. }
  460. }
  461. }
  462. }
  463. else
  464. {
  465. string folder_path = "Assets/LuaFramework/AssetBundleRes/ui/" + abName + "/prefab/";
  466. path = folder_path + resName + ".prefab";
  467. if (File.Exists(path))
  468. return path;
  469. }
  470. }
  471. return "";
  472. }
  473. }
  474. [Serializable]
  475. public class FilePathRule
  476. {
  477. public string Type;
  478. public string Key;
  479. public List<string> Paths;
  480. }
  481. [Serializable]
  482. public class FilePathRuleInfo
  483. {
  484. public List<FilePathRule> Rules;
  485. }
  486. #endif