Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Advanced Inspector - Never Write An Editor Again

Discussion in 'Assets and Asset Store' started by LightStriker, May 4, 2014.

  1. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Can you show what that button should do? You're talking about Editor utilities? If it's the case, you could simply #if UNITY_EDITOR around that specific method.

    Also, does this class only shows up in that ScriptableObject, or it shows up elsewhere?
     
  2. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Hi LS, when using the Draw method of FieldAttribute class, I notice that calling field.Editor.Draw ( field, null ); does not use the default style of the field. Is there any way to achieve it? (I also tried, field.Style but the result is '').
     
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    What is the default style of the field??
     
  4. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    When you call fiel.Editor.Draw you are telling to use the default editor that AI finds, right? Well, I guess that editor renders the field with a specific style, if set, or a general one if not.

    On my case, I'm talking about references to GameObjects, which appear as if they were an expandable collection.
     
  5. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Use this to see what I'm talking about on a MonoBehaviour field (you will need to define MyTestEditorAttribute):

    Code (CSharp):
    1. using System;
    2.  
    3. using AdvancedInspector;
    4.  
    5. using UnityEditor;
    6. using UnityEngine;
    7.  
    8. namespace MyNamespace
    9. {
    10.     [CanEditMultipleObjects]
    11.     public class MyTestEditor : FieldEditor
    12.     {
    13.         public override Type[] EditedTypes
    14.         {
    15.             get { return new Type[] { typeof ( MyTestEditorAttribute ) }; }
    16.         }
    17.  
    18.         public override bool IsExpandable ( InspectorField field )
    19.         {
    20.             return false;
    21.         }
    22.  
    23.         public override void Draw ( FieldAttribute attribute, InspectorField field )
    24.         {  
    25.             field.Editor.Draw ( field, null );
    26.         }
    27.     }
    28. }
    Like:

    [Inspect, MyTestEditorAttribute]
    public MyMonoBehaviour field;
     
    Last edited: Nov 28, 2016
  6. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    The way I found to make it display as it should is a workaround like this:

    Code (CSharp):
    1.         private MonoBehaviour1 test1;
    2.  
    3.         [Inspect, MyTestEditor]
    4.         protected UnityEngine.Object Test1 { get { return this.test1; } }
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Right now, I have the feeling your FieldEditor is doing nothing, as a FieldAttribute is drawn by a FieldDrawer, not a FieldEditor.

    How about you tell me what is the result you want, and not how you're trying to achieve it? Just make a field non-expandable? Just add [Expandable(false)] on it.
     
  8. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Actually, the FieldEditor is executing code on the Draw call. In fact, if you use the code I submitted a couple of post above, you will see that FieldEditor is working for FieldAttribute. Maybe that's the problem, that I should be using a FieldDrawer (that I thought were excluded of AI on previous versions) instead of FieldEditor to handle FieldAttributes.

    The interesting part is that Expandable(false) did the trick, which leads me to wonder mhy the IsExpandable method is being disregarded.
     
  9. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    I cannot find FieldDrawer anywhere to do this:

    public class MyTestDrawer : FieldDrawer

    instead of this:

    public class MyTestEditor : FieldEditor
     
  10. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Nevermind... I'm confused. I was sure the FieldDrawer class still existed, but it was merged with FieldEditor two version ago.

    However, I admit overriding "IsExpandable" on the FieldEditor of the attribute won't change anything; after all, what should take priority? You can put many attribute, each having different expandability. It only works if you have a FieldEditor that handle directly the field type.
     
  11. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Is there any way to override that from within the draw call (without having to use an extra attribute)? (in this case the ExpandableAttribute)
     
  12. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Found it:

    field.AddAttribute ( new ExpandableAttribute(false) ); // In case it's not already present
     
    Last edited: Nov 28, 2016
  13. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Hi, I ended up going for the easy way and just crammed all the logic inside the [Inspect] method wrapped with a #if UNITY_EDITOR. Thank you for the help.


    I have another small question. I really like the [Constructor] attribute on arrays. I was wondering if there is something similar for when an item is moved around (with drag/drop) inside the array. I would like to know that an item, previously on index A moved to index B. Is that possible?

    Regards,
     
  14. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Well, there is no direct call back just for that, because there's many operation possible on an array.

    You can expose a property, but that traps only adding and removing items.

    You can use the IDataChanged interface, which is called anytime something changed. But then you would have to keep an older version of the array to compare.

    Care to tell me what you would do knowing an item moved?
     
    Last edited: Nov 29, 2016
  15. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Hi,

    I've read that AI also shows static fields, and indeed it does (I've got a singleton using a static enum to track the current age the player is in, and I also need this to work in the Editor).

    But, what if I wanted to change its value in editor/runtime? Can it be done in AI?

    I'd also need a callback function for that.

    That is, when I change the current enum containing the Age, it broadcasts the change to other different MonoBehaviours that change the aspect of the scene accordingly (this is needed to help the level designer in his work).
    I don't feel I should Instantiate the singleton containing the static enum since I suspect this would lead to some unpredictable behaviour.

    Can AI help me on this? Could you please suggest me a better solution?

    I saw this on Unity Answers:
    Code (CSharp):
    1.  [CustomEditor(typeof(OtherObject))]
    2. public class OtherObjectEditor : Editor {
    3.      public override void OnInspectorGUI() {
    4.          StaticClass.staticEnumObject= (ENUM_TYPE)EditorGUILayout.EnumPopup("text next to enum field", staticClass.staticEnumObject);
    5.      }
    6. }
    7. public static class StaticClass{
    8.      public static ENUM_TYPE staticEnumObject = ENUM_TYPE.DEFAULT_ITEM;
    9.        
    10.      public enum ENUM_TYPE {
    11.          DEFAULT_ITEM,
    12.          ...
    13.      }
    14. }
    15. public class OtherObject: MonoBehaviour{
    16. ...
    17. // if you want it to reset on application stop
    18. void OnApplicationQuit() {
    19.          StaticClass.staticEnumObject = StaticClass.ENUM_TYPE.DEFAULT_ITEM;
    20. }
    21. // Alternatively you can make an inspector button to do this for you outside of the application running.
    22. }
    I was wondering if AI should be able to manage the thing as well.
     
  16. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Why not simply inspect a property?

    Code (CSharp):
    1.     public class OtherObject : MonoBehaviour
    2.     {
    3.         [Inspect]
    4.         public ENUM_TYPE StaticEnumObject
    5.         {
    6.             get { return StaticClass.staticEnumObject; }
    7.             set
    8.             {
    9.                 if (StaticClass.staticEnumObject == value)
    10.                     return;
    11.  
    12.                 StaticClass.staticEnumObject = value;
    13.                 // do something
    14.             }
    15.         }
    16.     }
     
    NeatWolf likes this.
  17. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Thanks,

    I replaced the commented line with the suggested changes:

    Code (CSharp):
    1. [ExecuteInEditMode]
    2. public class AgeManager : PersistentSingleton<AgeManager> {
    3.     //public static Ages currentAge = Ages.Present;
    4.     [Inspect]
    5.     public static Ages currentAge
    6.     {
    7.         get { return AgeManager.currentAge; }
    8.         set
    9.         {
    10.             AgeManager.currentAge = value;
    11.             Debug.Log("Broadcast!");
    12.         }
    13.     }
    but AI looks like it blowed up:

    upload_2016-12-2_18-14-0.png

    Also, of course, the inspector for the whole class stopped working, and throws more and more errors as the class inspector gets refreshed.

    Any idea?

    EDIT: oh, maybe I misunderstood, let me change a few things...
     
  18. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    You're doing a stackoverflow on the getter. The getter is returning itself, which is returning itself, etc.
     
    NeatWolf likes this.
  19. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Yeah, sorry, I changed everything on the fly, blindly as suggested, but I misread your example.

    Now I changed it to:

    Code (CSharp):
    1. [ExecuteInEditMode]
    2. public class AgeManager : PersistentSingleton<AgeManager> {
    3.     public static Ages currentAge = Ages.Present;
    4.     [Inspect]
    5.     public static Ages CurrentAge
    6.     {
    7.         get { return AgeManager.currentAge; }
    8.         set
    9.         {
    10.             AgeManager.currentAge = value;
    11.             Debug.Log("Broadcast!");
    12.         }
    13.     }
    No errors, but both fields are grayed out now...
    upload_2016-12-2_18-22-26.png
     
  20. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Static item are only editable at runtime, because their data is lost when you change play mode. So there's no real interest in having them editable when the engine is not running.

    I have a feeling you want that as a tool for level designers? If so, simply make your property non-static.
     
    NeatWolf likes this.
  21. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Well, it has interest when the level designer needs to switch era and all the scene should change accordingly to help him save valuable time with some automated features.

    It was non-static before, but I guess that accessing a singleton in edito mode would
    1) change the values of the existing singleton if it's in the scene
    2) create another singleton and destroy the previous
    3) the singleton may not exist in the scene since it's a singleton that doesn't get destroyed on scene changes so it is present in the scene only at design time, but in the end I'll have to remove it.

    I'm starting to believe that this could be a non-issue, since I could instantiate the Manager object containing the singleton, let the designer work with it, and remove it when the game is running

    I'm not familiar with the [ExecuteInEditorMode] attribute since I usually am also the level designer...
     
  22. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    How do you edit that Singleton if it doesn't exist? How do you select it?

    If you access it from an unrelated class, it doesn't need to be a singleton. A simple static class would work and be accessible everywhere at all time. Does that singleton has serialized data or is it only an utility class? Does it need to have a Unity update loop? What does it do?

    Honestly, I feel I'm lacking information to give you proper advice here.
     
  23. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    If it doesn't exist it will autoinstantiate itself.

    Yes, it will have to contain most of the Age related data so it also need to have serialized data - while still being also a uyility class.

    At the moment it doesn't need to have a update loop, but I may need to access its data from any object and it has to keep some information during the whole game, travelling from scene to scene.

    It's the class responsible to implement the actual changes to the scene so that every object reflects the stored Age value, but also contains utility functions called by dialogues, etc. that can set/get/check the current possibility to change Era, which era, and possibly other variables as well (the game designer still has to make a few changes)
     
  24. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Have you looked at this; https://www.assetstore.unity3d.com/en/#!/content/24227
     
    NeatWolf likes this.
  25. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Nope, never heard of it. I'll have a look.

    The problem is that I'm using at least 3 different assets together that need each one its own set of persistent-or-not managers, so I have to stick to a modular approach.

    I'll have a look at it. Thanks for the suggestion, I refactored quite a lot the whole class and it's running fine now, even in editor mode - I should have used a Property from the beginning :)

    Thanks again :)
     
    Last edited: Dec 2, 2016
  26. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Properties are so useful... Quite a waste that Unity never supported them.
     
    NeatWolf likes this.
  27. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Hi,

    The more I look at your asset, the more I realize I'm only scratching the surface.

    Anyway, I watched the videos, the tutorials, had a look at the docs, browsed throught the pages of both the threads related to AI, and I still am very confused about the usage of every Attribute.

    Do you have an example document, or scene/class collections where you give a sample of the use of each possible attribute or feature of the package?

    In particular I wanted to add 4 voices to the right-click context menu, but the only thing I found was this:


    Code (CSharp):
    1. public override void OnContextualClick(InspectorFieldfield, GenericMenumenu){
    2. menu.AddItem(newGUIContent("Zero"), false, Zero);
    3. menu.AddItem(newGUIContent("One"), false, One);
    4. menu.AddSeparator("");}
    5.  
    I remember Unity already being able to add items to the right menu that appears when you click on the inspector of a MonoBehaviour so now I'm wondering:

    How does IA work with that?
    Should I use a specific attribute in addition to the one defined in Unity?

    Also, would it be possible to have a group of methods/buttons on a single row?
     
  28. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    1) I think the most up-to-date way to see all features in action is to look at the AIExample classes. There's a scene with all the examples in it. There 42 right now I think, which each display the use of a single feature. Usually, I try to also keep the documentation up to date with all features. But... It's always possible I forgot some.

    But you're right, it is a huge asset, and even beyond the attributes, there's all the tools hidden in the right-click. Did you know Advanced Inspector also records your selection and you can go back and forth in your selection history using CTRL+Right/Left Arrow? Or that you can apply/revert each field indepently on a prefab? Or that the copy-paste feature is also totally recursive and work with ComponentMonoBehaviour? Or that you can embed a custom inspector inside an EditorWindow? Last time I checked, AI was about 50-60 thousand lines of code, and it does a lot of things Unity doesn't.

    2) Contextual menu in AI can be added per field type, unlike Unity that can only have a contextual menu per component. This involved writing a custom FieldEditor. This is the class that handle drawing a single field in AI. You can find all the existing one in the folder Plugins/AdvancedInspector/FieldEditors, if I remember correctly. There's currently no other way to add contextual option other than this one. Maybe it could be useful to add an attribute hook to add menu item, so you could add contextual option on a per-field basis.

    3) As for adding contextual item on the MonoBehaviour menu, it works the same as Unity, since Unity never exposed their inner working. You can use Unity's attribute, or write your own. AI also handles PropertyDrawers, so your old drawer should still work fine.

    4) Yes, you should look at the "Toolbar" example. However, that only shows up at the top or bottom of the inspector, because the separator would show up in the middle of it. Or you can draw whatever you wish using GUILayout with the IInspectorRunning interface, which gives you access to the header and the footer.
     
    NeatWolf likes this.
  29. abrechin

    abrechin

    Joined:
    Apr 29, 2014
    Posts:
    2
    Hi,
    I have a class that is in a DLL that has a list of classes within.

    Code (CSharp):
    1. // DLL
    2. [Serializable]
    3. public class A
    4. {
    5.     public List<B> m_List;
    6. }
    7.  
    8. [Serializable]
    9. public class B
    10. {
    11.     public int m_Number;
    12. }
    13.  
    14. // My Class
    15. [AdvancedInspector( true )]
    16. public class Test : MonoBehaviour
    17. {
    18.     [Expandable( true )]
    19.     public A m_TestA;
    20. }
    Advanced inspector is disabled by default and I am turning it on in certain scripts.
    It displays the list fine in class A but I cant get it to display the contents of class B within the list.
    Is there any way of doing this?

    Cheers

    Andrew
     
  30. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Option 1: Don't turn it off by default.

    Option 2: Write a custom InspectorEditor and manually add an ExpandableAttribute(true) to that specific field.
     
  31. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    I was only able to find a sample script, no scenes. Where in the hierarchy should this scene be located? I haven't moved any folder around.

    Well, I actually knew all of them since I watched the video and read the docs :D

    Also, I just realised that is THAT the reason behind ScriptInspector3's move-through-words shortcut (CTRL+left or right) not working! Could you please let us disable this functionality in the Preferences editor?

    As per above. Where is this "toolbar example" located in the asset?

    Thanks for your time :)
     
  32. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Assets/AdvancedInspector/Examples/CSharp/Examples_CShrap.unity

    You would be surprised how not everybody does :p

    Adding a shortcut to a menu item is done with the MenuItem attribute by Unity. I have no idea how I could "disable" that using preferences. What I could do is take the SelectionTracker class out of the DLL so you could comment it out or change the shortcuts.
     
    NeatWolf likes this.
  33. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Oh my! It has always been in front of my eyes! I was unconsciously associating it to ScriptInspector3! Also wondering HOW could such a complex asset be shipped without examples!
    Now THAT is what I was looking for! Sorry, and thanks! :(

    I could comment that shortcut myself. Unfortunately my project is already too crowded with 3rd party assets that I prefer not to move from their original folder. So I have no idea if you're already shipping a DLL or not. If not, and if iirc, having the original file in the appropriate folder should override that one defined in the DLL. Could you please PM me the file to be changed? I'd really love to get rid of that specific functionality.
     
  34. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    I'm pretty sure you can't override a file inside a DLL, since it's part of a compiled assembly.
     
    NeatWolf likes this.
  35. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Definitely, I was just daydreaming :-/

    I found this in the CSharp examples:
    Code (CSharp):
    1. // The AdvancedInspector attribute contains 3 property;
    2. // InspectDefaultItems; it displayes fields Unity would display by default.
    3. // ShowScript; show or hide the top "script" field.
    4. // Expandable; In case of an inlined variable, it can force the item to not be expandable (have an arrow on its left)
    So I tried it and discovered first of all that I needed to specify the namespace for the AdvancedInspector Attribute to work.
    Them I tried to also add the Expandable property to false, but it doesn't get recognised:

    upload_2016-12-7_0-14-40.png

    Even trying to put it inline:

    upload_2016-12-7_0-16-54.png

    in both cases I get this compile error:
    Code (CSharp):
    1. Assets/z_Scripts/FNSCameraManager.cs(9,20): error CS0117: `AdvancedInspector.AdvancedInspectorAttribute' does not contain a definition for `Expandable'
    Am I doind something wrong? I checked the AdvancedInspectorAttribute class and it actually is missing the Expandable property.

    I'd like to make both camera fields unexpandable:
    upload_2016-12-7_0-20-6.png

    also because, even if they're readonly, the Camera fields is always editable and expandable, even when nested inside the ProCamera!

    upload_2016-12-7_0-22-16.png

    So I tried this:

    upload_2016-12-7_0-25-45.png

    and finally seems to work.

    Am I doing it right? Are the docs a bit out of date about the Expandable field?

    Another question: in a subclass would it be possible to hide a few fields of the ancestor class without changing the base class?
     
  36. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    The comment is out of date.

    The expandable logic is in its own attribute.

    Sorry for the old comment. :)

    You can simply do "Expandable(false)".
     
    NeatWolf likes this.
  37. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Thanks, it's working fine now.

    I have a base ancestor class I don't want to modify because it's part of another asset.
    Would it be possible to hide a few fields of the ancestor class using AI without changing the base class?
     
  38. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    You can always write an InspectorEditor and manually add the fields you want... You can look for the file CameraEditor.cs, as an example.
     
    NeatWolf likes this.
  39. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Hi again,

    I was looking for a way to only rename the label of an exposed property/field (I need to give a reminder that the feature is WIP to the other members of the team, so I temporarily need to rename it in the inspector).

    So, if I have a public field "public float useDistance", I'd like to show it in the inspector as "Use Distance (WIP)" instead of just "Use Distance".

    In a second time I need to just remove it without compromising functionality.

    I looked several times in the examples, I'm pretty sure it's there but can't find it.

    Could you please tell me the name of the AI attribute I should be using? (or is it a native Unity attribute)

    Thank you.
     
  40. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    I also noticed (possibly a bug) that if you have a public, serialized class field and you change the fields of this nested class, the inspector doesn't reflect their "dirty" state (ie: if their value is different from the prefab values or if they've been tweaked)

    Default Inspector appearance:
    (reverting is impossible, yet the fields are marked as dirty, so any changes I make to the prefab don't get reflected here as the fields are marked as changed)
    asd.jpg

    ...and this is the same component in Unity Debug mode:
    asd2.jpg

    as you can see, the state of the fields is definitely not the one on the prefab (even if, by pure chance, they are), so any change I make to the prefab doesn't get reflected in the inspector because, behind the scenes, those fields have been marked as changed and all changes don't propagate.


    I also have a function that has an OnDrawGizmos to reflect the changes of two values.

    if I revert the changes of those fields while using AI, the OnDrawGizmos doesn't get called and in the Scene window they don't get refreshed until you move the camera inside the Scene window, forcing a refresh.

    Note that if I don't use AI, or switch to Unity's Debug mode in the inspector, the changes are reverted and updated immediately.
     
  41. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    I found another bug:

    I'm on Unity v5.4.2f2, building for Android, on Windows7 64bit Ultimate

    If you use the Revert function on a field when using AI, the changes are reverted to the ones of the prefab, but if you inspect the same component with the Unity Debug mode set in the inspector, you can see the field is still marked as changed and you have to right-click again on that field to do a true revert of the field, thus allowing again prefab changes to propagate properly to all the prefab instances.
     
  42. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    What you're looking for is the DescriptorAttribute, which allows you to control the displayed name, tooltip and URL of a web help page, related to a field. See AIExample5_Descriptor.

    Maybe it's because it's early in the morning, but I really don't understand what you mean here. So, I'm gonna try to re-read this later.

    Are you saying it's just a display bug and data is properly reverted, or that the data is different?
     
  43. NeatWolf

    NeatWolf

    Joined:
    Sep 27, 2013
    Posts:
    896
    Thanks, that's actually what I was looking for.

    What I mean, is that the "Revert" functionality from AI differs from the "Revert To Prefab Value" Unity native functionality.
    What AI does is reverting just the value, but the field (I checked with the Debug View, you can see the differences in the above screenshots) is still marked in Bold. This means, the value of the same field from the prefab and its instance are considered different and modified, even if the value has been restored to its prefab defaults.
    If I change the same field in the prefab, its value doesn't replicate to all instances of that prefab, because the field is still marked as modified, even if the value is the same.

    In short, using AI prevents me from knowing exactly which values have been modified, because they don't get shown in bold, and the Revert function just copies the prefab Value, without actually restoring its "virgin and untouched" state. The same state that allows changes from a prefab to propagate to all its instances.

    In addition, if the field is a serialized class with public fields, doesn't matter if you change one of the nested fields, the inspector never changes to Bold, and will never revert to the prefab original values (Revert is actually grayed out)
     
    Last edited: Dec 17, 2016
  44. Wild-Factor

    Wild-Factor

    Joined:
    Oct 11, 2010
    Posts:
    605
    Hello I made a custom property drawser, but each time I use it, I got the error message:

    "Trying to draw a Property Drawer of type LocEnumDrawer without a proper serialized property. This usually happen, while exposing a property-drawer driven value from a property or a dictionary."

    How can I fix this ? thanks

    LocalizeEnum is an enum

    Code (CSharp):
    1. public class enumDrawer : PropertyDrawer
    2. {
    3.  
    4.     public const float F_FIELD_TEXT_PROPORTION = 0.3f;
    5.     public const float F_FIELD_PROPORTION_RIGHT = 1.0f - F_FIELD_TEXT_PROPORTION;
    6.  
    7.     class EditionPropertyData
    8.     {
    9.         public string m_oEnumNameSearch = "";
    10.         public List<int> m_oTempListIndexForSearch = new List<int>();
    11.         public int m_iPreviousIndexSelected = 0;
    12.         public string[] m_oListPopup;
    13.         public bool m_bFirstDisplay = true;
    14.     }
    15.  
    16.     // dirty but didn't found another way to save data per var.
    17.     Dictionary<SerializedProperty, EditionPropertyData> m_oTempDataContainer = new Dictionary<SerializedProperty, EditionPropertyData>();
    18.     EditionPropertyData m_oCurrentEditionPropertyData;
    19.  
    20.     public void OnDisable()
    21.     {
    22.         m_oTempDataContainer.Clear();
    23.     }
    24.  
    25.     public override void OnGUI(Rect oPosition, SerializedProperty oProperty, GUIContent oLabel)
    26.     {
    27.         m_oCurrentEditionPropertyData = null;
    28.  
    29.         if (m_oTempDataContainer.ContainsKey(oProperty) )
    30.         {
    31.             m_oCurrentEditionPropertyData = m_oTempDataContainer[oProperty];
    32.         }
    33.         else
    34.         {
    35.             m_oCurrentEditionPropertyData = new EditionPropertyData();
    36.             m_oTempDataContainer.Add(oProperty, m_oCurrentEditionPropertyData);
    37.         }
    38.  
    39.  
    40.         // float fLabelWidth       = position.width * 0.3f;
    41.         float fSearchFieldWidth = oPosition.width * 0.4f;
    42.         float fEnumListWidth = oPosition.width - fSearchFieldWidth;
    43.  
    44.         DrawTextField(new Rect(oPosition.x, oPosition.y, fSearchFieldWidth, oPosition.height), oProperty, oLabel);
    45.  
    46.         EditorGUI.BeginChangeCheck();
    47.  
    48.  
    49.  
    50.         m_oCurrentEditionPropertyData.m_iPreviousIndexSelected = EditorGUI.Popup(new Rect(oPosition.x + fSearchFieldWidth, oPosition.y, fEnumListWidth, oPosition.height),
    51.             m_oCurrentEditionPropertyData.m_iPreviousIndexSelected, m_oCurrentEditionPropertyData.m_oListPopup);
    52.  
    53.         if (EditorGUI.EndChangeCheck())
    54.         {
    55.             SetValueFromIndex(oProperty);
    56.         }
    57.     }
    58.  
    59.  
    60.     void DrawTextField(Rect position, SerializedProperty property, GUIContent label)
    61.     {
    62.         // Draw the text field control GUI.
    63.         EditorGUI.BeginChangeCheck();
    64.         m_oCurrentEditionPropertyData.m_oEnumNameSearch = EditorGUI.TextField(position, label, m_oCurrentEditionPropertyData.m_oEnumNameSearch/*property.stringValue*/);
    65.  
    66.         if (EditorGUI.EndChangeCheck() || m_oCurrentEditionPropertyData.m_bFirstDisplay)
    67.         {
    68.             m_oCurrentEditionPropertyData.m_bFirstDisplay = false;
    69.  
    70.             if (m_oCurrentEditionPropertyData.m_oEnumNameSearch != "")
    71.             {
    72.                 m_oCurrentEditionPropertyData.m_iPreviousIndexSelected = 0;
    73.             }
    74.             else
    75.             {
    76.                 m_oCurrentEditionPropertyData.m_iPreviousIndexSelected = property.enumValueIndex;
    77.  
    78.                 if (m_oCurrentEditionPropertyData.m_iPreviousIndexSelected < 0 )
    79.                 {
    80.                     m_oCurrentEditionPropertyData.m_iPreviousIndexSelected = 0;
    81.                 }
    82.             }
    83.  
    84.             // creat the list with the search result
    85.             List<string> oTempListForSearch = new List<string>();
    86.             m_oCurrentEditionPropertyData.m_oTempListIndexForSearch.Clear();
    87.  
    88.             m_oCurrentEditionPropertyData.m_oEnumNameSearch = m_oCurrentEditionPropertyData.m_oEnumNameSearch.ToLower();
    89.  
    90.             List<string> ListForSearch = new List<string>(property.enumNames);
    91.  
    92.             for (int i = 0; i < ListForSearch.Count; i++)
    93.             {
    94.                 string oEnumLower = ListForSearch[i].ToLower();
    95.  
    96.                 if (m_oCurrentEditionPropertyData.m_oEnumNameSearch == "" || oEnumLower.Contains(m_oCurrentEditionPropertyData.m_oEnumNameSearch))
    97.                 {
    98.                     oTempListForSearch.Add(property.enumNames[i]);
    99.                     m_oCurrentEditionPropertyData.m_oTempListIndexForSearch.Add(i);
    100.  
    101.                     /* if (i == property.enumValueIndex)
    102.                      {
    103.                          m_iPreviousIndexSelected = m_oTempListForSearch.Count - 1;
    104.                      }*/
    105.                 }
    106.             }
    107.  
    108.             m_oCurrentEditionPropertyData.m_oListPopup = oTempListForSearch.ToArray();
    109.  
    110.             SetValueFromIndex(property);
    111.         }
    112.     }
    113.  
    114.  
    115.     void SetValueFromIndex(SerializedProperty property)
    116.     {
    117.         if (m_oCurrentEditionPropertyData.m_oTempListIndexForSearch.Count > 0)
    118.         {
    119.             property.enumValueIndex = m_oCurrentEditionPropertyData.m_oTempListIndexForSearch[m_oCurrentEditionPropertyData.m_iPreviousIndexSelected];
    120.         }
    121.     }
    122.  
    123. }
    124.  
    125.  
    126.  
    127. [CustomPropertyDrawer(typeof(LocalizeEnum))]
    128. class LocEnumDrawer : enumDrawer
    129. {
    130.  
    131. }
    132.  
     
  45. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Can you show me a place where you apply this drawer, the code where you inspect it? The error your getting is usually that you're trying to inspect a property, and Unity's PropertyDrawer are notoriously bad are handling those.

    Also, if you're using AdvancedInspector and it's not for a sharable asset, I would advise you to use the FieldEditor instead.
     
  46. Wild-Factor

    Wild-Factor

    Joined:
    Oct 11, 2010
    Posts:
    605
    Code (CSharp):
    1.     [System.Serializable]
    2.     public class DictionaryDescription : UDictionary<CharacterType, LocalizeEnum[]> { };
    3.  
    4.     [Inspect]
    5.     public DictionaryDescription m_oDictionaryDescription;
     
  47. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    Well... yeah... The error message says; "Trying to draw a Property Drawer of type LocEnumDrawer without a proper serialized property. This usually happen, while exposing a property-drawer driven value from a property or a dictionary.", and you're trying to inspect a dictionary. Unity's property drawer will never work on a dictionary, because it cannot generate a SerializedProperty for it. One of the deep annoyance of Unity's retarded serialization system.

    You could try FieldEditor instead. Should be a lot easier too. You can find all existing FieldEditor inside the FieldEditors folder.
     
  48. Wild-Factor

    Wild-Factor

    Joined:
    Oct 11, 2010
    Posts:
    605
    Easier, I'm not really sure. At least I have to redo it :)
     
  49. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,598
    I swear it's easier, since you don't have to work with SerializedObject and SerializedProperty, and you can access your object directly. :p
     
  50. blue_mc

    blue_mc

    Joined:
    Dec 6, 2016
    Posts:
    7
    [TextArea] or [TextField(TextFieldType.Area)] doesnt automatically expand textfield to vertical.
    Expanding the textfield to horizontal make it harder to read.
    advancedEditorTextFieldBug.PNG
     
    NeatWolf likes this.
unityunity