この記事でのバージョン
Unity 4.6.3f1
はじめに
前回、既存のスクリプトからテンプレを作れるようにはなったけど、
その後にCreateメニューに表示するためにコード書くのめんどくね?
って所で終わりました。
なので今回はテンプレメニューを自動で更新するエディタ拡張のご紹介!
プログラム
何はなくともプログラムから!長いですよ!
CustomScriptCreatorが前回同様、テンプレから新たにスクリプトを作るクラス、
TemplateScriptCreatorも前回同様、既存スクリプトから新たにテンプレを作るクラス、
TemplatePostprocessorが今回作成した、テンプレメニューを自動で更新するクラス、
AssetPostprocessorExは、以前作ったAssetPostprocessorの拡張クラス、
Extensionは、拡張子の定数クラス、
DirectoryPathは、ディレクトリへのパスの定数クラス、
TemplateTagNameは、Templateで使うタグ名の定数クラス、
CustomScriptCreatorにメニュー表示用コードを追加していくのでは無く、
各テンプレ毎にCustomScriptCreatorを継承したクラスを作りメニューを追加するようにしました。
さらに各テンプレ毎のCustomScriptCreatorはTemplatePostprocessorで自動更新をしています。
自動更新の方法はテンプレが入っているディレクトリを監視し、
テンプレが追加されれば、そのテンプレ用CustomScriptCreatorを作成、
テンプレが削除されれば該当するCustomScriptCreatorを削除、
とい言った具合です。
また、前回は共通して使う定数をScriptCreatorにまとめて、それを継承していましたが、
今回は各定数クラスにまとめていますのでご注意を!
使い方
まずAssetPostprocessorEx、TemplatePostprocessor、CustomScriptCreator、TemplateScriptCreator、
を以下のような構成で、Editorディレクトリに入れます
次にDirectoryPath、Extension、TemplateTagNameを
どこでもいいので、適当なディレクトリに入れます。
最後にScriptsというディレクトリを作り、
その下にさらにTemplatesというディレクトリを作り、準備完了です。
最初はCreateメニューにTemplate Scriptという項目が追加されただけですが、
任意スクリプト、例えばHeroというクラスを選択しTemplate Scriptを押し、
テンプレを作成すると……
Custom Scriptとその先にHeroという項目が自動で追加されます!
テンプレ作成後にコードを追加する手間が無くなりました!楽!
Template Scriptの詳しい使い方は前回記事、
Custom Scriptの詳しい使い方は前々回記事を参照のこと!
コード説明
ではでは項目ごとにTemplatePostprocessorのコード説明です!
CustomScriptCreator周りの説明は前々回記事を参照のこと。
TemplateScriptCreator周りの説明は前回記事を参照のこと。
OnPostprocessAllAssets
OnPostprocessAllAssetsでテンプレが入っているディレクトリを監視し、
変更があった時にCustomScriptCreatorの更新を行っています。
詳しくは下記の記事で!
念の為、[MenuItem(COMMAND_NAME)]を更新メソッドの前に書く事で、
任意のタイミングで更新を実行する事も出来るようにしています。
テンプレに対応するCustomScriptCreatorが無ければ作成
System.IO.Directory.GetFilesでテンプレのテキストを全て取得し、そのファイル名から
該当するCustomScriptCreatorのパスを作成、そのパスにファイルが無ければ、
CreateCustomScriptCreatorでCustomScriptCreatorを作成しています。
//テンプレートフォルダ内のtextファイルへのパスを全て取得 string templateDirectoryPath = DirectoryPath.TEMPLATE_SCRIPT_DIRECTORY_PATH; string[] templatePathArray = System.IO.Directory.GetFiles (templateDirectoryPath, "*" + Extension.TEMPLATE_SCRIPT); foreach(string templatePath in templatePathArray){ //拡張子を含まないファイル名を取得 string templateName = System.IO.Path.GetFileNameWithoutExtension(templatePath); //書き出し先 string exportPath = EXPORT_DIRECTORY_PATH + string.Format (EXPORT_SCRIPT_NAME_FORMAT, templateName); //このテンプレのCustomScriptCreatorが作成されていなければ作成 if (!System.IO.File.Exists(exportPath)){ CreateCustomScriptCreator (templateName, exportPath); } }
なお、テンプレ以外のファイルがあっても、処理を行ってしまうため、
注意が必要です。
CreateCustomScriptCreator
CreateCustomScriptCreatorではCustomScriptCreatorを継承したクラスを作成し、
新たにcreateのCustom Scriptにメニューを追加してます。
//CustomScriptCreatorを作成、Createのメニューで対象のテンプレートを選べるようになる private static void CreateCustomScriptCreator(string templateName, string exportPath){ string customScriptCreatorName = System.IO.Path.GetFileNameWithoutExtension(exportPath); //作成するスクリプトの内容 string scriptText = "using UnityEditor;\n\n" + "/// <summary>\n" + "/// " + templateName +"のテンプレートから新しくスクリプトを作るクラス\n" + "/// </summary>\n" + "public class " + customScriptCreatorName + " : CustomScriptCreator {\n\n\t" + "private const string TEMPLATE_SCRIPT_NAME = \"" + templateName + "\";\n\n\t" + "[MenuItem(MENU_PATH + TEMPLATE_SCRIPT_NAME)]\n\t" + "private static void CreateScript(){\n\t\t" + "ShowWindow (TEMPLATE_SCRIPT_NAME);\n\t" + "}\n\n" + "}\n"; //スクリプトを書き出し File.WriteAllText (exportPath, scriptText, Encoding.UTF8); AssetDatabase.Refresh (ImportAssetOptions.ImportRecursive); Debug.Log (exportPath + "を作成しました"); }
これでメニューに追加する部分を自動作成出来るように……!
該当するテンプレが無いCustomScriptCreatorを削除
テンプレを削除した場合にCustomScriptCreatorだけが残り、
createメニューに存在しないテンプレを表示し続けてしまうので、
以下のコードでCustomScriptCreatorの削除を行っています。
//テンプレートを再度取得し、テンプレートファイル名のリストを作る templatePathArray = System.IO.Directory.GetFiles (templateDirectoryPath, "*" + Extension.TEMPLATE_SCRIPT); List<string > templateNameList = templatePathArray. Select(path => System.IO.Path.GetFileNameWithoutExtension(path)). ToList(); //CustomScriptCreatorフォルダ内のスクリプトを全て取得 string[] customScriptCreatorPathArray = System.IO.Directory.GetFiles (EXPORT_DIRECTORY_PATH, "*" + Extension.SCRIPT); foreach (string customScriptCreatorPath in customScriptCreatorPathArray) { //拡張子を含まないファイル名を取得 string scriptName = System.IO.Path.GetFileNameWithoutExtension(customScriptCreatorPath); //スクリプトから元のテンプレ名を取得 string templateName = scriptName.Remove (scriptName.Length - EXPORT_SCRIPT_NAME_END.Length, EXPORT_SCRIPT_NAME_END.Length); //該当するテンプレが無ければCustomScriptCreatorを削除 if(!templateNameList.Contains(templateName)){ System.IO.File.Delete(customScriptCreatorPath); AssetDatabase.Refresh (ImportAssetOptions.ImportRecursive); Debug.Log (customScriptCreatorPath + "を削除しました"); } }
これまたCustomScriptCreator以外のファイルがあっても、処理を行ってしまうため、
注意が必要です。
あと、templateNameListの作成部分はLINQを使っています。
LINQについてはこちらをどうぞ!
おわりに
テンプレメニューを自動で更新するという目標は達成できましたが、
そもそもテンプレって頻繁に追加しなくね?
( ゚ Д゚)ハッ!
という事でこのシリーズは以上です!