static VisualElement CreatePropertyGUI(SerializedProperty property, LogicAttribute attribute)
        {
            Assert.AreEqual(property.type, nameof(Logic));
            var container = new VisualElement();

            var statementsProperty = property.FindPropertyRelative("statements");
            var statementsField    = CreateStatementsPropertyGUI(statementsProperty, attribute);

            container.Add(statementsField);

            return(container);
        }
        static VisualElement CreateStatementPropertyGUI(SerializedProperty property, LogicAttribute attribute)
        {
            Assert.AreEqual(property.type, nameof(Statement));
            var container = new VisualElement
            {
                style = { flexGrow = new StyleFloat(1) }
            };

            var targetStateProperty = property.FindPropertyRelative("singleStatement.targetState");
            var statementsField     = CreateTargetStatePropertyGUI(targetStateProperty, attribute.TargetStateTargetSelectables, attribute.FormatTargetStateTarget);

            container.Add(statementsField);

            var expressionProperty = property.FindPropertyRelative("singleStatement.expression");
            var expressionField    = CreateExpressionPropertyGUI(expressionProperty, attribute.SourceStateTargetSelectables, attribute.FormatSourceTarget);

            container.Add(expressionField);

            return(container);
        }
        static VisualElement CreateStatementsPropertyGUI(SerializedProperty property, LogicAttribute attribute)
        {
            Assert.IsTrue(property.isArray);
            Assert.AreEqual(property.arrayElementType, nameof(Statement));
            var container = new VisualElement();
            var list      = new VisualElement
            {
                style = { marginTop = new StyleLength(5) }
            };

            container.Add(list);

            var arraySizeProperty = property.FindPropertyRelative("Array.size");
            var arraySizeField    = new IntegerField
            {
                bindingPath = arraySizeProperty.propertyPath,
                style       = { display = new StyleEnum <DisplayStyle>(DisplayStyle.None) }
            };

            arraySizeField.RegisterValueChangedCallback(e =>
            {
                Refresh();
            });
            container.Add(arraySizeField);

            void AddArrayElement()
            {
                property.arraySize += 1;
                property.serializedObject.ApplyModifiedProperties();
            }

            void DeleteArrayElementAt(int i)
            {
                if (property.GetArrayElementAtIndex(i) != null)
                {
                    property.DeleteArrayElementAtIndex(i);
                }
                property.serializedObject.ApplyModifiedProperties();
            }

            void MoveArrayElement(int srcIndex, int dstIndex)
            {
                if (property.GetArrayElementAtIndex(srcIndex) != null)
                {
                    property.MoveArrayElement(srcIndex, dstIndex);
                }
                property.serializedObject.ApplyModifiedProperties();
            }

            VisualElement CreateCell(int i)
            {
                var listItem = new VisualElement
                {
                    style =
                    {
                        flexDirection  = new StyleEnum <FlexDirection>(FlexDirection.Row),
                        borderTopWidth = new StyleFloat(1),
#if UNITY_2019_3_OR_NEWER
                        borderTopColor = new StyleColor(Color.gray),
#else
                        borderColor    = new StyleColor(Color.gray),
#endif
                        paddingTop    = new StyleLength(5),
                        paddingBottom = new StyleLength(5)
                    }
                };

                var statementProperty = property.GetArrayElementAtIndex(i);
                var field             = CreateStatementPropertyGUI(statementProperty, attribute);

                listItem.Add(field);

                var listItemMenu = new VisualElement
                {
                    style =
                    {
                        borderLeftWidth = new StyleFloat(1),
#if UNITY_2019_3_OR_NEWER
                        borderLeftColor = new StyleColor(Color.gray),
#else
                        borderColor     = new StyleColor(Color.gray),
#endif
                    }
                };

                listItem.Add(listItemMenu);
                var moveUpButton = new Button(() => MoveArrayElement(i, i - 1))
                {
                    text    = "▲",
                    tooltip = "Move Up"
                };

                moveUpButton.SetEnabled(i > 0);
                listItemMenu.Add(moveUpButton);

                var removeButton = new Button(() => DeleteArrayElementAt(i))
                {
                    text    = "-",
                    tooltip = "Delete"
                };

                listItemMenu.Add(removeButton);

                var moveDownButton = new Button(() => MoveArrayElement(i, i + 1))
                {
                    text    = "▼",
                    tooltip = "Move Down"
                };

                moveDownButton.SetEnabled(i < property.arraySize - 1);
                listItemMenu.Add(moveDownButton);

                return(listItem);
            }

            void Refresh()
            {
                list.Unbind();
                list.Clear();
                for (var i = 0; i < property.arraySize; i++)
                {
                    list.Add(CreateCell(i));
                }
                var addButton = new Button(AddArrayElement)
                {
                    text    = "+",
                    tooltip = "Add"
                };

                list.Add(addButton);
            }

            Refresh();

            return(container);
        }