Control Types
Control Types are used to add the UIElement controls for various types and attributes. They are mainly used for the inspectors (such as the task or shared variable inspector) but can also be used to show content in other areas such as the within the node. As mentioned, there are two types of controls:
- Type Control: Used to add controls for the C# types, from a basic int to more complex objects such as a Shared Variable.
- Attribute Control: Used to add controls for C# attributes, such as the [Header] or [Flags] attribute.
Control Types are also used by the Ultimate Character Controller and the Ultimate Inventory System. If you’ve created a Control Type for one of those assets then it will also work with Behavior Designer.
Type Control
The script below shows an example of creating a Control Type for the bool type.
using Opsive.Shared.Editor.UIElements.Controls.Types; using UnityEngine.UIElements; [ControlType(typeof(bool))] public class BoolControl : TypeControlBase { /// <summary> /// Does the control use a label? /// </summary> public override bool UseLabel { get { return true; } } /// <summary> /// Returns the control that should be used for the specified ControlType. /// </summary> /// <param name="input">The input to the control.</param> /// <returns>The created control.</returns> protected override VisualElement GetControl(TypeControlInput input) { var toggle = new Toggle(); toggle.value = (bool)input.Value; // Ensure the control is kept up to date as the value changes. if (input.Field != null) { System.Action<object> onBindingUpdateEvent = (object newValue) => toggle.SetValueWithoutNotify((bool)newValue); toggle.RegisterCallback<AttachToPanelEvent>(c => { BindingUpdater.AddBinding(input.Field, input.ArrayIndex, input.Target, onBindingUpdateEvent); }); toggle.RegisterCallback<DetachFromPanelEvent>(c => { BindingUpdater.RemoveBinding(onBindingUpdateEvent); }); } toggle.RegisterValueChangedCallback(c => { if (!input.OnChangeEvent(c.newValue)) { toggle.SetValueWithoutNotify(c.previousValue); } c.StopPropagation(); }); return toggle; } }
Some things to pay attention to:
- The [ControlType] attribute specifies the object type that the control represents.
- The class implements TypeControlBase. This base type is used for controls that display object types.
- UseLabel is set to true. If this was set to false then no field label would be added to the UI.
- The BindingUpdater is used to ensure the the UIElement is updated when the field value changes outside of the UI. Remember UIElements is a persistent UI solution so if the BindingUpdater didn’t exist then the UI display would never change as the field value changes.
Attribute Control
Attribute Controls are similar to Type Controls. The script below is an implementing of the Attribute Control for the [Space] Attribute.
using Opsive.Shared.Editor.UIElements.Controls.Attributes; using System.Reflection; using UnityEngine.UIElements; [ControlType(typeof(UnityEngine.SpaceAttribute))] public class SpaceAttributeControl : AttributeControlBase { /// <summary> /// Does the attribute override the type control? /// </summary> public override bool OverrideTypeControl { get { return false; } } /// <summary> /// Does the control use a label? /// </summary> public override bool UseLabel { get { return false; } } /// <summary> /// Returns the attribute control that should be used for the specified AttributeControlType. /// </summary> /// <param name="input">The input to the control.</param> /// <returns>The created control.</returns> protected override VisualElement GetControl(AttributeControlInput input) { var spaceAttribute = input.Field.GetCustomAttribute<UnityEngine.SpaceAttribute>(); if (spaceAttribute == null) { return null; } var visualElement = new VisualElement(); visualElement.style.height = spaceAttribute.height; return visualElement; } }
Most of the concepts are the same as the Type Control. The only difference is that the AttributeControlBase has an OverrideTypeControl which allows the Attribute Control to replace the Type Control. If this property returns true then the Type Control will not be used for the object type that the attribute has been added to.