<|start_filename|>Runtime/Component/IMColorPicker/Test/TestOnGUI.cs<|end_filename|>
﻿using UnityEngine;

namespace RapidGUI.imColorPicker.Test
{

    public class TestOnGUI : MonoBehaviour {

        public IMColorPreset preset;
        public Color color = Color.red;

        IMColorPicker colorPicker;
        [SerializeField] bool window;

        void OnGUI()
        {
            if(colorPicker == null)
            {
                colorPicker = new IMColorPicker(color, preset);
            }

            using(new GUILayout.HorizontalScope())
            {
                window = GUILayout.Toggle(window, "Window");
            }

            if(window)
            {
                colorPicker.DrawWindow();
            } else
            {
                using(new GUILayout.HorizontalScope())
                {
                    GUILayout.Space(10f);
                    using(new GUILayout.VerticalScope())
                    {
                        GUILayout.Space(10f);
                        GUILayout.Label("IMColorPicker");
                        colorPicker.DrawColorPicker();
                    }
                }
            }

            color = colorPicker.color;
        } 

    }

}




<|start_filename|>Runtime/Component/Folds.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;


namespace RapidGUI
{
    public class Folds : TitleContents<Fold>
    {
        List<Fold> folds = new List<Fold>();

        public bool DoGUI()
        {
            var ret = false;

            if (dicChanged)
            {
                folds = dic.Values.ToList();
                dicChanged = false;
            }

            using (new GUILayout.VerticalScope())
            {
                ret = folds.Aggregate(false, (changed, fold) => changed || fold.DoGUI());
            }
            return ret;
        }
    }
}

<|start_filename|>Runtime/Component/Fold.cs<|end_filename|>
﻿using System.Linq;
using UnityEngine;


namespace RapidGUI
{
    public class Fold : TitleContent<Fold>
    {
        public Fold() : base() { }
        public Fold(string name) : base(name) { }

        public bool DoGUI()
        {
            var ret = false;
            var guiFuncs = GetGUIFuncs();

            if (guiFuncs.Any())
            {
                using (new GUILayout.HorizontalScope())
                {
                    isOpen = DoGUIHeader(isOpen, name);
                    titleAction?.Invoke();
                }

                using (new RGUI.IndentScope())
                {
                    if (isOpen)
                    {
                        ret |= guiFuncs.Aggregate(false, (changed, drawFunc) => changed || drawFunc());
                    }
                }
            }

            return ret;
        }

        public static bool DoGUIHeader(bool isOpen, string name, params GUILayoutOption[] options)
        {
            var foldStr = isOpen ? "▼" : "▶";
            isOpen ^= GUILayout.Button(foldStr + name, Style.Fold, options);

            return isOpen;
        }


        public static class Style
        {
            public static readonly GUIStyle Fold;
            static Texture2D tex;

            static Style()
            {
                var style = new GUIStyle(GUI.skin.label);
                var toggle = GUI.skin.toggle;
                style.normal.textColor = toggle.normal.textColor;
                style.hover.textColor = toggle.hover.textColor;
                style.margin.left = 0;

                tex = new Texture2D(1, 1);
                tex.SetPixels(new[] { new Color(0.5f, 0.5f, 0.5f, 0.5f) });
                tex.Apply();
                style.hover.background = tex;

                Fold = style;
            }
        }
    }
}

<|start_filename|>Example/Scripts/FieldWithClassExample.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using UnityEngine;


namespace RapidGUI.Example
{
    /// <summary>
    /// RGUI.Field() examples part2
    /// </summary>
    public class FieldWithClassExample : ExampleBase
    {
        /// <summary>
        /// Simple Class
        /// - RapidGUI displays member fields with the same rules as unity serialize(public, SerializeField, NonSerialized).
        /// - Field with RangAttribute display a slider
        /// - If field name is long, name and value are displayed in multiple lines
        /// </summary>
        [Serializable]
        public class MyClass
        {
            public int publicField;

            [SerializeField]
            protected int serializeField;

            [NonSerialized]
            public int nonSerializedField;

            [Range(0f, 10f)]
            public float rangeVal;

            [Range(0f, 10f)] // The Range attribute is applied to a variety of numeric types 
            public Vector3Int rangeVec3Int;

            public string longNameFieldWillBeMultiLine;
        }

        /// <summary>
        /// CustomGUIClass
        /// - If you can't add an attribute to a class, you can specify a GUI from outside by using CustomGUI.
        /// - See also Start().
        /// </summary>
        public class CustomGUIClass
        {
            public int value0;
            public int value1;
            public int value2;
        }


        /// <summary>
        /// RobustTestClass
        /// </summary>
        public class RobustTestClass
        {
            public RobustTestClass nullReference;
            public RobustTestClass selfReference; // set self reference at Start()
        }

        /// <summary>
        /// ClassWithIDoGUI
        /// - Class with IDoGUI will automatically call DoGUI within an Array/List and another class
        /// </summary>
        public class ClassWithIDoGUI : IDoGUI
        {
            public int myParam;

            public void DoGUI()
            {
                using (new GUILayout.HorizontalScope())
                {
                    GUILayout.Label("In DoGUI");
                    using (new GUILayout.HorizontalScope())
                    {
                        myParam = RGUI.Field(myParam);
                        if (GUILayout.Button("Add10")) myParam += 10;
                    }
                }
            }
        }

        /// <summary>
        /// ClassWithICloneable
        /// - If class is ICloneable or has Copy Constructor then Array/List element will be duplicate when add new element.
        /// </summary>
        public class ClassWithICloneable : ICloneable
        {
            public int myParam;

            public object Clone()
            {
                return new ClassWithICloneable()
                {
                    myParam = myParam
                };
            }
        }




        public MyClass myClass = new MyClass();
        public CustomGUIClass customGUIClass = new CustomGUIClass();
        public RobustTestClass robustTestClass = new RobustTestClass();
        public List<ClassWithIDoGUI> classWithIDoGUIList = new List<ClassWithIDoGUI>();
        public List<ClassWithICloneable> classWithICloneableList = new List<ClassWithICloneable>();

        private void Start()
        {
            robustTestClass.selfReference = robustTestClass; // circular reference

            CustomGUI.Label<CustomGUIClass>("value0", "label changed");
            CustomGUI.IgnoreMember<CustomGUIClass>("value1");
            CustomGUI.AddRange<CustomGUIClass>("value2", new MinMaxFloat() { max = 100f });
        }

        public override void DoGUI()
        {
            myClass = RGUI.Field(myClass, nameof(myClass));
            customGUIClass = RGUI.Field(customGUIClass, nameof(customGUIClass));
            robustTestClass = RGUI.Field(robustTestClass, nameof(robustTestClass));
            
            GUILayout.Label("ClassWithIDoGUI - automatically call DoGUI within an Array/List and another class.");
            classWithIDoGUIList = RGUI.Field(classWithIDoGUIList, nameof(classWithIDoGUIList));

            GUILayout.Label("ClassWithICloneable - element will be duplicated when add new element.");
            classWithICloneableList = RGUI.Field(classWithICloneableList, nameof(classWithICloneableList));
        }
        
        protected override string title => "RGUI.Field() with class";
    }
}

<|start_filename|>Runtime/Component/Utilities/UnparsedStr.cs<|end_filename|>
﻿using System;
using UnityEngine;


namespace RapidGUI
{
    /// <summary>
    /// UnparsedStr
    /// temporary display string that could not be parsed
    /// </summary>
    public class UnparsedStr
    {
        #region static

        static string lastStr;
        static int lastControlID;

        public static UnparsedStr Create()
        {
            if (ForcusChecker.IsChanged())
            {
                Reset();
            }

            return new UnparsedStr();
        }

        protected static void Reset()
        {
            lastStr = null;
            lastControlID = 0;
        }

        #endregion


        int controlID;

        protected UnparsedStr()
        {
            controlID = GUIUtility.GetControlID(FocusType.Passive);
        }

        public string Get()
        {
            return hasStr ? lastStr : null;
        }

        public void Set(string str)
        {
            if (str == null)
            {
                if ( hasStr )
                {
                    Reset();
                }
            }
            else
            {
                lastStr = str;
                lastControlID = controlID;
            }
        }

        public bool hasStr => (controlID == lastControlID);

        public bool CanParse(Type type)
        {
            var ret = false;
            var str = Get();

            if ( str != null)
            try
            {
                ret = Convert.ChangeType(str, type).ToString() == str;
            }
            catch { }

            return ret;
        }
    }
}

<|start_filename|>package.json<|end_filename|>
{
    "name": "ga.fuquna.rapidgui",
    "displayName": "RapidGUI",
    "version": "1.2.3",
    "unity": "2019.4",
    "description": "IMGUI extensions for Rapid prototyping/development",
    "keywords": ["IMGUI", "GUI"],
    "category": "Tool",
    "dependencies": { 
    },
    "author": {
        "name": "fuqunaga",
        "email": "<EMAIL>",
        "url": "https://fuquna.ga"
    }
}


<|start_filename|>Runtime/RGUI/Scope/BackgroundColorScope.cs<|end_filename|>
﻿using System.Collections.Generic;
using UnityEngine;


namespace RapidGUI
{
    public static partial class RGUI
    {
        static Stack<Color> bacgroundColorScopeStack = new Stack<Color>();

        public static void BeginBackgroundColor(Color color)
        {
            bacgroundColorScopeStack.Push(GUI.backgroundColor);
            GUI.backgroundColor = color;
        }

        public static void EndBackgroundColor()
        {
            GUI.backgroundColor = bacgroundColorScopeStack.Pop();
        }


        public class BackgroundColorScope : GUI.Scope
        {
            public BackgroundColorScope(Color color) => BeginBackgroundColor(color);

            protected override void CloseScope() => EndBackgroundColor();
        }
    }
}

<|start_filename|>Runtime/Component/WindowLauncher.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Experimental.Animations;


namespace RapidGUI
{
    public class WindowLauncher : TitleContent<WindowLauncher>, IDoGUIWindow
    {
        public Rect rect;

        public bool isMoved { get; protected set; }

        public event Action<WindowLauncher> onOpen;
        public event Action<WindowLauncher> onClose;

        public bool isEnable => funcDatas.Any(data => data.checkEnableFunc?.Invoke() ?? true);


        public WindowLauncher() : base() { }

        public WindowLauncher(string name, float width = 300f) : base(name)
        {
            rect.width = width;
        }

        public WindowLauncher SetWidth(float width)
        {
            rect.width = width;
            return this;
        }

        public WindowLauncher SetHeight(float height)
        {
            rect.height = height;
            return this;
        }


        public void DoGUI()
        {
            if (isEnable)
            {
                bool changed;
                using (new GUILayout.HorizontalScope())
                {
                    changed = isOpen != GUILayout.Toggle(isOpen, "❏ " + name, Style.toggle);
                    titleAction?.Invoke();
                }

                if (changed)
                {
                    isOpen = !isOpen;
                    if (isOpen)
                    {
                        isMoved = false;
                        rect.position = RGUIUtility.GetMouseScreenPos() + Vector2.right * 50f;
                        onOpen?.Invoke(this);
                    }
                    else
                    {
                        CloseWindow();
                    }
                }

                if (isOpen)
                {
                    WindowInvoker.Add(this);
                }
            }
        }


        #region IDoGUIWindow

        public void DoGUIWindow()
        {
            if (isOpen && isEnable)
            {
                var pos = rect.position;
                rect = RGUI.ResizableWindow(GetHashCode(), rect,
                    (id) =>
                    {
                        var buttonSize = new Vector2(40f, 15f);
                        var buttonPos = new Vector2(rect.size.x - buttonSize.x, 2f);
                        var buttonRect = new Rect(buttonPos, buttonSize);
                        if (GUI.Button(buttonRect, "✕", RGUIStyle.flatButton))
                        {
                            CloseWindow();
                        }
                        
                        foreach (var func in GetGUIFuncs())
                        {
                            func();
                        }
                        GUI.DragWindow();

                        if (Event.current.type == EventType.Used)
                        {
                            WindowInvoker.SetFocusedWindow(this);
                        }
                    }
                    , name, RGUIStyle.darkWindow);

                isMoved |= pos != rect.position;
            }
        }

        public void CloseWindow()
        {
            isOpen = false;
            onClose?.Invoke(this);
        }

        #endregion


        #region Style

        public static class Style
        {
            public static readonly GUIStyle toggle;
            const int LeftLine = 3;

            // GUIStyleState.background will be null 
            // if it set after secound scene load and don't use a few frame
            // to keep textures, set it to other member. at unity2019
            static readonly List<Texture2D> TexList = new List<Texture2D>();

            static Style()
            {
                Color onColor = new Color(0.3f, 0.5f, 0.98f, 0.9f);

                toggle = CreateToggle(onColor);
                toggle.name = "launcher_unit_toggle";
            }

            static GUIStyle CreateToggle(Color onColor)
            {
                var style = new GUIStyle(GUI.skin.button);
                style.alignment = TextAnchor.MiddleLeft;
                //style.border = new RectOffset(0, 0, 1, underLine + 1);
                style.border = new RectOffset(LeftLine + 1, 1, 0, 0);

                var bgColorHover = Vector4.one * 0.5f;
                var bgColorActive = Vector4.one * 0.7f;

                TexList.Add(style.onNormal.background = CreateToggleOnTex(onColor, Color.clear));
                TexList.Add(style.onHover.background = CreateToggleOnTex(onColor, bgColorHover));
                TexList.Add(style.onActive.background = CreateToggleOnTex(onColor * 1.5f, bgColorActive));

                TexList.Add(style.normal.background = CreateTex(Color.clear));
                TexList.Add(style.hover.background = CreateTex(bgColorHover));
                TexList.Add(style.active.background = CreateTex(bgColorActive));

                return style;
            }

            static Texture2D CreateToggleOnTex(Color col, Color bg)
            {
                //var tex = new Texture2D(1, underLine + 3);
                var tex = new Texture2D(LeftLine + 3,1);

                for (var x = 0; x < tex.width; ++x)
                {
                    var c = (x < LeftLine) ? col : bg;
                    for (var y = 0; y < tex.height; ++y)
                    {
                        //var c = (y < underLine) ? col : bg;
                        tex.SetPixel(x, y, c);
                    }
                }

                tex.Apply();

                return tex;
            }

            static Texture2D CreateTex(Color col)
            {
                var tex = new Texture2D(1, 1);
                tex.SetPixel(0, 0, col);
                tex.Apply();

                return tex;
            }
        }

        #endregion
    }
}

<|start_filename|>Runtime/Component/Utilities/TypeUtilityMemberInfo.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;


namespace RapidGUI
{
    /// <summary>
    /// TypeUtility.GetmemberInfoList() implements
    /// </summary>
    public static partial class TypeUtility
    {
        #region Type Define

        public abstract class MemberWrapper
        {
            public abstract string Name { get; }
            public abstract Type MemberType { get; }

            public abstract object GetValue(object value);
            public abstract void SetValue(object obj, object value);

            string label_;

            public string label
            {
                get
                {
                    return label_ ?? Name;
                }

                set
                {
                    label_ = value;
                }
            }

            public MinMaxFloat range { get; set; }
        }

        public class MemberFieldInfo : MemberWrapper
        {
            FieldInfo info;

            public MemberFieldInfo(FieldInfo info)
            {
                this.info = info;
                var rangeAttr = info.GetCustomAttribute<RangeAttribute>();
                if ( rangeAttr != null)
                {
                    range = new MinMaxFloat()
                    {
                        min = rangeAttr.min,
                        max = rangeAttr.max
                    };
                }
            }

            public override string Name => info.Name;

            public override Type MemberType => info.FieldType;

            public override object GetValue(object obj) => info.GetValue(obj);

            public override void SetValue(object obj, object value) => info.SetValue(obj, value);
        }

        public class MemberPropertyInfo : MemberWrapper
        {
            PropertyInfo info;

            public MemberPropertyInfo(PropertyInfo info)
            {
                this.info = info;
            }

            public override string Name => info.Name;

            public override Type MemberType => info.PropertyType;

            public override object GetValue(object obj) => info.GetValue(obj);

            public override void SetValue(object obj, object value) => info.SetValue(obj, value);
        }

        #endregion

        static Dictionary<Type, List<MemberWrapper>> memberInfoTable = new Dictionary<Type, List<MemberWrapper>>();
        public static List<MemberWrapper> GetMemberInfoList(Type type)
        {
            List<MemberWrapper> list;
            if (!memberInfoTable.TryGetValue(type, out list))
            {
                list = new List<MemberWrapper>();
                list.AddRange(GetPropertyInfoList(type).Select(info => new MemberPropertyInfo(info)));
                list.AddRange(GetFieldInfoList(type).Select(info => new MemberFieldInfo(info)));

                memberInfoTable[type] = list;
            }

            return list;
        }


        #region Property Info List

        static Dictionary<Type, List<PropertyInfo>> propertyInfoTable;
        static List<PropertyInfo> GetPropertyInfoList(Type type)
        {
            if (propertyInfoTable == null)
            {
                var list = new[]
                {
                    new {type = typeof(Vector2Int), names = new[]{"x", "y"} },
                    new {type = typeof(Vector3Int), names = new[]{"x", "y", "z"} },
                    new {type = typeof(Rect), names = new[]{"x", "y", "width", "height"} },
                    new {type = typeof(RectInt), names = new[]{"x", "y", "width", "height"} },
                    new {type = typeof(RectOffset), names = new []{"left", "right", "top", "bottom"} },
                    new {type = typeof(Bounds), names = new[]{"center", "extents"} },
                    new {type = typeof(BoundsInt), names = new[]{ "position", "size"} },
                };

                propertyInfoTable = list.ToDictionary(tn => tn.type, tn => tn.names.Select(name => tn.type.GetProperty(name)).ToList());
            };

            propertyInfoTable.TryGetValue(type, out var piList);

            return piList ?? new List<PropertyInfo>();
        }

        #endregion


        #region Field Info List

        static Dictionary<Type, List<FieldInfo>> fieldInfoTable = new Dictionary<Type, List<FieldInfo>>();

        static List<FieldInfo> GetFieldInfoList(Type type)
        {
            if (!fieldInfoTable.TryGetValue(type, out var fiList))
            {
                fiList = type
                    .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                    .Where(fi => !typeof(Delegate).IsAssignableFrom(fi.FieldType))
                    .Where(fi => fi.IsPublic ? fi.GetCustomAttribute<NonSerializedAttribute>() == null : fi.GetCustomAttribute<SerializeField>() != null)
                    .ToList();
                fieldInfoTable[type] = fiList;
            }

            return fiList;
        }

        #endregion
    }
}


<|start_filename|>Runtime/RGUI/Popup.cs<|end_filename|>
﻿using System;
using System.Linq;
using UnityEngine;

namespace RapidGUI
{
    public static partial class RGUI
    {
        static int popupControlId;
        static readonly PopupWindow popupWindow = new PopupWindow();

        public static string SelectionPopup(string current, string[] displayOptions)
        {
            var idx = Array.IndexOf(displayOptions, current);
            GUILayout.Box(current, RGUIStyle.alignLeftBox);
            var newIdx = PopupOnLastRect(idx, displayOptions);
            if ( newIdx != idx)
            {
                current = displayOptions[newIdx];
            }
            return current;
        }

        public static int SelectionPopup(int selectionIndex, string[] displayOptions)
        {
            var label = (selectionIndex < 0 || displayOptions.Length <= selectionIndex) ? "" : displayOptions[selectionIndex];
            GUILayout.Box(label, RGUIStyle.alignLeftBox);
            return PopupOnLastRect(selectionIndex, displayOptions);
        }


        public static int PopupOnLastRect(string[] displayOptions, string label = "") => PopupOnLastRect(-1, displayOptions, -1, label);
        public static int PopupOnLastRect(string[] displayOptions, int button, string label = "") => PopupOnLastRect(-1, displayOptions, button, label);

        public static int PopupOnLastRect(int selectionIndex, string[] displayOptions, int mouseButton=-1, string label = "") => Popup(GUILayoutUtility.GetLastRect(), mouseButton, selectionIndex, displayOptions, label);



        public static int Popup(Rect launchRect, int mouseButton, int selectionIndex, string[] displayOptions, string label = "")
        {
            var ret = selectionIndex;
            var controlId = GUIUtility.GetControlID(FocusType.Passive);

            // not Popup Owner
            if (popupControlId != controlId)
            {
                var ev = Event.current;
                var pos = ev.mousePosition;

                if ((ev.type == EventType.MouseUp)
                    && ((mouseButton < 0) || (ev.button == mouseButton))
                    && launchRect.Contains(pos)
                    && displayOptions != null 
                    && displayOptions.Any()
                    )
                {
                    popupWindow.pos = RGUIUtility.GetMouseScreenPos(Vector2.one * 150f);
                    popupControlId = controlId;
                    ev.Use();
                }
            }
            // Active
            else
            {
                var type = Event.current.type;
                
                var result = popupWindow.result;
                if (result.HasValue && type == EventType.Layout)
                {
                    if (result.Value >= 0) // -1 when the popup is closed by clicking outside the window
                    {
                        ret = result.Value;
                    }
                    popupWindow.result = null;
                    popupControlId = 0;
                }
                else
                {

                    if ((type == EventType.Layout) || (type == EventType.Repaint))
                    {
                        var buttonStyle = RGUIStyle.popupFlatButton;
                        var contentSize = Vector2.zero;
                        for (var i = 0; i < displayOptions.Length; ++i)
                        {
                            var textSize = buttonStyle.CalcSize(RGUIUtility.TempContent(displayOptions[i]));
                            contentSize.x = Mathf.Max(contentSize.x, textSize.x);
                            contentSize.y += textSize.y;
                        }

                        var margin = buttonStyle.margin;
                        contentSize.y += Mathf.Max(0, displayOptions.Length - 1) * Mathf.Max(margin.top, margin.bottom); // is this right?

                        var vbarSkin = GUI.skin.verticalScrollbar;
                        var vbarSize = vbarSkin.CalcScreenSize(Vector2.zero);
                        var vbarMargin = vbarSkin.margin;

                        var hbarSkin = GUI.skin.horizontalScrollbar;
                        var hbarSize = hbarSkin.CalcScreenSize(Vector2.zero);
                        var hbarMargin = hbarSkin.margin;

                        const float offset = 5f;
                        contentSize += new Vector2(vbarSize.x + vbarMargin.horizontal, hbarSize.y + hbarMargin.vertical) + Vector2.one * offset;
                        var size = RGUIStyle.popup.CalcScreenSize(contentSize);
                        var maxSize = new Vector2(Screen.width, Screen.height) - popupWindow.pos;

                        popupWindow.size = Vector2.Min(size, maxSize);
                    }

                    popupWindow.label = label;
                    popupWindow.displayOptions = displayOptions;
                    WindowInvoker.Add(popupWindow);
                }
            }

            return ret;
        }


        class PopupWindow : IDoGUIWindow
        {
            public string label;
            public Vector2 pos;
            public Vector2 size;
            public int? result;
            public string[] displayOptions;
            public Vector2 scrollPosition;

            static readonly int PopupWindowId = "Popup".GetHashCode();

            public Rect GetWindowRect() => new Rect(pos, size);

            public void DoGUIWindow()
            {
                GUI.ModalWindow(PopupWindowId, GetWindowRect(), (id) =>
                {
                    using (var sc = new GUILayout.ScrollViewScope(scrollPosition))
                    {
                        scrollPosition = sc.scrollPosition;

                        for (var j = 0; j < displayOptions.Length; ++j)
                        {
                            if (GUILayout.Button(displayOptions[j], RGUIStyle.popupFlatButton))
                            {
                                result = j;
                            }
                        }
                    }

                    var ev = Event.current;
                    if ((ev.rawType == EventType.MouseDown) && !(new Rect(Vector2.zero, size).Contains(ev.mousePosition)))
                    {
                        result = -1; ;
                    }
                }
                , label, RGUIStyle.popup);
            }

            public void CloseWindow() { result = -1; }
        }
    }
}

<|start_filename|>Runtime/RGUI/PrefixLabel.cs<|end_filename|>
﻿using System;
using UnityEngine;


namespace RapidGUI
{
    public static partial class RGUI
    {
        public static class PrefixLabelSetting
        {
            public static float width = 130f;
        }

        public static bool PrefixLabel(string label)
        {
            var isLong = false;

            if (!string.IsNullOrEmpty(label))
            {
                var style = GUI.skin.label;
                isLong = PrefixLabelSetting.width > 0f && style.CalcSize(RGUIUtility.TempContent(label)).x > PrefixLabelSetting.width;

                if (isLong)
                {
                    GUILayout.Label(label);
                }
                else
                {
                    GUILayout.Label(label, GUILayout.Width(PrefixLabelSetting.width));
                }
            }

            return isLong;
        }

        //public static object PrefixLabelDraggable(string label, object obj, Type type) => PrefixLabelDraggable(label, obj, type, out var _);

        public static object PrefixLabelDraggable(string label, object obj, Type type, out bool isLong)
        {
            isLong = false;
            if (!string.IsNullOrEmpty(label))
            {
                isLong = PrefixLabel(label);
                if (IsDraggable(type))
                {
                    obj = DoDrag(obj, type);
                }
            }

            return obj;
        }


        #region implement drag

        static Vector2 lastMousePos;
        static readonly int DoDragHash = "DoDrag".GetHashCode();

        static object DoDrag(object obj, Type type)
        {
            var controlId = GUIUtility.GetControlID(DoDragHash, FocusType.Passive);

            var rect = GUILayoutUtility.GetLastRect();

            var ev = Event.current;
            var evType = ev.GetTypeForControl(controlId);

            switch (evType)
            {
                case EventType.MouseDown:
                {
                    if ((ev.button == RapidGUIBehaviour.Instance.prefixLabelSlideButton) &&
                        rect.Contains(ev.mousePosition))
                    {
                        GUIUtility.hotControl = controlId;
                        lastMousePos = ev.mousePosition;

                        RGUIUtility.SetCursor(MouseCursor.ResizeHorizontal);
                        ev.Use();
                    }
                }
                break;

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

                case EventType.MouseDrag:
                {
                    if ((ev.button == RapidGUIBehaviour.Instance.prefixLabelSlideButton) &&
                        (GUIUtility.hotControl == controlId))
                    {
                        var diff = ev.mousePosition - lastMousePos;
                        var add = (Mathf.Abs(diff.x) > Mathf.Abs(diff.y)) ? diff.x : diff.y;
                        add = Math.Sign(add);

                        lastMousePos = ev.mousePosition;
                        if (typeof(int) == type)
                        {
                            var v = (int) obj;
                            v += (int) (add);
                            obj = v;
                        }
                        else if (typeof(float) == type)
                        {
                            var scale = 0.03f;
                            var v = (float) obj;
                            v += add * scale;
                            v = Mathf.Floor(v * 100f) * 0.01f; // chop
                            obj = v;
                        }

                        ev.Use();
                    }
                }
                break;
                
                case EventType.Repaint:
                {
                    if (GUIUtility.hotControl == controlId)
                    {
                        RGUIUtility.SetCursor(MouseCursor.ResizeHorizontal);
                    }
                }
                break;
            }

            return obj;
        }


        public static bool IsDraggable(Type type)
        {
            return (
                (typeof(int) == type) ||
                (typeof(float)) == type
            );
        }
    }

    #endregion
}

<|start_filename|>Runtime/Component/Utilities/Cursor/Cursor.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RapidGUI
{
    public enum MouseCursor
    {
        Default,
        ResizeHorizontal,
        ResizeVertical,
        ResizeUpLeft,
    }

    public static partial class RGUIUtility
    {
        static readonly Dictionary<MouseCursor, CursorData.Data> cursorTable;


        static RGUIUtility()
        {
            var data = Resources.Load<CursorData>("cursorData");

            cursorTable = new Dictionary<MouseCursor, CursorData.Data>()
            {
                { MouseCursor.Default, null},
                { MouseCursor.ResizeHorizontal, data.resizeHorizontal},
                { MouseCursor.ResizeVertical, data.resizeVertical},
                { MouseCursor.ResizeUpLeft, data.resizeUpLeft},
            };

            RapidGUIBehaviour.Instance.StartCoroutine(UpdateCursor());
        }


        static float cursorLimitTime;
        static float GetCursorTime() => Time.realtimeSinceStartup;

        public static void SetCursor(MouseCursor cursor, float life = 0.1f)
        {
            if (cursor == MouseCursor.Default)
            {
                SetCursorDefault();
            }
            else
            {
                var data = cursorTable[cursor];

                Cursor.SetCursor(data.tex, data.hotspot, CursorMode.Auto);
                cursorLimitTime = GetCursorTime() + life;
            }
        }

        public static void SetCursorDefault()
        {
            Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
            cursorLimitTime = float.MaxValue;
        }


        static IEnumerator UpdateCursor()
        {
            while (true)
            {
                yield return new WaitUntil(() => GetCursorTime() > cursorLimitTime);
                SetCursorDefault();
            }
        }
    }
}