NaughtyAttributes
NaughtyAttributes copied to clipboard
[Issue] ShowIf / EnableIf does not work with Arrays or Lists in nested classes
[ShowIf("ShowIfTest")]
public int[] test;
public bool ShowIfTest => false;
Here is the code I used to test it, no nesting.
It should be hidden, but no matter what, it will always show. Tried with List
as well.
I tried to search around current and past issues, but nothing came up on this issue. Is there any workaround for this issue, or did I miss the proper way to do this?
Thank you for all your work!
It works on my end mate. Can you try it on an empty project? It should work. Probably some other editor script is overriding NaughtyAtribute's inspector.
Hello! Thank you for the quick response :)
I'm trying this now (which is closer to my own use-case), and I'm failing to see what I could be doing wrong here, or how something is overriding NaughtyAtribute's inspector... any tips on what to look for that could be overriding this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using NaughtyAttributes;
public enum TestEnum
{
One,
Two
}
[System.Serializable]
public class TestClass
{
public TestEnum enumValue;
[ShowIf("ShowIfOne")]
[AllowNesting]
public int[] one;
[ShowIf("ShowIfTwo")]
[AllowNesting]
public int[] two;
public bool ShowIfOne => enumValue == TestEnum.One;
public bool ShowIfTwo => enumValue == TestEnum.Two;
}
public class testsomething : MonoBehaviour
{
public TestClass reactiveAction;
}
This is indeed a bug. If not nested it works fine, but when nested inside a subclass it doesn't work. I will fix it mate, thank you very much.
The strangest thing is that it doesn't work for lists and array. Everything else works.
public class _NaughtyComponent : MonoBehaviour
{
public NumEnum enumValue;
[ShowIf("ShowIfOne")]
public int[] one;
[ShowIf("ShowIfTwo")]
public int[] two;
public bool ShowIfOne => enumValue == NumEnum.One;
public bool ShowIfTwo => enumValue == NumEnum.Two;
}
Interesting! Thank you so much for looking into it :)
I understood why it's now working. Look at this example.
public class _NaughtyComponent : MonoBehaviour
{
public MyClass nest;
}
[System.Serializable]
public class MyClass
{
[ReadOnly]
public int[] one;
[ReadOnly]
public int[] two;
}
Even though I've marked the arrays with [ReadOnly]
the property drawer is applied to each element of the arrays, not the arrays themselves. This is how Unity applies CustomPropertyDrawers
to lists/arrays. This is what happens with the [AllowNesting]
attribute. [AllowNesting]
is a normal drawer, it just triggers the meta attributes' behaviors (like [ShowIf]
for instance). The problem is that NaughtyAttributes triggers the behaviors before the actual drawer is called. The drawer can't handle the visibility itself, because the parent property is already drawn. I can make it handle the visibility itself, but the result will be just like the [ReadOnly]
attribute. The array will be visible, only the child elements will not.
The reason why the [ShowIf]
works for not nested arrays is that I can get the array and say to Unity - "draw the property and its children". Before I draw the property and its children, I check if it is visible. If it's not I don't draw it at all.
I can't think of a way to fix it :(
I'm not very sure either how to fix it :(
I guess for now, if you ever find some sort of workaround, let me know!! Would be very useful to have! Thank you so much for investigating the issue however, I really appreciate it :)
Hi, I don't know exactly how it's implemented in Naughty, but until this is fixed, here's a temporary fix we used on our end - a drawer for @jurcaua's TestClass:
using NaughtyAttributes.Editor;
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(TestClass))]
public class TestClassDrawer : PropertyDrawer {
public override void OnGUI(Rect _, SerializedProperty property, GUIContent __) {
var childDepth = property.depth + 1;
EditorGUILayout.PropertyField(property, includeChildren: false);
if (!property.isExpanded) {
return;
}
EditorGUI.indentLevel++;
foreach (SerializedProperty child in property) {
if (child.depth == childDepth && PropertyUtility.IsVisible(child)) {
EditorGUILayout.PropertyField(child);
}
}
EditorGUI.indentLevel--;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
return EditorGUI.GetPropertyHeight(property, label, includeChildren: false)
- EditorGUIUtility.singleLineHeight - EditorGUIUtility.standardVerticalSpacing;
}
}
This is the code I used for our task, so it might have some extra lines, but it worked without any modifications for TestClass too ;)
Hi, I don't know exactly how it's implemented in Naughty, but until this is fixed, here's a temporary fix we used on our end - a drawer for @jurcaua's TestClass:
using NaughtyAttributes.Editor; using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(TestClass))] public class TestClassDrawer : PropertyDrawer { public override void OnGUI(Rect _, SerializedProperty property, GUIContent __) { var childDepth = property.depth + 1; EditorGUILayout.PropertyField(property, includeChildren: false); if (!property.isExpanded) { return; } EditorGUI.indentLevel++; foreach (SerializedProperty child in property) { if (child.depth == childDepth && PropertyUtility.IsVisible(child)) { EditorGUILayout.PropertyField(child); } } EditorGUI.indentLevel--; } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return EditorGUI.GetPropertyHeight(property, label, includeChildren: false) - 20; } }
This is the code I used for our task, so it might have some extra lines, but it worked without any modifications for TestClass too ;)
Thanks, I'll look into it
@dbrizov was this fixed? I'm still experiencing the same issue in v2.1.4
My solution for this was to create a NestedArray<T>
class with an Array/List inside. It's a bit unwieldy (adds an extra layer of depth to the inspector hierarchy) but at least I can Show/Hide collections.
[System.Serializable]
public class NestedArray<T>
{
public T[] Array;
}
My solution for this was to create a
NestedArray<T>
class with an Array/List inside. It's a bit unwieldy (adds an extra layer of depth to the inspector hierarchy) but at least I can Show/Hide collections.[System.Serializable] public class NestedArray<T> { public T[] Array; }
ye! i make HideNestedArrayAttribute
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// ____DESC:
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = true)]
public class HideNestedArrayAttribute : PropertyAttribute
{
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(HideNestedArrayAttribute))]
public class HideNestedArrayDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var array = property.FindPropertyRelative("Array");
EditorGUI.PropertyField(position, array, new GUIContent(property.displayName));
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var array = property.FindPropertyRelative("Array");
// These numbers are tried out. I don't know how to get it.
if (array.isExpanded)
{
return 70 + Mathf.Clamp((array.arraySize-1) * 20, 0, float.MaxValue);
}
else
return 20;
}
}
#endif
public class NewMonoBehaviour : MonoBehaviour
{
public bool useIds;
[HideNestedArray, ShowIf("useIds")]
public NestedArray<int> ids;
public TestArray testArray ;
[System.Serializable]
public class TestArray
{
public bool useIds;
[ShowIf("useIds"), AllowNesting, HideNestedArray]
public NestedArray<int> ids;
}
}