エディタ拡張でDefineSymbolsのプリセットを作成する

この記事は2017年06月28日にqiitaに投稿した内容です。

環境

Unity5.6.2f1

概要

同じビルドターゲットでDefine定義でのモード切り替えを行いたい為に、DefineSymbolsのプリセットを作成してみました ビルドターゲットはチェックボックスで複数指定できるので一括で変更できます

プログラム

Assets/Editor/DefineSymbolsWindow.cs

using System.IO;
using UnityEditor;
using UnityEngine;

public class DefineSymbolsWindow : EditorWindow
{
    [MenuItem( "Tools/DefineSymbols" )]
    public static void Create()
    {
        var window = GetWindow<DefineSymbolsWindow>( "DefineSymbolsWindow" );
        window.Show();
    }

    private DefineSymbols _obj = null;

    private void OnEnable()
    {
        var ms = MonoScript.FromScriptableObject( this );
        var path = AssetDatabase.GetAssetPath( ms );
        path = path.Replace( Path.GetFileName( path ), "" );
    //  Debug.Log( "path:" + path );
        path = path + "DefineSymbols.asset";
        _obj = AssetDatabase.LoadAssetAtPath<DefineSymbols>( path );
        if( _obj == null )
        {
            _obj = ScriptableObject.CreateInstance<DefineSymbols>();
            AssetDatabase.CreateAsset( _obj, path );
            AssetDatabase.ImportAsset( path, ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );
        }
    }

    private void OnDisable()
    {
        if( _obj == null )
            return;
        EditorUtility.SetDirty( _obj );
        AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( _obj ), ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive );
    }

    private void OnGUI()
    {
        _obj.OnGUI();
        Repaint();
    }
}

Assets/Editor/DefineSymbols.cs

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class DefineSymbols : ScriptableObject
{
    [Serializable]
    private class SymbolParam
    {
        public string name;
        public string symbols;
        public List<string> targets = new List<string>();
    }
    [SerializeField] private List<SymbolParam> _symbolParams = new List<SymbolParam>();
    [SerializeField] private int _selectedDropdownList = 0;
    private string _newParamName = "";
    private string _defineSymbols = null;

    private void OnEnable()
    {
    }

    private void OnDisable()
    {
    }

    public void OnGUI()
    {
        GUILayout.Label( "New Preset" );
        using ( var horizontalScope = new GUILayout.HorizontalScope() )
        {
            _newParamName = EditorGUILayout.TextField("", _newParamName );
            if( GUILayout.Button( "Add" ) == true )
            {
                if( _newParamName.Length > 0 && _symbolParams.Count( x => x.name == _newParamName ) == 0 )
                {
                    _selectedDropdownList = _symbolParams.Count;
                    var newParam = new SymbolParam();
                    newParam.name = _newParamName;
                    _symbolParams.Add( newParam );
                    _newParamName = null;
                }
            }
        }

        GUILayout.Label( "Presets" );

        var names = new string[ _symbolParams.Count ];
        for( int i = 0; i < _symbolParams.Count; i++ )
            names[ i ] = _symbolParams[ i ].name;
        var prevSelectedDropdownList = _selectedDropdownList;
        _selectedDropdownList = EditorGUILayout.Popup( "", _selectedDropdownList, names );
        SymbolParam param = null;
        if( _selectedDropdownList >= 0 &&  _selectedDropdownList < _symbolParams.Count )
            param = _symbolParams[ _selectedDropdownList ];

        if ( _selectedDropdownList != prevSelectedDropdownList )
        {
        //  if( param != null )
        //      FlushSymbolsByTargets( param );
        }


        using ( var horizontalScope = new GUILayout.HorizontalScope() )
        {
            EditorGUILayout.Space();
            EditorGUILayout.Space();
            EditorGUILayout.Space();
            if( GUILayout.Button( "Remove" ) == true )
            {
                if( param != null )
                {
                    _symbolParams.RemoveAt( _selectedDropdownList );
                    _selectedDropdownList = Mathf.Clamp( _selectedDropdownList, -1, _symbolParams.Count - 1 );
                    return; //消したのでここで打ち切る
                }
            }
        }

        GUILayout.Label( "Define Symboles" );

        if( param != null )
        {
            param.symbols = EditorGUILayout.TextField( "", param.symbols );
            var rect = GUILayoutUtility.GetLastRect();
            if( Event.current.type == EventType.Repaint && rect.Contains( Event.current.mousePosition ) == false )
            {
                if( _defineSymbols != param.symbols )
                {
                    //Debug.Log( "ChangeDefineSymbol:" + param.symbols );
                    _defineSymbols = param.symbols;
                    FlushSymbolsByTargets( param );
                }
            }
        }
        else
            EditorGUILayout.TextField( "", "" );

        GUILayout.Label( "Targets" );

        var targetNames = Enum.GetNames( typeof( BuildTargetGroup ) ).ToList();
        targetNames.Remove( "Unknown" );
        int cx = 3;
        int cy = targetNames.Count / cx + ( ( ( targetNames.Count % cx ) > 0 ) ? 1 : 0 );
        using ( var verticalScope = new GUILayout.VerticalScope() )
        {
            for( int y = 0; y < cy; y++ )
            {
                using ( var horizontalScope = new GUILayout.HorizontalScope() )
                {
                    for( int x = 0; x < cx; x++ )
                    {
                        var i = ( y * cx ) + x;
                        if( i >= targetNames.Count )
                        {
                            EditorGUILayout.LabelField( "" );
                            continue;
                        }

                        if( param != null )
                        {
                            var toggle = false;
                            if( param.targets.FirstOrDefault( name => name == targetNames[ i ] ) != null )
                                toggle = true;

                            var newToggle = EditorGUILayout.ToggleLeft( targetNames[ i ], toggle );
                            if( toggle == false && newToggle == true )
                            {
                                param.targets.Add( targetNames[ i ] );
                                FlushSymbols( targetNames[ i ], param.symbols );
                            }
                            else if( toggle == true && newToggle == false )
                            {
                                param.targets.Remove( targetNames[ i ] );
                                FlushSymbols( targetNames[ i ], "" );
                            }
                        }
                        else
                            EditorGUILayout.ToggleLeft( targetNames[ i ], false );
                    }
                }
            }
        }
    }

    private void FlushSymbols( string targetName, string defineSymbols )
    {
        var names = Enum.GetNames( typeof( BuildTargetGroup ) );
        var values = Enum.GetValues( typeof( BuildTargetGroup ) );
        var indices = names.Select( ( n, i ) => new { name = n, index = i } ).Where( x => x.name == targetName ).Select( x => x.index );
        if( indices.Count() == 0 )
            return;
        var index = indices.ElementAt( 0 );
        var target = (BuildTargetGroup)values.GetValue( index );
        PlayerSettings.SetScriptingDefineSymbolsForGroup( target, defineSymbols );
    }

    private void FlushSymbolsByTargets( SymbolParam param )
    {
        for( int i = 0; i < param.targets.Count; i++ )
            FlushSymbols( param.targets[ i ], param.symbols );
    }
}