248 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
| //
 | ||
| // Proto2CSEditor.cs
 | ||
| //
 | ||
| // Author:
 | ||
| //       JasonXuDeveloper(傑) <jasonxudeveloper@gmail.com>
 | ||
| //
 | ||
| // Copyright (c) 2020 JEngine
 | ||
| //
 | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||
| // of this software and associated documentation files (the "Software"), to deal
 | ||
| // in the Software without restriction, including without limitation the rights
 | ||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||
| // copies of the Software, and to permit persons to whom the Software is
 | ||
| // furnished to do so, subject to the following conditions:
 | ||
| //
 | ||
| // The above copyright notice and this permission notice shall be included in
 | ||
| // all copies or substantial portions of the Software.
 | ||
| //
 | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||
| // THE SOFTWARE.
 | ||
| 
 | ||
| using System.IO;
 | ||
| using Google.Protobuf.Reflection;
 | ||
| using ProtoBuf.Reflection;
 | ||
| using UnityEditor;
 | ||
| using UnityEngine;
 | ||
| 
 | ||
| namespace Guru
 | ||
| {
 | ||
|     internal class Proto2CSEditor : EditorWindow
 | ||
|     {
 | ||
|         private static Proto2CSEditor win;
 | ||
| 
 | ||
|         //[MenuItem("Tools/Protobuf/Show Generate Window")]
 | ||
|         //public static void ShowCSGenerateWindow()
 | ||
|         //{
 | ||
|         //    int index = Application.dataPath.LastIndexOf('/');
 | ||
|         //    var proto_dir = $"{Application.dataPath.Substring(0, index)}/ServerProtos";
 | ||
|         //    win = GetWindow<Proto2CSEditor>("Proto2CS Generator");
 | ||
|         //    win.folder = EditorUtility.OpenFolderPanel("Please select proto files directory",
 | ||
|         //        proto_dir, "");
 | ||
|         //    win.minSize = new Vector2(500, 500);
 | ||
|         //    win.Show();
 | ||
|         //}
 | ||
| 
 | ||
|         [MenuItem("Tools/Protobuf/Generate All")]
 | ||
|         public static void GenerateAllProtos()
 | ||
|         {
 | ||
|             int index = Application.dataPath.LastIndexOf('/');
 | ||
|             var proto_dir = $"{Application.dataPath.Substring(0, index)}/ServerProtos";
 | ||
|             var file_list = GetAllProtoFiles(proto_dir);
 | ||
|             var dest_folder = $"{Application.dataPath}/../Assets/Scripts/NetworkGen";
 | ||
| 
 | ||
|             if (Directory.Exists(dest_folder))
 | ||
|             {
 | ||
|                 Directory.Delete(dest_folder, true);
 | ||
| 
 | ||
|                 // Just in case the system has output_folder still locked for deletion
 | ||
|                 while (Directory.Exists(dest_folder))
 | ||
|                 {
 | ||
|                     System.Threading.Thread.Sleep(10);
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             Directory.CreateDirectory(dest_folder);
 | ||
| 
 | ||
|             Generate(proto_dir, file_list, dest_folder);
 | ||
|         }
 | ||
| 
 | ||
|         [MenuItem("Tools/Protobuf/View Proto Files")]
 | ||
|         private static void ViewDataPath()
 | ||
|         {
 | ||
|             int index = Application.dataPath.LastIndexOf('/');
 | ||
|             var proto_dir = $"{Application.dataPath.Substring(0, index)}/ServerProtos";
 | ||
| 
 | ||
|             if (!Directory.Exists(proto_dir))
 | ||
|             {
 | ||
|                 Directory.CreateDirectory(proto_dir);
 | ||
|             }
 | ||
| 
 | ||
|             EditorUtility.OpenWithDefaultApp(proto_dir);
 | ||
|         }
 | ||
| 
 | ||
|         [SerializeField] protected string[] _fileList = new string[0];
 | ||
|         protected string folder;
 | ||
|         protected SerializedObject _serializedObject;
 | ||
|         protected SerializedProperty _fileListProperty;
 | ||
| 
 | ||
| 
 | ||
|         protected void OnEnable()
 | ||
|         {
 | ||
|             //使用当前类初始化
 | ||
|             _serializedObject = new SerializedObject(this);
 | ||
|             //获取当前类中可序列话的属性
 | ||
|             _fileListProperty = _serializedObject.FindProperty("_fileList");
 | ||
|         }
 | ||
| 
 | ||
|         protected void OnGUI()
 | ||
|         {
 | ||
|             //绘制标题
 | ||
|             GUILayout.Space(10);
 | ||
|             GUIStyle textStyle = new GUIStyle();
 | ||
|             textStyle.fontSize = 24;
 | ||
|             textStyle.normal.textColor = Color.white;
 | ||
|             textStyle.alignment = TextAnchor.MiddleCenter;
 | ||
|             GUILayout.Label("Proto文件转CS文件", textStyle);
 | ||
|             textStyle.fontSize = 18;
 | ||
|             GUILayout.Label("Proto file to CS file", textStyle);
 | ||
|             GUILayout.Space(10);
 | ||
| 
 | ||
|             /*
 | ||
| 			 * 路径
 | ||
| 			 */
 | ||
|             GUILayout.Label("Proto file folder Proto文件路径");
 | ||
|             GUILayout.BeginHorizontal();
 | ||
|             EditorGUI.BeginDisabledGroup(true);
 | ||
|             folder = EditorGUILayout.TextField(folder);
 | ||
|             EditorGUI.EndDisabledGroup();
 | ||
| 
 | ||
|             GUILayout.Space(10);
 | ||
|             if (GUILayout.Button("Select Path 选择路径", GUILayout.ExpandWidth(false)))
 | ||
|             {
 | ||
|                 int index = Application.dataPath.LastIndexOf('/');
 | ||
|                 var proto_dir = $"{Application.dataPath.Substring(0, index)}/ServerProtos";
 | ||
| 
 | ||
|                 folder = EditorUtility.OpenFolderPanel("Select proto files source 请选择proto文件路径", proto_dir, "");
 | ||
|             }
 | ||
| 
 | ||
|             GUILayout.EndHorizontal();
 | ||
| 
 | ||
|             /*
 | ||
| 			 * 文件
 | ||
| 			 */
 | ||
|             GUILayout.Space(10);
 | ||
|             GUILayout.Label("Files to convert 需转换文件");
 | ||
|             //更新
 | ||
|             _serializedObject.Update();
 | ||
|             //开始检查是否有修改
 | ||
|             EditorGUI.BeginChangeCheck();
 | ||
|             //显示属性
 | ||
|             EditorGUILayout.PropertyField(_fileListProperty, true);
 | ||
| 
 | ||
|             //结束检查是否有修改
 | ||
|             if (EditorGUI.EndChangeCheck())
 | ||
|             {
 | ||
|                 //提交修改
 | ||
|                 _serializedObject.ApplyModifiedProperties();
 | ||
|             }
 | ||
| 
 | ||
|             /*
 | ||
| 			 * 按钮
 | ||
| 			 */
 | ||
|             GUILayout.Space(50);
 | ||
|             if (GUILayout.Button("Match all files from folder 从文件夹中匹配全部文件"))
 | ||
|             {
 | ||
|                 _fileList = GetAllProtoFiles(folder);
 | ||
|                 _serializedObject.Update();
 | ||
|             }
 | ||
| 
 | ||
|             GUILayout.Space(10);
 | ||
|             if (GUILayout.Button("Generate 生成"))
 | ||
|             {
 | ||
|                 var dest_folder = $"{Application.dataPath}/Gen/Network";
 | ||
|                 //Generate(folder, _fileList, dest_folder);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private static string[] GetAllProtoFiles(string path)
 | ||
|         {
 | ||
|             if (string.IsNullOrEmpty(path))
 | ||
|             {
 | ||
|                 Debug.LogError($"Folder path is empty!");
 | ||
|                 return null;
 | ||
|             }
 | ||
| 
 | ||
|             var file_list = Directory.GetFiles(path, "*.proto", SearchOption.AllDirectories);
 | ||
|             var file_name_list = new string[file_list.Length];
 | ||
| 
 | ||
|             for (int i = 0; i < file_list.Length; i++)
 | ||
|             {
 | ||
|                 file_name_list[i] = Path.GetFileName(file_list[i]);
 | ||
|             }
 | ||
| 
 | ||
|             return file_name_list;
 | ||
|         }
 | ||
| 
 | ||
|         private static void Generate(string inpath, string[] inprotos, string outpath)
 | ||
|         {
 | ||
|             if (!Directory.Exists(outpath))
 | ||
|             {
 | ||
|                 Directory.CreateDirectory(outpath);
 | ||
|             }
 | ||
| 
 | ||
|             var set = new FileDescriptorSet();
 | ||
|             set.AddImportPath(inpath);
 | ||
|             foreach (var inproto in inprotos)
 | ||
|             {
 | ||
|                 var s = inproto;
 | ||
|                 if (!inproto.Contains(".proto"))
 | ||
|                 {
 | ||
|                     s += ".proto";
 | ||
|                 }
 | ||
| 
 | ||
|                 set.Add(s, true);
 | ||
|             }
 | ||
| 
 | ||
|             set.Process();
 | ||
|             var errors = set.GetErrors();
 | ||
|             CSharpCodeGenerator.ClearTypeNames();
 | ||
|             var files = CSharpCodeGenerator.Default.Generate(set);
 | ||
| 
 | ||
|             foreach (var file in files)
 | ||
|             {
 | ||
|                 CSharpCodeGenerator.ClearTypeNames();
 | ||
|                 var full_file_name = file.Name;
 | ||
|                 int index = full_file_name.LastIndexOf('.');
 | ||
|                 var file_name = index > 0 ? full_file_name.Substring(0, index) : full_file_name;
 | ||
|                 file_name = file_name.ToLower();
 | ||
|                 var dest_filename = $"{NameNormalizer.AutoCapitalize(file_name)}.cs";
 | ||
|                 //var path = Path.Combine(outpath, file.Name);
 | ||
|                 var path = Path.Combine(outpath, dest_filename);
 | ||
|                 File.WriteAllText(path, file.Text);
 | ||
| 
 | ||
|                 Debug.Log($"Generated cs file for {full_file_name.Replace(".cs", ".proto")} successfully to: {path}");
 | ||
|             }
 | ||
| 
 | ||
|             EditorUtility.DisplayDialog("Complete",
 | ||
|                 "Proto文件已转CS,详细请看控制台输出" +
 | ||
|                 "\n" +
 | ||
|                 "Proto files has been convert into CS files, please go to console and view details",
 | ||
|                 "Close window");
 | ||
| 
 | ||
|             if (win != null)
 | ||
|             {
 | ||
|                 win.Close();
 | ||
|             }
 | ||
| 
 | ||
|             AssetDatabase.Refresh();
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| } |