簡要說明
創建代碼有多種方式。最簡單的,就按編輯器最初始的方法生成。稍微會點的就可以自己修改編輯器的模板。再深入一點的就可以自己定義一系列代碼模板,保存到文本文件,再讀出來,然後修改一些模板信息。用unity3d程序,我倒是習慣了在這程序中創建一個script而不是在vistual studio中去新建代碼。這樣的話,所有的代碼類型,如Interface,struct,enum都需要在創建出一個”不正確“的類後修改,修改是個重複的過程,這個過程必須去掉。
而遺憾的是unity至今還是對所有的代碼一視同仁,連圖標都是用c#這麼“經典”的一個圖標。前一段時候,用過一些方法,無非是編寫一個代碼模板文檔,創建時,調用這些模板。最大的缺陷是太複雜,在不同的項目或電腦上都要靠一些不想要的模板文件。
本文將使用Microsoft自己帶的代碼格式方案實現代碼的生成(因爲考慮到unity3d中暫不能很好的使用.net4.5,代碼解析的模塊還沒有開發)。
成果展示
1.如果你喜歡簡單一點,直接點右鍵快速創建不同的類
2.當然,也有基本的配製窗口
3.如果你需要創建一個不繼承於其他類的數據模型類,你可以這樣配製
4.以上這個配製後,點擊create就可以生成代碼模板到指定的文件夾了
5.以下是一個接口,創建效果。此外你已經熟悉代碼規範了就可以在設置裏面取消顯示
技術要點
1.將c#代碼單元生成字符串
代碼也是一個個的文檔,官方都有文檔的格式,c#也不例外。這裏只是按格式寫,然後生成字符串,
需要說明的是c#並不能真的從string變成文檔結構,至少官方貌似沒有提供,但如果你可以使用net4.5以上的環境,
倒是可以研究下NRefactory
using (Microsoft.CSharp.CSharpCodeProvider cprovider = new Microsoft.CSharp.CSharpCodeProvider())
{
StringBuilder fileContent = new StringBuilder();
var option = new System.CodeDom.Compiler.CodeGeneratorOptions();
option.BlankLinesBetweenMembers = false;
using (StringWriter sw = new StringWriter(fileContent))
{
cprovider.GenerateCodeFromNamespace(nameSpace, sw, option);
}
return fileContent.ToString();
}
2.結合unity自己創建代碼的方式
因爲還沒有找到,unity3d當前打開的文件夾路徑,所以用了一個妥協的方案。就是先調用自帶的方法創建一個腳本,
然後去修改裏面的字符串(如果你找到了,不防提醒了一下)
internal static void QuickCreateTemplate<T>() where T : ScriptTemplate, new()
{
EditorApplication.ExecuteMenuItem("Assets/Create/C# Script");
EditorApplication.update = () =>
{
if (Selection.activeObject)
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var temp = new T();
temp.headerInfo.scriptName = Path.GetFileNameWithoutExtension(path);
var dir = Path.GetDirectoryName(path);
var scr = temp.CreateScript();
temp.SaveToFile(dir, scr);
EditorApplication.update = null;
}
};
}
3.窗體緩存
因爲,將窗體的信息保存到本地文件,但又想要緩存一點信息,所以用了EditorPrefs和PlayerPrefs,
前面用來保存跨工程的用戶信息和窗體信息,後面用來保存當前程序的信息。即使這樣,因爲要緩存模板抽象類的信息,
還用到了類型記錄的一些方案
public static TempScriptWindow GetWindow()
{
var window = EditorWindow.GetWindow<TempScriptWindow>();
if (EditorPrefs.HasKey(prefer_key))
{
var json = EditorPrefs.GetString(prefer_window);
JsonUtility.FromJsonOverwrite(json, window);
window.LoadOldTemplates();
return window;
}
return window;
}
internal static ScriptTemplate LoadFromJson(ScriptTemplate old)
{
if (!string.IsNullOrEmpty(old.type) && old.GetType().FullName != old.type)
{
var type = Type.GetType(old.type);
if(type != null)
{
var temp = Activator.CreateInstance(type);
JsonUtility.FromJsonOverwrite(old.json, temp);
return temp as ScriptTemplate;
}
else
{
return old;
}
}
else
{
old.type = old.GetType().FullName;
return old;
}
}
4.unity3d自帶列表ReorderableList以前沒發現這個類,所以用了其他的插件來寫列表。以上你看到的列表效果就是這樣寫的
protected void InitDetailList()
{
detailList = new ReorderableList(headerInfo.detailInfo, typeof(string), true, false, true, true);
detailList.onAddCallback += (x) => { headerInfo.detailInfo.Add(""); };
detailList.drawHeaderCallback = (x) => { EditorGUI.LabelField(x, "詳細信息"); };
detailList.drawElementCallback += (x, y, z, w) => { headerInfo.detailInfo[y] = EditorGUI.TextField(x, headerInfo.detailInfo[y]); };
}
源碼分享
爲了方便拷貝使用,我直接在一個腳本中寫了這些功能。雖然用了面對象的基本思路,但實際上在個文檔中寫,實在是難過,以後也儘量不要這樣幹。主要的是這個代碼後面應該還會更新,如果喜歡,或者有建議可以到我github中去找:https://github.com/zouhunter/Editor_Extends/blob/master/Core/Editor/TempScriptWindow.cs
#region statement
/*************************************************************************************
* 作 者: zouhunter
* 時 間: 2018-02-02
* 詳 細: 1.支持枚舉、模型、結構和繼承等類的模板。
2.支持快速創建通用型UI界面腳本
3.支持自定義模板類
4.自動生成作者、創建時間、描述等功能
5.支持工程同步(EditorPrefer)
*************************************************************************************/
#endregion
using System;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using UnityEditorInternal;
using System.CodeDom;
using System.IO;
using System.Text;
using NUnit.Framework.Constraints;
using NUnit.Framework;
namespace EditorTools
{
#region Window
/// <summary>
/// 一個創建腳本模板的窗口
/// </summary>
public class TempScriptWindow : EditorWindow
{
[MenuItem("Window/TempScriptWindow")]
static void Open()
{
var window = TempScriptHelper.GetWindow();
window.wantsMouseMove = true;
}
[SerializeField]
private List<ScriptTemplate> templates;
ScriptTemplate currentTemplates { get { if (templates != null && templates.Count > currentIndex) return templates[currentIndex]; return null; } }
private MonoScript script;
[SerializeField]
private bool isSetting;
[SerializeField]
private string authorName;
[SerializeField]
private string[] templateNames;
[SerializeField]
private int currentIndex;
private Vector2 scrollPos;
[SerializeField]
private string[] templateType;
private bool showRule;
private string codeRule;
private void OnEnable()
{
InitEnviroment();
}
private void OnDisable()
{
if (templates != null)
{
foreach (var item in templates)
{
item.SaveToJson();
}
}
EditorUtility.SetDirty(this);
TempScriptHelper.SaveWindow(this);
}
private void OnGUI()
{
DrawHead();
if (isSetting)
{
//繪製設置信息
DrawSettings();
}
else
{
if (templates == null)
{
Debug.Log("template == null");
templates = new List<ScriptTemplate>();
}
if (templates.Count == 0)
{
Debug.Log("AddTemplates");
AddTemplates();
}
currentIndex = GUILayout.Toolbar(currentIndex, templateNames);
using (var scroll = new EditorGUILayout.ScrollViewScope(scrollPos))
{
scrollPos = scroll.scrollPosition;
if (currentTemplates != null)
{
if (currentTemplates.GetType().FullName != currentTemplates.type)
{
templates[currentIndex] = TempScriptHelper.LoadFromJson(currentTemplates);
}
currentTemplates.OnBodyGUI();
if (currentTemplates.GetType().FullName == typeof(ScriptTemplate).FullName)
{
if (templateType.Length > currentIndex)
{
var type = Type.GetType(templateType[currentIndex]);
if(type != null)
{
templates[currentIndex] = Activator.CreateInstance(type) as ScriptTemplate;
Debug.Log("create new:" + currentTemplates.GetType());
}
else
{
Debug.LogFormat("{0} missing: clear templates", currentTemplates.GetType().FullName);
templates.Clear();
}
}
else
{
Debug.Log("unknow err: clear templates");
templates.Clear();
}
}
}
else
{
templates.Clear();
Debug.Log("templates.Count <= currentIndex");
}
}
if (currentTemplates != null)
{
currentTemplates.OnFootGUI();
}
}
}
private void InitEnviroment()
{
if (script == null) script = MonoScript.FromScriptableObject(this);
showRule = TempScriptHelper.GetRuleShowState();
if (string.IsNullOrEmpty(codeRule)) codeRule = TempScriptHelper.GetCodeRule();
if (string.IsNullOrEmpty(authorName)) authorName = TempScriptHelper.GetAuthor();
if (string.IsNullOrEmpty(authorName))
{
isSetting = true;
}
}
private void AddTemplates()
{
var assemble = this.GetType().Assembly;
var allTypes = assemble.GetTypes();
foreach (var item in allTypes)
{
if (item.IsSubclassOf(typeof(ScriptTemplate)))
{
var template = Activator.CreateInstance(item);
templates.Add(template as ScriptTemplate);
}
}
foreach (var item in templates)
{
item.OnEnable();
}
templateNames = templates.ConvertAll<string>(x => x.Name).ToArray();
templateType = templates.ConvertAll<string>(x => x.GetType().FullName).ToArray();
}
public void LoadOldTemplates()
{
for (int i = 0; i < templates.Count; i++)
{
if (templates[i] == null)
{
templates = null;
return;
}
var newitem = TempScriptHelper.LoadFromJson(templates[i]);
if (newitem == null)
{
templates = null;
return;
}
templates[i] = newitem;
}
templateNames = templates.ConvertAll<string>(x => x.Name).ToArray();
templateType = templates.ConvertAll<string>(x => x.GetType().FullName).ToArray();
}
private void DrawHead()
{
using (var hor = new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.ObjectField(script, typeof(MonoScript), false);
if (!isSetting && GUILayout.Button("setting", EditorStyles.miniButtonRight, GUILayout.Width(60)))
{
isSetting = true;
}
else if (isSetting && GUILayout.Button("confer", EditorStyles.miniButtonRight, GUILayout.Width(60)) && !string.IsNullOrEmpty(authorName))
{
isSetting = false;
}
}
if (!isSetting && GUILayout.Button("Clear", EditorStyles.toolbarButton))
{
if (currentTemplates != null)
currentTemplates.headerInfo = new TempScriptHeader() ;
templates.Clear();
}
}
private void DrawSettings()
{
using (var hor = new EditorGUILayout.HorizontalScope())
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.SelectableLabel("作者:", EditorStyles.miniLabel, GUILayout.Width(60));
authorName = EditorGUILayout.TextField(authorName);
if (EditorGUI.EndChangeCheck())
{
if (!string.IsNullOrEmpty(authorName))
{
TempScriptHelper.SaveAuthor(authorName);
}
}
}
EditorGUI.BeginChangeCheck();
showRule = EditorGUILayout.ToggleLeft("在生成的代碼末尾顯示規範:(熟悉後可關閉此功能)", showRule);
if (EditorGUI.EndChangeCheck())
{
TempScriptHelper.SetRuleShowState(showRule);
}
if (showRule)
{
using (var scrop = new EditorGUILayout.ScrollViewScope(scrollPos))
{
scrollPos = scrop.scrollPosition;
EditorGUILayout.TextArea(codeRule);
}
}
}
}
#endregion
#region Tools
/// <summary>
/// 任何腳本的頭
/// </summary>
[System.Serializable]
public class TempScriptHeader
{
public string author;
public string time;
public string description;
public List<string> detailInfo = new List<string>();
public string scriptName;
public string nameSpace;
public void Update()
{
author = TempScriptHelper.GetAuthor();
time = System.DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
}
}
/// <summary>
/// 靜態工具類
/// </summary>
public static class TempScriptHelper
{
private const string prefer_key = "temp_script_autor_name";
private const string prefer_window = "temp_script_window";
private const string code_rule_show = "temp_script_code_rule_show";
public static void SaveAuthor(string author)
{
EditorPrefs.SetString(prefer_key, author);
}
public static string GetAuthor()
{
return EditorPrefs.GetString(prefer_key);
}
public static void SaveWindow(TempScriptWindow window)
{
var json = JsonUtility.ToJson(window);
EditorPrefs.SetString(prefer_window, json);
}
public static TempScriptWindow GetWindow()
{
var window = EditorWindow.GetWindow<TempScriptWindow>();
if (EditorPrefs.HasKey(prefer_key))
{
var json = EditorPrefs.GetString(prefer_window);
JsonUtility.FromJsonOverwrite(json, window);
window.LoadOldTemplates();
return window;
}
return window;
}
internal static ScriptTemplate LoadFromJson(ScriptTemplate old)
{
if (!string.IsNullOrEmpty(old.type) && old.GetType().FullName != old.type)
{
var type = Type.GetType(old.type);
if(type != null)
{
var temp = Activator.CreateInstance(type);
JsonUtility.FromJsonOverwrite(old.json, temp);
return temp as ScriptTemplate;
}
else
{
return old;
}
}
else
{
old.type = old.GetType().FullName;
return old;
}
}
internal static void SetRuleShowState(bool enabled)
{
PlayerPrefs.SetInt(code_rule_show, enabled ? 1 : 0);
}
internal static bool GetRuleShowState()
{
if (PlayerPrefs.HasKey(code_rule_show))
{
return PlayerPrefs.GetInt(code_rule_show) == 1;
}
return true;
}
/*
1.私有字段:_field,m_field
2.公有字段:field
2.屬性:Property
3.常量:CONST
4.靜態變量:Field,Property
*/
internal static string GetCodeRule()
{
return @"#region 代碼規範
/*************************************************************************************
【變量命名】:
1.私有字段:_field,m_field
2.公有字段:field
2.屬性:Property
3.常量:CONST
4.靜態變量:Field,Property
**************************************************************************************/
#endregion
";
}
internal static void QuickCreateTemplate<T>() where T : ScriptTemplate, new()
{
EditorApplication.ExecuteMenuItem("Assets/Create/C# Script");
EditorApplication.update = () =>
{
if (Selection.activeObject)
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var temp = new T();
temp.headerInfo.scriptName = Path.GetFileNameWithoutExtension(path);
var dir = Path.GetDirectoryName(path);
var scr = temp.CreateScript();
temp.SaveToFile(dir, scr);
EditorApplication.update = null;
}
};
}
}
#endregion
#region Templates
/// <summary>
/// 代碼創建模板的模板
/// </summary>
[System.Serializable]
public class ScriptTemplate
{
[System.Serializable]
public class FieldItem
{
public string type;
public string elementName;
public string comment;
}
[System.Serializable]
public class PropertyItem
{
public string type;
public string elementName;
public string comment;
public bool get;
public bool set;
public PropertyItem()
{
get = set = true;
}
}
[SerializeField]
protected List<FieldItem> fields = new List<FieldItem>();
[SerializeField]
protected List<PropertyItem> propertys = new List<PropertyItem>();
public string json;
public string type;
public TempScriptHeader headerInfo = new TempScriptHeader();
public string path;
public virtual string Name { get { return null; } }
private ReorderableList detailList;
public virtual void OnBodyGUI() { }
public virtual void OnFootGUI()
{
if (detailList == null)
{
InitDetailList();
}
if (detailList.list != headerInfo.detailInfo)
{
detailList.list = headerInfo.detailInfo;
}
using (var horm = new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("Namespace", GUILayout.Width(70));
headerInfo.nameSpace = EditorGUILayout.TextField(headerInfo.nameSpace, GUILayout.Width(60));
EditorGUILayout.LabelField("Type", GUILayout.Width(40));
headerInfo.scriptName = EditorGUILayout.TextField(headerInfo.scriptName, GUILayout.Width(60));
EditorGUILayout.LabelField("簡介", GUILayout.Width(40));
headerInfo.description = EditorGUILayout.TextField(headerInfo.description);
if (GUILayout.Button("Load", EditorStyles.miniButtonRight, GUILayout.Width(60)))
{
OnLoadButtonClicked();
}
}
using (var hor = new EditorGUILayout.HorizontalScope())
{
using (var vertical = new EditorGUILayout.VerticalScope())
{
detailList.DoLayoutList();
}
using (var vertical = new EditorGUILayout.VerticalScope(GUILayout.Width(60)))
{
if (GUILayout.Button("Create", EditorStyles.miniButtonRight, GUILayout.Height(60)))
{
OnCreateButtonClicked();
}
}
}
}
public void OnEnable()
{
type = this.GetType().FullName;
Debug.Log(type);
}
public string CreateScript()
{
var ns = CreateNameSpace();
if (ns == null) return null;
var nsstr = ComplieNameSpaceToString(ns);
if (string.IsNullOrEmpty(nsstr)) return null;
var scriptStr = GetHeader() + nsstr + GetFooter();
if (string.IsNullOrEmpty(scriptStr))
{
EditorUtility.DisplayDialog("生成失敗", "請看日誌!", "確認");
return null;
}
return scriptStr;
}
public void SaveToJson()
{
json = null;
json = JsonUtility.ToJson(this);
if (string.IsNullOrEmpty(type))
{
type = this.GetType().FullName;
}
}
protected void InitDetailList()
{
detailList = new ReorderableList(headerInfo.detailInfo, typeof(string), true, false, true, true);
detailList.onAddCallback += (x) => { headerInfo.detailInfo.Add(""); };
detailList.drawHeaderCallback = (x) => { EditorGUI.LabelField(x, "詳細信息"); };
detailList.drawElementCallback += (x, y, z, w) => { headerInfo.detailInfo[y] = EditorGUI.TextField(x, headerInfo.detailInfo[y]); };
}
protected void DrawFieldItem(Rect rect, FieldItem dataItem, bool haveType)
{
if (haveType)
{
var rect01 = new Rect(rect.x, rect.y, rect.width * 0.2f, EditorGUIUtility.singleLineHeight);
var typeRect = new Rect(rect.x + 0.2f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect02 = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var commentRect = new Rect(rect.x + 0.6f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect03 = new Rect(rect.x + rect.width * 0.7f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
dataItem.elementName = EditorGUI.TextField(rect01, dataItem.elementName);
EditorGUI.LabelField(typeRect, "Type");
dataItem.type = EditorGUI.TextField(rect02, dataItem.type);
EditorGUI.LabelField(commentRect, "Comment");
dataItem.comment = EditorGUI.TextField(rect03, dataItem.comment);
}
else
{
var left = new Rect(rect.x, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var right = new Rect(rect.x + rect.width * 0.4f, rect.y, rect.width * 0.6f, EditorGUIUtility.singleLineHeight);
var center = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
dataItem.elementName = EditorGUI.TextField(left, dataItem.elementName);
EditorGUI.LabelField(center, "Comment");
dataItem.comment = EditorGUI.TextField(right, dataItem.comment);
}
}
protected void DrawPropertyItem(Rect rect, PropertyItem propertyItem)
{
var rect01 = new Rect(rect.x, rect.y, rect.width * 0.2f, EditorGUIUtility.singleLineHeight);
var typeRect = new Rect(rect.x + 0.2f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect02 = new Rect(rect.x + rect.width * 0.3f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
var commentRect = new Rect(rect.x + 0.6f * rect.width, rect.y, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var rect03 = new Rect(rect.x + rect.width * 0.7f, rect.y, rect.width * 0.3f, EditorGUIUtility.singleLineHeight);
propertyItem.elementName = EditorGUI.TextField(rect01, propertyItem.elementName);
EditorGUI.LabelField(typeRect, "Type");
propertyItem.type = EditorGUI.TextField(rect02, propertyItem.type);
EditorGUI.LabelField(commentRect, "Comment");
propertyItem.comment = EditorGUI.TextField(rect03, propertyItem.comment);
var getLabelRect = new Rect(rect.x, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var getRect = new Rect(rect.x + 0.1f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var setLabelRect = new Rect(rect.x + 0.2f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
var setRect = new Rect(rect.x + 0.3f * rect.width, rect.y + EditorGUIUtility.singleLineHeight, rect.width * 0.1f, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(getLabelRect, "get");
propertyItem.get = EditorGUI.Toggle(getRect, propertyItem.get);
EditorGUI.LabelField(setLabelRect, "set");
propertyItem.set = EditorGUI.Toggle(setRect, propertyItem.set);
}
protected virtual CodeNamespace CreateNameSpace()
{
return null;
}
protected string GetHeader()
{
headerInfo.Update();
var str1 = "#region statement\r\n" +
"/************************************************************************************* \r\n" +
" * 作 者: {0}\r\n" +
" * 時 間: {1}\r\n" +
" * 說 明: ";
var str2 = "\r\n ";
var str3 = "\r\n* ************************************************************************************/" +
"\r\n#endregion\r\n";
var headerStr = string.Format(str1, headerInfo.author, headerInfo.time);
for (int i = 0; i < headerInfo.detailInfo.Count; i++)
{
if (i == 0)
{
headerStr += string.Format("{0}.{1}", i + 1, headerInfo.detailInfo[i]);
}
else
{
headerStr += string.Format("{0}{1}.{2}", str2, i + 1, headerInfo.detailInfo[i]);
}
}
headerStr += str3;
return headerStr;
}
protected string ComplieNameSpaceToString(CodeNamespace nameSpace)
{
using (Microsoft.CSharp.CSharpCodeProvider cprovider = new Microsoft.CSharp.CSharpCodeProvider())
{
StringBuilder fileContent = new StringBuilder();
var option = new System.CodeDom.Compiler.CodeGeneratorOptions();
option.BlankLinesBetweenMembers = false;
using (StringWriter sw = new StringWriter(fileContent))
{
cprovider.GenerateCodeFromNamespace(nameSpace, sw, option);
}
return fileContent.ToString();
}
}
protected string GetFooter()
{
if (TempScriptHelper.GetRuleShowState())
{
var rule = TempScriptHelper.GetCodeRule();
return rule;
}
return null;
}
/// <summary>
/// 點擊創建
/// </summary>
private void OnCreateButtonClicked()
{
if (string.IsNullOrEmpty(headerInfo.scriptName))
{
EditorUtility.DisplayDialog("腳本名爲空", "請填寫代碼名稱!", "確認");
return;
}
if (string.IsNullOrEmpty(path))
{
if (ProjectWindowUtil.IsFolder(Selection.activeInstanceID))
{
path = AssetDatabase.GetAssetPath(Selection.activeInstanceID);
}
else if (Selection.activeObject != null)
{
var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!string.IsNullOrEmpty(assetPath))
{
path = assetPath.Replace(System.IO.Path.GetFileName(assetPath), "");
}
}
}
var scriptStr = CreateScript();
if (!string.IsNullOrEmpty(scriptStr))
{
SaveToFile(path, scriptStr);
}
}
/// <summary>
/// 保存到文件
/// </summary>
/// <param name="path"></param>
/// <param name="scriptStr"></param>
public void SaveToFile(string path, string scriptStr)
{
if (!string.IsNullOrEmpty(path))
{
var scriptPath = string.Format("{0}/{1}.cs", path, headerInfo.scriptName);
System.IO.File.WriteAllText(scriptPath, scriptStr, System.Text.Encoding.UTF8);
AssetDatabase.Refresh();
}
else
{
EditorUtility.DisplayDialog("路徑不明", "請選中文件夾後重試", "確認");
}
}
/// <summary>
/// 點擊加載代碼
/// </summary>
private void OnLoadButtonClicked()
{
if (!(Selection.activeObject is TextAsset))
{
EditorUtility.DisplayDialog("未選中", "請選中需要解析的代碼後繼續", "確認");
return;
}
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!path.EndsWith(".cs"))
{
EditorUtility.DisplayDialog("未選中", "請選中需要解析的代碼後繼續", "確認");
return;
}
using (var provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp"))
{
EditorUtility.DisplayDialog("未開發", ".net 3.5暫無該實現", "確認");
var fileContent = System.IO.File.ReadAllText(path, Encoding.UTF8);
using (StringReader sr = new StringReader(fileContent))
{
var nameSpaceUnit = provider.Parse(sr);
Debug.Log(nameSpaceUnit);
}
}
}
}
#endregion
#region Enum
/// <summary>
/// 1.枚舉類型腳本
/// </summary>
[Serializable]
public class EnumScriptTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Enum", priority = 5)]
static void CreateEnum()
{
TempScriptHelper.QuickCreateTemplate<EnumScriptTemplate>();
}
public override string Name
{
get
{
return "Enum";
}
}
private ReorderableList reorderableList;
public EnumScriptTemplate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "枚舉列表"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], false);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsEnum = true;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(headerInfo.description, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
return nameSpace;
}
public override void OnBodyGUI()
{
reorderableList.DoLayoutList();
}
}
#endregion
#region DataModel
/// <summary>
/// 2.數據模擬類
/// </summary>
[Serializable]
public class DataModelTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Model", priority = 5)]
static void CreateModel()
{
TempScriptHelper.QuickCreateTemplate<DataModelTemplate>();
}
public override string Name
{
get
{
return "Model";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine",
"UnityEngine.UI",
"System.Collections",
"System.Collections.Generic",
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public DataModelTemplate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "模型名"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空間"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(System.SerializableAttribute).FullName));
wrapProxyClass.IsClass = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "數據模型" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
#region Static
/// <summary>
/// 3.靜態類
/// </summary>
[Serializable]
public class StaticClassTemplate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Static", priority = 5)]
static void CreateModel()
{
TempScriptHelper.QuickCreateTemplate<StaticClassTemplate>();
}
public override string Name
{
get
{
return "Static";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine"
};
private ReorderableList nameSpaceList;
private ReorderableList propertyList;
private ReorderableList fieldList;
public StaticClassTemplate()
{
fieldList = new ReorderableList(fields, typeof(string));
fieldList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
fieldList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "字段"); };
fieldList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
propertyList = new ReorderableList(propertys, typeof(string));
propertyList.onAddCallback += (x) => { propertys.Add(new PropertyItem()); };
propertyList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "屬性"); };
propertyList.elementHeightCallback = (x) => { return 2 * EditorGUIUtility.singleLineHeight; };
propertyList.drawElementCallback += (x, y, z, w) =>
{
DrawPropertyItem(x, propertys[y]);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空間"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> codeFields = new List<CodeMemberField>();
foreach (var item in fields)
{
CodeMemberField field = new CodeMemberField();
field.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
field.Attributes = MemberAttributes.Public | MemberAttributes.Static;
field.Name = item.elementName;
//field.InitExpression = invokeExpression;
field.Comments.Add(new CodeCommentStatement(item.comment));
codeFields.Add(field);
}
List<CodeMemberProperty> propertysMemper = new List<CodeMemberProperty>();
foreach (var item in propertys)
{
CodeMemberProperty prop = new CodeMemberProperty();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public|MemberAttributes.Static;
prop.Name = item.elementName;
prop.HasGet = item.get;
prop.HasSet = item.set;
//CodeExpression invokeExpression = new CodePropertyReferenceExpression();
prop.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
prop.Comments.Add(new CodeCommentStatement(item.comment));
propertysMemper.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;//沒有靜態?
wrapProxyClass.Attributes = MemberAttributes.Static;
wrapProxyClass.IsClass = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "靜態類" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var prop in propertysMemper)
{
wrapProxyClass.Members.Add(prop);
}
foreach (var field in codeFields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
fieldList.DoLayoutList();
propertyList.DoLayoutList();
}
}
#endregion
#region Struct
/// <summary>
/// 5.結構體模板
/// </summary>
[Serializable]
public class StructTempate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Struct", priority = 5)]
static void CreateStruct()
{
TempScriptHelper.QuickCreateTemplate<StructTempate>();
}
public override string Name
{
get
{
return "Struct";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine",
"UnityEngine.UI",
"System.Collections",
"System.Collections.Generic",
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public StructTempate()
{
reorderableList = new ReorderableList(fields, typeof(string));
reorderableList.onAddCallback += (x) => { fields.Add(new FieldItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "模型名"); };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawFieldItem(x, fields[y], true);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空間"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberField> fields = new List<CodeMemberField>();
foreach (var item in base.fields)
{
CodeMemberField prop = new CodeMemberField();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.Comments.Add(new CodeCommentStatement(item.comment));
fields.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsStruct = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "結構體" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var field in fields)
{
wrapProxyClass.Members.Add(field);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
#region Interface
/// <summary>
/// 6.接口創建模板
/// </summary>
[Serializable]
public class InterfaceTempate : ScriptTemplate
{
[MenuItem("Assets/Create/C# TempScripts/Interface", priority = 5)]
static void CreateEnum()
{
TempScriptHelper.QuickCreateTemplate<InterfaceTempate>();
}
public override string Name
{
get
{
return "Interface";
}
}
[SerializeField]
private List<string> imports = new List<string>() {
"System",
"UnityEngine"
};
private ReorderableList nameSpaceList;
private ReorderableList reorderableList;
public InterfaceTempate()
{
reorderableList = new ReorderableList(propertys, typeof(string));
reorderableList.onAddCallback += (x) => { propertys.Add(new PropertyItem()); };
reorderableList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "屬性"); };
reorderableList.elementHeightCallback = (x) => { return 2 * EditorGUIUtility.singleLineHeight; };
reorderableList.drawElementCallback += (x, y, z, w) =>
{
DrawPropertyItem(x, propertys[y]);
};
nameSpaceList = new ReorderableList(imports, typeof(string));
nameSpaceList.onAddCallback += (x) => { imports.Add(""); };
nameSpaceList.drawHeaderCallback += (x) => { EditorGUI.LabelField(x, "命名空間"); };
nameSpaceList.drawElementCallback += (x, y, z, w) =>
{
imports[y] = DrawNameSpace(x, imports[y]);
};
}
protected override CodeNamespace CreateNameSpace()
{
List<CodeMemberProperty> propertysMemper = new List<CodeMemberProperty>();
foreach (var item in propertys)
{
CodeMemberProperty prop = new CodeMemberProperty();
prop.Type = new CodeTypeReference(item.type, CodeTypeReferenceOptions.GenericTypeParameter);
prop.Attributes = MemberAttributes.Public;
prop.Name = item.elementName;
prop.HasGet = item.get;
prop.HasSet = item.set;
prop.Comments.Add(new CodeCommentStatement(item.comment));
propertysMemper.Add(prop);
}
CodeTypeDeclaration wrapProxyClass = new CodeTypeDeclaration(headerInfo.scriptName);
wrapProxyClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
wrapProxyClass.IsInterface = true;
var destription = string.IsNullOrEmpty(headerInfo.description) ? "接口" : headerInfo.description;
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
wrapProxyClass.Comments.Add(new CodeCommentStatement(destription, true));
wrapProxyClass.Comments.Add(new CodeCommentStatement("<summary>", true));
foreach (var prop in propertysMemper)
{
wrapProxyClass.Members.Add(prop);
}
CodeNamespace nameSpace = new CodeNamespace(headerInfo.nameSpace);
nameSpace.Types.Add(wrapProxyClass);
nameSpace.Imports.AddRange(imports.ConvertAll<CodeNamespaceImport>(x => new CodeNamespaceImport(x)).ToArray());
return nameSpace;
}
private string DrawNameSpace(Rect rect, string dataItem)
{
var rect1 = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
return EditorGUI.TextField(rect1, dataItem);
}
public override void OnBodyGUI()
{
nameSpaceList.DoLayoutList();
reorderableList.DoLayoutList();
}
}
#endregion
///下面可以自定義你的代碼生成模板
///...
/// <summary>
/// UI模板
/// </summary>
//[Serializable]
//public class UIPanelTempate : ScriptTemplate
//{
// public override string Name
// {
// get
// {
// return "UIPanel";
// }
// }
// protected override CodeNamespace CreateNameSpace()
// {
// return null;
// }
// public override void OnBodyGUI()
// {
// }
//}
}