public static void RenderVector3IntProperty(VisualElement container, string name, object value,
                                                    Action <object> setter)
        {
            var field = new Vector3IntField(name);

            field.SetValueWithoutNotify((Vector3Int)value);
            field.MarkDirtyRepaint();
            field.RegisterValueChangedCallback(evt => setter(evt.newValue));
            container.Add(field);
        }
        void Init()
        {
            Vector3IntField field = new Vector3IntField()
            {
                value = config.value != null ? (Vector3Int)config.value : new Vector3Int(),
            };

            field.EnableInClassList("compositeField", false);

            field.RegisterValueChangedCallback((e) => {
                config.OnValueChanged(e.newValue);
                MarkDirtyRepaint();
            });
            Add(field);
        }
        protected VisualElement CreateParameterControl(SingularSerializableParameter parameter, string controlName, Action <SingularSerializableParameter> clampAction = null)
        {
            VisualElement control;

            switch (parameter.Type)
            {
            case ParameterType.behaviorAction:

                control = new VisualElement();

                var buttons = new VisualElement {
                    style = { flexDirection = FlexDirection.Row, paddingRight = 2f, paddingLeft = 2f }
                };
                var actionLabel = new Label {
                    style = { paddingLeft = 8f, paddingRight = 8f }
                };

                var configureButton = new Button {
                    text = "Configure"
                };
                configureButton.clickable.clickedWithEventInfo +=
                    clickEvent =>
                {
                    var worldPosition = clickEvent.originalMousePosition + GraphView.editorWindow.position.position;

                    GraphView.actionSearcher.TargetParameter = parameter;
                    SearchWindow.Open(new SearchWindowContext(worldPosition), GraphView.actionSearcher);
                };

                var removeButton = new Button(() => parameter.BehaviorActionValue = null)
                {
                    text = "Remove"
                };

                buttons.Add(configureButton);
                buttons.Add(removeButton);

                control.Add(actionLabel);
                control.Add(buttons);

                parameter.OnValueChangedMethods += OnBehaviorActionChanged;
                OnBehaviorActionChanged();                         //Trigger a refresh

                void OnBehaviorActionChanged()
                {
                    parameter.LoadBehaviorAction(GraphView.editorWindow.ImportData);                             //Refresh action name
                    actionLabel.text = parameter.BehaviorActionValue == null ? "Missing Action" : parameter.BehaviorActionValue.ToString();

                    //Behavior action parameter controls
                    const string  ParameterGroupName = "Behavior Action Parameters Group";
                    VisualElement group = control.Q <VisualElement>(ParameterGroupName);

                    if (group != null)
                    {
                        control.Remove(group);                                            //If had old group remove/destroy it
                    }
                    var parameters = parameter.BehaviorActionValue?.method.Parameters;

                    if (parameters == null || parameters.Count == 0)
                    {
                        return;                                                                          //If no parameter for this action
                    }
                    group = new VisualElement {
                        name = ParameterGroupName
                    };                                                                                 //Create group
                    var accessor = ((SerializableParameter)parameter).BehaviorActionParameters;

                    for (int i = 0; i < parameters.Count; i++)
                    {
                        BehaviorActionParameterInfo parameterInfo = parameters[i];
                        group.Add(CreateParameterControl(accessor[i], parameterInfo.name));
                    }

                    control.Add(group);
                }

                break;

            case ParameterType.boolean:

                var toggle = new Toggle(controlName)
                {
                    value = parameter.BooleanValue
                };
                toggle.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.BooleanValue = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    toggle.SetValueWithoutNotify(parameter.BooleanValue);
                }
                    );

                control = toggle;
                break;

            case ParameterType.enumeration:

                control = new EnumField();
                //TODO

                break;

            case ParameterType.integer1:

                var integerField = new IntegerField(controlName)
                {
                    value = parameter.Integer1Value
                };
                integerField.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Integer1Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    integerField.SetValueWithoutNotify(parameter.Integer1Value);
                }
                    );

                control = integerField;
                break;

            case ParameterType.integer2:

                var vector2IntField = new Vector2IntField(controlName)
                {
                    value = parameter.Integer2Value
                };
                vector2IntField.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Integer2Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    vector2IntField.SetValueWithoutNotify(parameter.Integer2Value);
                }
                    );

                control = vector2IntField;
                break;

            case ParameterType.integer3:

                var vector3IntField = new Vector3IntField(controlName)
                {
                    value = parameter.Integer3Value
                };
                vector3IntField.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Integer3Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    vector3IntField.SetValueWithoutNotify(parameter.Integer3Value);
                }
                    );

                control = vector3IntField;
                break;

            case ParameterType.float1:

                var floatField = new FloatField(controlName)
                {
                    value = parameter.Float1Value
                };
                floatField.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Float1Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    floatField.SetValueWithoutNotify(parameter.Float1Value);
                }
                    );

                control = floatField;
                break;

            case ParameterType.float2:

                var vector2Field = new Vector2Field(controlName)
                {
                    value = parameter.Float2Value
                };
                vector2Field.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Float2Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    vector2Field.SetValueWithoutNotify(parameter.Float2Value);
                }
                    );

                control = vector2Field;
                break;

            case ParameterType.float3:

                var vector3Field = new Vector3Field(controlName)
                {
                    value = parameter.Float3Value
                };
                vector3Field.RegisterValueChangedCallback(
                    changeEvent =>
                {
                    parameter.Float3Value = changeEvent.newValue;
                    clampAction?.Invoke(parameter);
                    vector3Field.SetValueWithoutNotify(parameter.Float3Value);
                }
                    );

                control = vector3Field;
                break;

            default: throw ExceptionHelper.Invalid(nameof(parameter.Type), parameter.Type, InvalidType.unexpected);
            }

            control.Query <FloatField>().ForEach(field => field.style.minWidth = 60f);
            Label label = control.Q <Label>();

            if (label != null)
            {
                label.style.minWidth     = 0f;
                label.style.paddingRight = 20f;
            }

            return(control);
        }