源战役客户端
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.

1271 lines
41 KiB

  1. /*
  2. Copyright (c) 2015-2016 topameng(topameng@qq.com)
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in all
  10. copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. */
  19. //打开开关没有写入导出列表的纯虚类自动跳过
  20. //#define JUMP_NODEFINED_ABSTRACT
  21. using UnityEngine;
  22. using UnityEditor;
  23. using System;
  24. using System.Collections;
  25. using System.Collections.Generic;
  26. using System.Reflection;
  27. using System.Text;
  28. using System.IO;
  29. using System.Diagnostics;
  30. using LuaInterface;
  31. using LuaFramework;
  32. using Object = UnityEngine.Object;
  33. using Debug = UnityEngine.Debug;
  34. using Debugger = LuaInterface.Debugger;
  35. using System.Threading;
  36. [InitializeOnLoad]
  37. public static class ToLuaMenu
  38. {
  39. //不需要导出或者无法导出的类型
  40. public static List<Type> dropType = new List<Type>
  41. {
  42. typeof(ValueType), //不需要
  43. #if !UNITY_5
  44. typeof(Motion), //很多平台只是空类
  45. #endif
  46. typeof(UnityEngine.YieldInstruction), //无需导出的类
  47. typeof(UnityEngine.WaitForEndOfFrame), //内部支持
  48. typeof(UnityEngine.WaitForFixedUpdate),
  49. typeof(UnityEngine.WaitForSeconds),
  50. typeof(UnityEngine.Mathf), //lua层支持
  51. typeof(Plane),
  52. typeof(LayerMask),
  53. typeof(Vector3),
  54. typeof(Vector4),
  55. typeof(Vector2),
  56. typeof(Quaternion),
  57. typeof(Ray),
  58. typeof(Bounds),
  59. typeof(Color),
  60. typeof(Touch),
  61. typeof(RaycastHit),
  62. typeof(TouchPhase),
  63. //typeof(LuaInterface.LuaOutMetatable), //手写支持
  64. typeof(LuaInterface.NullObject),
  65. typeof(System.Array),
  66. typeof(System.Reflection.MemberInfo),
  67. typeof(System.Reflection.BindingFlags),
  68. typeof(LuaInterface.LuaFunction),
  69. typeof(LuaInterface.LuaTable),
  70. typeof(LuaInterface.LuaThread),
  71. typeof(LuaInterface.LuaByteBuffer), //只是类型标识符
  72. //typeof(DelegateFactory), //无需导出,导出类支持lua函数转换为委托。如UIEventListener.OnClick(luafunc)
  73. };
  74. //可以导出的内部支持类型
  75. public static List<Type> baseType = new List<Type>
  76. {
  77. typeof(System.Object),
  78. typeof(System.Delegate),
  79. typeof(System.String),
  80. typeof(System.Enum),
  81. typeof(System.Type),
  82. typeof(System.Collections.IEnumerator),
  83. typeof(UnityEngine.Object),
  84. typeof(LuaInterface.EventObject),
  85. typeof(LuaInterface.LuaMethod),
  86. typeof(LuaInterface.LuaProperty),
  87. typeof(LuaInterface.LuaField),
  88. typeof(LuaInterface.LuaConstructor),
  89. };
  90. private static bool beAutoGen = false;
  91. private static bool beCheck = false; // 不检测自动生成交互接口文件
  92. static List<BindType> allTypes = new List<BindType>();
  93. static ToLuaMenu()
  94. {
  95. if (!beCheck)
  96. return;
  97. string dir = CustomSettings.saveDir;
  98. string[] files = Directory.GetFiles(dir, "*.cs", SearchOption.TopDirectoryOnly);
  99. if (files.Length < 3 && beCheck)
  100. {
  101. if (EditorUtility.DisplayDialog("自动生成", "点击确定自动生成常用类型注册文件, 也可通过菜单逐步完成此功能", "确定", "取消"))
  102. {
  103. beAutoGen = true;
  104. GenLuaDelegates();
  105. AssetDatabase.Refresh();
  106. GenerateClassWraps();
  107. GenLuaBinder();
  108. beAutoGen = false;
  109. }
  110. beCheck = false;
  111. }
  112. }
  113. static string RemoveNameSpace(string name, string space)
  114. {
  115. if (space != null)
  116. {
  117. name = name.Remove(0, space.Length + 1);
  118. }
  119. return name;
  120. }
  121. public class BindType
  122. {
  123. public string name; //类名称
  124. public Type type;
  125. public bool IsStatic;
  126. public string wrapName = ""; //产生的wrap文件名字
  127. public string libName = ""; //注册到lua的名字
  128. public Type baseType = null;
  129. public string nameSpace = null; //注册到lua的table层级
  130. public List<Type> extendList = new List<Type>();
  131. public BindType(Type t)
  132. {
  133. if (typeof(System.MulticastDelegate).IsAssignableFrom(t))
  134. {
  135. throw new NotSupportedException(string.Format("\nDon't export Delegate {0} as a class, register it in customDelegateList", LuaMisc.GetTypeName(t)));
  136. }
  137. //if (IsObsolete(t))
  138. //{
  139. // throw new Exception(string.Format("\n{0} is obsolete, don't export it!", LuaMisc.GetTypeName(t)));
  140. //}
  141. type = t;
  142. nameSpace = ToLuaExport.GetNameSpace(t, out libName);
  143. name = ToLuaExport.CombineTypeStr(nameSpace, libName);
  144. libName = ToLuaExport.ConvertToLibSign(libName);
  145. if (name == "object")
  146. {
  147. wrapName = "System_Object";
  148. name = "System.Object";
  149. }
  150. else if (name == "string")
  151. {
  152. wrapName = "System_String";
  153. name = "System.String";
  154. }
  155. else
  156. {
  157. wrapName = name.Replace('.', '_');
  158. wrapName = ToLuaExport.ConvertToLibSign(wrapName);
  159. }
  160. int index = CustomSettings.staticClassTypes.IndexOf(type);
  161. if (index >= 0 || (type.IsAbstract && type.IsSealed))
  162. {
  163. IsStatic = true;
  164. }
  165. baseType = LuaMisc.GetExportBaseType(type);
  166. }
  167. public BindType SetBaseType(Type t)
  168. {
  169. baseType = t;
  170. return this;
  171. }
  172. public BindType AddExtendType(Type t)
  173. {
  174. if (!extendList.Contains(t))
  175. {
  176. extendList.Add(t);
  177. }
  178. return this;
  179. }
  180. public BindType SetWrapName(string str)
  181. {
  182. wrapName = str;
  183. return this;
  184. }
  185. public BindType SetLibName(string str)
  186. {
  187. libName = str;
  188. return this;
  189. }
  190. public BindType SetNameSpace(string space)
  191. {
  192. nameSpace = space;
  193. return this;
  194. }
  195. public static bool IsObsolete(Type type)
  196. {
  197. object[] attrs = type.GetCustomAttributes(true);
  198. for (int j = 0; j < attrs.Length; j++)
  199. {
  200. Type t = attrs[j].GetType();
  201. if (t == typeof(System.ObsoleteAttribute) || t == typeof(NoToLuaAttribute) || t.Name == "MonoNotSupportedAttribute" || t.Name == "MonoTODOAttribute")
  202. {
  203. return true;
  204. }
  205. }
  206. return false;
  207. }
  208. }
  209. static void AutoAddBaseType(BindType bt, bool beDropBaseType)
  210. {
  211. Type t = bt.baseType;
  212. if (t == null)
  213. {
  214. return;
  215. }
  216. if (t.IsInterface)
  217. {
  218. Debugger.LogWarning("{0} has a base type {1} is Interface, use SetBaseType to jump it", bt.name, t.FullName);
  219. bt.baseType = t.BaseType;
  220. }
  221. else if (dropType.IndexOf(t) >= 0)
  222. {
  223. Debugger.LogWarning("{0} has a base type {1} is a drop type", bt.name, t.FullName);
  224. bt.baseType = t.BaseType;
  225. }
  226. else if (!beDropBaseType || baseType.IndexOf(t) < 0)
  227. {
  228. int index = allTypes.FindIndex((iter) => { return iter.type == t; });
  229. if (index < 0)
  230. {
  231. #if JUMP_NODEFINED_ABSTRACT
  232. if (t.IsAbstract && !t.IsSealed)
  233. {
  234. Debugger.LogWarning("not defined bindtype for {0}, it is abstract class, jump it, child class is {1}", t.FullName, bt.name);
  235. bt.baseType = t.BaseType;
  236. }
  237. else
  238. {
  239. Debugger.LogWarning("not defined bindtype for {0}, autogen it, child class is {1}", t.FullName, bt.name);
  240. bt = new BindType(t);
  241. allTypes.Add(bt);
  242. }
  243. #else
  244. Debugger.LogWarning("not defined bindtype for {0}, autogen it, child class is {1}", t.FullName, bt.name);
  245. bt = new BindType(t);
  246. allTypes.Add(bt);
  247. #endif
  248. }
  249. else
  250. {
  251. return;
  252. }
  253. }
  254. else
  255. {
  256. return;
  257. }
  258. AutoAddBaseType(bt, beDropBaseType);
  259. }
  260. static BindType[] GenBindTypes(BindType[] list, bool beDropBaseType = true)
  261. {
  262. allTypes = new List<BindType>(list);
  263. for (int i = 0; i < list.Length; i++)
  264. {
  265. for (int j = i + 1; j < list.Length; j++)
  266. {
  267. if (list[i].type == list[j].type)
  268. throw new NotSupportedException("Repeat BindType:" + list[i].type);
  269. }
  270. if (dropType.IndexOf(list[i].type) >= 0)
  271. {
  272. LogManager.LogWarning(list[i].type.FullName + " in dropType table, not need to export");
  273. allTypes.Remove(list[i]);
  274. continue;
  275. }
  276. else if (beDropBaseType && baseType.IndexOf(list[i].type) >= 0)
  277. {
  278. LogManager.LogWarning(list[i].type.FullName + " is Base Type, not need to export");
  279. allTypes.Remove(list[i]);
  280. continue;
  281. }
  282. else if (list[i].type.IsEnum)
  283. {
  284. continue;
  285. }
  286. AutoAddBaseType(list[i], beDropBaseType);
  287. }
  288. return allTypes.ToArray();
  289. }
  290. [MenuItem("Lua/Gen Lua Wrap Files", false, 1)]
  291. public static void GenerateClassWraps()
  292. {
  293. if (!beAutoGen && EditorApplication.isCompiling)
  294. {
  295. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  296. return;
  297. }
  298. if (!File.Exists(CustomSettings.saveDir))
  299. {
  300. Directory.CreateDirectory(CustomSettings.saveDir);
  301. }
  302. allTypes.Clear();
  303. BindType[] typeList = CustomSettings.customTypeList;
  304. BindType[] list = GenBindTypes(typeList);
  305. ToLuaExport.allTypes.AddRange(baseType);
  306. for (int i = 0; i < list.Length; i++)
  307. {
  308. ToLuaExport.allTypes.Add(list[i].type);
  309. }
  310. for (int i = 0; i < list.Length; i++)
  311. {
  312. ToLuaExport.Clear();
  313. ToLuaExport.className = list[i].name;
  314. ToLuaExport.type = list[i].type;
  315. ToLuaExport.isStaticClass = list[i].IsStatic;
  316. ToLuaExport.baseType = list[i].baseType;
  317. ToLuaExport.wrapClassName = list[i].wrapName;
  318. ToLuaExport.libClassName = list[i].libName;
  319. ToLuaExport.extendList = list[i].extendList;
  320. ToLuaExport.Generate(CustomSettings.saveDir);
  321. }
  322. LogManager.Log("Generate lua binding files over");
  323. ToLuaExport.allTypes.Clear();
  324. allTypes.Clear();
  325. AssetDatabase.Refresh();
  326. }
  327. static HashSet<Type> GetCustomTypeDelegates()
  328. {
  329. BindType[] list = CustomSettings.customTypeList;
  330. HashSet<Type> set = new HashSet<Type>();
  331. BindingFlags binding = BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.Instance;
  332. for (int i = 0; i < list.Length; i++)
  333. {
  334. Type type = list[i].type;
  335. FieldInfo[] fields = type.GetFields(BindingFlags.GetField | BindingFlags.SetField | binding);
  336. PropertyInfo[] props = type.GetProperties(BindingFlags.GetProperty | BindingFlags.SetProperty | binding);
  337. MethodInfo[] methods = null;
  338. if (type.IsInterface)
  339. {
  340. methods = type.GetMethods();
  341. }
  342. else
  343. {
  344. methods = type.GetMethods(BindingFlags.Instance | binding);
  345. }
  346. for (int j = 0; j < fields.Length; j++)
  347. {
  348. Type t = fields[j].FieldType;
  349. if (ToLuaExport.IsDelegateType(t))
  350. {
  351. set.Add(t);
  352. }
  353. }
  354. for (int j = 0; j < props.Length; j++)
  355. {
  356. Type t = props[j].PropertyType;
  357. if (ToLuaExport.IsDelegateType(t))
  358. {
  359. set.Add(t);
  360. }
  361. }
  362. for (int j = 0; j < methods.Length; j++)
  363. {
  364. MethodInfo m = methods[j];
  365. if (m.IsGenericMethod)
  366. {
  367. continue;
  368. }
  369. ParameterInfo[] pifs = m.GetParameters();
  370. for (int k = 0; k < pifs.Length; k++)
  371. {
  372. Type t = pifs[k].ParameterType;
  373. if (t.IsByRef) t = t.GetElementType();
  374. if (ToLuaExport.IsDelegateType(t))
  375. {
  376. set.Add(t);
  377. }
  378. }
  379. }
  380. }
  381. return set;
  382. }
  383. [MenuItem("Lua/Gen Lua Delegates", false, 2)]
  384. static void GenLuaDelegates()
  385. {
  386. if (!beAutoGen && EditorApplication.isCompiling)
  387. {
  388. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  389. return;
  390. }
  391. ToLuaExport.Clear();
  392. List<DelegateType> list = new List<DelegateType>();
  393. list.AddRange(CustomSettings.customDelegateList);
  394. HashSet<Type> set = GetCustomTypeDelegates();
  395. foreach (Type t in set)
  396. {
  397. if (null == list.Find((p) => { return p.type == t; }))
  398. {
  399. list.Add(new DelegateType(t));
  400. }
  401. }
  402. ToLuaExport.GenDelegates(list.ToArray());
  403. set.Clear();
  404. ToLuaExport.Clear();
  405. AssetDatabase.Refresh();
  406. LogManager.Log("Create lua delegate over");
  407. }
  408. static ToLuaTree<string> InitTree()
  409. {
  410. ToLuaTree<string> tree = new ToLuaTree<string>();
  411. ToLuaNode<string> root = tree.GetRoot();
  412. BindType[] list = GenBindTypes(CustomSettings.customTypeList);
  413. for (int i = 0; i < list.Length; i++)
  414. {
  415. string space = list[i].nameSpace;
  416. AddSpaceNameToTree(tree, root, space);
  417. }
  418. DelegateType[] dts = CustomSettings.customDelegateList;
  419. string str = null;
  420. for (int i = 0; i < dts.Length; i++)
  421. {
  422. string space = ToLuaExport.GetNameSpace(dts[i].type, out str);
  423. AddSpaceNameToTree(tree, root, space);
  424. }
  425. return tree;
  426. }
  427. static void AddSpaceNameToTree(ToLuaTree<string> tree, ToLuaNode<string> parent, string space)
  428. {
  429. if (space == null || space == string.Empty)
  430. {
  431. return;
  432. }
  433. string[] ns = space.Split(new char[] { '.' });
  434. for (int j = 0; j < ns.Length; j++)
  435. {
  436. List<ToLuaNode<string>> nodes = tree.Find((_t) => { return _t == ns[j]; }, j);
  437. if (nodes.Count == 0)
  438. {
  439. ToLuaNode<string> node = new ToLuaNode<string>();
  440. node.value = ns[j];
  441. parent.childs.Add(node);
  442. node.parent = parent;
  443. node.layer = j;
  444. parent = node;
  445. }
  446. else
  447. {
  448. bool flag = false;
  449. int index = 0;
  450. for (int i = 0; i < nodes.Count; i++)
  451. {
  452. int count = j;
  453. int size = j;
  454. ToLuaNode<string> nodecopy = nodes[i];
  455. while (nodecopy.parent != null)
  456. {
  457. nodecopy = nodecopy.parent;
  458. if (nodecopy.value != null && nodecopy.value == ns[--count])
  459. {
  460. size--;
  461. }
  462. }
  463. if (size == 0)
  464. {
  465. index = i;
  466. flag = true;
  467. break;
  468. }
  469. }
  470. if (!flag)
  471. {
  472. ToLuaNode<string> nnode = new ToLuaNode<string>();
  473. nnode.value = ns[j];
  474. nnode.layer = j;
  475. nnode.parent = parent;
  476. parent.childs.Add(nnode);
  477. parent = nnode;
  478. }
  479. else
  480. {
  481. parent = nodes[index];
  482. }
  483. }
  484. }
  485. }
  486. static string GetSpaceNameFromTree(ToLuaNode<string> node)
  487. {
  488. string name = node.value;
  489. while (node.parent != null && node.parent.value != null)
  490. {
  491. node = node.parent;
  492. name = node.value + "." + name;
  493. }
  494. return name;
  495. }
  496. static string RemoveTemplateSign(string str)
  497. {
  498. str = str.Replace('<', '_');
  499. int index = str.IndexOf('>');
  500. while (index > 0)
  501. {
  502. str = str.Remove(index, 1);
  503. index = str.IndexOf('>');
  504. }
  505. return str;
  506. }
  507. [MenuItem("Lua/Gen LuaBinder File", false, 4)]
  508. static void GenLuaBinder()
  509. {
  510. if (!beAutoGen && EditorApplication.isCompiling)
  511. {
  512. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  513. return;
  514. }
  515. allTypes.Clear();
  516. ToLuaTree<string> tree = InitTree();
  517. StringBuilder sb = new StringBuilder();
  518. List<DelegateType> dtList = new List<DelegateType>();
  519. List<DelegateType> list = new List<DelegateType>();
  520. list.AddRange(CustomSettings.customDelegateList);
  521. HashSet<Type> set = GetCustomTypeDelegates();
  522. List<BindType> backupList = new List<BindType>();
  523. backupList.AddRange(allTypes);
  524. ToLuaNode<string> root = tree.GetRoot();
  525. string libname = null;
  526. foreach (Type t in set)
  527. {
  528. if (null == list.Find((p) => { return p.type == t; }))
  529. {
  530. DelegateType dt = new DelegateType(t);
  531. AddSpaceNameToTree(tree, root, ToLuaExport.GetNameSpace(t, out libname));
  532. list.Add(dt);
  533. }
  534. }
  535. sb.AppendLineEx("//this source code was auto-generated by tolua#, do not modify it");
  536. sb.AppendLineEx("using System;");
  537. sb.AppendLineEx("using UnityEngine;");
  538. sb.AppendLineEx("using LuaInterface;");
  539. sb.AppendLineEx();
  540. sb.AppendLineEx("public static class LuaBinder");
  541. sb.AppendLineEx("{");
  542. sb.AppendLineEx("\tpublic static void Bind(LuaState L)");
  543. sb.AppendLineEx("\t{");
  544. sb.AppendLineEx("\t\tfloat t = Time.realtimeSinceStartup;");
  545. sb.AppendLineEx("\t\tL.BeginModule(null);");
  546. GenRegisterInfo(null, sb, list, dtList);
  547. Action<ToLuaNode<string>> begin = (node) =>
  548. {
  549. if (node.value == null)
  550. {
  551. return;
  552. }
  553. sb.AppendFormat("\t\tL.BeginModule(\"{0}\");\r\n", node.value);
  554. string space = GetSpaceNameFromTree(node);
  555. GenRegisterInfo(space, sb, list, dtList);
  556. };
  557. Action<ToLuaNode<string>> end = (node) =>
  558. {
  559. if (node.value != null)
  560. {
  561. sb.AppendLineEx("\t\tL.EndModule();");
  562. }
  563. };
  564. tree.DepthFirstTraversal(begin, end, tree.GetRoot());
  565. sb.AppendLineEx("\t\tL.EndModule();");
  566. if (CustomSettings.dynamicList.Count > 0)
  567. {
  568. sb.AppendLineEx("\t\tL.BeginPreLoad();");
  569. for (int i = 0; i < CustomSettings.dynamicList.Count; i++)
  570. {
  571. Type t1 = CustomSettings.dynamicList[i];
  572. BindType bt = backupList.Find((p) => { return p.type == t1; });
  573. sb.AppendFormat("\t\tL.AddPreLoad(\"{0}\", LuaOpen_{1}, typeof({0}));\r\n", bt.name, bt.wrapName);
  574. }
  575. sb.AppendLineEx("\t\tL.EndPreLoad();");
  576. }
  577. sb.AppendLineEx("\t\tDebugger.Log(\"Register lua type cost time: {0}\", Time.realtimeSinceStartup - t);");
  578. sb.AppendLineEx("\t}");
  579. for (int i = 0; i < dtList.Count; i++)
  580. {
  581. ToLuaExport.GenEventFunction(dtList[i].type, sb);
  582. }
  583. if (CustomSettings.dynamicList.Count > 0)
  584. {
  585. for (int i = 0; i < CustomSettings.dynamicList.Count; i++)
  586. {
  587. Type t = CustomSettings.dynamicList[i];
  588. BindType bt = backupList.Find((p) => { return p.type == t; });
  589. GenPreLoadFunction(bt, sb);
  590. }
  591. }
  592. sb.AppendLineEx("}\r\n");
  593. allTypes.Clear();
  594. string file = CustomSettings.saveDir + "LuaBinder.cs";
  595. using (StreamWriter textWriter = new StreamWriter(file, false, Encoding.UTF8))
  596. {
  597. textWriter.Write(sb.ToString());
  598. textWriter.Flush();
  599. textWriter.Close();
  600. }
  601. AssetDatabase.Refresh();
  602. Debugger.Log("Generate LuaBinder over !");
  603. }
  604. static void GenRegisterInfo(string nameSpace, StringBuilder sb, List<DelegateType> delegateList, List<DelegateType> wrappedDelegatesCache)
  605. {
  606. for (int i = 0; i < allTypes.Count; i++)
  607. {
  608. Type dt = CustomSettings.dynamicList.Find((p) => { return allTypes[i].type == p; });
  609. if (dt == null && allTypes[i].nameSpace == nameSpace)
  610. {
  611. string str = "\t\t" + allTypes[i].wrapName + "Wrap.Register(L);\r\n";
  612. sb.Append(str);
  613. allTypes.RemoveAt(i--);
  614. }
  615. }
  616. string funcName = null;
  617. for (int i = 0; i < delegateList.Count; i++)
  618. {
  619. DelegateType dt = delegateList[i];
  620. Type type = dt.type;
  621. string typeSpace = ToLuaExport.GetNameSpace(type, out funcName);
  622. if (typeSpace == nameSpace)
  623. {
  624. funcName = ToLuaExport.ConvertToLibSign(funcName);
  625. string abr = dt.abr;
  626. abr = abr == null ? funcName : abr;
  627. sb.AppendFormat("\t\tL.RegFunction(\"{0}\", {1});\r\n", abr, dt.name);
  628. wrappedDelegatesCache.Add(dt);
  629. }
  630. }
  631. }
  632. static void GenPreLoadFunction(BindType bt, StringBuilder sb)
  633. {
  634. string funcName = "LuaOpen_" + bt.wrapName;
  635. sb.AppendLineEx("\r\n\t[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]");
  636. sb.AppendFormat("\tstatic int {0}(IntPtr L)\r\n", funcName);
  637. sb.AppendLineEx("\t{");
  638. sb.AppendLineEx("\t\ttry");
  639. sb.AppendLineEx("\t\t{");
  640. sb.AppendLineEx("\t\t\tLuaState state = LuaState.Get(L);");
  641. sb.AppendFormat("\t\t\tstate.BeginPreModule(\"{0}\");\r\n", bt.nameSpace);
  642. sb.AppendFormat("\t\t\t{0}Wrap.Register(state);\r\n", bt.wrapName);
  643. sb.AppendFormat("\t\t\tint reference = state.GetMetaReference(typeof({0}));\r\n", bt.name);
  644. sb.AppendLineEx("\t\t\tstate.EndPreModule(reference);");
  645. sb.AppendLineEx("\t\t\treturn 1;");
  646. sb.AppendLineEx("\t\t}");
  647. sb.AppendLineEx("\t\tcatch(Exception e)");
  648. sb.AppendLineEx("\t\t{");
  649. sb.AppendLineEx("\t\t\treturn LuaDLL.toluaL_exception(L, e);");
  650. sb.AppendLineEx("\t\t}");
  651. sb.AppendLineEx("\t}");
  652. }
  653. static string GetOS()
  654. {
  655. return LuaConst.osDir;
  656. }
  657. static string CreateStreamDir(string dir)
  658. {
  659. dir = Application.streamingAssetsPath + "/" + dir;
  660. if (!File.Exists(dir))
  661. {
  662. Directory.CreateDirectory(dir);
  663. }
  664. return dir;
  665. }
  666. static void BuildLuaBundle(string subDir, string sourceDir)
  667. {
  668. string[] files = Directory.GetFiles(sourceDir + subDir, "*.bytes");
  669. string bundleName = subDir == null ? "lua" + AppConst.ExtName : "lua" + subDir.Replace('/', '_') + AppConst.ExtName;
  670. bundleName = bundleName.ToLower();
  671. #if UNITY_5
  672. for (int i = 0; i < files.Length; i++)
  673. {
  674. AssetImporter importer = AssetImporter.GetAtPath(files[i]);
  675. if (importer)
  676. {
  677. importer.assetBundleName = bundleName;
  678. importer.assetBundleVariant = null;
  679. }
  680. }
  681. #else
  682. List<Object> list = new List<Object>();
  683. for (int i = 0; i < files.Length; i++)
  684. {
  685. Object obj = AssetDatabase.LoadMainAssetAtPath(files[i]);
  686. list.Add(obj);
  687. }
  688. BuildAssetBundleOptions options = BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.DeterministicAssetBundle;
  689. if (files.Length > 0)
  690. {
  691. string output = string.Format("{0}/{1}/" + bundleName, Application.streamingAssetsPath, GetOS());
  692. File.Delete(output);
  693. BuildPipeline.BuildAssetBundle(null, list.ToArray(), output, options, EditorUserBuildSettings.activeBuildTarget);
  694. }
  695. #endif
  696. }
  697. static void ClearAllLuaFiles()
  698. {
  699. string osPath = Application.streamingAssetsPath + "/" + GetOS();
  700. if (Directory.Exists(osPath))
  701. {
  702. string[] files = Directory.GetFiles(osPath, "Lua*" + AppConst.ExtName);
  703. for (int i = 0; i < files.Length; i++)
  704. {
  705. File.Delete(files[i]);
  706. }
  707. }
  708. string path = osPath + "/Lua";
  709. if (Directory.Exists(path))
  710. {
  711. Directory.Delete(path, true);
  712. }
  713. path = Application.streamingAssetsPath + "/Lua";
  714. if (Directory.Exists(path))
  715. {
  716. Directory.Delete(path, true);
  717. }
  718. path = Application.dataPath + "/temp";
  719. if (Directory.Exists(path))
  720. {
  721. Directory.Delete(path, true);
  722. }
  723. path = Application.dataPath + "/Resources/Lua";
  724. if (Directory.Exists(path))
  725. {
  726. Directory.Delete(path, true);
  727. }
  728. path = Application.persistentDataPath + "/" + GetOS() + "/Lua";
  729. if (Directory.Exists(path))
  730. {
  731. Directory.Delete(path, true);
  732. }
  733. }
  734. [MenuItem("Lua/Gen LuaWrap + Binder", false, 4)]
  735. static void GenLuaWrapBinder()
  736. {
  737. if (EditorApplication.isCompiling)
  738. {
  739. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  740. return;
  741. }
  742. beAutoGen = true;
  743. AssetDatabase.Refresh();
  744. GenerateClassWraps();
  745. GenLuaBinder();
  746. beAutoGen = false;
  747. }
  748. [MenuItem("Lua/Generate All", false, 5)]
  749. static void GenLuaAll()
  750. {
  751. if (EditorApplication.isCompiling)
  752. {
  753. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  754. return;
  755. }
  756. beAutoGen = true;
  757. GenLuaDelegates();
  758. AssetDatabase.Refresh();
  759. GenerateClassWraps();
  760. GenLuaBinder();
  761. beAutoGen = false;
  762. EditorUtility.DisplayDialog("提示", "生成全部接口文件成功", "确定");
  763. }
  764. [MenuItem("Lua/Clear wrap files", false, 6)]
  765. static void ClearLuaWraps()
  766. {
  767. string[] files = Directory.GetFiles(CustomSettings.saveDir, "*.cs", SearchOption.TopDirectoryOnly);
  768. for (int i = 0; i < files.Length; i++)
  769. {
  770. File.Delete(files[i]);
  771. }
  772. ToLuaExport.Clear();
  773. List<DelegateType> list = new List<DelegateType>();
  774. ToLuaExport.GenDelegates(list.ToArray());
  775. ToLuaExport.Clear();
  776. StringBuilder sb = new StringBuilder();
  777. sb.AppendLineEx("using System;");
  778. sb.AppendLineEx("using LuaInterface;");
  779. sb.AppendLineEx();
  780. sb.AppendLineEx("public static class LuaBinder");
  781. sb.AppendLineEx("{");
  782. sb.AppendLineEx("\tpublic static void Bind(LuaState L)");
  783. sb.AppendLineEx("\t{");
  784. sb.AppendLineEx("\t\tthrow new LuaException(\"Please generate LuaBinder files first!\");");
  785. sb.AppendLineEx("\t}");
  786. sb.AppendLineEx("}");
  787. string file = CustomSettings.saveDir + "LuaBinder.cs";
  788. using (StreamWriter textWriter = new StreamWriter(file, false, Encoding.UTF8))
  789. {
  790. textWriter.Write(sb.ToString());
  791. textWriter.Flush();
  792. textWriter.Close();
  793. }
  794. AssetDatabase.Refresh();
  795. EditorUtility.DisplayDialog("提示", "清理全部接口文件成功", "确定");
  796. }
  797. public static void CopyLuaBytesFiles(string sourceDir, string destDir, bool appendext = true, string searchPattern = "*.lua", SearchOption option = SearchOption.AllDirectories)
  798. {
  799. if (!Directory.Exists(sourceDir))
  800. {
  801. return;
  802. }
  803. string[] files = Directory.GetFiles(sourceDir, searchPattern, option);
  804. int len = sourceDir.Length;
  805. if (sourceDir[len - 1] == '/' || sourceDir[len - 1] == '\\')
  806. {
  807. --len;
  808. }
  809. for (int i = 0; i < files.Length; i++)
  810. {
  811. string str = files[i].Remove(0, len);
  812. string dest = destDir + "/" + str;
  813. if (appendext) dest += ".bytes";
  814. string dir = Path.GetDirectoryName(dest);
  815. Directory.CreateDirectory(dir);
  816. File.Copy(files[i], dest, true);
  817. }
  818. }
  819. [MenuItem("Lua/Copy Lua files to Resources", false, 51)]
  820. public static void CopyLuaFilesToRes()
  821. {
  822. ClearAllLuaFiles();
  823. string destDir = Application.dataPath + "/Resources" + "/Lua";
  824. CopyLuaBytesFiles(LuaConst.luaDir, destDir);
  825. AssetDatabase.Refresh();
  826. LogManager.Log("Copy lua files over");
  827. }
  828. [MenuItem("Lua/Copy Lua files to Persistent", false, 52)]
  829. public static void CopyLuaFilesToPersistent()
  830. {
  831. ClearAllLuaFiles();
  832. string destDir = Application.persistentDataPath + "/" + GetOS() + "/Lua";
  833. CopyLuaBytesFiles(LuaConst.luaDir, destDir, false);
  834. AssetDatabase.Refresh();
  835. LogManager.Log("Copy lua files over");
  836. }
  837. static void GetAllDirs(string dir, List<string> list)
  838. {
  839. string[] dirs = Directory.GetDirectories(dir);
  840. list.AddRange(dirs);
  841. for (int i = 0; i < dirs.Length; i++)
  842. {
  843. GetAllDirs(dirs[i], list);
  844. }
  845. }
  846. static void CopyDirectory(string source, string dest, string searchPattern = "*.lua", SearchOption option = SearchOption.AllDirectories)
  847. {
  848. string[] files = Directory.GetFiles(source, searchPattern, option);
  849. for (int i = 0; i < files.Length; i++)
  850. {
  851. string str = files[i].Remove(0, source.Length);
  852. string path = dest + "/" + str;
  853. string dir = Path.GetDirectoryName(path);
  854. Directory.CreateDirectory(dir);
  855. File.Copy(files[i], path, true);
  856. }
  857. }
  858. [MenuItem("Lua/Build Lua files to Resources (PC)", false, 53)]
  859. public static void BuildLuaToResources()
  860. {
  861. ClearAllLuaFiles();
  862. string tempDir = CreateStreamDir("Lua");
  863. string destDir = Application.dataPath + "/Resources" + "/Lua";
  864. string path = Application.dataPath.Replace('\\', '/');
  865. path = path.Substring(0, path.LastIndexOf('/'));
  866. File.Copy(path + "/Luajit/Build.bat", tempDir + "/Build.bat", true);
  867. CopyLuaBytesFiles(LuaConst.luaDir, tempDir, false);
  868. Process proc = Process.Start(tempDir + "/Build.bat");
  869. proc.WaitForExit();
  870. CopyLuaBytesFiles(tempDir + "/Out/", destDir, false, "*.lua.bytes");
  871. Directory.Delete(tempDir, true);
  872. AssetDatabase.Refresh();
  873. }
  874. [MenuItem("Lua/Build Lua files to Persistent (PC)", false, 54)]
  875. public static void BuildLuaToPersistent()
  876. {
  877. ClearAllLuaFiles();
  878. string tempDir = CreateStreamDir("Lua");
  879. string destDir = Application.persistentDataPath + "/" + GetOS() + "/Lua/";
  880. string path = Application.dataPath.Replace('\\', '/');
  881. path = path.Substring(0, path.LastIndexOf('/'));
  882. File.Copy(path + "/Luajit/Build.bat", tempDir + "/Build.bat", true);
  883. CopyLuaBytesFiles(LuaConst.luaDir, tempDir, false);
  884. Process proc = Process.Start(tempDir + "/Build.bat");
  885. proc.WaitForExit();
  886. path = tempDir + "/Out/";
  887. string[] files = Directory.GetFiles(path, "*.lua.bytes");
  888. int len = path.Length;
  889. for (int i = 0; i < files.Length; i++)
  890. {
  891. path = files[i].Remove(0, len);
  892. path = path.Substring(0, path.Length - 6);
  893. path = destDir + path;
  894. File.Copy(files[i], path, true);
  895. }
  896. Directory.Delete(tempDir, true);
  897. AssetDatabase.Refresh();
  898. }
  899. [MenuItem("Lua/Build bundle files not jit", false, 55)]
  900. public static void BuildNotJitBundles()
  901. {
  902. ClearAllLuaFiles();
  903. CreateStreamDir(GetOS());
  904. #if !UNITY_5
  905. string tempDir = CreateStreamDir("Lua");
  906. #else
  907. string tempDir = Application.dataPath + "/temp/Lua";
  908. if (!File.Exists(tempDir))
  909. {
  910. Directory.CreateDirectory(tempDir);
  911. }
  912. #endif
  913. CopyLuaBytesFiles(LuaConst.luaDir, tempDir);
  914. AssetDatabase.Refresh();
  915. List<string> dirs = new List<string>();
  916. GetAllDirs(tempDir, dirs);
  917. #if UNITY_5
  918. for (int i = 0; i < dirs.Count; i++)
  919. {
  920. string str = dirs[i].Remove(0, tempDir.Length);
  921. BuildLuaBundle(str.Replace('\\', '/'), "Assets/temp/Lua");
  922. }
  923. BuildLuaBundle(null, "Assets/temp/Lua");
  924. AssetDatabase.SaveAssets();
  925. string output = string.Format("{0}/{1}", Application.streamingAssetsPath, GetOS());
  926. BuildPipeline.BuildAssetBundles(output, BuildAssetBundleOptions.DeterministicAssetBundle, EditorUserBuildSettings.activeBuildTarget);
  927. //Directory.Delete(Application.dataPath + "/temp/", true);
  928. #else
  929. for (int i = 0; i < dirs.Count; i++)
  930. {
  931. string str = dirs[i].Remove(0, tempDir.Length);
  932. BuildLuaBundle(str.Replace('\\', '/'), "Assets/StreamingAssets/Lua");
  933. }
  934. BuildLuaBundle(null, "Assets/StreamingAssets/Lua");
  935. Directory.Delete(Application.streamingAssetsPath + "/Lua/", true);
  936. #endif
  937. AssetDatabase.Refresh();
  938. }
  939. [MenuItem("Lua/Build Luajit bundle files (PC)", false, 56)]
  940. public static void BuildLuaBundles()
  941. {
  942. ClearAllLuaFiles();
  943. CreateStreamDir(GetOS());
  944. #if !UNITY_5
  945. string tempDir = CreateStreamDir("Lua");
  946. #else
  947. string tempDir = Application.dataPath + "/temp/Lua";
  948. if (!File.Exists(tempDir))
  949. {
  950. Directory.CreateDirectory(tempDir);
  951. }
  952. #endif
  953. string path = Application.dataPath.Replace('\\', '/');
  954. path = path.Substring(0, path.LastIndexOf('/'));
  955. File.Copy(path + "/Luajit/Build.bat", tempDir + "/Build.bat", true);
  956. CopyLuaBytesFiles(LuaConst.luaDir, tempDir, false);
  957. Process proc = Process.Start(tempDir + "/Build.bat");
  958. proc.WaitForExit();
  959. AssetDatabase.Refresh();
  960. string sourceDir = tempDir + "/Out";
  961. List<string> dirs = new List<string>();
  962. GetAllDirs(sourceDir, dirs);
  963. #if UNITY_5
  964. for (int i = 0; i < dirs.Count; i++)
  965. {
  966. string str = dirs[i].Remove(0, sourceDir.Length);
  967. BuildLuaBundle(str.Replace('\\', '/'), "Assets/temp/Lua/Out");
  968. }
  969. BuildLuaBundle(null, "Assets/temp/Lua/Out");
  970. AssetDatabase.Refresh();
  971. string output = string.Format("{0}/{1}", Application.streamingAssetsPath, GetOS());
  972. BuildPipeline.BuildAssetBundles(output, BuildAssetBundleOptions.DeterministicAssetBundle, EditorUserBuildSettings.activeBuildTarget);
  973. Directory.Delete(Application.dataPath + "/temp/", true);
  974. #else
  975. for (int i = 0; i < dirs.Count; i++)
  976. {
  977. string str = dirs[i].Remove(0, sourceDir.Length);
  978. BuildLuaBundle(str.Replace('\\', '/'), "Assets/StreamingAssets/Lua/Out");
  979. }
  980. BuildLuaBundle(null, "Assets/StreamingAssets/Lua/Out/");
  981. Directory.Delete(tempDir, true);
  982. #endif
  983. AssetDatabase.Refresh();
  984. }
  985. [MenuItem("Lua/Clear all Lua files", false, 57)]
  986. public static void ClearLuaFiles()
  987. {
  988. ClearAllLuaFiles();
  989. }
  990. [MenuItem("Lua/Gen BaseType Wrap", false, 101)]
  991. static void GenBaseTypeLuaWrap()
  992. {
  993. if (!beAutoGen && EditorApplication.isCompiling)
  994. {
  995. EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定");
  996. return;
  997. }
  998. string dir = CustomSettings.toluaBaseType;
  999. if (!File.Exists(dir))
  1000. {
  1001. Directory.CreateDirectory(dir);
  1002. }
  1003. allTypes.Clear();
  1004. ToLuaExport.allTypes.AddRange(baseType);
  1005. List<BindType> btList = new List<BindType>();
  1006. for (int i = 0; i < baseType.Count; i++)
  1007. {
  1008. btList.Add(new BindType(baseType[i]));
  1009. }
  1010. GenBindTypes(btList.ToArray(), false);
  1011. BindType[] list = allTypes.ToArray();
  1012. for (int i = 0; i < list.Length; i++)
  1013. {
  1014. ToLuaExport.Clear();
  1015. ToLuaExport.className = list[i].name;
  1016. ToLuaExport.type = list[i].type;
  1017. ToLuaExport.isStaticClass = list[i].IsStatic;
  1018. ToLuaExport.baseType = list[i].baseType;
  1019. ToLuaExport.wrapClassName = list[i].wrapName;
  1020. ToLuaExport.libClassName = list[i].libName;
  1021. ToLuaExport.Generate(dir);
  1022. }
  1023. LogManager.Log("Generate base type files over");
  1024. allTypes.Clear();
  1025. AssetDatabase.Refresh();
  1026. }
  1027. static void CreateDefaultWrapFile(string path, string name)
  1028. {
  1029. StringBuilder sb = new StringBuilder();
  1030. path = path + name + ".cs";
  1031. sb.AppendLineEx("using System;");
  1032. sb.AppendLineEx("using LuaInterface;");
  1033. sb.AppendLineEx();
  1034. sb.AppendLineEx("public static class " + name);
  1035. sb.AppendLineEx("{");
  1036. sb.AppendLineEx("\tpublic static void Register(LuaState L)");
  1037. sb.AppendLineEx("\t{");
  1038. sb.AppendLineEx("\t\tthrow new LuaException(\"Please click menu Lua/Gen BaseType Wrap first!\");");
  1039. sb.AppendLineEx("\t}");
  1040. sb.AppendLineEx("}");
  1041. using (StreamWriter textWriter = new StreamWriter(path, false, Encoding.UTF8))
  1042. {
  1043. textWriter.Write(sb.ToString());
  1044. textWriter.Flush();
  1045. textWriter.Close();
  1046. }
  1047. }
  1048. [MenuItem("Lua/Clear BaseType Wrap", false, 102)]
  1049. static void ClearBaseTypeLuaWrap()
  1050. {
  1051. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_ObjectWrap");
  1052. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_DelegateWrap");
  1053. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_StringWrap");
  1054. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_EnumWrap");
  1055. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_TypeWrap");
  1056. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "System_Collections_IEnumeratorWrap");
  1057. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "UnityEngine_ObjectWrap");
  1058. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "LuaInterface_EventObjectWrap");
  1059. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "LuaInterface_LuaMethodWrap");
  1060. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "LuaInterface_LuaPropertyWrap");
  1061. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "LuaInterface_LuaFieldWrap");
  1062. CreateDefaultWrapFile(CustomSettings.toluaBaseType, "LuaInterface_LuaConstructorWrap");
  1063. LogManager.Log("Clear base type wrap files over");
  1064. AssetDatabase.Refresh();
  1065. }
  1066. }