Search Unity

Advanced Inspector - Never Write An Editor Again

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

  1. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    374
    Essentially - We'll be selecting a prefab that has a specific component that will have a reference to a location where a blob of data is. We'll be deserializing that data into our own classes. We want to display those classes of data as part of the prefab component display.
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Here you go;



    Code (CSharp):
    1.     public class AIExample44_IInspect : MonoBehaviour, IInspect
    2.     {
    3.         public Material material;
    4.  
    5.         [Expandable(false)]
    6.         public new Transform transform;
    7.  
    8.         public object[] Inspect
    9.         {
    10.             get { return new object[] { material, transform }; }
    11.         }
    12.     }
    You pass a list of object to the Inspect property from the IInspect interface, and Advanced Inspector handles creating and displaying extra editor after the current one.

    Mail me to admin@lightstrikersoftware.com if you want that beta feature.
     
    strich likes this.
  3. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    374
    Thanks for taking the time to look into this @LightStriker - Rock solid support. I've emailed you with regards to the beta. If you could also let me know a bit more how Inspect works either here or privately that'd be great - We'll want to be able to update the objects that are returned by Inspect() moment to moment, etc.
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    In the package, look at AIExample44_IInspect.

    Editors are refresh anytime the object returned are different and the Inspector is refreshed.
     
  5. KJoanette

    KJoanette

    Joined:
    Jun 8, 2013
    Posts:
    59
    I've been getting these for a while v1.69:

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. AdvancedInspector.InspectorEditor.RefreshFields () (at A:/LightStrikerSoftware/Projet/AdvancedInspector/AdvancedInspector 5/Lib/AdvancedInspector/AdvancedInspector/InspectorEditor.cs:454)
    3. AdvancedInspector.InspectorEditor.set_Instances (System.Object[] value) (at A:/LightStrikerSoftware/Projet/AdvancedInspector/AdvancedInspector 5/Lib/AdvancedInspector/AdvancedInspector/InspectorEditor.cs:104)
    4. AdvancedInspector.InspectorEditor.OnEnable () (at A:/LightStrikerSoftware/Projet/AdvancedInspector/AdvancedInspector 5/Lib/AdvancedInspector/AdvancedInspector/InspectorEditor.cs:190)
    5. AdvancedInspector.ScriptableEditor.OnEnable () (at A:/LightStrikerSoftware/Projet/AdvancedInspector/AdvancedInspector 5/Lib/AdvancedInspector/AdvancedInspector/InspectorEditors/ScriptableEditor.cs:26)
    6.  
     
  6. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Which version of Unity?
     
  7. KJoanette

    KJoanette

    Joined:
    Jun 8, 2013
    Posts:
    59
    5.3.5p7
     
  8. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Odd, I have no issue with 5.3 so far... Is it on a specific component or all of them?
     
  9. KJoanette

    KJoanette

    Joined:
    Jun 8, 2013
    Posts:
    59
    I happens even when I have nothing selected... I believe they usually show up when i hit run.
     
  10. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    That's even odder. I'll download 5.3.5 and see if I can reproduce it.
     
  11. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    So regarding the image issues and prefabs that I asked earlier, I am not sure if there currently is a way how to make it happen or is this a new feature that is coming to the editor, or is this something that out of the question of implementation in any way. The reason I am asking is just so I know how to continue with the development of the game I am making.

    Thank you
    Aleks
     
  12. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    It's not something that exist as a feature of AI right now.

    It sure can be done. It's actually something that can be added to the ObjectEditor.cs file with any modification to AI's core.
    I'm thinking about how to do it properly.

    Do you have any timetable for that feature?
     
  13. AleksLA

    AleksLA

    Joined:
    May 7, 2013
    Posts:
    22
    The game has a lot of other things that need to be done also, so some delay like a month or two is not big deal at all, but still some approximate time when it will be done would be fantastic . Thank you so much for looking into this.
    Overall I am very happy with AI and will leave a nice positive review on the assetstore.
     
  14. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    An interesting side effect is that you can get a preview of pretty much every asset type;


    I'm under the impression this shouldn't be controlled by an attribute, but be an option in the contextual right-click.

    EDIT: There;

     
    Last edited: Oct 2, 2016
  15. XaneFeather

    XaneFeather

    Joined:
    Sep 4, 2013
    Posts:
    97
    Any chance of seeing an AlwaysExpanded equivalent for collections? This would reduce the visual clutter of some of my list-heavy objects by a ton.

    And the object preview is looking tight!
     
  16. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Would that make the collection always expanded, the items in it, or both?
     
  17. XaneFeather

    XaneFeather

    Joined:
    Sep 4, 2013
    Posts:
    97
    Just the collection. For items we already have appropriate attributes.
     
  18. XaneFeather

    XaneFeather

    Joined:
    Sep 4, 2013
    Posts:
    97
    Also, unsure if it's a glitch or I'm doing something wrong, but when using Title inside a Group, the label for the title is shifted to the right.

     
  19. FBones

    FBones

    Joined:
    Aug 28, 2016
    Posts:
    73
    I have two questions:

    i) Is it possible to set things up so that all properties are automatically shown in the inspector rather than having to put [Inspect] in front of all of them?

    ii) Can you clarify which types of objects can be modified in the inspector and saved? Obviously, all the ones exposed by default can be, but it appears that one can safely change and store properties in the inspector even though this is not shown in the Unity Inspector.
     
  20. FBones

    FBones

    Joined:
    Aug 28, 2016
    Posts:
    73
    Hmmm, looks like I spoke too soon. It is possible to edit properties on a scriptableObject and have that stick, but it seems that you cannot modify a property on a Monobehavior and have it stick. That's a real shame.
     
  21. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    1) Not right now, because it would be probably a bit too far from Unity's conventions.

    2) A.I. can pretty much inspect everything the .NET framework support... With exception to HashSet. As for saving stuff, since A.I. does not modify Unity's serialization, it's up to you to convert your data into something Unity can chew. For example, you can easily convert a DateTime into a long or a string, while exposing it as a property so A.I. display the calendar gizmos.

    I have no idea what you mean by "have it stick"?
     
  22. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    I guess I could put that property in the Collection attribute.

    Probably a small glitch. Having everything line up properly is quite a challenge.
     
  23. FBones

    FBones

    Joined:
    Aug 28, 2016
    Posts:
    73
    I just mean have the data persist. I thought it was being saved when I saw it being preserved from one play to another, but it doesn't persist from one session to another because Unity does not serialize properties.
     
  24. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Yes, you have to have a backing field to save that data.

    Also, auto-properties are evil. You should never use them.
     
  25. deadlyboss

    deadlyboss

    Joined:
    Feb 8, 2015
    Posts:
    5
    Hi there!

    I was wondering if there is a solution for serializing an interface in Inspector, without needing to implement a custom editor for each one of them.

    Thanks!
     
  26. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Advanced Inspector is able to display interface just fine... However, AI does not modify Unity's serialization in any way.

    So you're stuck that your backing field has to be a properly serializable type. If you want to use interface, your saved data will have to be derived from UnityEngine.Object; by MonoBehaviour or by ScriptableObject.
     
  27. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Version 1.70 submitted to the Asset Store with the following changes;

    [CHANGES]
    • Added the IInspect interface which allows you to inspect extra object. Similar to a MeshRenderer displaying its materials at the bottom.
    • Added a Refresh static method to the AdvancedInspectorAttribute. This can force all AI's editor to be refresh and optionally rebuilt.
    • Added a icon preview beside object fields. Option to show/hide and size of the icons are available in the right-click menu.
    • Added an Always Expanded property in the Collection Attribute to make list and dictionary uncollapsible.
    [FIXES]
    • Fixed the UV Meter in Unity 5.4+
    • Fixed a culture variation exception in saving colors in the preferences.
    • Fixed a null occurring while watching a value.
    Note that this version is required if you use Unity 5.4.0. For some reason, Unity 5.4+ was throwing a null exception in the previous version of the UV meter.

    Unity 5.5 beta is working, but I recommend you to not allow the auto-updater to modify AI's package for now.

    A change that isn't in the documentation; a "Turn On" / "Turn Off" button in the preference was added in the second tab to quickly turn on/off all custom editor.
     
  28. XaneFeather

    XaneFeather

    Joined:
    Sep 4, 2013
    Posts:
    97
    Hey LightStriker!

    Excited to try out the update! Sounds very promising. Also, much obliged for the Always Expanded option!

    I've recently come across something that I wanted to address before. Currently, the label on groups gets drawn over and thus cut off from the right hand side. This limits the maximum length I can give labels and forces me to keep group names very short.
    Here's an example of what I'm referring to.


    Is it possible to have it display over the entire length of the group bar?
     
  29. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    That might be possible only for groups... I'll have to check. No promise.
     
  30. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    Hi LightStriker, I'm not seeing update 1.70 yet. How long does it usually take from the moment you submit the package until it gets approved and published on the assetstore?
     
  31. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Usually Unity takes 2-4 open days to review it.
     
    PedroGV likes this.
  32. Astro75

    Astro75

    Joined:
    Dec 18, 2014
    Posts:
    48
    Found a small issue with ComponentMonoBehaviour
    When I click Add Component and select my class that extends ComponentMonoBehaviour I see no visual changes. But after saving the scene I find in my git log that component is actually added to the gameobject.

    Edit: I also have a feature request. Inspect attribute methodName could allow boolean fields. Currently it only allows methods.

    Edit2: Another request. You have a great feature that shows which component is selected. But it does not work with colliders.
    upload_2016-11-11_15-0-45.png
     
    Last edited: Nov 11, 2016
  33. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    ComponentMonoBehaviour is supposed to be used with [CreateDerived]. See the example AIExample27_CreateDerived.

    Inspect can also take properties. I see no obvious reason why I couldn't add support for boolean fields.

    Odd. It's probably testing for MonoBehaviour, which a collider isn't. Should be fairly easy to fix.
     
  34. Astro75

    Astro75

    Joined:
    Dec 18, 2014
    Posts:
    48
    We are already using the correct way. My concern is if somebody adds it using Add Component accidentally or without knowing. I expected it to be removed automatically.
    When I add ComponentMonoBehaviour and then another component that has AdvancedInspector on the same GameObject. ComponentMonoBehaviour without parent gets removed automatically. So maybe it is possible to fix those components without parents in some way.
     
  35. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Hi,

    I want to add a button to the inspector of a given class, but I don't want to add it as a method of that said class because the button will invoke editor-only code. What's the best way to add a button to a type drawer without having to add a method to the class itself?

    If I were not using AI I'd just create a Property Drawer to extend the default drawer for that class. Can I do that in AI? or is there any other simpler/faster way of doing it?

    Regards,
     
  36. XaneFeather

    XaneFeather

    Joined:
    Sep 4, 2013
    Posts:
    97
    What I do is write classes that depend on special AI code as partial classes and add a "<classname>.Inspector.cs" file, wrap it around "if #UNITY_EDITOR" compiler directive and add AI-specific methods and properties declared as private.

    That way all AI-specific code will not compile for an end-user build and declaring all AI-specific code as private keeps classes clean. Works especially well if you need to implement any of the AI interfaces as only the AI partial class needs to implement it, keeping the base class untouched.

    Example:
    Code (CSharp):
    1. // InternalLayer.cs
    2. using AdvancedInspector;
    3. using Saurian.Systems.Praeda;
    4. using Saurian.Systems.Vita.Settings;
    5. using UnityEngine;
    6.  
    7. namespace Saurian.Systems.Vitas {
    8.     [System.Serializable]
    9.     [AdvancedInspector(InspectDefaultItems = false, ShowScript = false)]
    10.     public partial class InternalLayer : OrganicLayer {
    11.         #region Fields & Properties
    12.         // ----------------------------------------------------------------------------------------------------
    13.         /// <summary>
    14.         /// Gets the type of the layer.
    15.         /// </summary>
    16.         [Inspect, ReadOnly("InspectorHelper.IsApplicationRunningAI")]
    17.         [Restrict("EditorGetLayerTypes")]
    18.         [Group("Settings", Priority = 0, Expandable = false)]
    19.         public new InternalLayerType LayerType {
    20.             get { return this.layerType as InternalLayerType; }
    21.             private set { this.layerType = value; }
    22.         }
    23.         // ----------------------------------------------------------------------------------------------------
    24.         #endregion
    25.     }
    26. }
    Code (CSharp):
    1. // InternalLayer.Inspector.cs
    2. #if UNITY_EDITOR
    3. using AdvancedInspector;
    4. using Saurian.Systems.Biota;
    5. using Saurian.Systems.Biota.Attributes;
    6. using Saurian.Systems.Vita.Settings;
    7. using System.Collections.Generic;
    8. using UnityEditor;
    9. using UnityEngine;
    10.  
    11. namespace Saurian.Systems.Vitas {
    12.     public partial class InternalLayer {
    13.         #region Inspector Implementation
    14.         // ----------------------------------------------------------------------------------------------------
    15.         /// <summary>
    16.         /// Returns a list of valid layer types.
    17.         /// </summary>
    18.         private InternalLayerType[] EditorGetLayerTypes() {
    19.             var internalLayerTypes = LayerSettingsData.LayerSettings.InternalLayerTypes;
    20.             if (internalLayerTypes != null) {
    21.                 var returnList = new List<InternalLayerType>(internalLayerTypes.Count + 1);
    22.                 returnList.Add(null);
    23.                 returnList.AddRange(internalLayerTypes);
    24.  
    25.                 return returnList.ToArray();
    26.             }
    27.             return null;
    28.         }
    29.         // ----------------------------------------------------------------------------------------------------
    30.         #endregion
    31.     }
    32. }
    33. #endif
     
  37. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    The inspector already removes any "orphant" ComponentMonoBehaviour. You should look for a log entry saying so.
    There is no "proper" way to fix those.

    What you should do, is [AddComponentMenu("")] on your class. This prevent being able to add it from the AddComponent menu.
     
  38. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    You can wrap your method in a #if declaration. Which is very easy.

    Or you can write an editor that derive from InspectorEditor and add an InspectorField manually. You can look at file like CameraEditor.cs, which add functionalities to the camera in the editor side only.
     
  39. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    1.70 is now available.
     
  40. gpvd

    gpvd

    Joined:
    Nov 2, 2013
    Posts:
    78
    Hello LightStriker,

    Got 2 questions:

    1. Is it possible to set a default position for the separator. I use some lengthy fieldnames and it would be nice to display the separator at a position defined by me. (maybe in editor preference pane?)
    2. Is it possible to add spacing between 2 groups. Right now , when i add spacing to a group, the group pane is extended with space, instead of inbetween 2 groups.

    Greetz,
    G
     
  41. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    1. Sure, I can add that as a setting in the pref panel.

    2. Not right now... You would need a field inbetween your groups currently. I'll look into it.
     
  42. gpvd

    gpvd

    Joined:
    Nov 2, 2013
    Posts:
    78
    Thank you very much!
     
  43. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    Is there a way to sort the display of dictionary entries by key (ToString(), alphabetically for example)? When editing large dictionaries it's nearly impossible to find a specific entry.
     
  44. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Right-Click > Sort Alphabetically.

    Sure, it sorts everything alphabetically, but you can simply turn it back to none once you're done editing your dictionary.
     
    Froghuto likes this.
  45. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Thank you for the reply,

    I've tried it, but it's not exactly what I'm looking for. I want to extend a type editor to look *exactly* like it normally does with Advanced Inspector, and just add a button at the end.

    I want to have this


    Screen Shot 2016-11-24 at 15.08.31.png

    but, by creating a custom editor like so:
    Screen Shot 2016-11-24 at 15.05.18.png

    I end up with this

    Screen Shot 2016-11-24 at 15.05.09.png

    Is there any way of achieving what I'm looking for?

    Thank you
     
  46. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Can you check your console? I have a feeling you might be getting an exception. Because that's Unity default inspector, and it shows up only if there's something wrong happening.

    You could also post the StoryContainer code here... Is "Story" a property or a field? Is it public or not? It's also case-sensitive.
     
  47. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Oh, you're right, I was using .GetProperty() when Story is a normal field. Changing it to .GetField solved the problem. I didn't even notice the console error.

    Thank you so much.
     
  48. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    So,

    in the same vein as my previous post, now I want to achieve the same result (add a button) on a custom class (derived from System.Object) that exists inside the StoryContainer. I feel that the best way is to create a custom FieldEditor, but how then am I able to extend the draw method to draw exactly like it would if I had no custom FieldEditor, only with a button added to it? I would like to avoid having to manually draw all fields inside of it, since there are many, and I'm planning on adding more.

    I don't know if I made myself clear.

    Regards,
     
  49. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Not completly clear...

    And again, you cannot - or want not - to simply add a [Inspect] on a method in the class?
     
  50. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    The [Inspect] route is not feasible because the button must invoke logic that is inside an Editor-only Utility class.

    Let me make it clearer.

    I have a story container
    Screen Shot 2016-11-28 at 16.25.25.png

    that contains a Story with many pages
    Screen Shot 2016-11-28 at 16.25.51.png

    and each page has a bunch of stuff inside
    Screen Shot 2016-11-28 at 16.26.16.png

    I want to customize the appearance of a given page to have a button inside

    Screen Shot 2016-11-28 at 16.31.49.png

    but without using the [Inspect] attribute. Is it possible?