Пытаюсь сделать контрол в котором совмещено текстовое поле с кнопкой выбора варианта. Реализовано следующим образом
Синтаксис:
Используется csharp
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections;
public class PopupTextAttribute : PropertyAttribute
{
public PopupTextAttribute()
{
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(PopupTextAttribute))]
public class PopupTextDrawer : PropertyDrawer
{
protected string selectVal = null;
override public void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
position.height = EditorGUIUtility.singleLineHeight;
Rect r = EditorGUI.PrefixLabel(position, label);
EditorGUI.BeginChangeCheck();
Color oldColor = GUI.color;
r.width -= EditorGUIUtility.singleLineHeight * 2;
string result = property.stringValue;
if (!CheckCorrect(property.stringValue))
{
GUI.color = Color.grey;
}
result = GUI.TextField(r, result, EditorStyles.textField);
GUI.color = oldColor;
r.x += r.width;
r.width = EditorGUIUtility.singleLineHeight + 2;
if (GUI.Button(r, "L", EditorStyles.miniButton))
{
var menu = new GenericMenu();
string[] options = GetOptions();
foreach (string s in options)
{
string localS = s;
menu.AddItem(new GUIContent(localS.Replace(".", "/")),
false,
() => selectVal = localS
);
}
menu.ShowAsContext();
}
if (EditorGUI.EndChangeCheck())
{
SetValue(property, result);
}
r.x += r.width;
r.width = EditorGUIUtility.singleLineHeight + 2;
if (GUI.Button(r, "C", EditorStyles.miniButton))
{
Clear(property);
}
if (GetOptions().Length == 0)
{
position.y += EditorGUIUtility.singleLineHeight;
r = EditorGUI.PrefixLabel(position, new GUIContent(" "));
EditorGUI.LabelField(position, " ", "Не удалось получить список значений.");
return;
}
if (!string.IsNullOrEmpty(selectVal))
{
SetValue(property, selectVal);
selectVal = null;
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight * (GetOptions().Length > 0 ? 1 : 2 ) + 2;
}
virtual public void Clear(SerializedProperty property)
{
property.stringValue = "";
}
virtual public void SetValue(SerializedProperty property, string option)
{
property.stringValue = option;
}
/*virtual public void SetValue(SerializedProperty property, int selected)
{
}*/
virtual public bool CheckCorrect(string selected)
{
string[] options = GetOptions();
return Array.Exists(options, r => r == selected);
}
virtual public string[] GetOptions()
{
string[] ss = {"1","2","3","4","5"};
return ss;
}
virtual public bool IsSupported(SerializedProperty property){
return property.propertyType == SerializedPropertyType.String;
}
}
#endif
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections;
public class PopupTextAttribute : PropertyAttribute
{
public PopupTextAttribute()
{
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(PopupTextAttribute))]
public class PopupTextDrawer : PropertyDrawer
{
protected string selectVal = null;
override public void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
position.height = EditorGUIUtility.singleLineHeight;
Rect r = EditorGUI.PrefixLabel(position, label);
EditorGUI.BeginChangeCheck();
Color oldColor = GUI.color;
r.width -= EditorGUIUtility.singleLineHeight * 2;
string result = property.stringValue;
if (!CheckCorrect(property.stringValue))
{
GUI.color = Color.grey;
}
result = GUI.TextField(r, result, EditorStyles.textField);
GUI.color = oldColor;
r.x += r.width;
r.width = EditorGUIUtility.singleLineHeight + 2;
if (GUI.Button(r, "L", EditorStyles.miniButton))
{
var menu = new GenericMenu();
string[] options = GetOptions();
foreach (string s in options)
{
string localS = s;
menu.AddItem(new GUIContent(localS.Replace(".", "/")),
false,
() => selectVal = localS
);
}
menu.ShowAsContext();
}
if (EditorGUI.EndChangeCheck())
{
SetValue(property, result);
}
r.x += r.width;
r.width = EditorGUIUtility.singleLineHeight + 2;
if (GUI.Button(r, "C", EditorStyles.miniButton))
{
Clear(property);
}
if (GetOptions().Length == 0)
{
position.y += EditorGUIUtility.singleLineHeight;
r = EditorGUI.PrefixLabel(position, new GUIContent(" "));
EditorGUI.LabelField(position, " ", "Не удалось получить список значений.");
return;
}
if (!string.IsNullOrEmpty(selectVal))
{
SetValue(property, selectVal);
selectVal = null;
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight * (GetOptions().Length > 0 ? 1 : 2 ) + 2;
}
virtual public void Clear(SerializedProperty property)
{
property.stringValue = "";
}
virtual public void SetValue(SerializedProperty property, string option)
{
property.stringValue = option;
}
/*virtual public void SetValue(SerializedProperty property, int selected)
{
}*/
virtual public bool CheckCorrect(string selected)
{
string[] options = GetOptions();
return Array.Exists(options, r => r == selected);
}
virtual public string[] GetOptions()
{
string[] ss = {"1","2","3","4","5"};
return ss;
}
virtual public bool IsSupported(SerializedProperty property){
return property.propertyType == SerializedPropertyType.String;
}
}
#endif
Все отлично работает пока поле представлено обычным значением, но как только мне надо вывести массив начинаются проблемы. Ввод вручную работает нормально, а вот выбор изменяет только значение в первом элементе.
Вот тестовый скрипт, вешаем на любой объект сцены и смотрим результат в редакторе
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class PopupTextTest : MonoBehaviour
{
[PopupText] public string t1 = "";
[PopupText] public string t2 = "";
[PopupText] public string[] tt = new string[0];
}
using System.Collections;
public class PopupTextTest : MonoBehaviour
{
[PopupText] public string t1 = "";
[PopupText] public string t2 = "";
[PopupText] public string[] tt = new string[0];
}
подозреваю что проблема вот в этом месте
Синтаксис:
Используется csharp
menu.AddItem(new GUIContent(localS.Replace(".", "/")),
false,
() => selectVal = localS
);
false,
() => selectVal = localS
);
пробовал selectVal делать локальной для метода или сохранять значение сразу в property.stringValue но так не работает...
может кто знает как сие победить?