ScriptableObjectのAsset作成系

#環境
Unity5.6.1f1

#概要
ScriptableObjectのAsset作成系色々です。

#プログラム
##EditorCreateAssets
~~~csharp
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;

public class EditorCreateAssets : EditorWindow
{
	//-------------------------------------------------------------------------
	//メニューから独自にアセットを作成する
	//Windowメニュー
	//-------------------------------------------------------------------------
	[MenuItem( "TestCreateAssets/Create/TestAssetA" )]
	public static ScriptableObject CreateAsset()
	{
		var obj = ScriptableObject.CreateInstance( "TestAssetA" );
		ProjectWindowUtil.CreateAsset( obj, "TestAssetA.asset" );
		return obj;
	}

	//-------------------------------------------------------------------------
	//メニューから独自にアセットを作成する サブアセットも作成
	//Windowメニュー
	//-------------------------------------------------------------------------
	[MenuItem( "TestCreateAssets/Create/TestAssetA And TestAssetB" )]
	public static ScriptableObject CreateAssets()
	{
		var obj = ScriptableObject.CreateInstance( "TestAssetA" );

		var endNameEditAction = ScriptableObject.CreateInstance<EndNameEditActionTestAssetA>();
		endNameEditAction.onCreate = OnCreate;
		var icon = AssetPreview.GetMiniThumbnail( obj );
		ProjectWindowUtil.StartNameEditingIfProjectWindowExists( obj.GetInstanceID(), endNameEditAction, "TestAssetA.asset", icon, "" );
		return obj;
	}

	private static void OnCreate( TestAssetA TestAssetA, string pathName )
	{
		var TestAssetB = ScriptableObject.CreateInstance( "TestAssetB" );
		AssetDatabase.AddObjectToAsset( TestAssetB, TestAssetA );
		AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( TestAssetA ), ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );
	}
	//-------------------------------------------------------------------------
	//ファイルダブルクリック時
	//コンテキストメニューでOpenを選択時
	//-------------------------------------------------------------------------
	[OnOpenAssetAttribute(1)]
	public static bool OpenStep1( int instanceID, int line )
	{
		var obj = EditorUtility.InstanceIDToObject( instanceID );
		var name = obj.name;
		Debug.Log("Open Asset step: 1 ("+name+")");

		var TestAssetA = obj as TestAssetA;
		if( TestAssetA == null )
			return false;
		TestAssetA.Open();
		return false;
	}
	[OnOpenAssetAttribute(2)]
	public static bool OpenStep2( int instanceID, int line )
	{
		Debug.Log("Open Asset step: 2 ("+instanceID+")");
		return false;
	}

	//-------------------------------------------------------------------------
	//値を変更
	//独自のコンテキストメニュー
	//Assets/が必要
	//-------------------------------------------------------------------------
	[MenuItem( "Assets/TestCreateAssets/ChangeValue" )] 
	public static bool ChangeValue()
	{
		//GetObjectFolder( Selection.activeObject );

		var obj = Selection.activeObject;
		if( obj == null )
			return false;
		if( ( obj as TestAssetA ) != null )
		{
			var testAssetA = obj as TestAssetA;
			Undo.RecordObject( testAssetA, "ChangeValue:" + testAssetA.name );
			testAssetA.ChangeValue();
		}
		else if( ( obj as TestAssetB ) != null )
		{
			var testAssetB = obj as TestAssetB;
			Undo.RecordObject( testAssetB, "ChangeValue:" + testAssetB.name );
			testAssetB.ChangeValue();
		}
		else
			return false;
	
		//保存
		EditorUtility.SetDirty( obj );
		AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( obj ), ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );
	
		return true;
	}
	//-------------------------------------------------------------------------
	//サブアセット追加
	//独自のコンテキストメニュー
	//Assets/が必要
	//-------------------------------------------------------------------------
	[MenuItem( "Assets/TestCreateAssets/AddSubAsset" )]
	public static bool AddSubAsset()
	{
		var obj = Selection.activeObject;
		if( obj == null )
			return false;
		var TestAssetA = obj as TestAssetA;
		if( TestAssetA == null )
			return false;

		var TestAssetB = ScriptableObject.CreateInstance( "TestAssetB" );
		AssetDatabase.AddObjectToAsset( TestAssetB, TestAssetA );
		AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( TestAssetA ), ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );

		return true;
	}

	//-------------------------------------------------------------------------
	//サブアセット削除
	//独自のコンテキストメニュー
	//Assets/が必要
	//-------------------------------------------------------------------------
	[MenuItem( "Assets/TestCreateAssets/RemoveSubAsset" )]
	public static bool RemoveSubAsset()
	{
		var obj = Selection.activeObject;
		if( obj == null )
			return false;
		var TestAssetB = obj as TestAssetB;
		if( TestAssetB == null )
			return false;

		var mainAsetPath = AssetDatabase.GetAssetPath( TestAssetB );
		Object.DestroyImmediate( TestAssetB, true );
		AssetDatabase.ImportAsset( mainAsetPath, ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );
		return true;
	}

	//-------------------------------------------------------------------------
	//オブジェクトのフォルダを取得
	//-------------------------------------------------------------------------
	private static string GetObjectFolder( Object obj )
	{
		var path = AssetDatabase.GetAssetPath( obj );
		if( obj == null || string.IsNullOrEmpty( path ) == true )
			path = "Assets/";
		else
		{
			if( ProjectWindowUtil.IsFolder( obj.GetInstanceID() ) == false )
				path = path.Replace( Path.GetFileName( AssetDatabase.GetAssetPath( obj ) ), "" );
		}
		Debug.Log( "OpenFolder:" + path );
		return path;
	}
	//-------------------------------------------------------------------------
	//エディタスクリプトのフォルダを取得
	//-------------------------------------------------------------------------
	private static string GetEditorScriptFolder( ScriptableObject sobj )
	{
		//var ms = MonoScript.FromMonoBehaviour( sobj);
		var ms = MonoScript.FromScriptableObject( sobj);
		return GetObjectFolder( ms );
	}
}
~~~
##EndNameEditActionTestAssetA
~~~csharp
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
using UnityEngine;
using UnityEngine.Events;

public class EndNameEditActionTestAssetA : EndNameEditAction
{
	public UnityAction<TestAssetA, string> onCreate = null;

	public override void Action( int instanceId, string pathName, string resourceFile )
	{
		var TestAssetA = EditorUtility.InstanceIDToObject( instanceId ) as TestAssetA;
		AssetDatabase.CreateAsset( TestAssetA, pathName );
		AssetDatabase.ImportAsset( pathName );
		ProjectWindowUtil.ShowCreatedAsset( TestAssetA );

		if( onCreate != null )
			onCreate.Invoke( TestAssetA, pathName );
	}
}
~~~
##TestAssetA
~~~csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//アセットAの作成
//ContextメニューのCreateに追加される
[CreateAssetMenu( fileName = "TestAssetA", menuName = "TestCreateAssets/TestAssetA", order = 1 )]
public class TestAssetA : ScriptableObject
{
	[SerializeField] private int _intValue0 = 0;
	[SerializeField] private float _floatValue0 = 1.0f;

	public void Open()
	{
		Debug.Log( "Open!" + name );
	}

	public void ChangeValue()
	{
		Debug.Log( "ChangeValue!" + name );

		_intValue0 ++;
		_floatValue0 += 1.0f;
	}
}
~~~
##TestAssetB
~~~csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//アセットBの作成
//ContextメニューのCreateに追加される
[CreateAssetMenu( fileName = "TestAssetB", menuName = "TestCreateAssets/TestAssetB", order = 1 )]
public class TestAssetB : ScriptableObject
{
	[SerializeField] private int _intValue0 = 10;
	[SerializeField] private float _floatValue0 = 11.0f;

	public void Open()
	{
		Debug.Log( "Open!" + name );
	}

	public void ChangeValue()
	{
		Debug.Log( "ChangeValue!" + name );

		_intValue0 ++;
		_floatValue0 += 1.0f;
	}
}
~~~