Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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
1
Question by Ryuuguu · Jan 18, 2017 at 02:08 PM · inspectorcustom inspectordrawer

Change only PrefixLabel with Property drawer, use default drawing for rest of property.

I have a class with its first field an enum not a string. I would like an list of these classes to appear in the inspect with the the enum value as the PrefixLabel similar to the this would happen if it was a string. I can make this happen with the following ProperyDrawer code.

 [CustomPropertyDrawer (typeof (TempleIdleGenerator.SlotItemFreq))]
 public class SlotItemFreq : PropertyDrawer {
     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
         // Using BeginProperty / EndProperty on the parent property means that
         // prefab override logic works on the entire property.
         EditorGUI.BeginProperty (position, label, property);
 
         // Draw label
         int index = property.FindPropertyRelative ("slotID").enumValueIndex;
         label.text = property.FindPropertyRelative ("slotID").enumDisplayNames [index];
         position = EditorGUI.PrefixLabel (position, GUIUtility.GetControlID (FocusType.Passive), label);
            //What goes here?
         EditorGUI.EndProperty ();
           // or maybe here?
     }
 }

the class code is

     [System.Serializable]
     public class SlotItemFreq{
         public SlotID slotID;
         public List<ItemFreq> itemFreqs;
     }
 

II would like everything after the initial field to display in the inspector the same as would if I did not have a custom ProperyDrawer. What code do I need where the "//what goes here " or the "//maybe here?" comments are?

Cheers, Grant

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

2 Replies

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

Answer by Adam-Mechtley · Jan 18, 2017 at 05:17 PM

@Bunny83 wrote:

Unfortunately you can't use EditorGUI.PropertyField as it would call your property drawer again so you would crash due to an endless recursion.

Actually this is not correct. Unity has a PropertyDrawer stack internally, so it is perfectly valid to simply do something like this:

 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
       int index = property.FindPropertyRelative ("slotID").enumValueIndex;
       label.text = property.FindPropertyRelative ("slotID").enumDisplayNames [index];
       EditorGUI.PropertyField(position, property, label, true);
   }

You can see this done in the new scripting example for SerializedProperty.isExpanded in the 5.6.0 documentation.

Comment
Add comment · Show 3 · 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 Ryuuguu · Jan 18, 2017 at 06:13 PM 0
Share

This almost worked but there is some height field that is not being set. When I expand the property it shows the children but does change the height so each element remains one line apart and displays over the element below it.

avatar image Adam-Mechtley Ryuuguu · Jan 18, 2017 at 06:35 PM 0
Share

You need to also override PropertyDrawer.GetPropertyHeight(). Something like this:

 public override void GetPropertyHeight(SerializedProperty property, GUIContent label)
 {
     return property.isExpanded ?
         EditorGUIUtility.singleLineHeight * 3f + EditorGUIUtility.standardVerticalSpacing * 2f :
         EditorGUIUtility.singleLineHeight;
 }


avatar image Ryuuguu Adam-Mechtley · Jan 19, 2017 at 01:28 AM 0
Share

Copy directly from the example in SerializedProperty.isExpanded in the 5.6.0 documentation. You mentioned solves the height problem.

 public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
         // use the default property height, which takes into account the expanded state
         return EditorGUI.GetPropertyHeight(property);
     }
avatar image
0

Answer by Bunny83 · Jan 18, 2017 at 02:53 PM

Well, that's a problem. You would need to use EditorGUI.DefaultPropertyField which however is an internal method. If you want to replicate it manually, good luck ^^. Unfortunately you can't use EditorGUI.PropertyFieldas it would call your property drawer again so you would crash due to an endless recursion.

Actually the PropertyDrawer default implementation does call EditorGUI.DefaultPropertyField automatically, however they made that horrible decision to implement it like this:

 public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 {
     EditorGUI.DefaultPropertyField(position, property, label);
     EditorGUI.LabelField(position, label, EditorGUIUtility.TempContent("No GUI Implemented"));
 }

So it displays this additional "warning". So your solution could have been as easy as:

  public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
      int index = property.FindPropertyRelative ("slotID").enumValueIndex;
      label.text = property.FindPropertyRelative ("slotID").enumDisplayNames [index];
      base.OnGUI(position, property, label);
  }

But it's not possible because they "think" it would be convenient to tell the user that he implemented a PropertyDrawer and did not override the OnGUI method ...

So one option is to actually replicate what DefaultPropertyField does or to use reflection to call that internal method yourself ^^. Replicating is difficult since most methods DefaultPropertyField uses are internal or private as well. So the easiest option is to use reflection.

I quickly wrote this extension:

 namespace B83.EditorExtensions
 {
     using System.Reflection;
     public static class RefEditorGUI
     {
         public delegate bool DefaultPropertyFieldDelegate(Rect position, SerializedProperty property, GUIContent label);
         public static DefaultPropertyFieldDelegate DefaultPropertyField;
         static RefEditorGUI()
         {
             var t = typeof(EditorGUI);
             var delegateType = typeof(DefaultPropertyFieldDelegate);
             var m = t.GetMethod("DefaultPropertyField", BindingFlags.Static | BindingFlags.NonPublic);
             DefaultPropertyField = (DefaultPropertyFieldDelegate)System.Delegate.CreateDelegate(delegateType, m);
         }
     }
 }

Simply place it in an editor script somewhere. Instead of EditorGUI.DefaultPropertyField you should be able to simply use RefEditorGUI.DefaultPropertyField. Of course you need to put a using on top of your script where you use it or remove the namespace.

Note: I haven't tested the class. So if you use it would be nice to get feedback. If it doesn't work i will look into it.

edit
I had a bad feeling something could be wrong so i did a quick check and yes i messed something up ^^. I've fixed the code above. Now it works just fine.

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 Ryuuguu · Jan 18, 2017 at 06:09 PM 0
Share

Thanks I tried this but I did not realise I needed the include children so I tried the next answer.

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

64 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 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 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 avatar image

Related Questions

How to correctly use EditorGUILayout.MaskField in multi-edit ? 2 Answers

Custom inspector editor - how to put new editor fields in a specific place 1 Answer

Using EditorGUI.FloatField With Custom Class Inspectors? 1 Answer

Custom MaterialPropertyDrawer with argument 2 Answers

Show texture (image box) in inspector with custom editor [C#]? 3 Answers


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