PropertyDrawer: Foldout open all at once
I have a classe that use a property drawer with a single foldout, then I have an array of that class. When I fold or unfold one element of the array, every other open at once.
[CustomPropertyDrawer(typeof(CarouselElement))]
public class CarouselDrawer : PropertyDrawer {
public bool unfold = false;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){
position.height = 16;
unfold = EditorGUI.Foldout (position, unfold, label);
if (unfold){
/*Draw some properties*/
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label){
return unfold ? 16*4 : 16;
}
}
I take it that 'unfold' is being shared across all instances of the class? How am I supposed to keep track of every possible instance individually?
Edit : I did make the check, when creating several different property on a Monobehaviour they will unfold properly with this code, it's really when creating a array of properties that they somehow get all kined together. Is this some kind of bug or is this by design?
Answer by pitiku · Jul 20, 2017 at 01:41 PM
You can use the property.isExpanded flag for this.
[CustomPropertyDrawer(typeof(CarouselElement))]
public class CarouselDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){
position.height = 16;
property.isExpanded = EditorGUI.Foldout (position, property.isExpanded, label);
if (property.isExpanded) {
/*Show folded subproperty*/
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label){
return property.isExpanded ? 16*4 : 16;
}
}
This should be the accepted answer as it is the simplest one. Thanks for this!
Answer by Adam-Mechtley · May 07, 2017 at 04:37 AM
The way I usually handle a situation like this is to make unfold
a Dictionary<string, bool>
, where each key is property.propertyPath
This will have to do for now. This is working, but I find the resulting code to be kinda convoluted, or at least it looks like nothing I've seen elsewhere about how to use EditorGUI.Foldout() :
[CustomPropertyDrawer(typeof(CarouselElement))]
public class CarouselDrawer : PropertyDrawer {
public Dictionary<string, bool> unfold = new Dictionary<string, bool> ();
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){
position.height = 16;
if (!unfold.Contains$$anonymous$$ey (property.propertyPath))
unfold.Add (property.propertyPath, false);
unfold[property.propertyPath] = EditorGUI.Foldout (position, unfold[property.propertyPath], label);
if (unfold[property.propertyPath]) {
/*Show folded subproperty*/
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label){
if (unfold.Contains$$anonymous$$ey (property.propertyPath))
return unfold [property.propertyPath] ? 16*4 : 16;
else
return 16;
}
}
Plus I have a concern with using this technic, shoudn't I make sure that unused propertypathes are being cleaned off the dictionnary ? So it doesn't start piling up and take more and more memory ? How can I do that?
Plus I have a concern with using this technic, shoudn't I make sure that unused propertypathes are being cleaned off the dictionnary ? So it doesn't start piling up and take more and more memory ? How can I do that?
No need to worry about this. The PropertyDrawer instance will go out of scope (and subsequently be garbage collected) when the Editor using it is destroyed (e.g., you change selection)
Answer by ZammyIsOnFire1 · May 24, 2019 at 05:40 PM
Here is my version. Using Unity fold control.
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(DisplayScriptableObjectPropertiesAttribute))]
public class DisplayScriptableObjectPropertiesDrawer : PropertyDrawer
{
bool _showProperty = false;
float _drawerHeight;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
int indent = EditorGUI.indentLevel;
_drawerHeight = 0;
position.height = 16;
EditorGUI.PropertyField(position, property);
_showProperty = EditorGUI.Foldout(position, _showProperty, "");
position.y += 20;
position.x += 20;
position.width -= 40;
if (!_showProperty)
return;
var so = new SerializedObject(property.objectReferenceValue);
so.Update();
var prop = so.GetIterator();
prop.NextVisible(true);
int depthChilden = 0;
bool showChilden = false;
while (prop.NextVisible(true))
{
if (prop.depth == 0)
{
showChilden = false;
depthChilden = 0;
}
if (showChilden && prop.depth > depthChilden)
{
continue;
}
position.height = 16;
EditorGUI.indentLevel = indent + prop.depth;
if (EditorGUI.PropertyField(position, prop))
{
showChilden = false;
}
else
{
showChilden = true;
depthChilden = prop.depth;
}
position.y += 20;
_drawerHeight += 20;
}
if (GUI.changed)
{
so.ApplyModifiedProperties();
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float height = base.GetPropertyHeight(property, label);
height += _drawerHeight;
return height;
}
}
Your answer
Follow this Question
Related Questions
How to properly use ReorderableList inside CustomPropertyDrawer 2 Answers
Can I make a custom property drawer for Unity types? 0 Answers
How can I receive onAfterDeserialize and onBeforeSerialize in a propertydrawer? 0 Answers
indentation problems when drawing nested properties with Property Drawer 1 Answer