Workspace/Unity3d

[Unity3d][Editor][UIToolkit] Flexible한 3개의 Pane 구성하기

Bombus 2023. 10. 24. 10:10

| 개요

유니티 에디터에서 흔하게 볼 수 있는 Flexible한 UI 구성을 자주 볼 수 있다.

사소한 부분이긴 하지만, 사용 편의성이 크게 다가오기도 한다.

 

때문에, 커스텀한 에디터에서 차용하고 싶어도

기존의 IMGUI에선 구현하기가 번거로웠는데 UIToolkit의 TwoPaneSplitView를 이용하면 간단하게 구현이 가능하다.

 

 

Unity - Manual: Create a custom Editor window

Create a Custom Inspector Create a custom Editor window Custom Editor windows allow you to extend Unity by implementing your own editors and workflows. This guide covers creating an Editor window through code, reacting to user input, making the UI(User Int

docs.unity3d.com

위 매뉴얼을 참고하면 쉽게 구분되고 사이즈 조절이 가능한 두개의 패널을 구현할 수 있다.

그렇다면 3개로 구성하되 좌측과 우측은 고정적인 패널로 중앙 부분의 컨텐츠 패널은 Flexible하게 구성할 순 없을까?

 

| 구현

var splitView = new TwoPaneSplitView(0, 300, TwoPaneSplitViewOrientation.Horizontal);
var splitView2 = new TwoPaneSplitView(1, 300, TwoPaneSplitViewOrientation.Horizontal);
{
	// contentView (flexed)
	var scrollView = new ScrollView(ScrollViewMode.VerticalAndHorizontal);
	splitView2.Add(scrollView);

	var fixedPane = CreateInspectorPane();
	splitView2.Add(fixedPane);
}
		
var flexedPane = new VisualElement();
flexedPane.Add(splitView2);
flexedPane.style.minWidth = 200;

splitView.Add(CreateBoardView());
splitView.Add(flexedPane);

rootVisualElement.Add(splitView);
 

간단히 말하자면 2개의 TwoPaneSplitView를 활용하면 된다.

구분
Fixed
Flexed
첫번째 SplitView
Board View(Left)
두번째 SplitView
두번째 SplitView
Inspector (Right)
Content

위와 같이 첫 번째 SplitView는 Flexed Pane에 SplitView를 겹치면 된다.

(TwoPaneSplitView의 생성자에서 첫번째 인자로 Fixed 패널의 인덱스를 지정할 수 있는데 그 부분을 활용하였다.)

좌측/우측 패널은 위치를 고정하고, 컨텐츠 패널만 Flexible하게 구성할 수 있다.

| 예제 코드

using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.UIElements;

public class FooEditor : EditorWindow
{
	[MenuItem("Tools/Foo", false)]
	static public void Open()
	{
		var window = GetWindow<FooEditor>(false, "Foo", true);
		window.Initialize();
	}

	public void Initialize()
    {
		var splitView = new TwoPaneSplitView(0, 300, TwoPaneSplitViewOrientation.Horizontal);
		var splitView2 = new TwoPaneSplitView(1, 300, TwoPaneSplitViewOrientation.Horizontal);
		{
			// contentView (flexed)
			var scrollView = new ScrollView(ScrollViewMode.VerticalAndHorizontal);
            {
				scrollView.Add(new Label("Content"));
            }
			splitView2.Add(scrollView);

			var fixedPane = CreateInspectorPane();
			splitView2.Add(fixedPane);
        }		
		var flexedPane = new VisualElement();
		flexedPane.Add(splitView2);
		flexedPane.style.minWidth = 200;

		splitView.Add(CreateBoardView());
		splitView.Add(flexedPane);

		var toolBar = new Toolbar();
		{
			var fileButton = new ToolbarButton() { text = "File", name = "FileButton" };
			toolBar.Add(fileButton);

			toolBar.Add(new ToolbarSpacer() { flex = true });

			var helpButton = new ToolbarButton() { text = "Help" };
			toolBar.Add(helpButton);
		}

		rootVisualElement.Add(toolBar);
		rootVisualElement.Add(splitView);
	}

	// Left Pane
	public VisualElement CreateBoardView()
	{
		var boardView = new VisualElement();
		{
			var fooField = new TextField() { label = "Foo" };
			boardView.Add(fooField);

			var barButton = new Button() { text = "Bar" };
			boardView.Add(barButton);
		}
		return boardView;
	}

	// Right Pane
	public VisualElement CreateInspectorPane()
    {
		var inspectorPane = new VisualElement();
        {
			var fooToggle = new Toggle() { label = "Foo" };
			inspectorPane.Add(fooToggle);

			var barToggle = new Toggle() { label = "Bar" };
			inspectorPane.Add(barToggle);
		}
		return inspectorPane;
	}
}
 
반응형