Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Mirath · Sep 01, 2013 at 02:50 PM · editorguicustom-inspectorpropertydrawer

Variable property drawer height effects all in List

Hi all, this has been bugging me for a little while now, and can't seem to figure out a decent solution.

I'm writing a custom property drawer for an action class, which contains several foldouts. I've set it up so that each block of the foldout uses a float property for height that checks whether the bool for the foldout is toggled, and calculates it into the overall property height and positions of the inspector fields. This works fine when I have a single instance of the action class, but causes problems when they're put into a list, where hitting the toggle activates the same foldout in each element in the list.

Is this a problem with using Lists with Property Drawers? Or is it my use of properties outside the OnGUI method? Or something else entirely? And is there a way to resolve it?

Thanks so much for any help or insight you might offer.

Here's the code in question below:

 [CustomPropertyDrawer(typeof(CoreCharacterAction))]
 public class CoreCharacterActionDrawer : PropertyDrawer
 {
     bool 
         showContent = false,
         showCosts = false,
         showDuration = false,
         showMovementSpeed = false,
         showTurningSpeed = false;
 
     float CostsHeight {
         get { 
             if (showCosts)
                 return 45;
             else
                 return 15;
         }
     }
     float DurationsHeight {
         get { 
             if (showDuration)
                 return 75;
             else
                 return 15;
         }
     }
     float MovementsHeight {
         get { 
             if (showMovementSpeed)
                 return 75;
             else
                 return 15;
         }
     }
     float TurningHeight {
         get { 
             if (showTurningSpeed)
                 return 75;
             else
                 return 15;
         }
     }
 
     public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
         float tempHeight = 15;
         if (showContent) {
             tempHeight += CostsHeight + DurationsHeight + MovementsHeight + TurningHeight;
         }
         Debug.LogWarning (tempHeight);
         return tempHeight;
     }
 
     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
         EditorGUIUtility.LookLikeControls();
 
         SerializedProperty 
             name = property.FindPropertyRelative ("name"),
 
             stateEffect = property.FindPropertyRelative ("stateEffect"),
             primaryVitalType = property.FindPropertyRelative ("primaryVitalType"),
             secondaryVitalType = property.FindPropertyRelative ("secondaryVitalType"),
             primaryCost = property.FindPropertyRelative ("primaryCost"),
             secondaryCost = property.FindPropertyRelative ("secondaryCost"),
 
             activationType = property.FindPropertyRelative ("activationType"),
             enterDuration = property.FindPropertyRelative ("enterDuration"),
             activeDuration = property.FindPropertyRelative ("activeDuration"),
             activeInputName = property.FindPropertyRelative ("activeInputName"),
             exitDuration = property.FindPropertyRelative ("exitDuration"),
 
             moveType = property.FindPropertyRelative ("moveType"),
             enterMoveSpeed = property.FindPropertyRelative ("enterMoveSpeed"),
             activeMoveSpeed = property.FindPropertyRelative ("activeMoveSpeed"),
             exitMoveSpeed = property.FindPropertyRelative ("exitMoveSpeed"),
 
             lookType = property.FindPropertyRelative ("lookType"),
             enterLookSpeed = property.FindPropertyRelative ("enterTurnSpeed"),
             activeLookSpeed = property.FindPropertyRelative ("activeTurnSpeed"),
             exitLookSpeed = property.FindPropertyRelative ("exitTurnSpeed");
 
         showContent = EditorGUI.Foldout (new Rect (position.x, 
                                                    position.y,
                                                    position.width,
                                                    15),
                                          showContent, name.stringValue);
 
 
         if (showContent) {
             name.stringValue = EditorGUI.LabelField (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                                       position.y + 15,
                                                                                       position.width,
                                                                                       15)), name.stringValue);
 
 
             showCosts = EditorGUI.Foldout (EditorGUI.IndentedRect(new Rect (position.x, 
                                                      position.y+30,
                                                      position.width,
                                                      15)),
                                            showCosts, "Resource Costs");
 
             if (showCosts == true) {
                 EditorGUI.indentLevel = 2;
                 primaryVitalType.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                              position.y + 30,
                                                                              position.width / 3,
                                                                              15)), 
                                                                    primaryVitalType.enumValueIndex, primaryVitalType.enumNames);
 
                 if (primaryVitalType.enumValueIndex != 0)
                     primaryCost.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x + position.width / 3, 
                                                                          position.y + 30,
                                                                          position.width * 2 / 3,
                                                                          15)), 
                                                                primaryCost.floatValue, 0, 50);
     
                 secondaryVitalType.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                position.y + 45,
                                                                                position.width / 3,
                                                                                15)), 
                                                                      secondaryVitalType.enumValueIndex, secondaryVitalType.enumNames);
 
                 if (secondaryVitalType.enumValueIndex != 0)
                     secondaryCost.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x + position.width / 3, 
                                                                            position.y + 45,
                                                                            position.width * 2 / 3,
                                                                            15)),
                                                                  secondaryCost.floatValue, 0, 50);
 
                 EditorGUI.indentLevel = 1;
 
             }
 
             showDuration = EditorGUI.Foldout (EditorGUI.IndentedRect(new Rect (position.x, 
                                                         position.y + CostsHeight + 15,
                                                         position.width / 3,
                                                         15)),
                                               showDuration, "Effect Durations");
             if (showDuration == true) {
                 EditorGUI.indentLevel = 2;
                 activationType.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                  position.y + CostsHeight + 30,
                                                                  position.width,
                                                                  15)), 
                                                                  activationType.enumValueIndex, activationType.enumNames);
                 enterDuration.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                        position.y + CostsHeight + 45,
                                                                        position.width,
                                                                        15)),
                                                              "startup duration", enterDuration.floatValue, 0, 5);
                 if (activationType.enumValueIndex == 0)
                     activeDuration.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                   position.y + CostsHeight + 60,
                                                                                   position.width,
                                                                                   15)),
                                                                         "active duration", activeDuration.floatValue, 0, 5);
                 else
                     activeInputName.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                       position.y + CostsHeight + 60,
                                                                                       position.width,
                                                                                       15)),
                                                                             "active input", activeInputName.enumValueIndex, activeInputName.enumNames);
 
                 exitDuration.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                             position.y + CostsHeight + 75,
                                                                             position.width,
                                                                             15)),
                                                                   "cooldown duration", exitDuration.floatValue, 0, 5);
                 EditorGUI.indentLevel = 1;
             }
 
             showMovementSpeed = EditorGUI.Foldout (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                     position.y + CostsHeight + DurationsHeight + 15,
                                                                                     position.width,
                                                                                     15)),
                                                    showMovementSpeed, "Movement Speeds");
             if (showMovementSpeed) { 
                 EditorGUI.indentLevel = 2;
                 moveType.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                                              position.y + CostsHeight + DurationsHeight + 30,
                                                                                              position.width,
                                                                                              15)),
                                                            moveType.enumValueIndex, moveType.enumNames);
 
                 enterMoveSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                                                       position.y + CostsHeight + DurationsHeight + 45,
                                                                                                       position.width,
                                                                                                       15)),
                                                                     enterMoveSpeed.floatValue, 0, 25);
 
                 activeMoveSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                                                        position.y + CostsHeight + DurationsHeight + 60,
                                                                                                        position.width,
                                                                                                        15)),
                                                                      activeMoveSpeed.floatValue, 0, 25);
 
                 exitMoveSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect (new Rect (position.x, 
                                                                                                      position.y + CostsHeight + DurationsHeight + 75,
                                                                                                      position.width,
                                                                                                      15)),
                                                                    exitMoveSpeed.floatValue, 0, 25);
                 EditorGUI.indentLevel = 1;
             }
             showTurningSpeed = EditorGUI.Foldout (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                    position.y + CostsHeight + DurationsHeight + MovementsHeight + 15,
                                                                                    position.width,
                                                                                    15)),
                                                   showTurningSpeed, "Turn Speeds");
             if (showTurningSpeed) {
                 EditorGUI.indentLevel = 2;
                 lookType.enumValueIndex = EditorGUI.Popup (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                             position.y + CostsHeight + DurationsHeight + MovementsHeight + 30,
                                                                                             position.width,
                                                                                             15)),
                                                            lookType.enumValueIndex, lookType.enumNames);
                 enterLookSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                                position.y + CostsHeight + DurationsHeight + MovementsHeight + 45,
                                                                                                position.width,
                                                                                                15)),
                                                               enterLookSpeed.floatValue, 0, 25);
                 activeLookSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                                 position.y + CostsHeight + DurationsHeight + MovementsHeight + 60,
                                                                                                 position.width,
                                                                                                 15)),
                                                                activeLookSpeed.floatValue, 0, 25);
                 exitLookSpeed.floatValue = EditorGUI.Slider (EditorGUI.IndentedRect(new Rect (position.x, 
                                                                                               position.y + CostsHeight + DurationsHeight + MovementsHeight + 75,
                                                                                               position.width,
                                                                                               15)),
                                                              exitLookSpeed.floatValue, 0, 25);
                 EditorGUI.indentLevel = 1;
             }
         }
     }
 }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
4
Best Answer

Answer by Roland1234 · Nov 22, 2013 at 08:09 AM

I'd recommend you pull your SerializedProperties into class scope and initialize them in the GetPropertyHeight method. Then you'd have access to their corresponding isExpanded property which you'd use instead of manually managing your show_ booleans. You could pick a single property in your desired blocks to keep track of the foldout states.

I'm pretty sure something like this should work:

 [CustomPropertyDrawer(typeof(CoreCharacterAction))]
 public class CoreCharacterActionDrawer : PropertyDrawer
 {
     private SerializedProperty
         name,
         primaryVitalType,
         secondaryVitalType,
         primaryCost,
         secondaryCost;
 
     float CostsHeight
     {
         get
         {
             if(primaryVitalType.isExpanded)
                 return 45;
             else
                 return 15;
         }
     }
 
     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
     {
         name = property.FindPropertyRelative("name");
 
         primaryVitalType = property.FindPropertyRelative("primaryVitalType");
         secondaryVitalType = property.FindPropertyRelative("secondaryVitalType");
         primaryCost = property.FindPropertyRelative("primaryCost");
         secondaryCost = property.FindPropertyRelative("secondaryCost");
 
         float tempHeight = 15;
         if(name.isExpanded)
         {
             tempHeight += CostsHeight /* + ... + ... */;
         }
         Debug.LogWarning(tempHeight);
         return tempHeight;
     }
 
     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
     {
         EditorGUIUtility.LookLikeControls();
 
         name.isExpanded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, 15), name.isExpanded, name.stringValue);
 
         if(name.isExpanded)
         {
             //...
 
             primaryVitalType.isExpanded = EditorGUI.Foldout(EditorGUI.IndentedRect(new Rect(position.x, position.y + 30, position.width, 15)), primaryVitalType.isExpanded, "Resource Costs");
 
             if(primaryVitalType.isExpanded == true)
             {
                 //...
             }
         }
     }
 }

Failing that, I usually add the booleans to the actual object - encapsulating them in #if UNITY_EDITOR ... #endif directives.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
4

Answer by Luna4Dev1 · Oct 22, 2015 at 02:38 PM

This may have been added to Unity recently (This post is over two years old by this point!), but it took me a while to discover it buried in the documentation - posting it here for posterity;

 EditorGUI.GetPropertyHeight(SerializedProperty property, UIContent label = null, bool includeChildren = true);

This function will return the height of a SerializedProperty object, as used by Editor GUI functions. It also takes into account whether or not a list/array is expanded.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image RChrispy · Sep 29, 2019 at 06:32 PM 0
Share

This is an awesome find! +

avatar image
1

Answer by Democide · Jun 09, 2015 at 02:02 PM

All you need to really do is use the "isExpanded" field on the SerializedProperty:

http://docs.unity3d.com/ScriptReference/SerializedProperty-isExpanded.html

for example as such:

 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
     property.isExpanded = EditorGUI.Foldout(currentRect, property.isExpanded, "Sound");

     if (property.isExpanded) {
        ...
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by yoyo · Sep 04, 2013 at 05:49 AM

I believe the problem is that all instances of CoreCharacterAction, including each one in the list, are drawn with the same instance of the CoreCharacterActionDrawer -- so any member variables of the property drawer (showContent, etc.) are shared across the drawing of all the properties.

What you could do is keep track of the member variables for each property instance being drawn, so replace this:

 bool 
        showContent = false,
        showCosts = false,
        showDuration = false,
        showMovementSpeed = false,
        showTurningSpeed = false;

with this:

 private static class ShowInfo
 {
     public bool 
        showContent = false,
        showCosts = false,
        showDuration = false,
        showMovementSpeed = false,
        showTurningSpeed = false;
 }
 
 private Dictionary<SerializedProperty,ShowInfo> InfoPerProperty = new Dictionary<SerializedProperty,ShowInfo>();

Then in the OnGUI method ...

 ShowInfo showInfo;
 if (!InfoPerProperty.TryGetValue(property, out showInfo))
 {
     showInfo = new ShowInfo();
     InfoPerProperty.Add(property, showInfo);
 }
 
 ...
 
 if (showInfo.showContent)
 {
     ....
 }


Basically this maintains a dictionary of info to show for each SerializedProperty that is edited by the property drawer. In the OnGUI method it looks up the info for the current property. If not found it creates a new info instance.

Hope that helps.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Custom inspector variable resets automatically 1 Answer

EditorGUI.Foldout consumes click so GUI.Button doesnt work when inside of foldout region. 1 Answer

How to get width at which Inspector does line breaks (for Vectors) 1 Answer

Draw on Multiple Lines with EditorGUI 1 Answer

How to show type text in EditorGUI.ObjectField? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges