아카이빙/Unity3D

[Unity3D] 커스텀 에디터(3) - EditorWindow

셩님 2017. 4. 10. 00:48

유니티 커스텀 에디터 공부 세번째 - EditorWindow

에디터 윈도우는 인스펙터 창이아닌 Sprite Editor나 Animation처럼 새로운 윈도우를 띄울 수 있는 기능이다. 컴포넌트를 넣지 않아도 사용할 수 있기 떄문에 인스펙터 창을 커스터마이징 하는 것 보다 범용성이 높다고 볼 수 있다. 맵 툴, 혹은 데이터 관리 에디터를 만들 때 유용해보인다.

참고로 유니티 커스텀 에디터 포스팅 예제는 대부분 Unity Scripting API를 참조하였다.

1. EditorWindow 예제

using UnityEngine;
using UnityEditor;
public class MyWindow : EditorWindow
{
    string myString = "Hello World";
    bool groupEnabled;
    bool myBool = true;
    float myFloat = 1.23f;

    //Window 메뉴에 "My Window" 항목을 추가한다.
    [MenuItem("Window/My Window")]
    static void Init()
    {
        // 생성되어있는 윈도우를 가져온다. 없으면 새로 생성한다. 싱글턴 구조인듯하다.
        MyWindow window = (MyWindow)EditorWindow.GetWindow(typeof(MyWindow));
        window.Show();
    }

    void OnGUI()
    {
        GUILayout.Label("Base Settings", EditorStyles.boldLabel);
        myString = EditorGUILayout.TextField("Text Field", myString);

        groupEnabled = EditorGUILayout.BeginToggleGroup("Optional Settings", groupEnabled);
        myBool = EditorGUILayout.Toggle("Toggle", myBool);
        myFloat = EditorGUILayout.Slider("Slider", myFloat, -3, 3);
        EditorGUILayout.EndToggleGroup();
    }
}

앞선 포스팅에서 알아보았던 EditorGUILayout를 응용하여 EditorWindow에 활용한다.

ToggleGroup을 만들어 groupEnabled의 값에 따라 "Toggle", "Slider"가 활성화/비활성화 된다.

EditorStyles는 양이 꽤 많기 때문에 다음 포스팅에서 다룰 예정.

2. Begin-End Horizontal 예제

using UnityEngine;
using UnityEditor;

public class BeginEndHorizontalExample : EditorWindow
{
    [MenuItem("Examples/Begin-End Horizontal usage")]
    static void Init()
    {
        BeginEndHorizontalExample window =
          (BeginEndHorizontalExample)EditorWindow.GetWindow(typeof(BeginEndHorizontalExample));
        window.Show();
    }

    void OnGUI()
    {
        Rect r = EditorGUILayout.BeginHorizontal("Button");
        if (GUI.Button(r, GUIContent.none))
            Debug.Log("Go here");
        GUILayout.Label("I'm inside the button");
        GUILayout.Label("So am I");
        EditorGUILayout.EndHorizontal();
    }
}

이 예제는 InspectorGUI 에서 다루려고 했지만 EditorWindow와 관련된 예제라서 이번 포스팅에서 다룬다.

3.Begin-End Vertical 예제랑 비교하면서 보자.

3. Begin-End Vertical 예제

using UnityEngine;
using UnityEditor;

public class BeginVerticalExample : EditorWindow
{
    [MenuItem("Examples/Begin-End Vertical usage")]
    static void Init()
    {
        BeginVerticalExample window =
          (BeginVerticalExample)EditorWindow.GetWindow(typeof(BeginVerticalExample),
                                                       utility:true,
                                                       title:"Floating Window");
        window.Show();
    }

    void OnGUI()
    {
        Rect r = (Rect)EditorGUILayout.BeginVertical("Button");
        if (GUI.Button(r, GUIContent.none))
            Debug.Log("Go here");
        GUILayout.Label("I'm inside the button");
        GUILayout.Label("So am I");
        EditorGUILayout.EndVertical();
    }
}


Horizontal과 비교하면 EditorWindow.GetWindow()에서 utility옵션과 title옵션의 차이가 있다.

utilitytrue이면 floating utility window를 생성하고, false이면 normal window를 생성한다.

용어의 혼란이 있을 수 있겠지만 이미지를 보면 바로 이해가 갈 것.


4. Popup 예제

using UnityEditor;
using UnityEngine;
using System.Collections;

public class EditorGUILayoutPopup : EditorWindow
{
    public string[] options = new string[] {"Cube", "Sphere", "Plane"};
    public int index = 0;
    [MenuItem("Examples/Editor GUILayout Popup usage")]
    static void Init()
    {
        EditorWindow window = GetWindow(typeof(EditorGUILayoutPopup));
        window.Show();
    }

    void OnGUI()
    {
        index = EditorGUILayout.Popup(selectedIndex:index, displayedOptions:options);
        if (GUILayout.Button("Create"))
            InstantiatePrimitive();
    }

    void InstantiatePrimitive()
    {
        switch (index)
        {
        case 0:
            GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.transform.position = Vector3.zero;
            break;
        case 1:
            GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.position = Vector3.zero;
            break;
        case 2:
            GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
            plane.transform.position = Vector3.zero;
            break;
        default:
            Debug.LogError("Unrecognized Option");
            break;
        }
    }
}


Cube, Sphere, Plane을 옵션으로 선택할 수 있고, Create 버튼을 통해 오브젝트를 직접 생성하는 윈도우다. 이 부분이 에디터 스크립트의 가장 강력한 강점이 아닐까 싶다. 스크립트로 오브젝트를 생성할 수 있기 때문에 불필요한 반복작업을 확연히 줄일 수 있다.