// // Proto2CSEditor.cs // // Author: // JasonXuDeveloper(傑) // // 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("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 = proto_dir;// $"{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(); } } }