EditorWindowの分割(Editor拡張)

EditorWindowの分割(Editor拡張)

EditorWindowを分割するScriptを作成しました。

Script

 EditorWindowを分割するScriptは以下の通りです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;

namespace KaraNoKan.CustomEditorGUILayout
{
    public class EditorGUISplitArea
    {
        bool changed = true; //領域の分割に変更を加えた場合はtrueにする

        int border_width = 3;
        float min_height = 50f;
        float min_width = 50f;
        Color color_border = new Color(0.3f, 0.3f, 0.3f, 1f);

        Stack<Rect> stack_rect = new Stack<Rect>();
        Stack<float> stack_ratio = new Stack<float>();  //変更前のraitoの保存と使用
        Stack<float> temp_stack_ratio = new Stack<float>(); //変更したratioの受け取りと受け渡し用

        Vector2 mouse_pos;
        Rect rect_parent = new Rect(0, 0, 0, 0);

        //分割されている領域の構造を調べるために使用
        Stack<int> stack_vert_count = new Stack<int>();
        List<string> structure_vert = new List<string>();
        List<int> list_vert_count = new List<int>();
        int vert_area_count = 0;

        Stack<int> stack_horiz_count = new Stack<int>();
        List<string> structure_horiz = new List<string>();
        List<int> list_horiz_count = new List<int>();
        int horiz_area_count = 0;

        public bool Changed
        {
            set { changed = value; }
        }

        public EditorGUISplitArea() { }

        public EditorGUISplitArea(Color border_color) { color_border = border_color; }

        public EditorGUISplitArea(int min_width, int min_height, int border_width)
        {
            this.min_width = min_width;
            this.min_height = min_height;
            this.border_width = border_width;
        }

        public EditorGUISplitArea(int min_width, int min_height, int border_width, Color border_color)
        {
            this.min_width = min_width;
            this.min_height = min_height;
            this.border_width = border_width;
            color_border = border_color;
        }

        public void BeginSplitArea(Rect position)
        {
            Event ev = Event.current;
            mouse_pos = ev.mousePosition;

            //分割する領域のRectをStack
            rect_parent.width = position.width;
            rect_parent.height = position.height;
            stack_rect.Push(rect_parent);
        }

        public void EndSplitArea()
        {
            //各領域の分割数を取得
            if (changed)
            {
                list_vert_count = VerticalAreaCount(structure_vert);
                list_horiz_count = HorizontalAreaCount(structure_horiz);
                changed = false;
            }

            stack_rect.Clear();
            stack_ratio.Clear();
            temp_stack_ratio.Clear();

            structure_vert.Clear();
            vert_area_count = 0;

            structure_horiz.Clear();
            horiz_area_count = 0;

            //分割する領域のRectを取得
            if(Event.current.type == EventType.Repaint) rect_parent = GUILayoutUtility.GetLastRect();
        }

        //Verticalで分割した領域の分割数をListへ格納(最小高さの計算に使用する)
        List<int> VerticalAreaCount(List<string> structure)
        {
            //取得した記号を()と1へ置き換える
            List<string> temp_structure = new List<string>();
            for (int i = 0; i < structure.Count - 1; i++)
            {
                if (structure[i] == "BV" && structure[i + 1] == "NV")
                {
                    temp_structure.Add("(");
                    temp_structure.Add("1");
                }
                else if (structure[i] == "NV" && structure[i + 1] == "EV")
                {
                    temp_structure.Add("1");
                    temp_structure.Add(")");
                }
                else if (structure[i] == "NV" && structure[i + 1] == "NV")
                {
                    temp_structure.Add("1");
                }
                else if (structure[i] == "BV" && structure[i + 1] == "BV")
                {
                    temp_structure.Add("(");
                }
                else if (structure[i] == "EV" && structure[i + 1] == "EV")
                {
                    temp_structure.Add(")");
                }
            }
            structure.Clear();

            temp_structure.Reverse();
            List<string> temp_s = new List<string>();
            int line_count = 0;
            int count = 0;
            int max_count = 0;
            bool research = false;
            bool eos = true;

            //各領域の分割数を計算する
            for (int n = 0; n < temp_structure.Count; n++)
            {
                if (temp_structure[n] == "(") max_count += 1;
            }

            while (eos && count <= max_count)
            {
                for (int j = 0; j < temp_structure.Count; j++)
                {
                    if (temp_structure[j] == ")")
                    {
                        for (int k = j + 1; k < temp_structure.Count; k++)
                        {
                            string str = temp_structure[k];
                            if (str != "(") temp_s.Add(temp_structure[k]);
                            if (str == ")")
                            {
                                temp_s.Clear();
                                line_count = 0;
                                break;
                            }
                            else if (str == "(")
                            {
                                temp_structure.RemoveRange(j, k - j + 1);
                                temp_structure.Insert(j, line_count.ToString());
                                foreach (string s in temp_s) { structure.Insert(0, s); }
                                line_count = 0;
                                research = true;
                                break;
                            }
                            else
                            {
                                int result;
                                if (int.TryParse(str, out result))
                                {
                                    line_count += result;
                                }
                            }
                        }
                        temp_s.Clear();
                    }

                    if (research)
                    {
                        eos = temp_structure.Contains("(") && temp_structure.Contains(")");
                        research = false;
                        break;
                    }
                }
                count += 1;
            }

            //計算結果をstringからintへ変換
            List<int> area_count = new List<int>();
            foreach (string s in structure)
            {
                int val;
                if (int.TryParse(s, out val)) area_count.Add(val);
            }

            return area_count;
        }

        //Horizontalで分割した領域の分割数をListへ格納(最小幅の計算に使用する)
        List<int> HorizontalAreaCount(List<string> structure)
        {
            //取得した記号を()と1へ置き換える
            List<string> temp_structure = new List<string>();
            for (int i = 0; i < structure.Count - 1; i++)
            {
                if (structure[i] == "BH" && structure[i + 1] == "NH")
                {
                    temp_structure.Add("(");
                    temp_structure.Add("1");
                }
                else if (structure[i] == "NH" && structure[i + 1] == "EH")
                {
                    temp_structure.Add("1");
                    temp_structure.Add(")");
                }
                else if (structure[i] == "NH" && structure[i + 1] == "NH")
                {
                    temp_structure.Add("1");
                }
                else if (structure[i] == "BH" && structure[i + 1] == "BH")
                {
                    temp_structure.Add("(");
                }
                else if (structure[i] == "EH" && structure[i + 1] == "EH")
                {
                    temp_structure.Add(")");
                }
            }
            structure.Clear();

            temp_structure.Reverse();
            List<string> temp_s = new List<string>();
            int line_count = 0;
            int count = 0;
            int max_count = 0;
            bool research = false;
            bool eos = true;

            //各領域の分割数を計算する
            for (int n = 0; n < temp_structure.Count; n++)
            {
                if (temp_structure[n] == "(") max_count += 1;
            }

            while (eos && count <= max_count)
            {
                for (int j = 0; j < temp_structure.Count; j++)
                {
                    if (temp_structure[j] == ")")
                    {
                        for (int k = j + 1; k < temp_structure.Count; k++)
                        {
                            string str = temp_structure[k];
                            if (str != "(") temp_s.Add(temp_structure[k]);
                            if (str == ")")
                            {
                                temp_s.Clear();
                                line_count = 0;
                                break;
                            }
                            else if (str == "(")
                            {
                                temp_structure.RemoveRange(j, k - j + 1);
                                temp_structure.Insert(j, line_count.ToString());
                                foreach (string s in temp_s) { structure.Insert(0, s); }
                                line_count = 0;
                                research = true;
                                break;
                            }
                            else
                            {
                                int result;
                                if (int.TryParse(str, out result))
                                {
                                    line_count += result;
                                }
                            }
                        }
                        temp_s.Clear();
                    }

                    if (research)
                    {
                        eos = temp_structure.Contains("(") && temp_structure.Contains(")");
                        research = false;
                        break;
                    }
                }
                count += 1;
            }

            //計算結果をstringからintへ変換
            List<int> area_count = new List<int>();
            foreach (string s in structure)
            {
                int val;
                if (int.TryParse(s, out val)) area_count.Add(val);
            }

            return area_count;
        }

        public float[] BeginVerticalSplitArea(float[] area_split_ratio)
        {
            Rect rect_area = stack_rect.Peek();

            int area_split_ratio_length = area_split_ratio.Length;
            int division = area_split_ratio_length + 1; //分割数
            float temp_ratio = 0;
            Rect[] rect_split_area = new Rect[division];
            Rect temp_rect_border = new Rect(rect_area) { y = rect_area.y - border_width, height = border_width };  //最上部の境界線のRect(計算用の初期値)
            Rect temp_rect = rect_area;

            //一番上の領域から下から二番目の領域までのRectを計算
            for (int i = 0; i < area_split_ratio_length; i++)
            {
                temp_ratio += area_split_ratio[i];
                Rect rect_border = new Rect(temp_rect) { y = rect_area.y + (int)((rect_area.height - border_width * area_split_ratio_length) * temp_ratio + border_width * i), height = border_width };
                temp_rect = new Rect(rect_border) { y = temp_rect_border.y + temp_rect_border.height, height = (rect_area.height - border_width * area_split_ratio_length) * area_split_ratio[i] };
                temp_rect_border = rect_border;
                rect_split_area[i] = temp_rect;
            }

            //上の計算結果より最下部の領域のRectを計算(誤差を吸収)
            float bottom_height = rect_area.height - border_width * area_split_ratio_length;
            for (int j = 0; j < rect_split_area.Length; j++)
            {
                bottom_height -= rect_split_area[j].height;
            }
            rect_split_area[area_split_ratio_length] = new Rect(rect_area) { y = rect_area.y + rect_area.height - bottom_height, height = bottom_height };

            //保存したRectを逆順にStack
            for (int k = 0; k < division; k++) { stack_rect.Push(rect_split_area[area_split_ratio_length - k]); }

            //最下部のratioを計算し全てのratioをStack(誤差を吸収)
            stack_ratio.Push(1f - temp_ratio);
            for (int n = 0; n < area_split_ratio_length; n++) { stack_ratio.Push(area_split_ratio[area_split_ratio_length - 1 - n]); }

            float height = stack_rect.Peek().height;

            temp_stack_ratio.Push(0); //Begin~SplitAreaで実行されたことを示す初期値

            //領域の分割数を取得
            if (!changed)
            {
                for (int i = 0; i < division; i++)
                {
                    stack_vert_count.Push(list_vert_count[area_split_ratio_length + vert_area_count - i]);
                }
                vert_area_count += division;
            }

            structure_vert.Add("BV");

            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal(GUILayout.Height(height), GUILayout.MinHeight(min_height),GUILayout.Width(rect_area.width));

            return area_split_ratio;
        }

        public void NextVerticalSplitArea()
        {
            EditorGUILayout.EndHorizontal();

            //上下のRectを取得
            Rect rect_area_up = stack_rect.Pop();
            Rect rect_area_down = stack_rect.Peek();

            //取得したRectからボーダーラインのRectを取得し描画
            Rect rect_horiz_border = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.Width(rect_area_up.width), GUILayout.Height(border_width));
            EditorGUI.DrawRect(rect_horiz_border, color_border);
            Event ev = Event.current;

            float ratio_up = stack_ratio.Pop();
            float ratio_down = stack_ratio.Peek();

            bool change_ratio = false;

            int vert_count_up = 1;
            int vert_count_down = 1;
            if (!changed)
            {
                vert_count_up = stack_vert_count.Pop();
                vert_count_down = stack_vert_count.Peek();
            }

            int id = EditorGUIUtility.GetControlID(FocusType.Passive);
            if (ev.button == 0)
            {
                switch (ev.type)
                {
                    case EventType.MouseDown:
                        if (rect_horiz_border.Contains(mouse_pos))
                        {
                            EditorGUIUtility.hotControl = id;
                        }
                        break;

                    case EventType.MouseDrag:
                        if (EditorGUIUtility.hotControl == id && !changed)
                        {
                            //領域の全体を1として計算
                            float change_ratio_up = ((mouse_pos.y) - rect_area_up.y) / (rect_area_up.height + rect_area_down.height);
                            float change_up_height = (rect_area_up.height + rect_area_down.height) * change_ratio_up;
                            float change_down_height = (rect_area_up.height + rect_area_down.height) - change_up_height;

                            //マウス移動によって上下の領域が最小の高さ以下になったときの処理
                            float min_height_up = min_height * vert_count_up + border_width * (vert_count_up - 1);
                            if (change_up_height <= min_height_up)
                            {
                                change_ratio_up = min_height_up / (rect_area_up.height + rect_area_down.height); //上領域が最小となったときの比率を計算
                            }

                            float min_height_down = min_height * vert_count_down + border_width * (vert_count_down - 1);
                            if (change_down_height <= min_height_down)
                            {
                                float change_ratio_down = (min_height_down) / (rect_area_up.height + rect_area_down.height); //下領域が最小となったときの比率を計算
                                change_ratio_up = 1f - change_ratio_down;
                            }

                            //実際のraitoのスケールに変換
                            float ratio = ratio_up + ratio_down;
                            ratio_up = change_ratio_up * ratio;
                            ratio_down = ratio - ratio_up;

                            change_ratio = true;
                        }
                        HandleUtility.Repaint();
                        break;

                    case EventType.MouseUp:
                        if (EditorGUIUtility.hotControl == id)
                        {
                            EditorGUIUtility.hotControl = 0;
                        }
                        break;
                }
            }
            EditorGUIUtility.AddCursorRect(rect_horiz_border, MouseCursor.ResizeVertical);

            float temp_ratio = temp_stack_ratio.Pop();
            //Begin~SplitAreaの後で最初に実行されるNext(temp_ratio == 0)もしくは境界線が移動した場合は変更
            if (temp_ratio == 0 || change_ratio)
            {
                temp_stack_ratio.Push(ratio_up);
            }
            else
            {
                temp_stack_ratio.Push(temp_ratio);
            }
            temp_stack_ratio.Push(ratio_down);

            float height = rect_area_down.height;

            structure_vert.Add("NV");

            EditorGUILayout.BeginHorizontal(GUILayout.Height(height), GUILayout.MinHeight(min_height), GUILayout.Width(rect_area_up.width));
        }

        public float[] EndVerticalSplitArea(float[] area_split_ratio)
        {
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            Rect delete_bottom_rect = stack_rect.Pop();  //一番下のRectが残るので削除
            float delete_bottom_ratio = stack_ratio.Pop();  //一番下のratioが残るので削除
            delete_bottom_ratio = temp_stack_ratio.Pop();   //一番下のratioは不要なので削除
            if (!changed) { int delete_bottom_line_count = stack_vert_count.Pop(); }

            //変更したratioを取得
            for (int i = 0; i < area_split_ratio.Length; i++)
            {
                area_split_ratio[area_split_ratio.Length - 1 - i] = temp_stack_ratio.Pop();
            }

            structure_vert.Add("EV");

            return area_split_ratio;
        }

        public float[] BeginHorizontalSplitArea(float[] area_split_ratio)
        {
            Rect rect_area = stack_rect.Peek();

            int area_split_ratio_length = area_split_ratio.Length;
            int division = area_split_ratio_length + 1; //分割数
            float temp_ratio = 0;
            Rect[] rect_split_area = new Rect[division];
            Rect temp_rect_border = new Rect(rect_area) { x = rect_area.x - border_width, width = border_width };
            Rect temp_rect = rect_area;

            //一番←の領域から右から二番目の領域までのRectを計算
            for (int i = 0; i < area_split_ratio_length; i++)
            {
                temp_ratio += area_split_ratio[i];
                Rect rect_border = new Rect(temp_rect) { x = rect_area.x + (int)((rect_area.width - border_width * area_split_ratio_length) * temp_ratio + border_width * i), width = border_width };
                temp_rect = new Rect(rect_border) { x = temp_rect_border.x + temp_rect_border.width, width = (rect_area.width - border_width * area_split_ratio_length) * area_split_ratio[i] };
                temp_rect_border = rect_border;
                rect_split_area[i] = temp_rect;
            }

            //上の計算結果より右端の領域のRectを計算(誤差を吸収)
            float right_width = rect_area.width - border_width * area_split_ratio_length;
            for (int j = 0; j < rect_split_area.Length; j++)
            {
                right_width -= rect_split_area[j].width;
            }
            rect_split_area[area_split_ratio_length] = new Rect(rect_area) { x = rect_area.x + rect_area.width - right_width, width = right_width };

            //保存したRectを逆順にStack
            for (int k = 0; k < division; k++)
            {
                stack_rect.Push(rect_split_area[area_split_ratio_length - k]);
            }

            //右端のratioを計算し全てのratioをStack(誤差を吸収)
            stack_ratio.Push(1f - temp_ratio);
            for (int n = 0; n < area_split_ratio_length; n++) { stack_ratio.Push(area_split_ratio[area_split_ratio_length - 1 - n]); }

            float width = stack_rect.Peek().width;

            temp_stack_ratio.Push(0); //Begin~SplitAreaで実行されたことを示す初期値

            //領域の分割数を取得
            if (!changed)
            {
                for (int i = 0; i < division; i++)
                {
                    stack_horiz_count.Push(list_horiz_count[area_split_ratio_length + horiz_area_count - i]);
                }
                horiz_area_count += division;
            }

            structure_horiz.Add("BH");

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.MinWidth(min_width), GUILayout.Height(rect_area.height));

            return area_split_ratio;
        }

        public void NextHorizontalSplitArea()
        {
            EditorGUILayout.EndHorizontal();

            //左右のRectを取得
            Rect rect_area_left = stack_rect.Pop();
            Rect rect_area_right = stack_rect.Peek();

            //取得したRectからボーダーラインのRectを取得し描画
            Rect rect_vert_border = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.Height(rect_area_left.height), GUILayout.Width(border_width));
            EditorGUI.DrawRect(rect_vert_border, color_border);
            Event ev = Event.current;

            float ratio_left = stack_ratio.Pop();
            float ratio_right = stack_ratio.Peek();

            bool change_ratio = false;

            int horiz_count_left = 1;
            int horiz_count_right = 1;
            if (!changed)
            {
                horiz_count_left = stack_horiz_count.Pop();
                horiz_count_right = stack_horiz_count.Peek();
            }

            int id = EditorGUIUtility.GetControlID(FocusType.Passive);
            if (ev.button == 0)
            {
                switch (ev.type)
                {
                    case EventType.MouseDown:
                        if (rect_vert_border.Contains(mouse_pos)) EditorGUIUtility.hotControl = id;
                        break;

                    case EventType.MouseDrag:
                        if (EditorGUIUtility.hotControl == id)
                        {
                            //領域の全体を1として計算
                            float change_ratio_left = ((mouse_pos.x) - rect_area_left.x) / (rect_area_left.width + rect_area_right.width);
                            float change_left_width = (rect_area_left.width + rect_area_right.width) * change_ratio_left;
                            float change_right_width = (rect_area_left.width + rect_area_right.width) - change_left_width;

                            //マウス移動によって左右の領域が最小の幅以下になったときの処理
                            float min_width_left = min_width * horiz_count_left + border_width * (horiz_count_left - 1);
                            if (change_left_width <= min_width_left)
                            {
                                change_ratio_left = min_width_left / (rect_area_left.width + rect_area_right.width); //左の領域が最小となったときの比率を計算
                            }

                            float min_width_right = min_width * horiz_count_right + border_width * (horiz_count_right - 1);
                            if (change_right_width <= min_width_right)
                            {
                                float change_ratio_right = min_width_right / (rect_area_left.width + rect_area_right.width); //右の領域が最小となったときの比率を計算
                                change_ratio_left = 1f - change_ratio_right;
                            }

                            //実際のraitoのスケールに変換
                            float ratio = ratio_left + ratio_right;
                            ratio_left = change_ratio_left * ratio;
                            ratio_right = ratio - ratio_left;

                            change_ratio = true;
                        }
                        HandleUtility.Repaint();
                        break;

                    case EventType.MouseUp:
                        if (EditorGUIUtility.hotControl == id) id = 0;
                        break;
                }
            }
            EditorGUIUtility.AddCursorRect(rect_vert_border, MouseCursor.ResizeHorizontal);

            float temp_ratio = temp_stack_ratio.Pop();
            //Begin~SplitAreaの後で最初に実行されるNext(temp_ratio == 0)もしくは境界線が移動した場合は変更
            if (temp_ratio == 0 || change_ratio)
            {
                temp_stack_ratio.Push(ratio_left);
            }
            else
            {
                temp_stack_ratio.Push(temp_ratio);
            }
            temp_stack_ratio.Push(ratio_right);

            float width = rect_area_right.width;

            structure_horiz.Add("NH");

            EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.MinWidth(min_width), GUILayout.Height(rect_area_left.height));
        }

        public float[] EndHorizontalSplitArea(float[] area_split_ratio)
        {
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndHorizontal();

            Rect delete_right_rect = stack_rect.Pop();  //一番右のRectが残るので削除
            float delete_right_ratio = stack_ratio.Pop();  //一番右のratioが残るので削除
            delete_right_ratio = temp_stack_ratio.Pop();   //一番右のratioは不要なので削除
            if (!changed) { int delete_bottom_line_count = stack_horiz_count.Pop(); }

            //変更したratioを取得
            for (int i = 0; i < area_split_ratio.Length; i++)
            {
                area_split_ratio[area_split_ratio.Length - 1 - i] = temp_stack_ratio.Pop();
            }

            structure_horiz.Add("EH");
            return area_split_ratio;
        }
    }
}

使用例に使用したScriptは以下の通りです。

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using KaraNoKan.CustomEditorGUILayout;

public class SplitTest : EditorWindow
{
    EditorGUISplitArea editorGUISplitArea = new EditorGUISplitArea();

    float[] split_ratio_a = { 0.3f, 0.5f };
    float[] split_ratio_b = { 0.3f };
    float[] split_ratio_c = { 0.6f };

    Vector2 scroll_pos_a = Vector2.zero;
    Vector2 scroll_pos_b = Vector2.zero;
    Vector2 scroll_pos_c = Vector2.zero;
    Vector2 scroll_pos_d = Vector2.zero;
    Vector2 scroll_pos_e = Vector2.zero;

    Rect rect_box = new Rect(0, 0, 0, 0);
    Rect rect_toggle = new Rect(0, 0, 0, 0);
    bool flg_toggle = false;

    Color col = new Color(0.2f, 0.5f, 0.7f, 1f);
    float val = 0f;
    bool flg = true;

    [MenuItem("Tools/SplitTest")]
    public static void OpenWindow()
    {
        EditorWindow ed = EditorWindow.GetWindow(typeof(SplitTest), false, "SplitTest");
        //ed.minSize = new Vector2(888, 471);
        ed.minSize = new Vector2(510, 300);
    }

    private void OnGUI()
    {
        //垂直方向へ二分割
        //editorGUISplitArea.BeginSplitArea(position);
        //Example1();
        //editorGUISplitArea.EndSplitArea();

        //水平方向へ二分割
        //editorGUISplitArea.BeginSplitArea(position);
        //Example2();
        //editorGUISplitArea.EndSplitArea();

        //垂直方向へ三分割
        //editorGUISplitArea.BeginSplitArea(position);
        //Example3();
        //editorGUISplitArea.EndSplitArea();

        //垂直方向へ三分割(入れ子)
        //editorGUISplitArea.BeginSplitArea(position);
        //Example4();
        //editorGUISplitArea.EndSplitArea();

        //境界線を同時に移動(四分割)
        //editorGUISplitArea.BeginSplitArea(position);
        //Example5();
        //editorGUISplitArea.EndSplitArea();

        //大きさと位置を変更
        GUI.Box(rect_box, GUIContent.none);
        EditorGUILayout.Space(70);
        EditorGUILayout.BeginHorizontal();
        {
            GUILayout.FlexibleSpace();
            editorGUISplitArea.BeginSplitArea(new Rect(0, 0, 300, 200));
            Example6();
            editorGUISplitArea.EndSplitArea();
            if (Event.current.type == EventType.Repaint) rect_box = GUILayoutUtility.GetLastRect();
            GUILayout.FlexibleSpace();
        }
        EditorGUILayout.EndHorizontal();

        //分割する領域の要素を動的に変更
        //EditorGUI.BeginChangeCheck();
        //flg_toggle = EditorGUILayout.Toggle("change split area", flg_toggle);
        //if (EditorGUI.EndChangeCheck())
        //{
        //    editorGUISplitArea.Changed = true;
        //}

        //GUIStyle style_toggle = new GUIStyle(EditorStyles.toggle);
        //if (Event.current.type == EventType.Repaint) rect_toggle = GUILayoutUtility.GetLastRect();
        //float toggle_height = rect_toggle.height + style_toggle.margin.top + style_toggle.margin.bottom;

        //Rect rect_split_area = new Rect(0, 0, position.width, position.height - toggle_height);
        //editorGUISplitArea.BeginSplitArea(rect_split_area);
        //if (flg_toggle)
        //{
        //    Example6();
        //}
        //else
        //{
        //    Example1();
        //}
        //editorGUISplitArea.EndSplitArea();

        //editorGUISplitArea.BeginSplitArea(position);
        //Example7();
        //editorGUISplitArea.EndSplitArea();
    }

    void Example1()
    {
        split_ratio_b = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_b);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
            EditorGUILayout.LabelField("f");
            EditorGUILayout.LabelField("g");
            EditorGUILayout.LabelField("h");
            EditorGUILayout.LabelField("i");
            EditorGUILayout.LabelField("j");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_b = editorGUISplitArea.EndVerticalSplitArea(split_ratio_b);
    }

    void Example2()
    {
        split_ratio_b = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_b);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitArea.NextHorizontalSplitArea();
        {
            scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
            EditorGUILayout.LabelField("f");
            EditorGUILayout.LabelField("g");
            EditorGUILayout.LabelField("h");
            EditorGUILayout.LabelField("i");
            EditorGUILayout.LabelField("j");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_b = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_b);
    }
    void Example3()
    {
        split_ratio_a = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_a);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
            EditorGUILayout.LabelField("f");
            EditorGUILayout.LabelField("g");
            EditorGUILayout.LabelField("h");
            EditorGUILayout.LabelField("i");
            EditorGUILayout.LabelField("j");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
            EditorGUILayout.LabelField("k");
            EditorGUILayout.LabelField("l");
            EditorGUILayout.LabelField("m");
            EditorGUILayout.LabelField("n");
            EditorGUILayout.LabelField("o");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_a = editorGUISplitArea.EndVerticalSplitArea(split_ratio_a);
    }

    void Example4()
    {
        split_ratio_b = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_b);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            split_ratio_c = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_c);
            {
                scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
                EditorGUILayout.LabelField("f");
                EditorGUILayout.LabelField("g");
                EditorGUILayout.LabelField("h");
                EditorGUILayout.LabelField("i");
                EditorGUILayout.LabelField("j");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextVerticalSplitArea();
            {
                scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
                EditorGUILayout.LabelField("k");
                EditorGUILayout.LabelField("l");
                EditorGUILayout.LabelField("m");
                EditorGUILayout.LabelField("n");
                EditorGUILayout.LabelField("o");
                EditorGUILayout.EndScrollView();
            }
            split_ratio_c = editorGUISplitArea.EndVerticalSplitArea(split_ratio_c);
        }
        split_ratio_b = editorGUISplitArea.EndVerticalSplitArea(split_ratio_b);
    }

    void Example5()
    {
        split_ratio_b = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_b);
        {
            split_ratio_c = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_c);
            {
                scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
                EditorGUILayout.LabelField("a");
                EditorGUILayout.LabelField("b");
                EditorGUILayout.LabelField("c");
                EditorGUILayout.LabelField("d");
                EditorGUILayout.LabelField("e");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextVerticalSplitArea();
            {
                scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
                EditorGUILayout.LabelField("f");
                EditorGUILayout.LabelField("g");
                EditorGUILayout.LabelField("h");
                EditorGUILayout.LabelField("i");
                EditorGUILayout.LabelField("j");
                EditorGUILayout.EndScrollView();
            }
            split_ratio_c = editorGUISplitArea.EndVerticalSplitArea(split_ratio_c);
        }
        editorGUISplitArea.NextHorizontalSplitArea();
        {
            split_ratio_c = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_c);
            {
                scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
                EditorGUILayout.LabelField("k");
                EditorGUILayout.LabelField("l");
                EditorGUILayout.LabelField("m");
                EditorGUILayout.LabelField("n");
                EditorGUILayout.LabelField("o");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextVerticalSplitArea();
            {
                scroll_pos_d = EditorGUILayout.BeginScrollView(scroll_pos_d);
                EditorGUILayout.LabelField("p");
                EditorGUILayout.LabelField("q");
                EditorGUILayout.LabelField("r");
                EditorGUILayout.LabelField("s");
                EditorGUILayout.LabelField("t");
                EditorGUILayout.EndScrollView();
            }
            split_ratio_c = editorGUISplitArea.EndVerticalSplitArea(split_ratio_c);
        }
        split_ratio_b = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_b);
    }

    void Example6()
    {
        split_ratio_b = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_b);
        {
            split_ratio_c = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_c);
            {
                scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
                EditorGUILayout.LabelField("a");
                EditorGUILayout.LabelField("b");
                EditorGUILayout.LabelField("c");
                EditorGUILayout.LabelField("d");
                EditorGUILayout.LabelField("e");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
                EditorGUILayout.LabelField("f");
                EditorGUILayout.LabelField("g");
                EditorGUILayout.LabelField("h");
                EditorGUILayout.LabelField("i");
                EditorGUILayout.LabelField("j");
                EditorGUILayout.EndScrollView();
            }
            split_ratio_c = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_c);
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            split_ratio_a = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_a);
            {
                scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
                EditorGUILayout.LabelField("k");
                EditorGUILayout.LabelField("l");
                EditorGUILayout.LabelField("m");
                EditorGUILayout.LabelField("n");
                EditorGUILayout.LabelField("o");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_d = EditorGUILayout.BeginScrollView(scroll_pos_d);
                EditorGUILayout.LabelField("p");
                EditorGUILayout.LabelField("q");
                EditorGUILayout.LabelField("r");
                EditorGUILayout.LabelField("s");
                EditorGUILayout.LabelField("t");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_e = EditorGUILayout.BeginScrollView(scroll_pos_e);
                EditorGUILayout.LabelField("u");
                EditorGUILayout.LabelField("v");
                EditorGUILayout.LabelField("w");
                EditorGUILayout.LabelField("x");
                EditorGUILayout.LabelField("y");
                EditorGUILayout.EndScrollView();
            }
            split_ratio_a = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_a);
        }
        split_ratio_b = editorGUISplitArea.EndVerticalSplitArea(split_ratio_b);
    }

    void Example7()
    {
        split_ratio_b = editorGUISplitArea.BeginVerticalSplitArea(split_ratio_b);
        {
            split_ratio_c = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_c);
            {
                scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
                flg = EditorGUILayout.Toggle("toggle", flg);
                col = EditorGUILayout.ColorField("main color", col);
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
                EditorGUILayout.LabelField("slider");
                val = EditorGUILayout.Slider(val, 0f, 1f);
                EditorGUILayout.EndScrollView();
            }
            split_ratio_c = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_c);
        }
        editorGUISplitArea.NextVerticalSplitArea();
        {
            split_ratio_a = editorGUISplitArea.BeginHorizontalSplitArea(split_ratio_a);
            {
                scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
                EditorGUILayout.LabelField("right area", GUILayout.Width(60));
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_d = EditorGUILayout.BeginScrollView(scroll_pos_d);
                EditorGUILayout.LabelField("main area");
                GUILayout.FlexibleSpace();
                GUILayout.Button("button");
                EditorGUILayout.EndScrollView();
            }
            editorGUISplitArea.NextHorizontalSplitArea();
            {
                scroll_pos_e = EditorGUILayout.BeginScrollView(scroll_pos_e);
                GUILayout.FlexibleSpace();
                EditorGUILayout.BeginHorizontal();
                {
                    GUILayout.FlexibleSpace();
                    EditorGUILayout.LabelField("left area", GUILayout.Width(50));
                    GUILayout.FlexibleSpace();
                }
                EditorGUILayout.EndHorizontal();
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndScrollView();
            }
            split_ratio_a = editorGUISplitArea.EndHorizontalSplitArea(split_ratio_a);
        }
        split_ratio_b = editorGUISplitArea.EndVerticalSplitArea(split_ratio_b);
    }
}

使い方

 このScriptを利用するにあたってはインスタンスの作成が必要となります。インスタンスを作成する際に、各領域の最小幅、最小高さ、境界線の太さ及び境界線の色を設定することができます。

//デフォルト
EditorGUISplitView editorGUISplitView = new EditorGUISplitView();

//境界線の色を設定
EditorGUISplitView editorGUISplitView = new EditorGUISplitView(new Color(1f, 0f, 0f, 1f));

//境界線の最小幅、最小高さ及び境界線の太さを設定
EditorGUISplitView editorGUISplitView = new EditorGUISplitView(80, 50, 6);

//境界線の最小幅、最小高さ、境界線の太さ及び境界線の色を設定
EditorGUISplitView editorGUISplitView = new EditorGUISplitView(80, 50, 6, new Color(1f, 0, 0, 1f));

二分割

垂直方向

 垂直方向へウィンドウを二分割するScriptです。分割に使用する比率は上から下へもしくは左から右へ指定します。また、最下部及び右端の比率は記述しません。そして、比率の合計値が1未満となるように指定します。

public class SplitTest : EditorWindow
{
    EditorGUISplitView editorGUISplitView = new EditorGUISplitView();

    float[] split_ratio_b = { 0.3f }; //分割したい比率

    Vector2 scroll_pos_a = Vector2.zero;
    Vector2 scroll_pos_b = Vector2.zero;

    [MenuItem("Tools/SplitTest")]
    public static void OpenWindow()
    {
        EditorWindow ed = EditorWindow.GetWindow(typeof(SplitTest), false, "SplitTest");
        ed.minSize = new Vector2(200, 300);
    }

    private void OnGUI()
    {
        //分割したい領域の大きさを設定
        editorGUISplitView.BeginSplitArea(position);
        Example1();
        editorGUISplitView.EndSplitArea();
    }

    void Example1()
    {
        split_ratio_b = editorGUISplitView.BeginVerticalSplitArea(split_ratio_b);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitView.NextVerticalSplitArea();
        {
            scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
            EditorGUILayout.LabelField("f");
            EditorGUILayout.LabelField("g");
            EditorGUILayout.LabelField("h");
            EditorGUILayout.LabelField("i");
            EditorGUILayout.LabelField("j");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_b = editorGUISplitView.EndVerticalSplitArea(split_ratio_b);
    }
}

BeginSplitAreaで領域の分割を始めます。また、EndSplitAreaでBeginSplitAreaで開始された領域の分割を終了します。

editorGUISplitView.BeginSplitArea(position);
・・・
editorGUISplitView.EndSplitArea();

垂直方向への領域の分割はBeginVerticalSplitAreaで開始し、EndVerticalSplitAreaで終了します。この間にNextVerticalSplitAreaを挿入することで分割を行います。コントロールはこれらの間に記述します。このScriptではスクロールビューを使用していますが、使用しない場合はコントロールの高さが領域の最小高さとなってしまいます。指定した最小高さよりも領域内のコントロールの高さが大きくなると正常に動作しないので注意してください。

split_ratio_b = editorGUISplitView.BeginVerticalSplitArea(split_ratio_b);
{
    scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
    EditorGUILayout.LabelField("a");
    EditorGUILayout.LabelField("b");
    EditorGUILayout.LabelField("c");
    EditorGUILayout.LabelField("d");
    EditorGUILayout.LabelField("e");
    EditorGUILayout.EndScrollView();
}
editorGUISplitView.NextVerticalSplitArea();
{
    scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
    EditorGUILayout.LabelField("f");
    EditorGUILayout.LabelField("g");
    EditorGUILayout.LabelField("h");
    EditorGUILayout.LabelField("i");
    EditorGUILayout.LabelField("j");
    EditorGUILayout.EndScrollView();
}
split_ratio_b = editorGUISplitView.EndVerticalSplitArea(split_ratio_b);

境界線は以下のように左クリック&ドラッグによって移動させることができます。

水平方向

 上記Scriptの「BeginVerticalSplitArea、NextVerticalSplitArea及びEndVerticalSplitArea」を「BeginHorizontalSplitArea、NextHorizontalSplitArea及びEndHorizontalSplitArea」へ変更すれば水平方向へ分割できます。

void Example2()
{
    split_ratio_b = editorGUISplitView.BeginHorizontalSplitArea(split_ratio_b);
    {
        scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
        EditorGUILayout.LabelField("a");
        EditorGUILayout.LabelField("b");
        EditorGUILayout.LabelField("c");
        EditorGUILayout.LabelField("d");
        EditorGUILayout.LabelField("e");
        EditorGUILayout.EndScrollView();
    }
    editorGUISplitView.NextHorizontalSplitArea();
    {
        scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
        EditorGUILayout.LabelField("f");
        EditorGUILayout.LabelField("g");
        EditorGUILayout.LabelField("h");
        EditorGUILayout.LabelField("i");
        EditorGUILayout.LabelField("j");
        EditorGUILayout.EndScrollView();
    }
    split_ratio_b = editorGUISplitView.EndHorizontalSplitArea(split_ratio_b);
}

このScriptを実行すると以下のように水平方向へ分割することができます。

分割数の増やし方

Next~SplitAreaを追加

 Next~SplitAreaを追加することで分割数を増やすことができます。

split_ratio_a = editorGUISplitView.BeginVerticalSplitArea(split_ratio_a);
{
    scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
    EditorGUILayout.LabelField("a");
    EditorGUILayout.LabelField("b");
    EditorGUILayout.LabelField("c");
    EditorGUILayout.LabelField("d");
    EditorGUILayout.LabelField("e");
    EditorGUILayout.EndScrollView();
}
editorGUISplitView.NextVerticalSplitArea();
{
    scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
    EditorGUILayout.LabelField("f");
    EditorGUILayout.LabelField("g");
    EditorGUILayout.LabelField("h");
    EditorGUILayout.LabelField("i");
    EditorGUILayout.LabelField("j");
    EditorGUILayout.EndScrollView();
}
editorGUISplitView.NextVerticalSplitArea();
{
    scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
    EditorGUILayout.LabelField("k");
    EditorGUILayout.LabelField("l");
    EditorGUILayout.LabelField("m");
    EditorGUILayout.LabelField("n");
    EditorGUILayout.LabelField("o");
    EditorGUILayout.EndScrollView();
}
split_ratio_a = editorGUISplitView.EndVerticalSplitArea(split_ratio_a);

このScriptを実行すると以下のように垂直方向へ三分割できます。

入れ子にして分割

 入れ子にすることで分割した領域をさらに分割することができます。

split_ratio_b = editorGUISplitView.BeginVerticalSplitArea(split_ratio_b);
{
    scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
    EditorGUILayout.LabelField("a");
    EditorGUILayout.LabelField("b");
    EditorGUILayout.LabelField("c");
    EditorGUILayout.LabelField("d");
    EditorGUILayout.LabelField("e");
    EditorGUILayout.EndScrollView();
}
editorGUISplitView.NextVerticalSplitArea();
{
    split_ratio_c = editorGUISplitView.BeginVerticalSplitArea(split_ratio_c);
    {
        scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
        EditorGUILayout.LabelField("f");
        EditorGUILayout.LabelField("g");
        EditorGUILayout.LabelField("h");
        EditorGUILayout.LabelField("i");
        EditorGUILayout.LabelField("j");
        EditorGUILayout.EndScrollView();
    }
    editorGUISplitView.NextVerticalSplitArea();
    {
        scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
        EditorGUILayout.LabelField("k");
        EditorGUILayout.LabelField("l");
        EditorGUILayout.LabelField("m");
        EditorGUILayout.LabelField("n");
        EditorGUILayout.LabelField("o");
        EditorGUILayout.EndScrollView();
    }
    split_ratio_c = editorGUISplitView.EndVerticalSplitArea(split_ratio_c);
}
split_ratio_b = editorGUISplitView.EndVerticalSplitArea(split_ratio_b);

入れ子となっている領域は、その領域に接する境界線を移動させると比率を保ったまま縮小及び拡大します。

境界線を同時に移動

 別々の領域へ使用する比率に同じ配列を使用することで境界線を一致させることができます。これを利用して領域を四分割したScriptは以下の通りです。

split_ratio_b = editorGUISplitView.BeginHorizontalSplitArea(split_ratio_b);
{
    split_ratio_c = editorGUISplitView.BeginVerticalSplitArea(split_ratio_c);
    {
        scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
        EditorGUILayout.LabelField("a");
        EditorGUILayout.LabelField("b");
        EditorGUILayout.LabelField("c");
        EditorGUILayout.LabelField("d");
        EditorGUILayout.LabelField("e");
        EditorGUILayout.EndScrollView();
    }
    editorGUISplitView.NextVerticalSplitArea();
    {
        scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
        EditorGUILayout.LabelField("f");
        EditorGUILayout.LabelField("g");
        EditorGUILayout.LabelField("h");
        EditorGUILayout.LabelField("i");
        EditorGUILayout.LabelField("j");
        EditorGUILayout.EndScrollView();
    }
    split_ratio_c = editorGUISplitView.EndVerticalSplitArea(split_ratio_c);
}
editorGUISplitView.NextHorizontalSplitArea();
{
    split_ratio_c = editorGUISplitView.BeginVerticalSplitArea(split_ratio_c);
    {
        scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
        EditorGUILayout.LabelField("k");
        EditorGUILayout.LabelField("l");
        EditorGUILayout.LabelField("m");
        EditorGUILayout.LabelField("n");
        EditorGUILayout.LabelField("o");
        EditorGUILayout.EndScrollView();
    }
    editorGUISplitView.NextVerticalSplitArea();
    {
        scroll_pos_d = EditorGUILayout.BeginScrollView(scroll_pos_d);
        EditorGUILayout.LabelField("p");
        EditorGUILayout.LabelField("q");
        EditorGUILayout.LabelField("r");
        EditorGUILayout.LabelField("s");
        EditorGUILayout.LabelField("t");
        EditorGUILayout.EndScrollView();
    }
    split_ratio_c = editorGUISplitView.EndVerticalSplitArea(split_ratio_c);
}
split_ratio_b = editorGUISplitView.EndHorizontalSplitArea(split_ratio_b);

水平な境界線は左右で別々の境界線ですが、比率を一致させることで一本の境界線として動作します。

分割領域の大きさと位置の変更

 BeginSplitAreaへRectを渡すことで大きさの変更はできます。しかし、位置の変更はできません(位置指定ができないにも関わらずRectを指定しているのは単にEditorWindow.positionをそのまま渡したいため)。このScriptではBeginHorizontal及びBeginVerticalを使用して分割を行っています。そのため、分割する領域の周りにコントロールを追加することができます。これを利用することで位置を調整することができます。

Script

 以下のScriptでは分割した領域をEditorGUILayout.Spaceによって下へ移動させ、さらにGUILayout.FlexibleSpaceによって中央揃えにしています。また、GUILayoutUtility.GetLastRectによって分割領域のRectを取得することができます。これを用いてGUI.Boxを追加しています。

GUI.Box(rect_box, GUIContent.none);
EditorGUILayout.Space(70);
EditorGUILayout.BeginHorizontal();
{
    GUILayout.FlexibleSpace();
    editorGUISplitArea.BeginSplitArea(new Rect(0, 0, 300, 200));
    Example6();
    editorGUISplitArea.EndSplitArea();
    if (Event.current.type == EventType.Repaint) rect_box = GUILayoutUtility.GetLastRect();
    GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
void Example6()
{
    split_ratio_b = editorGUISplitView.BeginVerticalSplitArea(split_ratio_b);
    {
        split_ratio_c = editorGUISplitView.BeginHorizontalSplitArea(split_ratio_c);
        {
            scroll_pos_a = EditorGUILayout.BeginScrollView(scroll_pos_a);
            EditorGUILayout.LabelField("a");
            EditorGUILayout.LabelField("b");
            EditorGUILayout.LabelField("c");
            EditorGUILayout.LabelField("d");
            EditorGUILayout.LabelField("e");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitView.NextHorizontalSplitArea();
        {
            scroll_pos_b = EditorGUILayout.BeginScrollView(scroll_pos_b);
            EditorGUILayout.LabelField("f");
            EditorGUILayout.LabelField("g");
            EditorGUILayout.LabelField("h");
            EditorGUILayout.LabelField("i");
            EditorGUILayout.LabelField("j");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_c = editorGUISplitView.EndHorizontalSplitArea(split_ratio_c);
    }
    editorGUISplitView.NextVerticalSplitArea();
    {
        split_ratio_a = editorGUISplitView.BeginHorizontalSplitArea(split_ratio_a);
        {
            scroll_pos_c = EditorGUILayout.BeginScrollView(scroll_pos_c);
            EditorGUILayout.LabelField("k");
            EditorGUILayout.LabelField("l");
            EditorGUILayout.LabelField("m");
            EditorGUILayout.LabelField("n");
            EditorGUILayout.LabelField("o");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitView.NextHorizontalSplitArea();
        {
            scroll_pos_d = EditorGUILayout.BeginScrollView(scroll_pos_d);
            EditorGUILayout.LabelField("p");
            EditorGUILayout.LabelField("q");
            EditorGUILayout.LabelField("r");
            EditorGUILayout.LabelField("s");
            EditorGUILayout.LabelField("t");
            EditorGUILayout.EndScrollView();
        }
        editorGUISplitView.NextHorizontalSplitArea();
        {
            scroll_pos_e = EditorGUILayout.BeginScrollView(scroll_pos_e);
            EditorGUILayout.LabelField("u");
            EditorGUILayout.LabelField("v");
            EditorGUILayout.LabelField("w");
            EditorGUILayout.LabelField("x");
            EditorGUILayout.LabelField("y");
            EditorGUILayout.EndScrollView();
        }
        split_ratio_a = editorGUISplitView.EndHorizontalSplitArea(split_ratio_a);
    }
    split_ratio_b = editorGUISplitView.EndVerticalSplitArea(split_ratio_b);
}

上記Scriptを実行すると以下のようになります。

分割する領域の要素を変更

 BeginSplitAreaとEndSplitAreaの間のコードは動的に変更することができます。ただし、変更する際にはeditorGUISplitView.Changed = trueとします。以下は分割する領域の要素をトグルによって変更するScriptです。

EditorGUI.BeginChangeCheck();
flg_toggle = EditorGUILayout.Toggle("change split area", flg_toggle);
if (EditorGUI.EndChangeCheck())
{
    editorGUISplitView.Changed = true;
}

GUIStyle style_toggle = new GUIStyle(EditorStyles.toggle);
if (Event.current.type == EventType.Repaint) rect_toggle = GUILayoutUtility.GetLastRect();
float toggle_height = rect_toggle.height + style_toggle.margin.top + style_toggle.margin.bottom;

Rect rect_split_area = new Rect(0, 0, position.width, position.height - toggle_height);
editorGUISplitView.BeginSplitArea(rect_split_area);
if (flg_toggle)
{
    Example6();
}
else
{
    Example1();
}
editorGUISplitView.EndSplitArea();

このように分割している領域のを切り替えができます。