FloatFieldの作成(Editor拡張)2020/07/11修正

FloatFieldの作成(Editor拡張)2020/07/11修正

 EditorGUILayout.FloatFieldで作成したFloatFieldのラベルの色を変更しようとGUIStyleを変更したところ、テキスト入力部分のスタイルしか変更できませんでした。そこで、FloatFieldを自作することで、自由にラベルの色等を変更できるようにしました。

LabelFieldとFloatFieldを横並びで表示

 FloatFieldを作成すると、ラベル部分(LabelField)と数値入力部分(TextField)が同時に作成されます。これらを、別々に作成し横並びに配置することで、それぞれのスタイルや位置を自由に変更できるようにします。

Script

 EditorGUILayout.BeginHorizontal();とEditorGUILayout.EndHorizontal();の間にあるコントロールは横並びになります。よって、LabelFieldとFloatFieldを以下のように記述すると、ラベルとテキスト部分が分離したFloatFieldを作成することができます。

float FloatField(string label, float val)
{
    EditorGUILayout.BeginHorizontal();
    {
        EditorGUILayout.LabelField(label);
        GUILayout.FlexibleSpace();
        val = EditorGUILayout.FloatField(val, GUILayout.Width(65));
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

次に、それぞれのGUIStyleを変更できるようにします。

float FloatField(string label, float val, GUIStyle style_label, GUIStyle style_float)
{
    EditorGUILayout.BeginHorizontal();
    {
        EditorGUILayout.LabelField(label, style_label);
        GUILayout.FlexibleSpace();
        val = EditorGUILayout.FloatField(val, style_float, GUILayout.Width(65));
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

さらに、それぞれにオプションを設定できるようにします。

float FloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, GUILayoutOption[] label_options, GUILayoutOption[] float_filed_options)
{
    EditorGUILayout.BeginHorizontal();
    {
        EditorGUILayout.LabelField(label, style_label, label_options);
        GUILayout.FlexibleSpace();
        val = EditorGUILayout.FloatField(val, style_float, float_filed_options);
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

これで、ラベルのスタイルを自由に変更できるFloatFieldが作成できました。

実行結果

 作成したFloatFieldをEditorWindowで実行するScriptは以下の通りです。

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

public class GenerateFloatField : EditorWindow
{

    private float value_a = 0, value_b = 0, value_c = 0;


    [MenuItem("Tools/GenerateFloatField")]
    public static void OpenWindow()
    {
        EditorWindow ed = EditorWindow.GetWindow(typeof(GenerateFloatField), false, "GenerateFloatField");
        ed.minSize = new Vector2(285, 456);
        ed.wantsMouseMove = true;
    }

    void OnGUI()
    {
        GUIStyle style_label = new GUIStyle(GUI.skin.label);
        style_label.normal.textColor = Color.red;

        GUIStyle style_float = new GUIStyle(GUI.skin.textField);

        value_a = FloatField("float", value_a);
        value_b = FloatField("float", value_b, style_label, style_float);
        value_c = FloatField("float", value_c, style_label, style_float, new GUILayoutOption[] { GUILayout.Width(30) }, new GUILayoutOption[] { GUILayout.Width(120) });
    }

    float FloatField(string label, float val)
    {
        EditorGUILayout.BeginHorizontal();
        {
            EditorGUILayout.LabelField(label);
            GUILayout.FlexibleSpace();
            val = EditorGUILayout.FloatField(val, GUILayout.Width(65));
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }

    float FloatField(string label, float val, GUIStyle style_label, GUIStyle style_float)
    {
        EditorGUILayout.BeginHorizontal();
        {
            EditorGUILayout.LabelField(label, style_label);
            GUILayout.FlexibleSpace();
            val = EditorGUILayout.FloatField(val, style_float, GUILayout.Width(65));
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }

    float FloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, GUILayoutOption[] label_options, GUILayoutOption[] float_filed_options)
    {
        EditorGUILayout.BeginHorizontal();
        {
            EditorGUILayout.LabelField(label, style_label, label_options);
            GUILayout.FlexibleSpace();
            val = EditorGUILayout.FloatField(val, style_float, float_filed_options);
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }
}

このScriptを実行すると以下のようになります。ラベルの色及びFloatFieldの大きさの変更が行われていることが分かります。

Focusの追加

 EditorGUILayout.FloatFieldで作成したFloatFieldはラベルをクリックするとラベルの色が変更され、さらにTextFieldへFocusが移ります。また、TextFieldがFocusされると、ラベルの色が変わります。この機能を、先ほど作成したFloatFieldへ追加します。

Script

 Focusを追加したFloatFieldのコードは以下の通りです。

float FocusFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, Event ev)
{
    EditorGUILayout.BeginHorizontal();
    {
        string control_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString();

        GUIStyle style_temp = new GUIStyle(style_label);
        if(GUI.GetNameOfFocusedControl() == control_name)
        {
            style_temp.normal.textColor = style_label.focused.textColor;
            Repaint();
        }

        EditorGUILayout.LabelField(label, style_temp);
        Rect rect_label = GUILayoutUtility.GetLastRect();
        GUILayout.FlexibleSpace();
        GUI.SetNextControlName(control_name);
        val = EditorGUILayout.FloatField(val, style_float, GUILayout.Width(65));

        if (rect_label.Contains(ev.mousePosition) && ev.type == EventType.MouseDown && ev.button == 0)
        {
            GUI.FocusControl(control_name);
        }
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

Focusを制御するにあたり、コントロールに名前を付ける必要があります。GUIUtility.GetControlID(FocusType.Passive)によってIDを取得し、名前へ追加することでコントロールごとに名前が変わるように処理を行っています。この名前は後に作成するFloatFieldへ設定します。

string control_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString();

GUI.GetNameOfFocusedControlでFocusされているコントロールに設定されている名前を取得することができます。FloatFieldへ設定する名前(control_name)とFocusされているコントロールの名前が一致した場合、ラベルの色を変更する処理を追加しています。その際、Repaintによってウィンドウの再描画を行っています。

GUIStyle style_temp = new GUIStyle(style_label);
if(GUI.GetNameOfFocusedControl() == control_name)
{
    style_temp.normal.textColor = style_label.focused.textColor;
    Repaint();
}

ラベルを作成した後に、GUILayoutUtility.GetLastRectによってラベルのRectを取得しています。次に、GUI.SetNextControlNameによってFloatFieldへ先ほど作成した名前(control_name)を設定しています。

EditorGUILayout.LabelField(label, style_temp);
Rect rect_label = GUILayoutUtility.GetLastRect();
GUILayout.FlexibleSpace();
GUI.SetNextControlName(control_name);
val = EditorGUILayout.FloatField(val, style_float, GUILayout.Width(65));

rect_label.Contains(ev.mousePosition)でマウスカーソルがラベル上にあるかを、ev.type == EventType.MouseDownによってマウスがクリックされたか、また、ev.button == 0によって左クリックであることを判定しています(ev=Event.current)。これらによってラベル上で左クリックが行われたかを判定し、その結果により、GUI.FocusControl(control_name)でFloatFiledへFocusを移します。

if (rect_label.Contains(ev.mousePosition) && ev.type == EventType.MouseDown && ev.button == 0)
{
    GUI.FocusControl(control_name);
}

実行結果

 Focusを追加したFloatFieldをEditorWindowで実行するScriptは以下の通りです。

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

public class GenerateFloatField : EditorWindow
{

    private float value_a = 0, value_b = 0;


    [MenuItem("Tools/GenerateFloatField")]
    public static void OpenWindow()
    {
        EditorWindow ed = EditorWindow.GetWindow(typeof(GenerateFloatField), false, "GenerateFloatField");
        ed.minSize = new Vector2(285, 456);
        ed.wantsMouseMove = true;
    }

    void OnGUI()
    {
        GUIStyle style_label = new GUIStyle(GUI.skin.label);
        style_label.normal.textColor = Color.black;
        style_label.focused.textColor = Color.blue;

        GUIStyle style_float = new GUIStyle(GUI.skin.textField);

        Event event_current = Event.current;
        value_a = FocusFloatField("float", value_a, style_label, style_float, event_current);
        value_b = FocusFloatField("float", value_b, style_label, style_float, new GUILayoutOption[] { GUILayout.Width(30) }, new GUILayoutOption[] { GUILayout.Width(120) }, event_current);
    }

    float FocusFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, Event ev)
    {
        EditorGUILayout.BeginHorizontal();
        {
            string control_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString();

            GUIStyle style_temp = new GUIStyle(style_label);
            if (GUI.GetNameOfFocusedControl() == control_name)
            {
                style_temp.normal.textColor = style_label.focused.textColor;
                Repaint();
            }

            EditorGUILayout.LabelField(label, style_temp);
            Rect rect_label = GUILayoutUtility.GetLastRect();
            GUILayout.FlexibleSpace();
            GUI.SetNextControlName(control_name);
            val = EditorGUILayout.FloatField(val, style_float, GUILayout.Width(65));

            if (rect_label.Contains(ev.mousePosition) && ev.type == EventType.MouseDown && ev.button == 0)
            {
                GUI.FocusControl(control_name);
            }
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }
    float FocusFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, GUILayoutOption[] label_options, GUILayoutOption[] float_filed_options, Event ev)
    {
        EditorGUILayout.BeginHorizontal();
        {
            string control_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString();

            GUIStyle style_temp = new GUIStyle(style_label);
            if (GUI.GetNameOfFocusedControl() == control_name)
            {
                style_temp.normal.textColor = style_label.focused.textColor;
                Repaint();
            }

            EditorGUILayout.LabelField(label, style_temp, label_options);
            Rect rect_label = GUILayoutUtility.GetLastRect();
            GUILayout.FlexibleSpace();
            GUI.SetNextControlName(control_name);
            val = EditorGUILayout.FloatField(val, style_float, float_filed_options);

            if (rect_label.Contains(ev.mousePosition) && ev.type == EventType.MouseDown && ev.button == 0)
            {
                GUI.FocusControl(control_name);
            }
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }
}

このScriptを実行すると以下のようになります。ラベル及びFloatFieldをクリックすることでラベルの色が変化していることが分かります。

ドラッグによる数値変更

 EditorGUILayout.FloatFieldによって作成されたFloatFieldは、ラベル上で左クリックした後にドラッグを行うことで数値の変更ができます。この機能を追加します。

Script

 ドラッグによる数値変更を追加したFloatFieldのScriptは以下の通りです。

float CustomFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, Event ev)
{
    EditorGUILayout.BeginHorizontal();
    {
        float val_speed = 0.3f;
        string label_name = label + GUIUtility.GetControlID(FocusType.Passive);
        string float_control_name = label_name + "_float_field";

        GUIStyle style_temp = new GUIStyle(style_label);
        GUIStyle style_float_temp = new GUIStyle(style_float);

        string focus_control_name = GUI.GetNameOfFocusedControl();
        if (focus_control_name == label_name || focus_control_name == float_control_name)
        {
            style_temp.normal.textColor = style_label.focused.textColor;
            style_float_temp.normal.background = style_float.focused.background;
        }

        GUI.SetNextControlName(label_name);
        EditorGUILayout.LabelField(label, style_temp, GUILayout.Width(position.width - 77));
        int id = GUIUtility.GetControlID(FocusType.Passive);
        Rect rect_label = GUILayoutUtility.GetLastRect();

        GUILayout.FlexibleSpace();
        GUI.SetNextControlName(float_control_name);
        val = EditorGUILayout.FloatField(val, style_float_temp, GUILayout.Width(65));

        Vector2 mous_pos = ev.mousePosition;
        if (ev.button == 0)
        {
            switch (ev.type)
            {
                case EventType.MouseDown:
                    if (rect_label.Contains(mous_pos))
                    {
                        GUIUtility.hotControl = id;
                        GUI.FocusControl(label_name);
                        ev.Use();
                    }
                    break;

                case EventType.MouseDrag:
                    if (GUIUtility.hotControl == id)
                    {
                        float dis = ev.delta.x;
                        val = val * 100.0f + dis * 10.0f * val_speed;
                        val = Mathf.Floor(Mathf.Abs(val)) / 100f * Mathf.Sign(val);
                        GUI.FocusControl(label_name);
                        Repaint();
                    }
                    break;

                case EventType.MouseUp:
                    if (GUIUtility.hotControl == id)
                    {
                        GUIUtility.hotControl = 0;
                    }
                    break;
            }
        }

        EditorGUIUtility.AddCursorRect(rect_label, MouseCursor.SlideArrow);
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

ev.mousePositionでマウスの位置を取得しています。また、ev.button==0で左クリックをされているかを判定しています。さらに、switch文でマウスの状態によって処理を分けています。

Vector2 mous_pos = ev.mousePosition;
if (ev.button == 0)
{
    switch (ev.type)
    {
        case EventType.MouseDown:
            ・・・
            break;

        case EventType.MouseDrag:
            ・・・
            break;

        case EventType.MouseUp:
            ・・・
            break;
    }
}

マウスが左クリックされている場合、GUIUtility.hotControlへFloatFieldのid(id)を渡し、コントロール権をFloatFieldへ与えます。また、GUI.FocusControlでラベルへFocusを移します。そして、ev.Use()によって他のコントロールが反応しないようにしています。

case EventType.MouseDown:
    if (rect_label.Contains(mous_pos))
    {
        GUIUtility.hotControl = id;
        GUI.FocusControl(label_name);
        ev.Use();
    }
    break;

ドラッグが行われた際の処理です。GUIUtility.hotControlのidがFloatFieldのidと同じ場合に処理が行われるようにしています。ev.delta.xによってマウスカーソルの横方向への移動量を取得し、FloatFieldの数値を100倍(val*100f)した数値へ加算することで数値を増減させています。その後、変更した数値の小数を切り捨てた後に、100で割ることで小数点第2位まで変更できるようにしています。また、FloatFieldをFocusすると変更した数値が反映されないため、GUI.FocusControl(label_name)でラベルへFocusを移しています。その後、Repaint()によってウィンドウの再描画を行っています。

case EventType.MouseDrag:
    if (GUIUtility.hotControl == id)
    {
        float dis = ev.delta.x;
        val = val * 100.0f + dis * 10.0f * val_speed;
        val = Mathf.Floor(Mathf.Abs(val)) / 100f * Mathf.Sign(val);
        GUI.FocusControl(label_name);
        Repaint();
    }
    break;

最後に以下のコードでマウスカーソルがラベル上にある場合、カーソルの画像を変更する処理を加えています。

EditorGUIUtility.AddCursorRect(rect_label, MouseCursor.SlideArrow);

実行結果

 ドラッグによる数値変更を追加したFloatFieldをEditorWindowで実行するScriptは以下の通りです。

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

public class GenerateFloatField : EditorWindow
{

    private float value_a = 0, value_b = 0, value_c = 0;

    [MenuItem("Tools/GenerateFloatField")]
    public static void OpenWindow()
    {
        EditorWindow ed = EditorWindow.GetWindow(typeof(GenerateFloatField), false, "GenerateFloatField");
        ed.minSize = new Vector2(285, 456);
        ed.wantsMouseMove = true;
    }

    void OnGUI()
    {
        GUIStyle style_label = new GUIStyle(GUI.skin.label);
        style_label.normal.textColor = Color.black;
        style_label.focused.textColor = Color.blue;

        GUIStyle style_inv_label = new GUIStyle(GUI.skin.label);
        style_inv_label.normal.textColor = Color.black;
        style_inv_label.focused.textColor = Color.blue;
        style_inv_label.alignment = TextAnchor.MiddleRight;

        GUIStyle style_float = new GUIStyle(GUI.skin.textField);
        //GUISkin gui_dark_skin = (GUISkin)EditorGUIUtility.Load("DarkSkin.guiskin");
        //GUIStyle style_float = gui_dark_skin.textField;

        Event event_current = Event.current;
        value_a = CustomFloatField("float", value_a, style_label, style_float, event_current);
        value_b = CustomFloatField("float", value_b, style_label, style_float, new GUILayoutOption[] { GUILayout.Width(position.width - 131) }, new GUILayoutOption[] { GUILayout.Width(120) }, event_current);
    }

    float CustomFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, Event ev)
    {
        EditorGUILayout.BeginHorizontal();
        {
            float val_speed = 0.3f;
            string label_name = label + GUIUtility.GetControlID(FocusType.Passive);
            string float_control_name = label_name + "_float_field";

            GUIStyle style_temp = new GUIStyle(style_label);
            GUIStyle style_float_temp = new GUIStyle(style_float);

            string focus_control_name = GUI.GetNameOfFocusedControl();
            if (focus_control_name == label_name || focus_control_name == float_control_name)
            {
                style_temp.normal.textColor = style_label.focused.textColor;
                style_float_temp.normal.background = style_float.focused.background;
            }

            GUI.SetNextControlName(label_name);
            EditorGUILayout.LabelField(label, style_temp, GUILayout.Width(position.width - 77));
            int id = GUIUtility.GetControlID(FocusType.Passive);
            Rect rect_label = GUILayoutUtility.GetLastRect();

            GUILayout.FlexibleSpace();
            GUI.SetNextControlName(float_control_name);
            val = EditorGUILayout.FloatField(val, style_float_temp, GUILayout.Width(65));

            Vector2 mous_pos = ev.mousePosition;
            if (ev.button == 0)
            {
                switch (ev.type)
                {
                    case EventType.MouseDown:
                        if (rect_label.Contains(mous_pos))
                        {
                            GUIUtility.hotControl = id;
                            GUI.FocusControl(label_name);
                            ev.Use();
                        }
                        break;

                    case EventType.MouseDrag:
                        if (GUIUtility.hotControl == id)
                        {
                            float dis = ev.delta.x;
                            val = val * 100.0f + dis * 10.0f * val_speed;
                            val = Mathf.Floor(Mathf.Abs(val)) / 100f * Mathf.Sign(val);
                            GUI.FocusControl(label_name);
                            Repaint();
                        }
                        break;

                    case EventType.MouseUp:
                        if (GUIUtility.hotControl == id)
                        {
                            GUIUtility.hotControl = 0;
                        }
                        break;
                }
            }

            EditorGUIUtility.AddCursorRect(rect_label, MouseCursor.SlideArrow);
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }

    float CustomFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, GUILayoutOption[] label_options, GUILayoutOption[] float_field_options, Event ev)
    {
        EditorGUILayout.BeginHorizontal();
        {
            float val_speed = 0.3f;
            string label_name = label + GUIUtility.GetControlID(FocusType.Passive);
            string float_control_name = label_name + "_float_field";

            GUIStyle style_temp = new GUIStyle(style_label);
            GUIStyle style_float_temp = new GUIStyle(style_float);

            string focus_control_name = GUI.GetNameOfFocusedControl();
            if (focus_control_name == label_name || focus_control_name == float_control_name)
            {
                style_temp.normal.textColor = style_label.focused.textColor;
                style_float_temp.normal.background = style_float.focused.background;
            }

            GUI.SetNextControlName(label_name);
            EditorGUILayout.LabelField(label, style_temp, label_options);
            int id = GUIUtility.GetControlID(FocusType.Passive);
            Rect rect_label = GUILayoutUtility.GetLastRect();

            GUI.SetNextControlName(float_control_name);
            val = EditorGUILayout.FloatField(val, style_float_temp, float_field_options);

            Vector2 mous_pos = ev.mousePosition;
            bool flg_on_rect = rect_label.Contains(mous_pos);

            if (ev.button == 0)
            {
                switch (ev.type)
                {
                    case EventType.MouseDown:
                        if (flg_on_rect)
                        {
                            GUIUtility.hotControl = id;
                            GUI.FocusControl(label_name);
                            ev.Use();
                        }
                        break;

                    case EventType.MouseDrag:
                        if (GUIUtility.hotControl == id)
                        {
                            float dis = ev.delta.x;
                            val = val * 100.0f + dis * 10.0f * val_speed;
                            val = Mathf.Floor(Mathf.Abs(val)) / 100f * Mathf.Sign(val);
                            GUI.FocusControl(label_name);
                            Repaint();
                        }
                        break;

                    case EventType.MouseUp:
                        if (GUIUtility.hotControl == id)
                        {
                            GUIUtility.hotControl = 0;
                        }
                        break;
                }
            }

            EditorGUIUtility.AddCursorRect(rect_label, MouseCursor.SlideArrow);
        }
        EditorGUILayout.EndHorizontal();

        return val;
    }
}

このScriptを実行すると以下のようになります。ドラッグによってFloatFieldの数値を変更できていることが分かります。ただ、FloatFieldのBackground用デフォルト画像を取得できなかったため、ラベルへFocusが移ると通常の表示に戻ります。

そこで、以下のコードによりDarkSkinを取得し、FloatFieldのStyleを変更します。

GUISkin gui_dark_skin = (GUISkin)EditorGUIUtility.Load("DarkSkin.guiskin");
GUIStyle style_float = gui_dark_skin.textField;

このStyleを利用し、実行すると

となり、ラベルがFocusされた際にもFloatFieldがFocusされている表示になります。

さらに

 自身で作成したFloatFieldなので、ラベルとテキスト部分を逆に表示することもできます。

void OnGUI()
{
    GUIStyle style_label = new GUIStyle(GUI.skin.label);
    style_label.normal.textColor = Color.black;
    style_label.focused.textColor = Color.blue;
    style_label.alignment = TextAnchor.MiddleRight;

    GUIStyle style_float = new GUIStyle(GUI.skin.textField);

    Event event_current = Event.current;
    value_a = InvCustomFloatField("float", value_a, style_label, style_float, event_current);
}



float InvCustomFloatField(string label, float val, GUIStyle style_label, GUIStyle style_float, Event ev)
{
    EditorGUILayout.BeginHorizontal();
    {
        float val_speed = 0.3f;
        string label_name = label + GUIUtility.GetControlID(FocusType.Passive);
        string float_control_name = label_name + "_float_field";

        GUIStyle style_temp = new GUIStyle(style_label);
        GUIStyle style_float_temp = new GUIStyle(style_float);

        string focus_control_name = GUI.GetNameOfFocusedControl();
        if (focus_control_name == label_name || focus_control_name == float_control_name)
        {
            style_temp.normal.textColor = style_label.focused.textColor;
            style_float_temp.normal.background = style_float.focused.background;
        }

        GUI.SetNextControlName(float_control_name);
        val = EditorGUILayout.FloatField(val, style_float_temp, GUILayout.Width(65));

        GUILayout.FlexibleSpace();
        GUI.SetNextControlName(label_name);
        EditorGUILayout.LabelField(label, style_temp, GUILayout.Width(position.width - 77));
        int id = GUIUtility.GetControlID(FocusType.Passive);
        Rect rect_label = GUILayoutUtility.GetLastRect();

        Vector2 mous_pos = ev.mousePosition;
        if (ev.button == 0)
        {
            switch (ev.type)
            {
                case EventType.MouseDown:
                    if (rect_label.Contains(mous_pos))
                    {
                        GUIUtility.hotControl = id;
                        GUI.FocusControl(label_name);
                        ev.Use();
                    }
                    break;

                case EventType.MouseDrag:
                    if (GUIUtility.hotControl == id)
                    {
                        float dis = ev.delta.x;
                        val = val * 100.0f + dis * 10.0f * val_speed;
                        val = Mathf.Floor(Mathf.Abs(val)) / 100f * Mathf.Sign(val);
                        GUI.FocusControl(label_name);
                        Repaint();
                    }
                    break;

                case EventType.MouseUp:
                    if (GUIUtility.hotControl == id)
                    {
                        GUIUtility.hotControl = 0;
                    }
                    break;
            }
        }

        EditorGUIUtility.AddCursorRect(rect_label, MouseCursor.SlideArrow);
    }
    EditorGUILayout.EndHorizontal();

    return val;
}

上記Scriptの実行結果は以下の通りです。

 Inspectorで表示されるShaderPropertiesのTexture部分を作成してみました。

Texture CustomTextureField(string label, GUIStyle style_label, GUIStyle style_float, Texture tex, ref Vector2 tiling, ref Vector2 offset, Event ev)
{
    int font_size = 13;
    EditorGUILayout.BeginHorizontal();
    {
        string tex_control_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString() + "tex";
        string tiling_label_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString() + "tiling";
        string offset_label_name = label + GUIUtility.GetControlID(FocusType.Passive).ToString() + "offset";
        GUIStyle style_temp = new GUIStyle(style_label);
        GUIStyle style_tiling = new GUIStyle(style_label);
        GUIStyle style_offset = new GUIStyle(style_label);

        if (GUI.GetNameOfFocusedControl() == tex_control_name)
        {
            style_temp.normal.textColor = style_label.focused.textColor;
            Repaint();
        }
        else if (GUI.GetNameOfFocusedControl() == tiling_label_name)
        {
            style_tiling.normal.textColor = style_label.focused.textColor;
            Repaint();
        }
        else if (GUI.GetNameOfFocusedControl() == offset_label_name)
        {
            style_offset.normal.textColor = style_label.focused.textColor;
            Repaint();
        }

        EditorGUILayout.BeginVertical();
        {
            EditorGUILayout.LabelField(label, style_temp, GUILayout.Height(26));
            Rect rect_label = GUILayoutUtility.GetLastRect();
            if (ev.type == EventType.MouseDown && rect_label.Contains(ev.mousePosition))
            {
                GUI.FocusControl(tex_control_name);
            }

            EditorGUILayout.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
                int tex_width = (int)((position.width - 187) * 0.5f);
                GUI.SetNextControlName(tiling_label_name);
                EditorGUILayout.LabelField("Tiling", style_tiling, GUILayout.Width(50));

                Rect rect_tiling_label = GUILayoutUtility.GetLastRect();
                if (ev.type == EventType.MouseDown && rect_tiling_label.Contains(ev.mousePosition))
                {
                    GUI.FocusControl(tiling_label_name);
                }

                tiling.x = CustomFloatField("X", tiling.x, style_label, style_float, new[] { GUILayout.Width(font_size) }, new[] { GUILayout.Width(tex_width) }, ev);
                tiling.y = CustomFloatField("Y", tiling.y, style_label, style_float, new[] { GUILayout.Width(font_size) }, new[] { GUILayout.Width(tex_width) }, ev);
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
                int tex_width = (int)((position.width - 187) * 0.5f);
                GUI.SetNextControlName(offset_label_name);
                EditorGUILayout.LabelField("Offset", style_offset, GUILayout.Width(50));

                Rect rect_offset_label = GUILayoutUtility.GetLastRect();
                if (ev.type == EventType.MouseDown && rect_offset_label.Contains(ev.mousePosition))
                {
                    GUI.FocusControl(offset_label_name);
                }

                offset.x = CustomFloatField("X", offset.x, style_label, style_float, new[] { GUILayout.Width(font_size) }, new[] { GUILayout.Width(tex_width) }, ev);
                offset.y = CustomFloatField("Y", offset.y, style_label, style_float, new[] { GUILayout.Width(font_size) }, new[] { GUILayout.Width(tex_width) }, ev);
            }
            EditorGUILayout.EndHorizontal();
        }
        EditorGUILayout.EndHorizontal();

        GUI.SetNextControlName(tex_control_name);
        tex = EditorGUILayout.ObjectField(tex, typeof(Texture), false, GUILayout.Width(64), GUILayout.Height(65)) as Texture;
    }
    EditorGUILayout.EndVertical();

    return tex;
}

実行結果は以下の通りです。

修正履歴

2020/07/11

 下の画像に示すように、テキスト入力部分をクリックしてフォーカスを移動した際、一番上のテキストフィールドのみテキストが選択された状態になります。

case EventType.MouseUp:
    GUIUtility.hotControl = 0;
    break;

そのため、上記のコードを以下のように修正しました。

case EventType.MouseUp:
    if (GUIUtility.hotControl == id)
    {
        GUIUtility.hotControl = 0;
    }
    break;

実行すると以下のようになります。全てのテキストエリアで、テキストが選択されるようになりました。