Closed ACCIAI0 closed 3 months ago
Hi,
according to the screenshot, you seems are using IMGUI instead of UI Toolkit.
For SaintsField
, only UI Toolkit can fallback to a CustomPropertyDrawer
of a data type.
IMGUI has some limitation. I tried once but failed. If you have some good suggestion about IMGUI please share.
So, as an example, this is the code:
Source.cs
[Serializable]
public struct Source
{
[SerializeField] private string[] serializedEntries;
}
SourceDrawer.cs
using UnityEditor;
using UnityEngine;
#if UNITY_2021_3_OR_NEWER
using UnityEngine.UIElements;
using UnityEditor.UIElements;
#endif
[CustomPropertyDrawer(typeof(Source))]
public class SourceDrawer : PropertyDrawer
{
#region IMGUI
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
return EditorGUI.GetPropertyHeight(arrProperty, label, true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
EditorGUI.PropertyField(position, arrProperty, label, true);
}
#endregion
#if UNITY_2021_3_OR_NEWER
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
return new PropertyField(arrProperty, property.displayName);
}
#endif
}
SourceExample.cs
public class SourceExample : MonoBehaviour
{
public Source normal;
[ShowIf, InfoBox("Type CustomDrawer fallback only works on UI Toolkit", above: true)] public Source withIf;
}
Then, in IMGUI it won't use the custom drawer:
But UI Toolkit works fine:
In short:
data type
to a decorator type
, which you need to define a PropertyAttribute
, the write drawer for that attributeEdit:
I did write it in change log but forget in document... will update the document soon.
2.4.2
Since this version, UI Toolkit now can property fallback to
CustomPropertyDrawer
of a custom type (previously it only supports to fallback to customPropertyAttribute
drawer).Note: this feature is only for UI Toolkit. IMGUI does not support this feature.
Note: combining with
RichLabel
, UI Toolkit will find the firstunity-label
class label which in some case might not be correct. This feature can not be turned off yet. Please report issue if you face any problem.
... Wait... I sort of having some idea...
@TylerTemp The fact is I AM using UIElements. the only difference between my code and your example is that the custom editor is technically assigned to the abstract parent type of the one I serialize in my screenshot, with editorOfChildClasses = true
@ACCIAI0 Do you mean:
[Serializable]
public abstract class SuperSource
{
}
[Serializable]
public class Source: SuperSource
{
[SerializeField] private string[] serializedEntries;
}
// public Source normal;
[HideIf(nameof(toggle)), InfoBox("Type CustomDrawer fallback", above: true)] public Source withIf;
with drawer:
[CustomPropertyDrawer(typeof(ImGuiFallback.SuperSource))] // super class of the data
public class SourceDrawer : PropertyDrawer
{
#region IMGUI
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
return EditorGUI.GetPropertyHeight(arrProperty, label, true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
EditorGUI.PropertyField(position, arrProperty, label, true);
}
#endregion
#if UNITY_2021_3_OR_NEWER
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
SerializedProperty arrProperty = property.FindPropertyRelative("serializedEntries");
return new PropertyField(arrProperty, property.displayName);
}
#endif
}
I still can not re-produce it on Unity 2022.2.0f1, 2021.3.0f1 under UI Toolkit. Please share more information, like your Unity version, and a simple drawer that has this issue
I'm using it in Unity 2022.3.20f1, but I'm unsure if it makes any difference. The bare-bones skeleton of my code is as follows:
[Serializable]
public class Container<T1, T2>
{
[Serializable]
protected sealed class Entry
{
public T1 Name;
public T2 Object;
}
[SerializeField]
protected List<Entry> Entries;
}
[Serializable]
public sealed class ContainerChild<T> : Container<string, T>
{
public T GetByName(string name)
{
var entry = Entries.Find(e => e.Name == name);
return entry == default ? default : entry.Object;
}
}
while the property drawer is as follows:
[CustomPropertyDrawer(typeof(Container<,>), true)]
public sealed class ContainerDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var entries = property.FindPropertyRelative("Entries");
var listView = new ListView
{
headerTitle = property.displayName,
showBorder = true,
showFoldoutHeader = true,
showAddRemoveFooter = true,
showAlternatingRowBackgrounds = AlternatingRowBackground.All,
virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
showBoundCollectionSize = true,
makeItem = MakeItem,
bindItem = BindItem
};
listView.BindProperty(entries);
return listView;
VisualElement MakeItem()
{
var element = new VisualElement();
var name = new TextField("Name") { name = "Name" };
var obj = new PropertyField { label = "Object", name = "Object" };
name.AddToClassList(BaseField<object>.alignedFieldUssClassName);
element.Add(name);
element.Add(obj);
return element;
}
void BindItem(VisualElement element, int index)
{
var name = element.Q<TextField>("Name");
var obj = element.Q<PropertyField>("Object");
var item = entries.GetArrayElementAtIndex(index);
name.BindProperty(item.FindPropertyRelative("Name"));
obj.BindProperty(item.FindPropertyRelative("Object"));
}
}
}
Using this exact code it works, but the original code affected by this bug still doesn't. I'll investigate further and let you know if I find something.
NOTE: The property drawer is technically wrong, as it works only for that single subclass I made, but for the sake of the example it doesn't matter
Bug confirmed
Hi @ACCIAI0
Please check if it's fixed in 3.0.6
given the code you provide with:
[Serializable]
public class GameObjectChild : ContainerChild<GameObject>
{
}
public bool toggle;
public GameObjectChild normal;
[HideIf(nameof(toggle)), InfoBox("Inherent Fallback", above: true)] public GameObjectChild inherent;
[HideIf(nameof(toggle)), InfoBox("Direct Fallback", above: true)] public ContainerChild<GameObject> direct;
gives:
This issue is closed cuz it's fixed.
If you still have a problem with this issue, please comment here and I'll open this issue again.
Sorry, I had a lot of stuff to do and this slipped my mind. I tried it out and can confirm it works like a charm. Nice job, your speed at addressing issues make this library very valuable to me!
If I use either
ShowIf
orHideIf
attribute on a field or property with a Type with a custom property drawer, that field is rendered in the inspector with a default PropertyField instead of using the custom drawer. For Example:This is how it looks like with the
HideIf
attribute,This is how it should be using the custom drawer (it only shows the internal list of entries)