FoldoutGroup attribute does not work when placed on a class

Issue #408 open
Former user created an issue
  1. I placed the [FoldoutGroup("Things")] attribute on a class, and I expected references to those classes in my SerializedMonoBehaviours to all be within the "Things" foldout group, but they were not. The same issue occurs for BoxGroups, so I'm assuming it occurs for all group attributes.

  2. Add the following script to your project in a file called ThingTest.cs:
    using System;
    using Sirenix.OdinInspector;

public class ThingTest : SerializedMonoBehaviour
{
public Thing one;
public Thing two;
public Thing three;

[FoldoutGroup("More Things")]
public Thing four;
[FoldoutGroup("More Things")]
public Thing five;
[FoldoutGroup("More Things")]
public Thing six;

}

[FoldoutGroup("Things"), Serializable]
public class Thing
{
public int a;
}

Add the ThingTest Component to an empty game object, and note that Things one, two, and three are not grouped properly like four, five, and six are.

  1. 2017.3.1f1
  2. 2.0.1
  3. No
  4. Windows 10 Home

Comments (4)

  1. Dominic Antonelli
    using System;
    using Sirenix.OdinInspector;
    
    public class ThingTest : SerializedMonoBehaviour
    {
        public Thing one;
        public Thing two;
        public Thing three;
    
        [FoldoutGroup("More Things")]
        public Thing four;
        [FoldoutGroup("More Things")]
        public Thing five;
        [FoldoutGroup("More Things")]
        public Thing six;
    }
    
    [BoxGroup("Things"), Serializable]
    public class Thing
    {
        public int a;
    }
    
  2. Bjarke Elias Clauson-Kaas ├śrrild
    • changed status to open

    Thanks!

    It's something we've discussed internally before, and decided not to add support for by default for now.

    It has weird cases related to polymorphism - If a user changes the value of a unity object field, and say that type has a TabGroup attribute, then we would first have to to rebuild part of the property tree, and furthermore, as soon as he assings the value, it would potentially disapear because it would suddenly become hidden in some group.

    We could perhaps enable it by only looking at the return type of the given member, and search for group attributes there.

    You can try this behaviour out by adding the following snippet to your code:

        [ResolverPriority(1000)]
        public class TypeDefinitionGroupAttributeProcessor : OdinAttributeProcessor
        {
            public override bool CanProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member)
            {
                return member.GetReturnType() != null;
            }
    
            public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List<Attribute> attributes)
            {
                var current = member.GetReturnType();
    
                while (ContinueAddingAttributesFor(current))
                {
                    attributes.AddRange(current.GetAttributes().Where(x => x is PropertyGroupAttribute));
                    current = current.BaseType;
                }
            }
    
            private static bool ContinueAddingAttributesFor(Type type)
            {
                if (type == null) return false;
                var flag = AssemblyUtilities.GetAssemblyTypeFlag(type.Assembly);
                if (flag == AssemblyTypeFlags.OtherTypes) return false;
                if (flag == AssemblyTypeFlags.UnityTypes) return false;
                return true;
            }
        }
    
  3. Dominic Antonelli

    When you say "return type", are you saying that you'd only look at attributes on the class that was declared for the variable, not the actual subclass of the actual instance that was placed there? So, in my example, you would only look at the "Thing" type, not the subclass of Thing that we actually instatiated to put there?

    And is that was this snippet does?

  4. Log in to comment