I’m working on a property drawer for a custom type. I’m almost there, and as far as I can tell, this code should display the popup for the given type. I can get my Debug.Log to fire, but the Popup call never draws. This has behaved this way in 2019.4.20f1 through 2019.4.22f1. So I’m pretty sure it’s something wrong with how I’m calling it, or trying to position it, or something. It used to use the direct position from the property drawer argument, so I adjusted those numbers in the popup call in case I was somehow drawing behind the dropdown button.
Relevant types below. Armor type uses the reference for some DB lookups and works in runtime as intended. The editor is another story. The name lookup for the active armor type appears on the GUIDropdownButton. The call to EditorUtils.GetArmorLabels works as intended and give an array of strings for the function. The calls to DamageTable all work as intended.
[Serializable]
public class ArmorType
{
public int reference;
}
using UnityEngine;
public class Armor : MonoBehaviour
{
[SerializeField] protected ArmorType armorType;
}
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ArmorType))]
public class ArmorTypeDrawerUGUI : PropertyDrawer
{
int armorTypeIndex = 0;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
DamageTable.Init();
var armorTypes = DamageTable.AllArmorTypes();
SerializedProperty targetProperty = property.FindPropertyRelative("reference");
armorTypeIndex = targetProperty.intValue;
if (EditorGUI.DropdownButton(position, new GUIContent("Armor Type: " + armorTypes[armorTypeIndex].name, "Changes damage taken vs damage types"), FocusType.Passive))
{
Debug.Log("Aha");
armorTypeIndex = EditorGUI.Popup(new Rect(position.x, position.y + 30, position.width, position.height * armorTypes.Count), armorTypeIndex, EditorUtils.GetArmorLabels());
targetProperty.intValue = armorTypeIndex;
}
}
You’re trying to use EditorGUI.Popup but that’s a full field component, not only the popup. What your code is basically doing, is trying to show a popup button very briefly when the user clicks the dropdown button. Instead, you need to trigger a popup menu or open a custom window when the user clicks.
I’ve updated the editor to the GenericMenu example, but I can’t seem to set the property I actually want using this method. My code is below. Since I’m trying to do this as a property drawer, I’m trying to cache the property being edited, and assigning back to it in the callback, but this does not appear to be saving the clicked item to the property, so I’m still missing something.
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ArmorType))]
public class ArmorTypeDrawerUGUI : PropertyDrawer
{
int armorTypeIndex = 0;
SerializedProperty targetProperty;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
DamageTable.Init();
var armorTypes = DamageTable.AllArmorTypes();
targetProperty = property.FindPropertyRelative("reference");
armorTypeIndex = targetProperty.intValue;
if (EditorGUI.DropdownButton(position, new GUIContent("Armor Type: " + armorTypes[armorTypeIndex].name, "Changes damage taken vs damage types"), FocusType.Passive))
{
GenericMenu menu = new GenericMenu();
for (int armorID = 0; armorID < armorTypes.Count; armorID++)
{
menu.AddItem(new GUIContent(armorTypes[armorID].name), false, handleItemClicked, armorID);
}
menu.DropDown(position);
//label.text += " - " + armorTypes[armorTypeIndex].name;
//Debug.Log("Aha");
//armorTypeIndex = EditorGUI.Popup(new Rect(position.x, position.y + 30, position.width, position.height * armorTypes.Count), armorTypeIndex, EditorUtils.GetArmorLabels());
//targetProperty.intValue = armorTypeIndex;
}
}
private void handleItemClicked(object parameter)
{
Debug.Log(parameter);
targetProperty.intValue = armorTypeIndex;
}
}
I’m new to writing editors. I don’t know quite where to put the undo call. Would this be in the handleItemClicked? the example doesn’t have an Undo, so I didn’t use one. And, would the Undo call set the property to save on its own? The problem isn’t that I can’t undo, it’s that I can’t do in the first place.
The menu shows, and the Debug shows the int sent into handleItemClicked, but the next line isn’t reflected in the object editor, so the setting isn’t saving. I’ve tried putting the menu in a BeginChangeCheck block, but still the property doesn’t save.
I think you could put it at the start of handleItemClicked() and give it the targetProperty you are changing, and a short string description of what you’re doing, which will show up in the menu as “Undo Fluidminds Big Change” for instance.
I believe what it does is say “See this? I’m going to modify it, you keep track of what it was before and make an Undo record. And this is what I want that undo to be called label-wise.”
I was overthinking this. In the end, Adrian’s advice about EditorGUI.Popup being its own field renderer, I finally tried using it as the base type. the following works the charm.
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ArmorType))]
public class ArmorTypeDrawerUGUI : PropertyDrawer
{
int armorTypeIndex = 0;
SerializedProperty targetProperty;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
DamageTable.Init();
var armorTypes = DamageTable.ArmorNames();
targetProperty = property.FindPropertyRelative("reference");
armorTypeIndex = targetProperty.intValue;
armorTypeIndex = EditorGUI.Popup(position, armorTypeIndex, armorTypes);
targetProperty.intValue = armorTypeIndex;
}
}