Пример #1
0
        public void PropertyElement_Target_CanBeSetAndGet()
        {
            var element = new PropertyElement();

            Assert.That(element.TryGetTarget(out UIContainer _), Is.False);
            Assert.Throws <InvalidOperationException>(() => element.GetTarget <UIContainer>());

            var container = new UIContainer();

            Assert.DoesNotThrow(() => element.SetTarget(container));
            Assert.That(element.TryGetTarget(out UIContainer _), Is.True);
            Assert.DoesNotThrow(() => element.GetTarget <UIContainer>());

            Assert.DoesNotThrow(() => element.SetTarget((object)container));
            Assert.That(element.TryGetTarget(out UIContainer _), Is.True);
            Assert.DoesNotThrow(() => element.GetTarget <UIContainer>());

            Assert.DoesNotThrow(() => element.SetTarget(container));
            Assert.That(element.TryGetTarget(out object _), Is.True);
            Assert.DoesNotThrow(() => element.GetTarget <object>());

            var container2 = new ComplexUIContainer();

            Assert.That(element.TryGetTarget(out ComplexUIContainer _), Is.False);
            Assert.Throws <InvalidCastException>(() => element.GetTarget <ComplexUIContainer>());
            Assert.DoesNotThrow(() => element.SetTarget(container2));
            Assert.That(element.TryGetTarget(out ComplexUIContainer _), Is.True);
            Assert.DoesNotThrow(() => element.GetTarget <ComplexUIContainer>());

            var container3 = new ComplexUIChildContainer();

            Assert.DoesNotThrow(() => element.SetTarget(container3));
            Assert.That(element.TryGetTarget(out ComplexUIContainer _), Is.True);
            Assert.DoesNotThrow(() => element.GetTarget <ComplexUIContainer>());
        }
Пример #2
0
        public void TypeWithCustomInspector_WhenNoSpecializedInspectorExists_UsesDeclaredTypeInspector()
        {
            var element  = new PropertyElement();
            var instance = new ASD();

            instance.Type = new NoInspectorDerivedType();
            element.SetTarget(instance);
            Assert.That(element.Q <Label>(className: BaseType.Label).text, Is.EqualTo(nameof(BaseType)));
            element.ClearTarget();
            instance.Type = new HasInspectorDerivedType();
            element.SetTarget(instance);
            Assert.That(element.Q <Label>(className: BaseType.Label).text, Is.EqualTo(nameof(HasInspectorDerivedType)));
        }
Пример #3
0
        public void DefaultInspector_ForField_MimicsGenericInspector()
        {
            var fieldInspector = new PropertyElement();

            fieldInspector.SetTarget(new Types.DefaultFieldInspector()
            {
                NoInspectorType      = new Types.NoInspectorType(),
                DefaultInspectorType = new Types.DefaultInspectorType()
            });

            var noInspector =
                fieldInspector.Q <Foldout>(nameof(Types.DefaultFieldInspector.NoInspectorType));

            Assert.That(noInspector.Query <CustomInspectorElement>().ToList().Count, Is.EqualTo(0));
            Assert.That(noInspector.childCount, Is.EqualTo(3));

            var customInspectorElements = fieldInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(1));
            var customInspectorElement = customInspectorElements[0].Q <Foldout>(nameof(Types.DefaultFieldInspector.DefaultInspectorType));

            Assert.That(customInspectorElement.childCount, Is.EqualTo(3));

            for (var i = 0; i < 3; ++i)
            {
                var lhs = noInspector.ElementAt(i);
                var rhs = customInspectorElement.ElementAt(i);
                Assert.That(lhs.GetType(), Is.EqualTo(rhs.GetType()));
                Assert.That(lhs.childCount, Is.EqualTo(rhs.childCount));
                Assert.That((lhs as BindableElement)?.bindingPath, Is.EqualTo((rhs as BindableElement)?.bindingPath));
            }
        }
Пример #4
0
        public void CustomInspector_CallingDefaultOnEachField_MimicsGenericInspector()
        {
            var noInspector = new PropertyElement();

            noInspector.SetTarget(new Types.NoInspectorType());
            Assert.That(noInspector.Query <CustomInspectorElement>().ToList().Count, Is.EqualTo(0));
            Assert.That(noInspector.childCount, Is.EqualTo(3));

            var allDefaultInspector = new PropertyElement();

            allDefaultInspector.SetTarget(new Types.AllDefaultInspectorType());
            var customInspectorElements = allDefaultInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(1));
            var customInspectorElement = customInspectorElements[0].ElementAt(0);

            Assert.That(customInspectorElement.childCount, Is.EqualTo(3));

            for (var i = 0; i < 3; ++i)
            {
                var lhs = noInspector.ElementAt(i);
                var rhs = customInspectorElement.ElementAt(i);
                Assert.That(lhs.GetType(), Is.EqualTo(rhs.GetType()));
                Assert.That(lhs.childCount, Is.EqualTo(rhs.childCount));
                Assert.That((lhs as BindableElement)?.bindingPath, Is.EqualTo((rhs as BindableElement)?.bindingPath));
            }
        }
Пример #5
0
        public void CodeInspector_WithBindings_GetsValuesSet()
        {
            var fieldInspector = new PropertyElement();

            fieldInspector.SetTarget(new Types.CodeInspectorType()
            {
                Float  = 25.0f,
                Int    = 15,
                String = "Yup"
            });

            var customInspectorElements = fieldInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(1));
            var customInspectorElement = customInspectorElements[0].ElementAt(0);

            Assert.That(customInspectorElement.childCount, Is.EqualTo(3));
            var floatField = customInspectorElement.ElementAt(0) as FloatField;

            Assert.That(floatField.value, Is.EqualTo(25.0f));
            var intField = customInspectorElement.ElementAt(1) as IntegerField;

            Assert.That(intField.value, Is.EqualTo(15));
            var stringField = customInspectorElement.ElementAt(2) as TextField;

            Assert.That(stringField.value, Is.EqualTo("Yup"));
        }
        protected PropertyElement CreateContent <TValue>(IComponentProperty property, ref TValue value)
        {
            Resources.Templates.Inspector.InspectorStyle.AddStyles(this);
            AddToClassList(UssClasses.Resources.Inspector);
            AddToClassList(UssClasses.Resources.ComponentIcons);

            InspectorUtility.CreateComponentHeader(this, property.Type, DisplayName);
            var foldout   = this.Q <Foldout>(className: UssClasses.Inspector.Component.Header);
            var toggle    = foldout.Q <Toggle>();
            var container = Container;

            toggle.AddManipulator(new ContextualMenuManipulator(evt => { OnPopulateMenu(evt.menu); }));

            var componentMenu = this.Q <VisualElement>(className: UssClasses.Inspector.Component.Menu);

            var content = new PropertyElement();

            foldout.contentContainer.Add(content);
            content.AddContext(Context);
            content.SetTarget(value);

            content.OnChanged += OnComponentChanged;

            foldout.contentContainer.AddToClassList(UssClasses.Inspector.Component.Container);

            if (container.IsReadOnly)
            {
                SetReadonly(foldout);
                foldout.RegisterCallback <ClickEvent, EntityInspectorContext>(OnClicked, Context, TrickleDown.TrickleDown);
            }

            return(content);
        }
        public override VisualElement Build()
        {
            m_Root = new VisualElement();
            Resources.Templates.KeyValuePairElement.Clone(m_Root);
            m_Root.AddToClassList(UssClasses.KeyValuePairElement.KeyValuePair);

            m_Key = m_Root.Q <PropertyElement>(className: UssClasses.KeyValuePairElement.Key);
            m_Key.SetTarget(new KeyContainer(Target.Key));
            if (m_Key.contentContainer.Q <Foldout>() is Foldout foldout)
            {
                foldout.SetEnabled(true);
                foldout.contentContainer.SetEnabled(false);
            }
            else
            {
                m_Key.contentContainer.SetEnabled(false);
            }

            var remove = m_Root.Q <Button>(className: UssClasses.KeyValuePairElement.RemoveButton);

            remove.clickable.clicked += () =>
            {
                DictionaryElement.RemoveAtKey(m_Key.GetTarget <KeyContainer>().Key);
            };

            m_Value = m_Root.Q <PropertyElement>(className: UssClasses.KeyValuePairElement.Value);
            m_Value.SetTarget(new ValueContainer(Target.Value));
            m_Value.OnChanged += OnValueChanged;

            return(m_Root);
        }
Пример #8
0
 void ElementOnOnChanged(PropertyElement element)
 {
     m_Container.SetComponent(element.GetTarget <T>());
     element.SetTarget(m_Container.GetComponent <T>());
     SetBorderColor();
     OnChanged();
 }
Пример #9
0
        private void OnEnable()
        {
            var propertyElement = new PropertyElement();

            propertyElement.SetTarget(paramValue);
            rootVisualElement.Add(propertyElement);
        }
Пример #10
0
        public void PropertyElement_IsPathValid_ReturnsTrueForValidPath()
        {
            var element   = new PropertyElement();
            var container = GetContainer();

            element.SetTarget(container);

            var path = new PropertyPath();
            {
                path.Clear();
                path.PushName(nameof(ComplexUIContainer.FloatField));
                Assert.That(element.IsPathValid(path), Is.True);
            }

            {
                path.Clear();
                path.PushName(nameof(ComplexUIContainer.IntField));
                Assert.That(element.IsPathValid(path), Is.True);
            }

            {
                path.Clear();
                path.PushName(nameof(ComplexUIContainer.StringField));
                Assert.That(element.IsPathValid(path), Is.True);
            }

            {
                path.Clear();
                path.PushName(nameof(ComplexUIContainer.IntListField));
                Assert.That(element.IsPathValid(path), Is.True);
                for (var i = 0; i < container.IntListField.Count; ++i)
                {
                    path.PushIndex(i);
                    Assert.That(element.IsPathValid(path), Is.True);
                    path.Pop();
                }
            }

            {
                path.Clear();
                path.PushName(nameof(ComplexUIContainer.IntIntDictionary));
                Assert.That(element.IsPathValid(path), Is.True);
                foreach (var kvp in container.IntIntDictionary.ToList())
                {
                    path.PushKey(kvp.Key);
                    Assert.That(element.IsPathValid(path), Is.True);

                    path.PushName("Key");
                    Assert.That(element.IsPathValid(path), Is.True);
                    path.Pop();

                    path.PushName("Value");
                    Assert.That(element.IsPathValid(path), Is.True);
                    path.Pop();

                    path.Pop();
                }
            }
        }
        public void ResettingTargets_FromCustomInspector_ShouldNotThrow()
        {
            var value   = new NestedPropertyElementWithInterfaces();
            var element = new PropertyElement();

            Assert.DoesNotThrow(() => element.SetTarget(value));
            Assert.DoesNotThrow(() => element.Query <CustomInspectorElement>().ForEach(i => (i as IBinding).Update()));
        }
Пример #12
0
        public void NullElement_WithUnderlyingDataNotNullAnymore_UpdatesCorrectly()
        {
            var container = new Container();
            var element   = new PropertyElement();

            element.SetTarget(container);

            var someTypes = new List <NullElement <SomeType> >();

            element.Query <NullElement <SomeType> >().ToList(someTypes);
            Assert.That(someTypes.Count, Is.EqualTo(1));

            var someOtherTypes = new List <NullElement <SomeOtherType> >();

            element.Query <NullElement <SomeOtherType> >().ToList(someOtherTypes);
            Assert.That(someOtherTypes.Count, Is.EqualTo(1));

            container.NonNullFieldWithNestedNullField.NestedField = new SomeOtherType();
            foreach (IBinding binding in someTypes)
            {
                binding.Update();
            }

            foreach (IBinding binding in someOtherTypes)
            {
                binding.Update();
            }
            someTypes.Clear();
            someOtherTypes.Clear();

            element.Query <NullElement <SomeType> >().ToList(someTypes);
            Assert.That(someTypes.Count, Is.EqualTo(1));

            element.Query <NullElement <SomeOtherType> >().ToList(someOtherTypes);
            Assert.That(someOtherTypes.Count, Is.EqualTo(0));

            container.NullField = new SomeType {
                NestedField = new SomeOtherType()
            };
            foreach (IBinding binding in someTypes)
            {
                binding.Update();
            }

            foreach (IBinding binding in someOtherTypes)
            {
                binding.Update();
            }
            someTypes.Clear();
            someOtherTypes.Clear();

            element.Query <NullElement <SomeType> >().ToList(someTypes);
            Assert.That(someTypes.Count, Is.EqualTo(0));

            element.Query <NullElement <SomeOtherType> >().ToList(someOtherTypes);
            Assert.That(someOtherTypes.Count, Is.EqualTo(0));
        }
Пример #13
0
        public void PropertyElement_WithNullFields_CreatesNullElement()
        {
            var container = new Container();
            var element   = new PropertyElement();

            element.SetTarget(container);

            Assert.That(element.Query <NullElement <SomeType> >().ToList().Count, Is.EqualTo(1));
            Assert.That(element.Query <NullElement <SomeOtherType> >().ToList().Count, Is.EqualTo(1));
        }
Пример #14
0
        public void PropertyElement_FieldWithHideInInspector_AreNotShown()
        {
            var withHideInInspectorField = new PropertyElement();

            withHideInInspectorField.SetTarget(new Types.FieldWithHideInInspector());
            var customInspectorElements = withHideInInspectorField.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(0));
            Assert.That(withHideInInspectorField.childCount, Is.EqualTo(2));
            Assert.That(withHideInInspectorField.Query <IntegerField>().First(), Is.Null);
        }
Пример #15
0
        public void NullInspector_ForRootType_HasNoChildren()
        {
            var noOverrideInspector = new PropertyElement();

            noOverrideInspector.SetTarget(new Types.NullInspectorType());
            var customInspectorElements = noOverrideInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(1));
            var customInspectorElement = customInspectorElements[0];

            Assert.That(customInspectorElement.childCount, Is.EqualTo(0));
        }
        public override void OnActivate(string searchContext, VisualElement rootElement)
        {
            // TODO: Switch to use uxml/uss for this.
            var root = new VisualElement();

            rootElement.Add(root);
            var title = new Label(Title);

            title.style.unityFontStyleAndWeight = FontStyle.Bold;
            title.style.marginTop      = 1;
            title.style.fontSize       = 19;
            title.style.unityTextAlign = TextAnchor.MiddleLeft;
            title.style.height         = 26;
            root.Add(title);

            Resources.Templates.Settings.AddStyles(rootElement);
            foreach (var kvp in s_Settings)
            {
                if (kvp.Value.All(w => w.Internal) && !Unsupported.IsDeveloperMode())
                {
                    continue;
                }

                var label = new Label {
                    text = kvp.Key
                };
                label.style.unityFontStyleAndWeight = FontStyle.Bold;
                root.Add(label);

                foreach (var wrapper in kvp.Value)
                {
                    if (wrapper.Internal && !Unsupported.IsDeveloperMode())
                    {
                        continue;
                    }

                    var setting = wrapper.Setting;
                    var element = new PropertyElement();
                    element.style.marginLeft = -3;
                    element.SetAttributeFilter(AttributeFilter);
                    element.SetTarget(setting);
                    element.OnChanged += (propertyElement, path) => setting.OnSettingChanged(path);
                    root.Add(element);
                    element.RegisterCallback <GeometryChangedEvent>(evt =>
                                                                    StylingUtility.AlignInspectorLabelWidth(element));
                }
            }
            root.AddToClassList("unity-inspector-element");
            root.style.paddingLeft = 10;

            base.OnActivate(searchContext, rootElement);
        }
Пример #17
0
        public void NullElement_WithStringField_CreatesAButton()
        {
            var container = new TypeWithString();
            var element   = new PropertyElement();

            element.SetTarget(container);

            var stringField = element.Q <NullElement <string> >();

            Assert.That(stringField, Is.Not.Null);
            Assert.That(stringField.Q <Button>(), Is.Not.Null);
            Assert.That(stringField.Q <PopupField <Type> >(), Is.Null);
        }
        public void EnumFields_WhenUnderlyingTypeIsLong_AreSkipped()
        {
            var element = new PropertyElement();

            element.SetTarget(new TypeWithLargeEnums());
#if !UNITY_2020_2_OR_NEWER
            Assert.That(element.Query <EnumField>().ToList().Count, Is.EqualTo(0));
            Assert.That(element.Query <EnumFlagsField>().ToList().Count, Is.EqualTo(0));
#else
            Assert.That(element.Query <EnumField>().ToList().Count, Is.EqualTo(1));
            Assert.That(element.Query <EnumFlagsField>().ToList().Count, Is.EqualTo(1));
#endif

            element.SetTarget(new TypeWithLargeAndRegularEnums());
#if !UNITY_2020_2_OR_NEWER
            Assert.That(element.Query <EnumField>().ToList().Count, Is.EqualTo(1));
            Assert.That(element.Query <EnumFlagsField>().ToList().Count, Is.EqualTo(1));
#else
            Assert.That(element.Query <EnumField>().ToList().Count, Is.EqualTo(2));
            Assert.That(element.Query <EnumFlagsField>().ToList().Count, Is.EqualTo(2));
#endif
        }
Пример #19
0
        public void NullElement_WithSingleConstructableType_CreatesAButton()
        {
            var container = new SomeType();
            var element   = new PropertyElement();

            element.SetTarget(container);

            var stringField = element.Q <NullElement <SomeOtherType> >();

            Assert.That(stringField, Is.Not.Null);
            Assert.That(stringField.Q <Button>(), Is.Not.Null);
            Assert.That(stringField.Q <PopupField <Type> >(), Is.Null);
        }
Пример #20
0
        public void NullElement_WithMultipleConstructableTypes_CreatesAPopup()
        {
            var container = new TypeWithDerivableField();
            var element   = new PropertyElement();

            element.SetTarget(container);

            var stringField = element.Q <NullElement <MultipleDerivedTypes> >();

            Assert.That(stringField, Is.Not.Null);
            Assert.That(stringField.Q <Button>(), Is.Null);
            Assert.That(stringField.Q <PopupField <Type> >(), Is.Not.Null);
        }
        public void DefaultInspector_ForCollectionField_MimicsGenericInspector()
        {
            var fieldInspector = new PropertyElement();

            fieldInspector.SetTarget(new Types.TypeWithCollections());

            var customInspectorElements = fieldInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements[0].childCount, Is.EqualTo(1));
            Assert.That(customInspectorElements[0][0], Is.TypeOf <Label>());
            Assert.That(customInspectorElements[1].childCount, Is.EqualTo(1));
            Assert.That(customInspectorElements[1][0], Is.TypeOf <CustomInspectorElement.DefaultInspectorElement>());
            Assert.That(customInspectorElements[2].childCount, Is.EqualTo(0));
        }
Пример #22
0
 public void Update()
 {
     if (m_Container.HasComponent <T>())
     {
         m_Element.style.display = DisplayStyle.Flex;
         m_MissingComponentLabel.style.display = DisplayStyle.None;
         m_Element.SetTarget(m_Container.GetComponent <T>());
     }
     else
     {
         m_Element.style.display = DisplayStyle.None;
         m_MissingComponentLabel.style.display = DisplayStyle.Flex;
     }
 }
Пример #23
0
        void RemoveComponent()
        {
            m_Container.RemoveComponent(m_Type);
            if (m_Container.HasComponent(m_Type))
            {
                m_Element?.SetTarget(m_Container.GetComponent <T>());
                SetBorderColor();
            }
            else
            {
                RemoveFromHierarchy();
            }

            OnChanged();
        }
        void IBinding.Update()
        {
            var container = Container;

            if (!Context.World.IsCreated || !Context.EntityManager.Exists(Container.Entity))
            {
                RemoveFromHierarchy();
                return;
            }

            if (PropertyContainer.TryGetValue <EntityContainer, TComponent>(ref container, Path, out var component))
            {
                m_Content.SetTarget(component);
            }
        }
Пример #25
0
        public void PropertyElement_WithAttributeFilter_FiltersHierarchyGeneration()
        {
            var element = new PropertyElement();

            element.SetTarget(new FilterByAttribute());
            Assert.That(element.contentContainer.childCount, Is.EqualTo(4));
            Assert.That(element[0], Is.InstanceOf <IntegerField>());
            Assert.That(element[1], Is.InstanceOf <TextField>());
            Assert.That(element[2], Is.InstanceOf <DoubleField>());
            Assert.That(element[3], Is.InstanceOf <FloatField>());

            element.SetAttributeFilter(attributes => null == attributes.OfType <HideAttribute>().FirstOrDefault());

            Assert.That(element.contentContainer.childCount, Is.EqualTo(1));
            Assert.That(element[0], Is.InstanceOf <FloatField>());
        }
Пример #26
0
        public void NullInspector_ForField_HasNoChildren()
        {
            var fieldInspector = new PropertyElement();

            fieldInspector.SetTarget(new Types.NullFieldInspector
            {
                NullInspectorType = new Types.NullInspectorType()
            });

            var customInspectorElements = fieldInspector.Query <CustomInspectorElement>().ToList();

            Assert.That(customInspectorElements.Count, Is.EqualTo(1));
            var customInspectorElement = customInspectorElements[0];

            Assert.That(customInspectorElement.childCount, Is.EqualTo(0));
        }
        VisualElement Build()
        {
            if (m_Root == null)
            {
                m_Root = new VisualElement();
            }

            if (Source != null && Source && Target != null && Target)
            {
                var configRoot = new PropertyElement();
                configRoot.SetTarget(new BuildConfigurationInspectorData(Source, Target));
                configRoot.AddContext(new BuildConfigurationContext(this));
                m_Root.contentContainer.Add(configRoot);
            }

            m_Root.contentContainer.Add(new IMGUIContainer(ApplyRevertGUI));
            return(m_Root);
        }
Пример #28
0
        public HierarchicalComponentContainerElement(HierarchicalComponentContainer <TContainer, TComponent> container, T component, bool optional)
        {
            this.AddStyleSheetAndVariant(ClassNames.BaseClassName);

            m_Container  = container;
            m_IsOptional = optional;

            AddToClassList(ClassNames.BaseClassName);

            var componentContainerName = component.GetType().Name;
            var foldout = new Foldout {
                text = ObjectNames.NicifyVariableName(componentContainerName)
            };

            foldout.AddToClassList(ClassNames.Component);
            foldout.AddToClassList(componentContainerName);
            Add(foldout);

            var toggle = foldout.Q <Toggle>();

            toggle.AddToClassList(ClassNames.Header);

            m_AddButton = new Button(AddComponent);
            m_AddButton.AddToClassList(ClassNames.AddComponent);
            toggle.Add(m_AddButton);

            m_RemoveButton = new Button(RemoveComponent);
            m_RemoveButton.AddToClassList(ClassNames.RemoveComponent);
            toggle.Add(m_RemoveButton);

            m_Element            = new PropertyElement();
            m_Element.OnChanged += ElementOnOnChanged;
            m_Element.SetTarget(component);

            foldout.contentContainer.Add(m_Element);
            foldout.contentContainer.AddToClassList(ClassNames.Fields);

            m_MissingComponentLabel = new Label($"Component of type {typeof(T).Name} is missing");
            m_MissingComponentLabel.style.display = DisplayStyle.None;
            foldout.contentContainer.Add(m_MissingComponentLabel);

            SetStyle();
        }
        void Initialize(EntitySelectionProxy proxy)
        {
            m_Context.SetContext(proxy);
            m_Root.Clear();

            var header = new PropertyElement();

            header.AddContext(m_Context);
            header.SetTarget(new EntityHeader(m_Context));
            m_Root.Add(header);
            m_SearchField = header.Q <ToolbarSearchField>();
            m_SearchField.RegisterValueChangedCallback(evt =>
            {
                m_Filters.Clear();
                var value   = evt.newValue.Trim();
                var matches = value.Split(' ');
                foreach (var match in matches)
                {
                    m_Filters.Add(match);
                }

                SearchChanged();
            });

            m_Settings = m_Root.Q <ToolbarMenu>();
            // TODO: Remove once we have menu items.
            m_Settings.Hide();

            m_ComponentsRoot = new VisualElement();

            m_Root.Add(m_ComponentsRoot);
            Resources.Templates.Inspector.ComponentsRoot.AddStyles(m_ComponentsRoot);
            m_ComponentsRoot.AddToClassList("entity-inspector__components-root");
            m_ComponentsRoot.RegisterCallback <GeometryChangedEvent>(OnGeometryChanged);
            m_TagsRoot = new TagComponentContainer(m_Context);
            m_ComponentsRoot.Add(m_TagsRoot);

            m_InspectorVisitor = new EntityInspectorVisitor(m_ComponentsRoot, m_TagsRoot, m_Context);
            PropertyContainer.Visit(m_Context.EntityContainer, m_InspectorVisitor);

            m_Root.ForceUpdateBindings();
        }
        internal static void SetCallbacks <TValue>(
            ref TValue value,
            PropertyPath path,
            PropertyElement root,
            PropertyElement field)
        {
            field.SetRoot(root);
            field.SetTarget(value);
            field.binding = new PropertyBinding <TValue>(field, root, path);

            var r = root;
            var p = path;

            field.OnChanged += (element, propertyPath) =>
            {
                r.SetValue(p, element.GetTarget <TValue>());
                element.SetTarget(r.GetValue <TValue>(p));
                var fullPath = new PropertyPath();
                fullPath.PushPath(p);
                fullPath.PushPath(propertyPath);
                r.NotifyChanged(fullPath);
            };
        }