Search Unity

Assets [WIP] Odin Inspector & Serializer Looking for Feedback

Discussion in 'Works In Progress - Archive' started by jorisshh, Feb 22, 2017.

  1. jingray

    jingray

    Joined:
    Feb 6, 2015
    Posts:
    53
    Asset can use for Editor window ?!
     
  2. hepphep

    hepphep

    Joined:
    Feb 1, 2013
    Posts:
    24
    Hi,

    First of all, thanks for great tool, it really brings lots of things that has been lacking from Unity.
    However, I also ran into one bug related to serialization and auto-properties (or then I have misunderstood something).

    Steps to reproduce
    1. Create SerializedMonoBehavior having auto-property (in my simple test case it was float, also happens at least with Transform).
    2. Use that in scene, modifying its value. Works perfectly fine in both editor and play mode
    3. Make prefab out of that gameobject and play
    4. You cannot change that value in the gameobject of your scene anymore. When you change it, it will always revert instantly back to the value in the prefab. You can change the values in prefab which are instantly reflected to gameobject

    The code I tried with is following.
    The SerializeField field works all the time as it should, so it can be also changed for the GameObject after making prefab as well. Both properties with private and public setters are bugged.

    Code (CSharp):
    1.  public class OdinPropertyBugPoc : SerializedMonoBehaviour
    2.     {
    3.         [SerializeField]
    4.         private float _nonOdin;
    5.         public float NonOding { get { return _nonOdin; }}
    6.  
    7.         [OdinSerialize]
    8.         public float OdinizedWithPrivateSet { get; private set; }
    9.  
    10.         [OdinSerialize]
    11.         public float OdinizedWithPublicSet { get; set; }
    12.  
    13.     }
     
  3. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    188
    Huh, that's funny. We'll have a look at that promptly. There must be some case with auto properties and prefab modifications that we're not catching. Thanks for the report!

    Odin can be used anywhere you might want to draw an inspector for any object, including editor windows - though in that case you will have to write a little bit of code. See my answer to the question "Can you use Odin styling for EditorWindows?" close to the top of the previous page of this thread.
     
  4. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    When using [AssetList] on List<> fields, is it possible to show the path to the assets somewhere (like it does for non-List fields in the drop down menu)?
    Also is it possible to have [AssetList] search objects in the scene instead of in project assets?
    One more thing, When an FBX contains multiple meshes AssetList will only display the first one, not the others.
     
    Last edited: May 19, 2017
  5. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Hey, I just picked this up but unless I'm doing something wrong I'm noticing Unity's OnValidate no longer seems to work. I realize Odin has Validate functions however I'm curious will this break every OnValidate call in my project? Also is this intended behaviour?

    Also I have an array of GameObjects. When I try adding an element a popup comes up asking me to select a scene object to use. It is kind of annoying and I prefer dragging and dropping from the hierarchy. Is there anyway I can disable this?
     
    Last edited: May 19, 2017
  6. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Example from the previous page
    Example from the previous page:
    a.png

    Thanks for reporting the FBX issue, We'll make sure to add support for that.

    We don't have an option to show the asset path right now, I'll give it some thought. But for now you can click on the object-field and it will ping the object in the project window. For scene objects, we've discussed adding a ToggleList attribute where you provide the source yourself. We've discussed it a bit over here: https://bitbucket.org/sirenix/odin-inspector/issues/16/applying-the-assetlist-and


    OnValidate not working is a bug, and is fixed in the next patch which we are just waiting for Unity to approve. Until then you can use the [OnValueChanged("OnValidate")] attribute.

    Dragging items from the hierarchy or the project window and into a list should be possible, is this not working for you?
     
    Last edited: May 20, 2017
  7. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Cool glad to hear it :)

    Yea it does work. What I'm saying is when I click to add a new element, a window will popup asking me to first select an element from the hierarchy. I can click cancel and it will still add the element. But if I want to add say 10 elements it is annoying that I have to keep cancelling the popup. What I'm saying is I would rather add a bunch of elements without the popup and then drag them from hierarchy. That works fine.

    For example in the Image, if I click the button to add a new element this window will popup. Its not causing issues its just more annoying than anything.

    Amazing product either way! Really happy with it :)
     

    Attached Files:

    • a.png
      a.png
      File size:
      94.5 KB
      Views:
      1,099
  8. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Ahh, I think I hear you. How about making it so that ctrl+clicking the add button would just add a null value to the list without opening the asset-picker popup window? A right-click context menu item for setting the length of the array / list is also something we've been wanting to do for a while.

    On a side note, what on earth happened to the icons o_O. Have they always been all black for you?

    And good to hear you are enjoying the tool :)
     
  9. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Yea something like that would be perfect :)

    And yea haha they have. I just assumed they were suppose to look like that. But considering you seem surprised, I'm guessing not. Also just looking at the images in the manual and such I'm surprised I haven't thought of this before now haha.
     
  10. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Cool, I'll make sure to add that feature in.

    Hehe, that is so strange. What version of Unity and what OS are you using?
     
  11. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    It's Unity 5.6.1f1 and Windows 7
     
  12. MrG

    MrG

    Joined:
    Oct 6, 2012
    Posts:
    368
    Can't you just drag one or more elements to the list without clicking the + first...they should add themselves automatically. Use the padlock on the inspector to lock it so it doesn't change while you're selecting elements.
     
  13. RecursiveRuby

    RecursiveRuby

    Joined:
    Jun 5, 2013
    Posts:
    163
    Yea that actually works really nice! Didn't know about it. Thanks for that :)
     
    MrG likes this.
  14. TheBlackBox

    TheBlackBox

    Joined:
    Jan 13, 2014
    Posts:
    33
    Hi, I've just installed the inspector into my project - however I'm noticing that none of the attributes are working for me.

    I've browsed the first demo scene, looking at the variety of scripts, all of which are working as intended.

    Whenever I try to add the TabGroup attribute I get this message:

    Code (CSharp):
    1. Assets/DebugPos.cs(7,6): error CS0246: The type or namespace name `TabGroup' could not be found. Are you missing an assembly reference?
    2.  
    I'm assuming I've missed a step in the installation, but I've read the documentation multiple times and everything seems to work as it should in the demo scenes so I'm kind of lost...

    Any help would be appreciated, I'm running 5.6.1f1, on MacOS.

    Thanks!
     
  15. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Sounds like you just need to add a reference to the Sirenix.OdinInspector namespace in your .cs file like so:

    Code (CSharp):
    1. using UnityEngine;
    2. using Sirenix.OdinInspector; // Namespace containing all Odin attributes and base-classes such as SerializedMonoBehaviour.
    3.  
    4. public class MyComponent : MonoBehaviour
    5. {
    6.     [TabGroup("Tab 1")]
    7.     public int A;
    8.  
    9.     [TabGroup("Tab 1")]
    10.     public Vector3 B;
    11.  
    12.     [TabGroup("Tab 2")]
    13.     public Vector3 C;
    14. }
    We should properly mention this in the manual as well :D. Hope this solve it for you.
     
  16. TheBlackBox

    TheBlackBox

    Joined:
    Jan 13, 2014
    Posts:
    33
    Thanks so much for this! I figured that would be the case, but when looking through your example scripts there wasn't a reference so I figured what the heck.

    Cheers for the help!
     
  17. dizzy2003

    dizzy2003

    Joined:
    Nov 25, 2013
    Posts:
    108


    Hopefully that image works if not image here https://imgur.com/a/6hSM4

    Loving Odin (tab groups are superb), some small issues though (possibly some just due to ignorance)

    Image shows a list of Structs with some horizontal groups.

    In my screenshot I am losing the end of the label text of a bunch of my int fields, and if I drag the inspector wider, it just makes the int value box bigger (Not the Label) (I only actually need a 2 digit number field) (Note the horizontal groups normally dont do this so I think its a combo of tabs, lists and Horizontal groups)

    Something to let me specify the size of the label/size of the input field would be great in general.As well as fixing the above bug (if it is one)

    Lists odd/even color difference could do with being more pronounced
    Lists have all members expanded, Unity Reordererable Lists lets you open close individual elements of a list

    The struct elements are drawn in some unspecified order rather than the order in my struct, I guess thats due to the horizontal groups and I think I might have seen something that lets me re order items?

    I think thats it for now :)
     
  18. jingray

    jingray

    Joined:
    Feb 6, 2015
    Posts:
    53
    Thank you, bjarkeck.

    Asset really good. I buy it. Odin Inspector there should be documentation on the build editor window. Include image, text, layout ...
    :D
     
  19. Thordain

    Thordain

    Joined:
    May 16, 2017
    Posts:
    2
    Fantastic asset, well worth the money. Very well thought out and implemented, kudos to the team.

    Any update on SerializedMonoBehavior causing the scene to be marked dirty after play mode? I'd like to start using Odin serialization but that is driving me nuts.

    Are there any plans to allow the PropertyTree to grab the current Editor (say if you inherit from OdinEditor for a custom editor) and expose that? I'm currently using this (probably very dirty) solution:

    Code (CSharp):
    1. using Sirenix.OdinInspector.Editor;
    2. using System.Runtime.CompilerServices;
    3.  
    4. public static class OdinCustomEditorBinder {
    5.     static ConditionalWeakTable<object, object> bindingTable = new ConditionalWeakTable<object, object>();
    6.     static object locker = new object();
    7.  
    8.     public static void RegisterCustomEditor(object target, object editor) {
    9.         lock (locker) {
    10.             if (target != null) {
    11.                 object existing;
    12.                 if (bindingTable.TryGetValue(target, out existing)) {
    13.                     // Assume the newer editor is the correct one.
    14.                     bindingTable.Remove(target);
    15.                     bindingTable.Add(target, editor);
    16.                 } else {
    17.                     bindingTable.Add(target, editor);
    18.                 }
    19.             }
    20.         }
    21.     }
    22.  
    23.     public static void UnregisterCustomEditor(object target) {
    24.         lock (locker) {
    25.             if (target != null) {
    26.                 bindingTable.Remove(target);
    27.             }
    28.         }
    29.     }
    30.  
    31.     public static object GetCustomEditorFor(object target) {
    32.         lock (locker) {
    33.             object obj;
    34.             if (bindingTable.TryGetValue(target, out obj)) {
    35.                 return obj;
    36.             } else {
    37.                 return null;
    38.             }
    39.         }
    40.     }
    41. }
    42.  
    43.  
    44. public class RegisteredOdinEditor : OdinEditor {
    45.     protected override void OnEnable() {
    46.         OdinCustomEditorBinder.RegisterCustomEditor(serializedObject.targetObject, this);
    47.         base.OnEnable();
    48.     }
    49.  
    50.     protected override void OnDisable() {
    51.         base.OnDisable();
    52.         OdinCustomEditorBinder.UnregisterCustomEditor(serializedObject.targetObject);
    53.     }
    54. }
    55.  
    This allows me to call methods on the custom editor (without dirtying the actual component with editor-ish code) and still use Odin attributes to do style and layout for almost everything:
    Code (CSharp):
    1. using Sirenix.OdinInspector.Editor;
    2. using Sirenix.Utilities;
    3. using Sirenix.Utilities.Editor;
    4. using System;
    5. using System.Reflection;
    6. using UnityEngine;
    7.  
    8.  
    9. [OdinDrawer]
    10. [DrawerPriority(DrawerPriorityLevel.WrapperPriority)]
    11. public class OnInspectorGUICustomEditorAttributeDrawer : OdinAttributeDrawer<OnInspectorGUICustomEditorAttribute> {
    12.     public class Config {
    13.         public string error;
    14.         public Action<object> invoker;
    15.         public Action<object, CustomGUIInspectorContext> contextInvoker;
    16.         public WeakReference editor;
    17.         public bool passContext;
    18.     }
    19.  
    20.     protected override void DrawPropertyLayout(InspectorProperty property, OnInspectorGUICustomEditorAttribute attribute, GUIContent label) {      
    21.         var methodConfig = property.Context.Get(this, "Config", (Config)null);
    22.  
    23.         if (methodConfig.Value == null) {
    24.             methodConfig.Value = new Config();
    25.  
    26.             // I don't think this will work correctly for hierarchical stuff.  Might have to
    27.             // look into using property.Tree.UnitySerializedObject.targetObject?
    28.             bool multiParent = property.ParentValues.Count > 1;
    29.             object parent = property.ParentValues.Count == 1 ? property.ParentValues[0] : null;
    30.          
    31.             if (parent != null) {
    32.                 object editor = OdinCustomEditorBinder.GetCustomEditorFor(parent);
    33.  
    34.                 if (editor != null) {
    35.                     methodConfig.Value.editor = new WeakReference(editor);
    36.  
    37.                     var methodInfo = editor.GetType().FindMember().IsMethod().IsNamed(attribute.MethodName).HasParameters<CustomGUIInspectorContext>().ReturnsVoid().GetMember<MethodInfo>();
    38.                     if (methodInfo != null) {
    39.                         methodConfig.Value.passContext = true;
    40.                         methodConfig.Value.contextInvoker = EmitUtilities.CreateWeakInstanceMethodCaller<CustomGUIInspectorContext>(methodInfo);
    41.                     } else {
    42.                         methodInfo = editor.GetType().FindMember().IsMethod().IsNamed(attribute.MethodName).HasNoParameters().ReturnsVoid().GetMember<MethodInfo>(out methodConfig.Value.error);
    43.                         if (methodConfig.Value.error == null) {
    44.                             methodConfig.Value.passContext = false;
    45.                             methodConfig.Value.invoker = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo);
    46.                         }
    47.                     }
    48.                 } else {
    49.                     methodConfig.Value.error = $"Unable to find registered custom editor for target.  Did you forget to inherit from {typeof(RegisteredOdinEditor).Name}?";
    50.                 }
    51.  
    52.             } else {
    53.                 if (multiParent) {
    54.                     methodConfig.Value.error = "Field has multiple parents, cannot invoke custom editor method.  Probably invoked via multiple selection.";
    55.                 } else {
    56.                     methodConfig.Value.error = "Cannot find parent object.  Probably caused by your face.";
    57.                 }
    58.             }
    59.         }
    60.  
    61.         switch (attribute.Order) {
    62.             case CustomGUIInspectorOrder.Before:
    63.                 InvokeCustomGui(property, attribute, label, methodConfig);
    64.                 CallNextDrawer(property, label);
    65.                 break;
    66.  
    67.             case CustomGUIInspectorOrder.After:
    68.                 CallNextDrawer(property, label);
    69.                 InvokeCustomGui(property, attribute, label, methodConfig);
    70.                 break;
    71.  
    72.             case CustomGUIInspectorOrder.Replace:
    73.                 InvokeCustomGui(property, attribute, label, methodConfig);
    74.                 break;
    75.  
    76.             default:
    77.                 SirenixEditorGUI.ErrorMessageBox("Invalid CustomGUIInspectorOrder specified.");
    78.                 break;
    79.         }
    80.  
    81.     }
    82.  
    83.     private void InvokeCustomGui(InspectorProperty property, OnInspectorGUICustomEditorAttribute attribute, GUIContent label, PropertyContext<Config> methodConfig) {
    84.         if (methodConfig.Value.error != null) {
    85.             SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.error);
    86.         } else {
    87.             if (methodConfig.Value.editor.IsAlive) {
    88.                 if (methodConfig.Value.passContext) {
    89.                     methodConfig.Value.contextInvoker(methodConfig.Value.editor.Target, new CustomGUIInspectorContext { Label = label, Property = property });
    90.                 } else {
    91.                     methodConfig.Value.invoker(methodConfig.Value.editor.Target);
    92.                 }
    93.             } else {
    94.                 methodConfig.Value.error = "Custom editor instance has been collected.";
    95.                 SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.error);
    96.             }
    97.         }
    98.     }
    99. }
    100.  
    101. public struct CustomGUIInspectorContext {
    102.     public InspectorProperty Property;
    103.     public GUIContent Label;
    104. }
    105.  
    (If anyone wants to re-use this code you are more than welcome to, but be warned that this is my third day working with Unity editor scripting (and Odin). It's probably full of terrible ideas and bad assumptions).

    A clean and fully-supported way to accomplish this type of functionality would be great. It seems that adding a parameter for capturing the "custom editor" to PropertyTree.Create and then exposing that as a read-only property in the tree would solve this quite easily.
     
    Last edited: May 22, 2017
  20. MaddoScientisto

    MaddoScientisto

    Joined:
    Jan 30, 2015
    Posts:
    62
    I just noticed that [ShowInInspector] tagged variables don't update in real time in play mode but only do so when another value tagged [SerializeField] updates or the object is reselected, is this intended behavior?
     
  21. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    it's most likely because they are bound to unity's serialization callbacks, and these only happen when something is de-/serialized.
     
  22. Tor-Vestergaard

    Tor-Vestergaard

    Joined:
    Mar 20, 2013
    Posts:
    188
    We're currently looking into the scene being marked dirty for no apparent reason - it's a known issue at the time - sorry for the inconvenience :)

    I can see the idea behind the pattern you propose. It does seem a little odd, though - I'll bring this up with the others. Perhaps we should add a dedicated tree context for storing specific values in the tree.

    One thing you could do, though, that's a lot easier than your method, would be to use the global context of a specific property in the tree, say the first root property, and set the editor to that - then you can always get that anywhere.

    Code (CSharp):
    1. public static class PropertyTreeExtensions
    2. {
    3.     public static void SetEditor(this PropertyTree tree, Editor editor)
    4.     {
    5.         tree.GetRootProperty(0).Context.GetGlobal("TREE_EDITOR", (Editor)null).Value = editor;
    6.     }
    7.  
    8.     public static Editor GetEditor(this PropertyTree tree)
    9.     {
    10.         return tree.GetRootProperty(0).Context.GetGlobal("TREE_EDITOR", (Editor)null).Value;
    11.     }
    12. }
    Now you merely have to call SetEditor and GetEditor on the property tree:

    Code (CSharp):
    1. public class RegisteredOdinEditor : OdinEditor {
    2.     protected override void OnEnable() {
    3.         this.Tree.SetEditor(this);
    4.         base.OnEnable();
    5.     }
    6.  
    7.     protected override void OnDisable() {
    8.         base.OnDisable();
    9.         this.Tree.SetEditor(null); // Technically this is now entirely unnecessary, as far as I can tell, as there is no static state to correct
    10.     }
    11. }
    This way, you can get the current editor from your tree merely by calling tree.GetEditor() from anywhere you have a reference to the tree. It does have the caveat that it won't work in a tree with zero properties, but that probably isn't a very relevant limitation.

    That is indeed correct - Unity only updates the editor when a serialized value changes, so values only shown due to HideInInspector would not be updated until something else triggers an update, like clicking the mouse in the window.

    We have a few ideas for ways to get around this, but it might prove tricky, and we have a bunch of higher priority tasks on our plate right now, such as finishing up the manual and fixing bugs as they crop up. We will probably get around to this eventually, though.
     
    Last edited: May 22, 2017
  23. betovena

    betovena

    Joined:
    Dec 4, 2012
    Posts:
    82
    The asset is really great!

    But something is happening,s some temp files are been created inside my project folder and not inside the temp folder inside the project.

    Example:
     

    Attached Files:

  24. ldlework

    ldlework

    Joined:
    Jan 22, 2014
    Posts:
    46
    Hello, I recently purchased Odin and I am using it inside of an editor window by way of the boilerplate previously provided in this thread. However, in using some tab groups I notice that the tabs supposedly have some sort of animation but it does not animate automatically. One needs to drag the window around, or click on it or otherwise send input events to the window to get it to redraw.

    BTW: Is there anyway to be able to determine which tab group is currently visible?
     
    Last edited: May 22, 2017
  25. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Thanks, just fixed this. It was indeed a bug caused by the tab groups. It disabled the EditorGUIUtility.hierarchyMode which makes Unity ignore the EditorGUIUtility.labelWidth amongst others.

    And yeah, I think a [LabelWidth] attribute would fit in nicely. I'll make sure to add that in.

    You can get this behaviour as well by using the ListDrawerSettings attribute:
    Code (CSharp):
    1. public class MyComponent : MonoBehaviour
    2. {
    3.     [ListDrawerSettings(ShowIndexLabels = true)]
    4.     public List<MyStruct> someList;
    5. }
    6.  
    You could also do something like this:
    Code (CSharp):
    1. public class MyComponent : MonoBehaviour
    2. {
    3.     public List<MyStruct> someList;
    4. }
    5.  
    6. [Serializable]
    7. public struct MyStruct
    8. {
    9.     [FoldoutGroup("Foldout", "Name")]
    10.     public string Name;
    11.  
    12.     [FoldoutGroup("Foldout", "Name")]
    13.     public int A;
    14.  
    15.     [FoldoutGroup("Foldout", "Name")]
    16.     public int B;
    17.  
    18.     [FoldoutGroup("Foldout", "Name")]
    19.     public int C;
    20. }
    a.png

    However currently only one group is allowed per field, so if you are already using HorizontalGroup within the struct, this is properly not an option for you. But you can also achieve this behaviour with OnInspectorGUI:

    Code (CSharp):
    1.  
    2. public class MyComponent : MonoBehaviour
    3. {
    4.     public List<MyStruct> someList;
    5. }
    6.  
    7. [Serializable]
    8. public struct MyStruct
    9. {
    10.     [ShowIf("isVisible")]
    11.     public string Name;
    12.  
    13.     [ShowIf("isVisible")]
    14.     public int A;
    15.  
    16.     [ShowIf("isVisible")]
    17.     public int B;
    18.  
    19.     [ShowIf("isVisible")]
    20.     public int C;
    21.  
    22. #if UNITY_EDITOR
    23.     private bool isVisible;
    24.  
    25.     [OnInspectorGUI, PropertyOrder(int.MinValue)]
    26.     public void OnInspectorGUIBegin()
    27.     {
    28.         SirenixEditorGUI.BeginBox();
    29.         SirenixEditorGUI.BeginBoxHeader();
    30.         {
    31.             this.isVisible = SirenixEditorGUI.Foldout(this.isVisible, this.Name);
    32.         }
    33.         SirenixEditorGUI.EndBoxHeader();
    34.     }
    35.  
    36.     [OnInspectorGUI, PropertyOrder(int.MaxValue)]
    37.     public void OnInspectorGUIEnd()
    38.     {
    39.         SirenixEditorGUI.EndBox();
    40.     }
    41. #endif
    42. }
    Yup exactly! [PropertyOrder]

    Ah, sorry! The example forgot one line of code at the end of the OnGUI method:
    Code (CSharp):
    1.  
    2.     private void OnGUI()
    3.     {
    4.         ...
    5.         this.RepaintIfRequested();
    6.     }
    Not in the attributes sorry. But the tab-groups are available in the API so if you can draw them yourself you have full control over them. Here is the example from the documentation on how to use them:

    http://sirenix.net/odininspector/documentation/sirenix/utilities/editor/guitabgroup

    Code (CSharp):
    1. var tabGroup = SirenixEditorGUI.CreateAnimatedTabGroup(someKey);
    2. // Register your tabs before starting BeginGroup.
    3. var tab1 = tabGroup.RegisterTab("tab 1");
    4. var tab2 = tabGroup.RegisterTab("tab 2");
    5.  
    6. tabGroup.BeginGroup(drawToolbar: true);
    7. {
    8.     if (tab1.BeginPage())
    9.     {
    10.         // Draw GUI for the first tab page;
    11.     }
    12.     tab1.EndPage();
    13.  
    14.     if (tab2.BeginPage())
    15.     {
    16.         // Draw GUI for the second tab page;
    17.     }
    18.     tab2.EndPage();
    19. }
    20. tabGroup.EndGroup();
    21.  
    22. // Control the animation speed.
    23. tabGroup.AnimationSpeed = 0.2f;
    24.  
    25. // If true, the tab group will have the height equal to the biggest page. Otherwise the tab group will animate in height as well when changing page.
    26. tabGroup.FixedHeight = true;
    27.  
    28. // You can change page by calling:
    29. tabGroup.GoToNextPage();
    30. tabGroup.GoToPreviousPage();

    Thanks! This is fixed in the next patch which we are waiting for Unity to approve.
     
    Last edited: May 22, 2017
  26. Thordain

    Thordain

    Joined:
    May 16, 2017
    Posts:
    2
    I know at first glance the pattern I'm using here seems odd, but it's quite useful. I found myself in a scenario where I put together a fantastic layout with flyouts and tab groups, and I needed to put some custom GUI in those flyouts (which were inside tab groups). This solution lets me keep all the UnityEditor and GUI code inside my custom editor, where it belongs. I can inject whatever extra controls I need inside the nice and tidy Odin layout without having to implement it all myself, and any buttons or custom actions can execute in the context of the custom editor.

    To be fair, the custom editor in question is a multi-component map editor that's doing a lot of substantial work at edit time. If it were a few lines of code to do something trivial I'd probably just use the existing OnCustomGUI/Button attributes and use #if/#endif guards.

    That is a fantastic idea, and quite a bit cleaner. Thanks for the suggestion.
     
  27. ldlework

    ldlework

    Joined:
    Jan 22, 2014
    Posts:
    46
    Thanks that great. One thing I always get confused about is, if I'm going to just use OnGUI to do all the editor drawing myself, is there anyway to take a property or field and say "Hey Odin, draw this single field however you do normally."?
     
  28. ldlework

    ldlework

    Joined:
    Jan 22, 2014
    Posts:
    46
    Do you mind sharing some of these practices / code? I am working on a level editor myself, and as I get to the point where I need more things I can't really build it with just the attributes.
     
  29. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    You'll need to wrap that property in an object and create a PropertyTree for it and draw that. Odin's drawers does not return a value, they change members of objects directly.

    I would love to hear a bit more about what sort of level editor you are creating, and how you in an ideal world would like to use Odin. But without knowing too much about what you are creating, here is something general advice you maybe could consider:

    Maybe try doing it the other way around. Instead of trying to get Odin to write a single property then draw everything using Odin, and then if you have any exceptions where you want to draw something in a way which can't be achieved using Odin, use the HideInInspector on the fields you wish to draw yourself, and add a method with an [OnInspectorGUI] to draw your custom GUI stuff. Odin can also draw properties with the ShowInInspector attribute, so this is great if you want to draw static variables and such.

    But in general; Odin is really good at drawing objects. But if you want an advanced Editor Window, but it hasn't much to do with any object, in particular then maybe creating a PropertyTree and drawing everything using Odin is not the best option for you?

    But if you have an object instance of a Level type, I would suggest using Odin to draw it and customize it from there using attributes.
     
  30. ldlework

    ldlework

    Joined:
    Jan 22, 2014
    Posts:
    46
  31. jingray

    jingray

    Joined:
    Feb 6, 2015
    Posts:
    53
    Odin Inspector working on Editor Window. But I don't know attribute "Layout"
     
    Last edited: May 23, 2017
  32. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    Is there a way to write a custom string from a method inside a header/Title/InfoBox, like this:
    Code (CSharp):
    1. [Title("CustomMethod")]
    2. public int SomeValue;
    3.  
    4. private string CustomMethod() {
    5. return "Some custom title " + Random.value;
    6. }
     
  33. mSkull

    mSkull

    Joined:
    Apr 19, 2016
    Posts:
    11
    Hi, Froghuto

    I'm currently working on extending all attributes which contains some sort of title string, so that if you add a $ as the first character, it'll look for a member field, property or method to get a title from; otherwise it just displays the string given. Here is an example of what its going to look like:

    title.png
     
    Froghuto and bjarkeck like this.
  34. hepphep

    hepphep

    Joined:
    Feb 1, 2013
    Posts:
    24
    Hi again,

    Two questions and one note here.

    First a note. Serialization seems to have some major problems (as documentation warned that something might come up). Every now and then some of data I've configured with OdinSerialize simply disappear. I haven't been able to reproduce it with simple example / regularly. However, that happens every now and then which renders serialization related functionality unusable for now. I have a hunch that it might have something to do with building the Unity project as I started to notice those at least more often after that. Something worth to just take note that there is something fishy. Been using it in combination of SerializedScriptableObjects and SerializedMonoBehaviours.

    And the question. When using AssetList for asset selection, for some reason it seems to go through whole project structure. In our case going through something like 1.7k objects, before filtering to the right folder which only has 15 items. It correctly shows only those items to pick then, but the phase where it iterates all of those through slows down things when going through items to modify

    upload_2017-5-24_13-18-27.png

    I use following set of tags for that field.

    Code (CSharp):
    1.         [SerializeField]
    2.         [AssetsOnly]
    3.         [Required]
    4.         [AssetList(Path = "/GameWorld/Items/Weapons")]
    5.         [InlineEditor(InlineEditorModes.LargePreview)]
    6.         private GameObject _prefab;
    7.  
    Is there something that I could / should do differently to not scan whole structure but immediately focus only to given path?

    I'd also love to take advantage of selecting implementing class on inspector based on interface, but that is most likely something I cannot do by any means now that Odin serialization cannot be used (even though there could be possibility that I could use serialization only for that, because did not issues with this and serialization)?
     
  35. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    I've just implemented a fix to this so it only scans for objects within the folder you've specified.


    I'm not entirely sure what you mean by this. But if your'e using your own serialization and want to show it in the inspector and be able to create instances of types that implements an interface etc.. You could just add the [ShowInInspector] attribute. Not sure if this answers your question though.

    Auch. Sad that you where not able to reproduce the error. If you could show us the class in which the values disappeared, we could spend some time trying to trigger the problem. Also what platform are you building to?
     
  36. Reddevildragg

    Reddevildragg

    Joined:
    May 19, 2014
    Posts:
    50
    Quick Question
    Is there a way to draw unity custom handles and still keep the Odin inspector working as in order to draw the handles i need to inherent from Editor which intern stops Odin editor from being drawn? Had a quick look through the prop draws for a handle one but could not find anything. Any help would be great :)

    Edit:
    Ok, i found Sirenix.OdinInspector.Editor.OdinEditor which i can extend from and then draw the handles in onSceneGui. This seemed to have worked for anyone looking to do a similar thing
     
    Last edited: May 24, 2017
    Froghuto likes this.
  37. SuneT

    SuneT

    Joined:
    Feb 29, 2016
    Posts:
    41
    A huge update just went live yesterday, by the way!
    Thanks a bunch for all the bug reports and feature requests - keep 'em coming :)

    Version 1.0.1.5:
    Fixes

    • OnValidate is now properly invoked when values that are drawn by Odin are changed.
    • Fixed case where adding [AssemblyVersion] with rolling (IE, constantly changing) version numbers would cause Odin to constantly regenerate editors, and also cause Odin to be unable to draw. Versioning is now ignored when resolving Unity user-assemblies generated from project scripts, when in Unity's primary loaded AppDomain.
    • Editor generation is now far more robust. Type name collisions will no longer occur, as it now makes use of extern aliases to compile editors for types with the same full names (though Unity does not seem to be able to handle this properly). Additionally, it now correctly refuses to generate editors for types with names that are reserved keywords (such as "switch" or "class"), and gives proper warning messages when this case occurs.
    • Unity property drawers now show up be default, as CompositeDrawer's priority is no longer (0, 0, 1), above the default Unity property drawer priority, (0, 0, 0.5), but (0, 0, 0) as it should be.
    • Fixed issue where Odin wouldn't handle the case when a type is drawn because it is derived from a class that draws an inherited type and its child classes. This caused Odin to generate editors for types where it normally shouldn't.
    • Fixed case where prefab list length modifications couldn't be applied to lists (not arrays) with an element type that is a value type.
    • Members decorated with [OdinSerialize] that would also be serialized by Unity, are now properly caught by Odin's property system as backed by Odin serialization. This fixes an issue where enum values would be reset to their default values when prefab values were applied.
    • Fixed issue with mixed values for some struct types when multi-selecting.
    • Fixed case where Odin scanning for custom editors would trigger a Unity error message: "Failed to load CustomEditor inspected type".
    • About window should now work again in all Unity versions.
    • Editor generation code should now be put into the proper Temp path on Unix-based systems, instead of a folder outside on the same level as the project root.
    • Fixed a bug where some editor icons would disappear after a scene load.
    • Fixed rare case where Odin-drawn Unity references would sometimes be set to null after a scene load.
    • Fixed a bug where some GUIStyles was initialized outside of the Unity GUI thread. This happened in some cases in newer unity versions when clicking on an Odin reference object picker.
    • Matrix4x4's 16 field properties now all always work in the inspector whether the Matrix4x4 is represented in a SerializedObject or not.
    • Odin can now properly compile 0 editors when there are no editors to compile, without any compiler errors.
    • Fixed case where editor types tree view would not display child conflicts correctly.
    • Polymorphism is no longer supported by property entries backed by Unity serialization; they will now always be the base type of the field, regardless of the type of the actual value being represented.
    • Vectors now shows the mixed value indicator for each component individually.
    • Odin now correctly guesses that Unity will serialize non-generic custom UnityEventBase-derived classes.
    • Odin now correctly draws custom Unity events in the inspector.
    • Added a parameterless constructor to the [HorizontalGroup] attribute.
    • Fixed an issue where backslash was used instead of forward slash in specific file paths, which resulted in some files being stored in the the wrong places on mac.
    • Added option in the Editor Type preferences window to enable editor generation logging, which provides information as to why a recompilation has happened.
    • Boxed value types can now be set to null in the inspector using the right-click context menu.
    Changes
    • Overhauled the MinMaxSlider completely.
    • Downgraded "unexpected entry when expecting a node entry" serialization error to a warning.
    • Odin will now never recompile editors when in play mode.
    • Changes were made to InspectorUtilities to make selective property drawing more convenient.
    • BoxGroupAttribute now have a parameterless constructor in cases where you want a bug without a title.
    • If a SerializedObject is not provided for a property tree targeting a type derived from UnityEngine.Object, a SerializedObject instance for those targets will now be created for the property tree when using any of the PropertyTree.Create overloads.
    • Tweaked the serialization warning text to remove formatting tags.
    • OdinEditor,OnInspectorGUI no longer waits until it has seen its first layout call to start drawing. The onus is now on the creator of the editor instance to ensure that the layout stack is valid and GUI calls come in the right order.
    • Vector and rect fields elements are now treated as seperate properties, and can therefore be mixed individually. All SirenixEditorGUI popup and dropdown methods have been marked as obsolete. Use SirenixEditorFields.Dropdown methods instead.
    Added
    • Added option for duration and to disable shake animations.
    • Added two new attributes (EnableForPrefabOnly and ShowForPrefabOnly) which can be used to hide or disable properties on instances of prefabs.
    • Added inline Rect extension SetSize.
    • Added methods for drawing MinMaxSlider to SirenixEditorFields.
    • Ctrl-clicking the add button on lists and arrays of UnityEngine.Object types now adds a null value without prompting the user with the unity object-picker window.

    Upgrade Notes
    • Import new package
    • Delete Sirenix/Assemblies/Editor/GeneratedOdinEditors.dll after upgrading, which will cause it to regenerate an updated version of itself if you have this behaviour enabled. The old .dll may cause a multitude of Mono.Cecil type lookup errors to be generated in the console. (These messages are harmless, but annoying.)
     
  38. bwheatley

    bwheatley

    Joined:
    Jun 23, 2012
    Posts:
    45
    How would you create a vertical scrollbar?
    I thought it would be
    SirenixEditorGUI.BeginVerticalList()

    but that doesn't seem to give me the scrollbar i'd get with the standard unity
    scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUI.skin.horizontalScrollbar,
    GUI.skin.verticalScrollbar, GUILayout.Width(150), GUILayout.Height(250));
     
  39. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Hi. Odin seems excellent so far, however it's broken a custom property drawer that I've been using for a while. The class is designed to allow for scene files to be dropped into an inspector field. Here's the code:

    Code (CSharp):
    1. using UnityEngine;
    2. #if UNITY_EDITOR
    3. using UnityEditor;
    4. #endif
    5.  
    6. [System.Serializable]
    7. public class SceneField
    8. {
    9.     [SerializeField]
    10.     private Object m_SceneAsset;
    11.     [SerializeField]
    12.     private string m_SceneName = "";
    13.     public string SceneName
    14.     {
    15.         get { return m_SceneName; }
    16.     }
    17.     // makes it work with the existing Unity methods (LoadLevel/LoadScene)
    18.     public static implicit operator string( SceneField sceneField )
    19.     {
    20.         return sceneField.SceneName;
    21.     }
    22.     public SceneField(string name)
    23.     {
    24.         m_SceneName = name;
    25.     }
    26. }
    27.  
    28. #if UNITY_EDITOR
    29. [CustomPropertyDrawer(typeof(SceneField))]
    30. public class SceneFieldPropertyDrawer : PropertyDrawer
    31. {
    32.     public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
    33.     {
    34.         EditorGUI.BeginProperty(_position, GUIContent.none, _property);
    35.         SerializedProperty sceneAsset = _property.FindPropertyRelative("m_SceneAsset");
    36.         SerializedProperty sceneName = _property.FindPropertyRelative("m_SceneName");
    37.         _position = EditorGUI.PrefixLabel(_position, GUIUtility.GetControlID(FocusType.Passive), _label);
    38.         if (sceneAsset != null)
    39.         {
    40.             EditorGUI.BeginChangeCheck();
    41.  
    42.             Object value = EditorGUI.ObjectField(_position, sceneAsset.objectReferenceValue, typeof(SceneAsset), false);
    43.             if (EditorGUI.EndChangeCheck() )
    44.             {
    45.                 sceneAsset.objectReferenceValue = value;
    46.                 if (sceneAsset.objectReferenceValue != null)
    47.                 {
    48.                     sceneName.stringValue = (sceneAsset.objectReferenceValue as SceneAsset).name;
    49.                 }
    50.             }
    51.         }
    52.         EditorGUI.EndProperty( );
    53.     }
    54. }
    55. #endif
    After installing Odin instead of a field that only accepts scene assets, it's just an object field and string field. I really like this custom property and I've used it in several of my scripts. How do I get it to work with Odin?
     
  40. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    We don't have any custom scrollbars. We also use Unity's EditorGUILayout.BeginScrollView(). The SirenixEditorGUI.BeginVerticalList() simply helps styling list item elements. Coloring every second row a bit different, etc. Are you trying to create a VerticalScrollGroup attribute by any chance :D ?

    Are you using the Unity 2017 beta version? Unity introduced a bug in the beta version which forced us to disable parts of Odin in order to get it running. The feature in question is drawing custom Unity Property Drawers for data which is not serialized by Unity. If a property drawer seems to have no effect in 2017.1, it is likely because it was implemented by a custom Unity Property Drawer and the data is not being serialized by Unity.

    Example:

    Code (CSharp):
    1. public class MyComponent : SerializedMonoBehaviour
    2. {
    3.     public SceneField WorksIn2017; // Serialized By Unity
    4.     public OdinSerializedType OdinSerializedType; // Serialized By Odin
    5. }
    6.  
    7. public class OdinSerializedType // No System.Serializable attribute, So Unity will not serialize it, but Odin will.
    8. {
    9.     public SceneField WillNotCurrentlyWorkIn2017; // For now..
    10. }
    Luckily they've fixed the error in 2017.1.0b7. So we will enable the feature again in a future patch.

    But for now you will need to create the drawer using Odin instead:

    Code (CSharp):
    1. [System.Serializable]
    2. public class SceneField
    3. {
    4.     [SerializeField]
    5.     private Object m_SceneAsset;
    6.  
    7.     [SerializeField, HideInInspector]
    8.     private string m_SceneName = "";
    9.  
    10.     public string SceneName
    11.     {
    12.         get { return m_SceneName; }
    13.     }
    14.  
    15.     // makes it work with the existing Unity methods (LoadLevel/LoadScene)
    16.     public static implicit operator string(SceneField sceneField)
    17.     {
    18.         return sceneField.SceneName;
    19.     }
    20.  
    21.     public SceneField(string name)
    22.     {
    23.         m_SceneName = name;
    24.     }
    25.  
    26.  
    27. #if UNITY_EDITOR
    28.  
    29.     [OdinDrawer]
    30.     [DrawerPriority(0,0, 3000)] // Override the nullable reference drawer, as this one handles null. Checkout http://sirenix.net/odininspector/documentation/sirenix/odininspector/showdrawerchainattribute
    31.     public class SceneFieldPropertyDrawer : OdinValueDrawer<SceneField>
    32.     {
    33.         protected override void DrawPropertyLayout(IPropertyValueEntry<SceneField> entry, GUIContent label)
    34.         {
    35.             var val = entry.SmartValue ?? (entry.SmartValue = new SceneField(null));
    36.             val.m_SceneAsset = SirenixEditorGUI.ObjectField(label, val.m_SceneAsset, typeof(SceneAsset), false);
    37.             var sceneAsset = val.m_SceneAsset as SceneAsset;
    38.             val.m_SceneName = sceneAsset == null ? null : sceneAsset.name;
    39.  
    40.         }
    41.     }
    42. #endif
    43.  
    44. }
    45.  
    Hope this is the problem you are having, otherwise we will need to investigate a bit more.
     
    Last edited: May 29, 2017
  41. apprenticegc

    apprenticegc

    Joined:
    Apr 21, 2012
    Posts:
    25
    Although this might not be a common use case, I am just wondering when Odin Inspector will support for MonoBehaviour derivatives which also realize some interfaces. I do aware that currently using non-MonoBehaviour interface realization is supported, but there are times when direct drag and drop those sub classes of MonoBehaviour which also realize interfaces into inspector is indeed very handy.

    I bought Odin Inspector about a week ago to replace Full Inspector(sine it is not updated for quite some time, I am worried it will be discontinued soon). But then, I found out this missing feature makes me go back to the old workaround, storing GameObject and explicitly get interfaces by GetComponent. It works but I feel it is suboptimal. Especially after I purchase Odin Inspector, I think it should do the job naturally.

    I understand there will be priorities when developing new feature of Odin Inspector, but hopefully, this feature will be added soon. Thanks.
     
  42. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    This is definitely one of our bigger priorities!

    In our next patch, you will be able to drag and drop scriptableObjects, gameObjects etc.. into interface fields. It will then locate the components containing the interface and assign that.

    We are also working on a universal object picker as we speak, which handles assets, instances, scene objects and everything. It will also handle constructors, generic types and stuff like that. But that is probably a few patches away still though.

    But for now you could do something like this as a temporary solution:
    Code (CSharp):
    1.  
    2. public class MyComponent : MonoBehaviour, IMyInterface
    3. {
    4.     [SerializeField]
    5.     [RequireInterface(typeof(IMyInterface))]
    6.     private UnityEngine.Object obj;
    7.  
    8.     public IMyInterface Obj
    9.     {
    10.         get { return this.obj as IMyInterface; }
    11.     }
    12. }
    13.  
    14. public interface IMyInterface
    15. {
    16. }
    Code (CSharp):
    1.  
    2. public class RequireInterfaceAttribute : Attribute
    3. {
    4.     public readonly Type InterfaceType;
    5.  
    6.     public RequireInterfaceAttribute(Type interfaceType)
    7.     {
    8.         this.InterfaceType = interfaceType;
    9.     }
    10. }
    11.  
    12. [OdinDrawer]
    13. [DrawerPriority(DrawerPriorityLevel.WrapperPriority)]
    14. public class RequireInterfaceAttributeDrawer : OdinAttributeDrawer<RequireInterfaceAttribute, UnityEngine.Object>
    15. {
    16.     protected override void DrawPropertyLayout(IPropertyValueEntry<UnityEngine.Object> entry, RequireInterfaceAttribute attribute, GUIContent label)
    17.     {
    18.         var value = entry.SmartValue;
    19.  
    20.         if (value != null && !value.GetType().ImplementsOrInherits(attribute.InterfaceType))
    21.         {
    22.             SirenixEditorGUI.ErrorMessageBox(value.name + " does not implement the required interface: " + attribute.InterfaceType.GetNiceName());
    23.         }
    24.  
    25.         this.CallNextDrawer(entry, label);
    26.  
    27.         var go = value as GameObject;
    28.         if (go != null)
    29.         {
    30.             value = go.GetComponentsInChildren<MonoBehaviour>()
    31.                 .FirstOrDefault(x => x.GetType().ImplementsOrInherits(attribute.InterfaceType));
    32.  
    33.             if (value != null)
    34.             {
    35.                 entry.SmartValue = value;
    36.             }
    37.         }
    38.     }
    39. }
    Hope this will be good enough for you until then!
     
    Last edited: May 31, 2017
  43. bwheatley

    bwheatley

    Joined:
    Jun 23, 2012
    Posts:
    45
    Thanks for taking the time to answer, I appreciate it! I got side tracked and just wound up writing my own typical view but leverages the odin gui stuff to make it look nice, and built my own tabs. :)

    I ended up doing this
    Code (CSharp):
    1. private void OnGUI() {
    2.  
    3.         if (tree == null) {
    4.             tree = PropertyTree.Create(this);
    5.         }
    6.  
    7.         scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUI.skin.horizontalScrollbar,
    8.             GUI.skin.verticalScrollbar, GUILayout.Height(tabHeight));
    9.         //tree.Draw(true);
    10.  
    11.         var tabGroup = SirenixEditorGUI.CreateAnimatedTabGroup(tabKey);
    12.  
    13.         //Register tabs before the starting BeginGroup
    14.         var regimeTab = tabGroup.RegisterTab("Regimes");
    15.         var counterTab = tabGroup.RegisterTab(counterTabName);
    16.  
    17.         //Can we embed a tabgroup inside of a foldout
    18.         sectionOneVisual = SirenixEditorGUI.Foldout(sectionOneVisual, "Add Units");
    19.         if (sectionOneVisual) {
    20.             SirenixEditorGUI.BeginBox();
    21.             //SirenixEditorGUI.BeginBoxHeader();
    22.  
    23.             tabGroup.BeginGroup(drawToolbar: true);
    24.             {
    25.                 if (regimeTab.BeginPage()) {
    26.                     ShowRegimeTab();
    27.                 }
    28.                 regimeTab.EndPage();
    29.  
    30.                 if (counterTab.BeginPage()) {
    31.                     ShowCounters();
    32.                 }
    33.                 counterTab.EndPage();
    34.  
    35.  
    36.             }
    37.             tabGroup.EndGroup();
    38.             //SirenixEditorGUI.EndBoxHeader();
    39.  
    40.             SirenixEditorGUI.EndBox();
    41.         }
    42.  
    43.         sectionTwoVisual = SirenixEditorGUI.Foldout(sectionTwoVisual, "Reset");
    44.         if (sectionTwoVisual) {
    45.             SirenixEditorGUI.BeginBox();
    46.  
    47.             if (GUILayout.Button("Reset Tab")) {
    48.                 OnDisable();
    49.                 OnEnable();
    50.                 unitfoldOut.Clear();
    51.             }
    52.  
    53.  
    54.             SirenixEditorGUI.EndBox();
    55.         }
    56.  
    57.  
    58.         sectionThreeVisual = SirenixEditorGUI.Foldout(sectionThreeVisual, "Misc");
    59.         if (sectionThreeVisual) {
    60.             SirenixEditorGUI.BeginBox();
    61.  
    62.             if (GUILayout.Button("Clean RegimeList")) {
    63.                 gameManager.CleanUp();
    64.             }
    65.            
    66.             SirenixEditorGUI.EndBox();
    67.         }
    68.  
    69.  
    70.         //Will draw
    71.         //SirenixEditorGUI.BeginVerticalList();
    72.         //SirenixEditorGUI.ToolbarToggle(true, "Test1");
    73.         //SirenixEditorGUI.ToolbarToggle(true, "Test2");
    74.         //SirenixEditorGUI.ToolbarToggle(true, "Test3");
    75.         //var scrollBox = SirenixEditorGUI.BeginVerticalList(true);
    76.         //SirenixEditorGUI.EndVerticalList();
    77.  
    78.         EditorGUILayout.EndScrollView();
    79.  
    80.     }
     
    bjarkeck likes this.
  44. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Thanks for the reply. I'm using 5.6.0f3. Does the bug effect this version as well? It's also broken some of my other editor scripts.

    Thanks for taking the time to modify that code. It works, though I had to expose the SceneField private fields...
     
  45. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Ah I updated Odin and that seems to have fixed the problems, sorry about that!!
     
  46. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Nice! Would love to see a screenshot :D

    Aha, perfect then!
     
  47. bwheatley

    bwheatley

    Joined:
    Jun 23, 2012
    Posts:
    45
    Since you asked
    http://imgur.com/a/bU5rZ
     
    bjarkeck likes this.
  48. Owlglass_Moot

    Owlglass_Moot

    Joined:
    Jan 4, 2015
    Posts:
    9
    Just a follow up to this post (because I've now run into the opposite problem, haha): Is there any plan on expanding [LabelText], [BoxGroup], etc. to support member referencing like [FoldoutGroup] does?

    I know I can use [OdinSerialize], but I'm trying to avoid it as per the warning at the end of the documentation.
     
  49. bjarkeck

    bjarkeck

    Joined:
    Oct 26, 2014
    Posts:
    301
    Awesome, thanks a lot!

    Yup! And it will be there in the next patch, here is a small teaser:

    a.png

    This currently works for [InfoBox] [LabelText], [ValidateInput], [BoxGroup], [ToggleGroup], [FoldoutGroup], [Title], [Header], [Button], [Tooltip], [Required] and a couple of new attributes we'll be introducing.
     
    Last edited: Jun 4, 2017
  50. Owlglass_Moot

    Owlglass_Moot

    Joined:
    Jan 4, 2015
    Posts:
    9
    Sweet! Thanks.

    Another quick question about [FoldoutGroup]: In "Unity Preferences > Odin Preferences > General" I have "Expand Foldout by Default" selected, but all my foldouts (at least in custom scripts) are closed by default. And if I have a FoldoutGroup open, deselect the object in the hierarchy and then re-select it, the FoldoutGroup is closed again.

    Is there a way to force [FoldoutGroup] to expand by default beyond ticking the box in Odin Preferences? Or at least force it to "remember" what state I left it in so it doesn't reset every time it's deselected?