using System; using Alchemy.Inspector; using UnityEditor; using UnityEditor.UIElements; using UnityEngine.UIElements; namespace Alchemy.Editor.Elements { /// /// Visual Element that draws properties based on Alchemy attributes /// public sealed class AlchemyPropertyField : BindableElement { public AlchemyPropertyField(SerializedProperty property, Type type, bool isArrayElement = false) { var labelText = ObjectNames.NicifyVariableName(property.displayName); switch (property.propertyType) { // NOTE: RectOffset is a generic property type, but it doesn't have a SerializeField. Instead, use PropertyField. case SerializedPropertyType.Generic when property.type == "RectOffset": default: element = new PropertyField(property); break; case SerializedPropertyType.ObjectReference: if (property.GetAttribute() != null) { element = new InlineEditorObjectField(property, type); } else { element = GUIHelper.CreateObjectPropertyField(property, type); } break; case SerializedPropertyType.Generic: var targetType = property.GetPropertyType(isArrayElement); var isManagedReferenceProperty = property.propertyType == SerializedPropertyType.ManagedReference; if (InternalAPIHelper.GetDrawerTypeForType(targetType, isManagedReferenceProperty) != null) { element = new PropertyField(property); } else if (property.isArray) { element = new PropertyListView(property); } else if (targetType.TryGetCustomAttribute(out var groupAttribute)) // custom group { var drawer = AlchemyEditorUtility.CreateGroupDrawer(groupAttribute, targetType); var root = drawer.CreateRootElement(labelText); InspectorHelper.BuildElements(property.serializedObject, root, property.GetValue(), name => property.FindPropertyRelative(name)); if (root is BindableElement bindableElement) bindableElement.BindProperty(property); element = root; } else { var foldout = new Foldout() { text = labelText }; var clickable = InternalAPIHelper.GetClickable(foldout.Q()); InternalAPIHelper.SetAcceptClicksIfDisabled(clickable, true); InspectorHelper.BuildElements(property.serializedObject, foldout, property.GetValue(), name => property.FindPropertyRelative(name)); foldout.BindProperty(property); element = foldout; } break; case SerializedPropertyType.ManagedReference: element = new SerializeReferenceField(property); break; } Add(element); } readonly VisualElement element; public VisualElement FieldElement => element; public string Label { get { return element switch { Foldout foldout => foldout.text, PropertyField propertyField => propertyField.label, SerializeReferenceField serializeReferenceField => serializeReferenceField.foldout.text, InlineEditorObjectField inlineEditorObjectField => inlineEditorObjectField.Label, PropertyListView propertyListView => propertyListView.Label, _ => null, }; } set { switch (element) { case Foldout foldout: foldout.text = value; break; case PropertyField propertyField: propertyField.label = value; break; case SerializeReferenceField serializeReferenceField: serializeReferenceField.foldout.text = value; break; case InlineEditorObjectField inlineEditorObjectField: inlineEditorObjectField.Label = value; break; case PropertyListView propertyListView: propertyListView.Label = value; break; } } } } }