Страница 1 из 2

Коллекция Property Drawers

СообщениеДобавлено: 25 фев 2014, 22:01
Unitmen
Предыстория: Во время разработки классов для использования в команде часто требуется делать для них интерфейс удобный для не программистов.
У меня таких классов вагон и маленькая тележка, без нормального инструментария привести их в божеский вид - сложная задачка. Короче теперь инструментарий есть Property Drawers, но на его разработку тоже тратится время.
Предлагаю делится своими Property Drawers.
Но для начала небольшой туториал на русском по их созданию (в отличии от известного тутора Property Drawers in Unity 4 - этот проще для понимания, так как основан на простейшем примере)

В виду того, что движок форума упорно заменяет открывающие скобки на заменяющие символы и весь код просто становится ничетаемым урок переехал на github, собственно и все примеры туда оформлю как будет время.

Далее предлагаю постить в эту тему свои Property Drawers.
Желательно оформлять по единому шаблону, например вот так:


Property Drawers HelpAttribute

help_demo.png

Example: test.cs
Синтаксис:
Используется csharp
using UnityEngine;

public class test : MonoBehaviour {
        [HelpAttribute("Анимация открытия дверей")]
        public Animator OpenDor;
}


Attribute: HelpAttribute.cs
Синтаксис:
Используется csharp
using UnityEngine;

public class HelpAttribute : PropertyAttribute
{
        public string HelpMessageText;
        public HelpAttribute(string text)
        {
                this.HelpMessageText = text;
        }
}


Drawer HelpDrawer.cs
Синтаксис:
Используется csharp
using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(HelpAttribute))]
public class HelpDrawer : PropertyDrawer {

        private int helpHeight = 50, textHeight = 16, HeaderY = 2;
       
        HelpAttribute helpAttribute
        {
                get
                {
                        return (HelpAttribute) attribute;
                }
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){
                if(!string.IsNullOrEmpty(helpAttribute.HelpMessageText))
                {
                        position.height = textHeight;

                        EditorGUI.PropertyField(position,property,label);

                        position.y += textHeight + HeaderY;
                        position.height = helpHeight;

                        EditorGUI.HelpBox(position , helpAttribute.HelpMessageText, MessageType.Info); 
                }
                else
                {
                        EditorGUI.PropertyField(position,property,label);
                }
        }
       
        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
                return base.GetPropertyHeight(property, label) + helpHeight + (string.IsNullOrEmpty(helpAttribute.HelpMessageText) ? 0 : textHeight);
        }
}

Re: Коллекция Property Drawers

СообщениеДобавлено: 26 фев 2014, 13:45
Unitmen
Админам: Резервирую.

Property Drawers: PopupAttribute

Примечание: Основная реализация PopupDrawer.cs не моя, я только устранил несколько ошибок и немного причесал.
Взято с японского форума, адрес уже потерялся, надеюсь автор не будет против.


Примечание 2: Следите за соответствием типов при использовании PopupAttribute. То-есть, если у вас тип переменной float, не стоит подставлять ей строку.

popup_demo.png


Example: PopupExample.cs
Синтаксис:
Используется csharp
using UnityEngine;

public class PopupExample : MonoBehaviour
{
    [Popup("Spot","Directional","Point","Area")]
    public string LightType;
    [Popup(2,4,16,256,65536)]
    public int Integer;
    [Popup(0.5f,1.0f,1.5f,2.0f,2.5f,3.0f)]
    public float Float;
        [PopupAttribute ("red", "blue", "gray")]
        public string Color;
}

Attribute: PopupAttribute.cs
Синтаксис:
Используется csharp
using UnityEngine;

/// <summary>
/// Popup attribute - позволяют создать выпадающие списки предопределенных значений.
/// </summary>
public class PopupAttribute : PropertyAttribute
{
        /// <summary>
        /// list - массив предопределенных значений.
        /// </summary>
        public object[] ValuesArray;
   
        /// <summary>
        /// Инициализирует новый экземпляр класса <see cref="PopupAttribute"/>.
        /// </summary>
        /// <param name="list">Массив предопределенных значений.</param>
    public PopupAttribute (params object[] list)
    {
                this.ValuesArray = list;
    }
}


Drawer: PopupDrawer.cs
Синтаксис:
Используется csharp
using UnityEngine;
using UnityEditor;
using System;

[CustomPropertyDrawer(typeof(PopupAttribute))]
public class PopupDrawer : PropertyDrawer
{
       
        private Action<int> setValue;
        private Func<int, int> validateValue;
        private string[] _list = null;
       
        private string[] list
        {
                get
                {
                        if (_list == null)
                        {
                                _list = new string[popupAttribute.ValuesArray.Length];
                                for (int i = 0; i < popupAttribute.ValuesArray.Length; i++)
                                {
                                        _list[i] = popupAttribute.ValuesArray[i].ToString();
                                }
                        }
                        return _list;
                }
        }
       
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
                if (validateValue == null && setValue == null)
                        SetUp(property);
               
               
                if (validateValue == null && setValue == null)
                {
                        base.OnGUI(position, property, label);
                        return;
                }
               
                int selectedIndex = 0;
               
                for (int i = 0; i < list.Length; i++)
                {
                        selectedIndex = validateValue(i);
                        if (selectedIndex != 0)
                                break;
                }
               
                EditorGUI.BeginChangeCheck();
                selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, list);
                if (EditorGUI.EndChangeCheck())
                {
                        setValue(selectedIndex);
                }
        }
       
        void SetUp(SerializedProperty property)
        {
                if (variableType == typeof(string))
                {
                       
                        validateValue = (index) =>
                        {
                                return property.stringValue == list[index] ? index : 0;
                        };
                       
                        setValue = (index) =>
                        {
                                property.stringValue = list[index];
                        };
                }
                else if (variableType == typeof(int))
                {
                       
                        validateValue = (index) =>
                        {
                                return property.intValue == Convert.ToInt32(list[index]) ? index : 0;
                        };
                       
                        setValue = (index) =>
                        {
                                property.intValue = Convert.ToInt32(list[index]);
                        };
                }
                else if (variableType == typeof(float))
                {
                        validateValue = (index) =>
                        {
                                return property.floatValue == Convert.ToSingle(list[index]) ? index : 0;
                        };
                        setValue = (index) =>
                        {
                                property.floatValue = Convert.ToSingle(list[index]);
                        };
                }
               
        }
       
        PopupAttribute popupAttribute
        {
                get { return (PopupAttribute)attribute; }
        }
       
        private Type variableType
        {
                get
                {
                        return popupAttribute.ValuesArray[0].GetType();
                }
        }
}

Re: Коллекция Property Drawers

СообщениеДобавлено: 26 фев 2014, 14:14
Unitmen
Резервирую.

Property Drawers: TooltipAttribute

tooltip_demo.png


Example: TooltipExample.cs
Синтаксис:
Используется csharp
using UnityEngine;

public class TooltipExample : MonoBehaviour
{
        [TooltipAttribute("Всплывающая подсказка по WheelCollider")]
    public WheelCollider wheelCollider;
}


Attribute: TooltipAttribute.cs
Синтаксис:
Используется csharp
using UnityEngine;

/// <summary>
/// Tooltip attribute - Атрибут позволяет Выводить всплывающую подсказку при наведении мышки на контрол.
/// </summary>
public class TooltipAttribute : PropertyAttribute
{
        /// <summary>
        /// Значение типа строка для всплывающей подсказки.
        /// </summary>
    public string Tooltip;
        /// <summary>
        /// Создание экземпляра класса <see cref="TooltipAttribute"/>.
        /// </summary>
        /// <param name="tooltip">Значение типа строка для всплывающей подсказки.</param>
    public TooltipAttribute(string tooltip)
    {
        this.Tooltip = tooltip;
    }
}


Drawer: TooltipDrawer.cs
Синтаксис:
Используется csharp
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(TooltipAttribute))]
public class TooltipDrawer : PropertyDrawer
{
    TooltipAttribute tooltipAttribute
    {
        get
        {
            return (TooltipAttribute) attribute;
        }
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        if (!string.IsNullOrEmpty(tooltipAttribute.Tooltip))
        {
            label.tooltip = tooltipAttribute.Tooltip;
        }
        EditorGUI.PropertyField(position, property, label);
    }
}

Re: Коллекция Property Drawers

СообщениеДобавлено: 26 фев 2014, 15:32
Strannik
свои еще не писал, но когда ознакамливался, наткнулся на эту коллекцию Property Drawers:
https://github.com/anchan828/property-drawer-collection

Re: Коллекция Property Drawers

СообщениеДобавлено: 26 фев 2014, 16:07
Unitmen
Strannik писал(а):свои еще не писал, но когда ознакамливался, наткнулся на эту коллекцию Property Drawers:
https://github.com/anchan828/property-drawer-collection

Посмотрел, в принципе часть из них у меня уже есть, только в нормальном виде. Как набор заготовок для создания собственный Property Drawers - самое оно. Кстати изначальный PopupAttribute похоже именно из этого сборника.

Re: Коллекция Property Drawers

СообщениеДобавлено: 27 мар 2014, 13:02
KingPeas
Unitmen писал(а):Drawer: TooltipDrawer.cs


При использовании для поля типа Vector3 или Vector2 проблема с высотой поля. При узком окне инспектора для Vector свойство выводится в две строки, а Drawer отрисовывает высотой в одну строку. Как не пытался так и не смог сие победить.

Re: Коллекция Property Drawers

СообщениеДобавлено: 27 мар 2014, 14:13
Nicloay
вот вам коллекция built in аттрибутов. такие вещи как popup - там уже есть.
https://docs.unity3d.com/Documentation/ ... =Attribute

Re: Коллекция Property Drawers

СообщениеДобавлено: 28 мар 2014, 06:01
KingPeas
Nicloay писал(а):вот вам коллекция built in аттрибутов. такие вещи как popup - там уже есть.
https://docs.unity3d.com/Documentation/ ... =Attribute

Что-то не по глазам, а где там popup?

Re: Коллекция Property Drawers

СообщениеДобавлено: 19 апр 2014, 15:55
Unitmen
KingPeas писал(а):При использовании для поля типа Vector3 или Vector2 проблема с высотой поля. При узком окне инспектора для Vector свойство выводится в две строки, а Drawer отрисовывает высотой в одну строку. Как не пытался так и не смог сие победить.

Попробовал, так и есть, видимо нужно переопределять и перерисовывать и сами vector2/vector3 поля...
Синтаксис:
Используется csharp
        if (!string.IsNullOrEmpty(tooltipAttribute.Tooltip))
        {
            label.tooltip = tooltipAttribute.Tooltip;
           
            // Здесь меняем property (вначале проверить тип property  т.д.)

        }
        EditorGUI.PropertyField(position, property, label);
 

Сейчас разбираться нет времени, есть желание - поправьте...

Re: Коллекция Property Drawers

СообщениеДобавлено: 23 апр 2014, 06:24
KingPeas
Ну на сколько я понимаю гораздо правильнее было бы переопределить высоту поля. Осталось только определить что рисуется поле с типом вектора и вычислить что в данном случае он должен отрисоваться в две строки потому как Editor окно узкое.

Re: Коллекция Property Drawers

СообщениеДобавлено: 25 мар 2015, 20:35
KingPeas
Для того чтобы определить выводятся ли большинство типов полей (Vector2-4, Rect, и т.п.) в одну строку или в несколько нужно пользоваться EditorGUIUtility.wideMode, именно в этой переменной хранится как осуществляется вывод сложных полей, выводится метка на первой строке, а объект ниже или же поля выводятся после метки в той же первой строке.
Наконец добил свой плагин PropertyDrawerCollection выложил в AssetSore. :ymparty:
В планах для 2 версии добавить поддержку массивов с возможностью сортировки, вставки, удаления и переноса элементов внутри массива.

Re: Коллекция Property Drawers

СообщениеДобавлено: 11 дек 2015, 12:41
Tolking
Вот такую штуку запилил для не очень кастомных монобехов...

Re: Коллекция Property Drawers

СообщениеДобавлено: 09 янв 2016, 06:27
Unitmen
Tolking писал(а):Вот такую штуку запилил для не очень кастомных монобехов...

(3A4OT) Более подробно можно про разработочку?

Re: Коллекция Property Drawers

СообщениеДобавлено: 09 янв 2016, 14:03
Tolking
1) Ищу монобехи и помечаю галкой, тот который хочу кастомизировать.
2) Помеченный монобех разбираю через рефлексию и составляю список полей для вывода, сохраняю в скриптаблеОбжект.
3) Генерирую текст кастомного вывода монобеха и компилю. В кастомном выводе из скриптаблеОбжект берется список полей и выводиться...
4) Сделал формочку кастомизации вывода.
| а) Очередность
| б) Название
| в) коментарий
| г) добавление пробела между полями
| д) группировка полей
все это сохраняется в скриптаблеОбжект и выводится...

Для подготовки компонента для геймдизайнера очень экономит время. +скрывать в отдельной папке "служебные" поля и коментарии чтоб не забыть что и зачем...

Re: Коллекция Property Drawers

СообщениеДобавлено: 28 янв 2016, 23:14
Unitmen
Tolking писал(а):Для подготовки компонента для геймдизайнера очень экономит время. +скрывать в отдельной папке "служебные" поля и коментарии чтоб не забыть что и зачем...

:-bd Отличная идея, беру на вооружение...