Custom inspector for items in array
Hi. I have non serialized class called: Item: [System.Serializable] public class Item { public string name; public int cost; public Sprite image; public ItemType item_type; public WeaponType weapon_type; public ArmorType armor_type;
public enum ItemType { Item, Armor, Weapon };
public enum WeaponType { ShortSecant, LongSecant, Blunt, Prickly, Distance };
public enum ArmorType { Cuirass, Helmet, Boots };
//weapon
public int damages;
//armor
public int armor_points;
public Item(string name, int cost)
{
this.name = name;
this.cost = cost;
}
}
And I have an array of this class objects in another script inherited from Monobehaviour:
public class Test2 : MonoBehaviour
{
public Item[] Items;
}
And the Item class have enum called ItemType, some variables are not necessary for some item types, for example: If the item have type: Armor, i need to set up ArmorType, cost, name, image and armor_points, i dont need WeaponType and damages.
So I want to create Custom Inspector class or something that will be hide for me some fields when other fields have specified value.
What I must write to show in inspector only that fields I need, in the same way that standard inspector shows array?
Answer by ElijahShadbolt · Nov 15, 2016 at 07:26 AM
Create a custom PropertyDrawer for the Item class.
If you want to display the class over more than one line, make sure you override the GetPropertyHeight method.
Edit: I created a Custom PropertyDrawer for your Item class.
Test2.cs
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[System.Serializable]
public class Item
{
public string name;
public int cost;
public Sprite image;
public ItemType item_type;
public WeaponType weapon_type;
public ArmorType armor_type;
public enum ItemType { Item, Armor, Weapon };
public enum WeaponType { ShortSecant, LongSecant, Blunt, Prickly, Distance };
public enum ArmorType { Cuirass, Helmet, Boots };
//weapon
public int damages;
//armor
public int armor_points;
public Item(string name, int cost)
{
this.name = name;
this.cost = cost;
}
#if UNITY_EDITOR
public bool _expanded = false;
#endif
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(Item))]
public class Item_PropertyDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float h = base.GetPropertyHeight(property, label);
int rows = 1;
if (property.FindPropertyRelative("_expanded").boolValue)
{
rows += 4;
Item.ItemType itemType = (Item.ItemType)property.FindPropertyRelative("item_type").enumValueIndex;
if (itemType == Item.ItemType.Armor)
rows += 2;
else if (itemType == Item.ItemType.Weapon)
rows += 2;
}
return h * rows;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Draw label
SerializedProperty p_expanded = property.FindPropertyRelative("_expanded");
float h = base.GetPropertyHeight(property, label);
position.height = h;
p_expanded.boolValue = EditorGUI.Foldout(position, p_expanded.boolValue, label);
if (p_expanded.boolValue)
{
position.y += h;
position.height = GetPropertyHeight(property, label) - h;
EditorGUI.BeginProperty(position, label, property);
//position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
++EditorGUI.indentLevel;
// Calculate rects
float x = position.x,
y = position.y,
w = position.width;
Rect r_name = new Rect(x, y, w, h);
y += h;
Rect r_cost = new Rect(x, y, w, h);
y += h;
Rect r_image = new Rect(x, y, w, h);
y += h;
Rect r_item_type = new Rect(x, y, w, h);
// draw properties
SerializedProperty p_name = property.FindPropertyRelative("name");
SerializedProperty p_cost = property.FindPropertyRelative("cost");
SerializedProperty p_image = property.FindPropertyRelative("image");
SerializedProperty p_item_type = property.FindPropertyRelative("item_type");
EditorGUI.PropertyField(r_name, p_name, new GUIContent(p_name.displayName));
EditorGUI.PropertyField(r_cost, p_cost, new GUIContent(p_cost.displayName));
EditorGUI.PropertyField(r_image, p_image, new GUIContent(p_image.displayName));
EditorGUI.PropertyField(r_item_type, p_item_type, new GUIContent(p_item_type.displayName));
// hidden item type fields
++EditorGUI.indentLevel;
Item.ItemType itemType = (Item.ItemType)p_item_type.enumValueIndex;
if (itemType == Item.ItemType.Weapon)
{
y += h;
Rect r_weapon_type = new Rect(x, y, w, h);
y += h;
Rect r_damages = new Rect(x, y, w, h);
SerializedProperty p_weapon_type = property.FindPropertyRelative("weapon_type");
SerializedProperty p_damages = property.FindPropertyRelative("damages");
EditorGUI.PropertyField(r_weapon_type, p_weapon_type, new GUIContent(p_weapon_type.displayName));
EditorGUI.PropertyField(r_damages, p_damages, new GUIContent(p_damages.displayName));
}
else if (itemType == Item.ItemType.Armor)
{
y += h;
Rect r_armor_type = new Rect(x, y, w, h);
y += h;
Rect r_armor_points = new Rect(x, y, w, h);
SerializedProperty p_armor_type = property.FindPropertyRelative("armor_type");
SerializedProperty p_armor_points = property.FindPropertyRelative("armor_points");
EditorGUI.PropertyField(r_armor_type, p_armor_type, new GUIContent(p_armor_type.displayName));
EditorGUI.PropertyField(r_armor_points, p_armor_points, new GUIContent(p_armor_points.displayName));
}
--EditorGUI.indentLevel;
--EditorGUI.indentLevel;
EditorGUI.EndProperty();
}
}
}
#endif
public class Test2 : MonoBehaviour
{
public Item[] items;
}
Okay, but what I must do, to have the expansion effect, the same as in normal array of objects? I Don't want to see all object details, i want that effect:
What i must do?