| Parameter | Description |
|---|---|
| container | The parent element to add the content to. |
| property | The serialized property that represents the UXML serialized data instance. |
| childProperty | The serialized property for the attribute to draw. |
Creates the GUI for a single attribute of the UXML serialized data.
The default implementation adds a UxmlAttributeField bound to
childProperty. Override this method to draw specific attributes with a custom
layout, and call the base method for the rest.
The following example draws specific attributes with custom layouts and action buttons.
// Override CreateChildPropertyGUI to render specific properties with custom layouts. // // This example targets an InfoPanel element with two string [UxmlAttribute] properties: // - "text": a freeform description rendered as a multiline TextField with a Clear button. // - "documentationUrl": a URL rendered as a single-line TextField with an Open button. // // Both fields use a UxmlAttributeFieldDecorator so they retain override and binding affordances. // All other properties fall back to the default UxmlAttributeField rendering via the base class. [CustomPropertyDrawer(typeof(InfoPanel.UxmlSerializedData))] public class InfoPanelDrawer : UxmlSerializedDataPropertyDrawer { protected override void CreateChildPropertyGUI(VisualElement container, SerializedProperty property, SerializedProperty childProperty) { switch (childProperty.name) { case "text": container.Add(BuildMultilineFieldWithClear(property, childProperty)); break;
case "documentationUrl": container.Add(BuildUrlFieldWithOpen(property, childProperty)); break;
default: base.CreateChildPropertyGUI(container, property, childProperty); break; } }
// Builds a row with a multiline TextField inside a UxmlAttributeFieldDecorator and a Clear button. static VisualElement BuildMultilineFieldWithClear(SerializedProperty property, SerializedProperty childProperty) { // Cache the path and the object — both properties are references that may be recycled after // this method returns, so the button callback must not touch either one. string propertyPath = childProperty.propertyPath; SerializedObject serializedObject = property.serializedObject;
VisualElement row = new VisualElement(); row.style.flexDirection = FlexDirection.Row;
UxmlAttributeFieldDecorator decorator = new UxmlAttributeFieldDecorator(); TextField textField = new TextField(childProperty.displayName); textField.bindingPath = propertyPath; textField.multiline = true; textField.style.flexGrow = 1; decorator.Add(textField); row.Add(decorator);
row.Add(new Button(() => { SerializedProperty serializedProperty = serializedObject.FindProperty(propertyPath); if (serializedProperty != null) { serializedProperty.stringValue = string.Empty; serializedObject.ApplyModifiedProperties(); } }) { text = "Clear" });
return row; }
// Builds a row with a single-line TextField inside a UxmlAttributeFieldDecorator and an Open button. static VisualElement BuildUrlFieldWithOpen(SerializedProperty property, SerializedProperty childProperty) { string propertyPath = childProperty.propertyPath; SerializedObject serializedObject = property.serializedObject;
VisualElement row = new VisualElement(); row.style.flexDirection = FlexDirection.Row;
UxmlAttributeFieldDecorator decorator = new UxmlAttributeFieldDecorator(); TextField textField = new TextField(childProperty.displayName); textField.bindingPath = propertyPath; textField.style.flexGrow = 1; decorator.Add(textField); row.Add(decorator);
row.Add(new Button(() => { SerializedProperty serializedProperty = serializedObject.FindProperty(propertyPath); if (serializedProperty != null && !string.IsNullOrEmpty(serializedProperty.stringValue)) Application.OpenURL(serializedProperty.stringValue); }) { text = "Open" });
return row; } }