Search Unity

Custompropertydrawer to emulate weak references -- foldout does not expand

Discussion in 'Immediate Mode GUI (IMGUI)' started by esrever2357, Feb 26, 2019.

  1. esrever2357

    esrever2357

    Joined:
    Dec 12, 2018
    Posts:
    23
    Intro: I want weak references to avoid infinite serialization depth. E.g.

    Code (CSharp):
    1. class Foo
    2. {
    3.     Foo[] children;  
    4. }
    The above of course triggers unity alerts for serialization depth. So let's change it to the following:

    Code (CSharp):
    1. class FooId
    2. {
    3.     int id;
    4. }
    5.  
    6. class Foo
    7. {
    8.     FooId[] children;
    9. }
    10.  
    11. class SomeBehaviour: MonoBehaviour
    12. {
    13.     List<Foo> pool;
    14.     FooId root;
    15. }
    So, now I have my tree hierarchy of arbitrary depth, so unity doesn't complain. But, viewing the tree in the inspector is problematic, as I have to manually jump back and forth. So, to tackle this, I tried to create a custom property drawer for the FooId, which looks like this:

    Code (CSharp):
    1. [CustomPropertyDrawer(typeof(FooId))]
    2. public class MineEntityIdDrawer : PropertyDrawer
    3. {
    4.     // Draw the property inside the given rect
    5.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    6.     {
    7.         var e = SwitchProp(ref property);
    8.         label.text = string.Format("{0} [{1}]", e.Name, label.text.Replace("Element ", ""));
    9.         EditorGUI.PropertyField(position, property, label);
    10.     }
    11.  
    12.     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    13.     {
    14.         SwitchProp(ref property);
    15.         return base.GetPropertyHeight(property, label);
    16.     }
    17. }
    So, in the above, SwitchProp replaces the FooId property with the Foo property. BUT the foo property in the tree is a foldout that never expands... What could be the problem? Does unity absolutely forbid me to serialize a property twice or more? Once in the pool and more when redirecting through ids.

    Thanks.
     
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    You need to includeChildren when calling PropertyField. Check out the docs.
     
    esrever2357 likes this.
  3. esrever2357

    esrever2357

    Joined:
    Dec 12, 2018
    Posts:
    23
    It still doesn't work... Ok this might actually be a problem with the foldout.
    If I force property.isExpanded = true after I switch, I get the property expanded and everything shows as it should. But neither the property nor its children listen to clicks on any labels that would normally fold/unfold the foldouts.
     
  4. esrever2357

    esrever2357

    Joined:
    Dec 12, 2018
    Posts:
    23
    What seems to be semi-working is to do this:

    Code (CSharp):
    1. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    2.     {
    3.         var propOrg = property;
    4.         var expanded = property.isExpanded;
    5.         var e = SwitchProp(ref property);
    6.         property.isExpanded = expanded;
    7.         label.text = string.Format("{0} [{1}]", e.Name, label.text.Replace("Element ", ""));
    8.         EditorGUI.PropertyField(position, property, label, true);
    9.         propOrg.isExpanded = expanded;
    10.     }
    So, basically, copy the "isExpanded" state to the target property, call property field, and then set it again to the original.
    includeChildren does need to be set to true indeed.

    The problems that remain ar:
    • Unfolded referenced property looks like a mess and I can't seem to get the proper propertyHeight for it
    • foldouts of properties UNDER this "weak-referenced" property do not work, so effectively the same problem, down the tree...
     
  5. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    I'd forgotten about this until you mentioned it, but unity's built-in array inspector doesn't support differing heights between elements.

    You're deep in the rabbit hole of custom editor creation now. Probably easier to just make your own array editor (can't remember if ReorderableList supports multiple elements heights either, but worth checking out).
     
    esrever2357 likes this.
  6. esrever2357

    esrever2357

    Joined:
    Dec 12, 2018
    Posts:
    23
    Noooo don't say that, the last thing I want is to start messing with custom editors and inspectors... I'm willing to make GetPropertyHeight complicated by traversing property tree and checking properties for isExpanded, rather than start spawning classes here and there... It's the click behaviour that's killing me really, as I can't expand children under the property I switch to
     
  7. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    Doesn't matter -- the array inspector will use one height for all of its children. I'm not entirely sure about the other issues, as I tend not to work with serialized objects if I can help it, but I'm not overly surprised that they're happening.

    It's not that bad. You could most likely throw together a custom editor fairly quickly for this.
     
    esrever2357 likes this.