void AddDropdownCallbackDelegate(Rect buttonRect, ReorderableList list)
        {
            var databases = new[]
            {
                ComponentSearcherDatabases.GetBuildStepsDatabase(
                    new HashSet <Type>(BuildStep.GetAvailableTypes(type => !IsShown(type))),
                    GetDisplayName),
            };

            var searcher = new Searcher(
                databases,
                new AddBuildSettingsComponentAdapter("Add Build Step"));

            var editorWindow = EditorWindow.focusedWindow;

            SearcherWindow.Show(
                editorWindow,
                searcher,
                AddStep,
                buttonRect.min + Vector2.up * 90.0f,
                a => { },
                new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top,
                                             SearcherWindow.Alignment.Horizontal.Left)
                );
        }
Beispiel #2
0
        public override VisualElement Build()
        {
            var typeField = Assets.LoadVisualTreeAsset(nameof(TypeInspector <T>)).CloneTree();

            var label = typeField.Q <Label>("label");

            label.text = DisplayName;

            var input = typeField.Q <VisualElement>("input");

            input.RegisterCallback <MouseUpEvent>(mouseUpEvent =>
            {
                var database  = TypeSearcherDatabase.Populate <T>(TypeFilter, TypeNameResolver, TypeCategoryResolver);
                var searcher  = new Searcher(database, new AddTypeSearcherAdapter(SearcherTitle));
                var position  = input.worldBound.min + Vector2.up * (input.worldBound.height + 19f);
                var alignment = new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top, SearcherWindow.Alignment.Horizontal.Left);
                SearcherWindow.Show(EditorWindow.focusedWindow, searcher, OnTypeSelected, position, null);
            });

            var type = Target?.GetType();

            if (type != null)
            {
                m_Text      = typeField.Q <TextElement>("text");
                m_Text.text = TypeNameResolver?.Invoke(type) ?? type.Name;
            }

            return(typeField);
        }
        public void OnDropOutsidePort(Edge edge, Vector2 position)
        {
            var draggedPort = (edge.output != null ? edge.output.edgeConnector.edgeDragHelper.draggedPort : null) ?? (edge.input != null ? edge.input.edgeConnector.edgeDragHelper.draggedPort : null);

            m_SearchWindowProvider.connectedPort = (ShaderPort)draggedPort;
            SearcherWindow.Show(m_editorWindow, (m_SearchWindowProvider as SearcherProvider).LoadSearchWindow(),
                                item => (m_SearchWindowProvider as SearcherProvider).OnSearcherSelectEntry(item, position),
                                position, null);
        }
        public void OnDropOutsidePort(Edge edge, Vector2 position)
        {
            var port = edge.output?.edgeConnector.edgeDragHelper.draggedPort ?? edge.input?.edgeConnector.edgeDragHelper.draggedPort;

            searchWindowProvider.ConnectedPort     = port;
            searchWindowProvider.RegenerateEntries = true;
            SearcherWindow.Show(editorView.EditorWindow, searchWindowProvider.LoadSearchWindow(), item => searchWindowProvider.OnSelectEntry(item, position), position, null);
            searchWindowProvider.RegenerateEntries = true;
        }
        public void OnDropOutsidePort(Edge edge, Vector2 position)
        {
            var draggedPort = (edge.output != null ? edge.output.edgeConnector.edgeDragHelper.draggedPort : null) ?? (edge.input != null ? edge.input.edgeConnector.edgeDragHelper.draggedPort : null);

            m_SearchWindowProvider.connectedPort     = (ShaderPort)draggedPort;
            m_SearchWindowProvider.regenerateEntries = true;//need to be sure the entires are relevant to the edge we are dragging
            SearcherWindow.Show(m_editorWindow, (m_SearchWindowProvider as SearcherProvider).LoadSearchWindow(),
                                item => (m_SearchWindowProvider as SearcherProvider).OnSearcherSelectEntry(item, position),
                                position, null);
            m_SearchWindowProvider.regenerateEntries = true;//entries no longer necessarily relevant, need to regenerate
        }
Beispiel #6
0
        public override VisualElement Build()
        {
            var typeField = Assets.LoadVisualTreeAsset(nameof(TypeInspector <T>)).CloneTree();

            typeField.AddStyleSheetAndVariant(nameof(TypeInspector <T>));

            var label = typeField.Q <Label>("label");

            label.text = DisplayName;

            var input = typeField.Q <VisualElement>("input");

            input.RegisterCallback <MouseUpEvent>(mouseUpEvent =>
            {
                var database  = TypeSearcherDatabase.Populate <T>(TypeFilter, TypeNameResolver, TypeCategoryResolver);
                var searcher  = new Searcher(database, new AddTypeSearcherAdapter(SearcherTitle));
                var position  = input.worldBound.min + Vector2.up * (input.worldBound.height + 19f);
                var alignment = new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top, SearcherWindow.Alignment.Horizontal.Left);
                SearcherWindow.Show(EditorWindow.focusedWindow, searcher, OnTypeSelected, position, null);
            });

            m_HelpBox = typeField.Q <VisualElement>("helpbox");

            var icon = m_HelpBox.Q <Image>("icon");

            icon.image     = EditorGUIUtility.IconContent("d_console.erroricon.sml").image;
            icon.scaleMode = ScaleMode.ScaleToFit;

            m_Message = m_HelpBox.Q <Label>("message");
            if (!string.IsNullOrEmpty(ErrorMessage))
            {
                m_HelpBox.style.display = DisplayStyle.Flex;
                m_Message.text          = ErrorMessage;
            }
            else
            {
                m_HelpBox.style.display = DisplayStyle.None;
                m_Message.text          = string.Empty;
            }

            var type = Target?.GetType();

            if (type != null)
            {
                m_Text      = typeField.Q <TextElement>("text");
                m_Text.text = TypeNameResolver?.Invoke(type) ?? type.Name;
            }

            return(typeField);
        }
Beispiel #7
0
        // Used to display data that is not meant to be persisted. The database will be overwritten after each call to SearcherWindow.Show(...).
        internal static void ShowTransientData(EditorWindow host, IEnumerable <SearcherItem> items,
                                               ISearcherAdapter adapter, Action <SearcherItem> selectionDelegate, Vector2 pos)
        {
            var database = SearcherDatabase.Create(items.ToList(), "", false);
            var searcher = new Searcher.Searcher(database, adapter);

            SearcherWindow.Show(host, searcher, x =>
            {
                host.Focus();
                selectionDelegate(x);

                return(!(Event.current?.modifiers.HasFlag(EventModifiers.Control)).GetValueOrDefault());
            }, pos, null);
        }
Beispiel #8
0
 void OnRunStepSelectorClicked(EventBase @event)
 {
     SearcherWindow.Show(
         EditorWindow.focusedWindow,
         new Searcher(
             TypeSearcherDatabase.GetRunStepDatabase(new HashSet <Type>(RunStep.GetAvailableTypes(type => !IsShown(type)))),
             new AddTypeSearcherAdapter("Select Run Script")),
         UpdateRunStep,
         @event.originalMousePosition + Vector2.up * 35.0f,
         a => { },
         new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top,
                                      SearcherWindow.Alignment.Horizontal.Left)
         );
 }
Beispiel #9
0
        internal static void ShowCriteria(ComponentQueryDeclarationModel query, string title, Vector2 position,
                                          Action <TypeHandle, TypeMember, BinaryOperatorKind> onComponentSelected)
        {
            var provider        = (EcsSearcherDatabaseProvider)query.GraphModel.Stencil.GetSearcherDatabaseProvider();
            var databases       = provider.GetCriteriaSearcherDatabases(query);
            var criteriaAdapter = new SimpleSearcherAdapter(title);
            var searcher        = new Searcher.Searcher(databases, criteriaAdapter);

            SearcherWindow.Show(
                EditorWindow.focusedWindow,
                searcher,
                item => OnItemSelected(item, onComponentSelected),
                position,
                null);
        }
Beispiel #10
0
        public static void ShowTypes(Stencil stencil, Vector2 position, Action <TypeHandle, int> callback,
                                     SearcherFilter userFilter = null)
        {
            var databases = stencil.GetSearcherDatabaseProvider().GetTypesSearcherDatabases();

            foreach (var database in databases)
            {
                database.MatchFilter = (query, item) =>
                {
                    if (!(item is TypeSearcherItem typeItem))
                    {
                        return(false);
                    }

                    var filter = stencil.GetSearcherFilterProvider()?.GetTypeSearcherFilter();
                    var res    = true;

                    if (filter != null)
                    {
                        res &= GetFilterResult(filter, typeItem.Data);
                    }

                    if (userFilter != null)
                    {
                        res &= GetFilterResult(userFilter, typeItem.Data);
                    }

                    return(res);
                };
            }

            var searcher = new Searcher.Searcher(databases, k_TypeAdapter)
            {
                SortComparison = k_TypeSort
            };

            SearcherWindow.Show(EditorWindow.focusedWindow, searcher, item =>
            {
                if (!(item is TypeSearcherItem typeItem))
                {
                    return(false);
                }

                callback(typeItem.Type, 0);
                return(true);
            }, position, null);
Beispiel #11
0
        void OnRunStepSelectorClicked(EventBase @event)
        {
            var database = TypeSearcherDatabase.Populate <RunStep>(
                type => !type.HasAttribute <HideInInspector>(),
                type => RunStep.GetName(type),
                type => RunStep.GetCategory(type));

            SearcherWindow.Show(
                EditorWindow.focusedWindow,
                new Searcher(database, new AddTypeSearcherAdapter("Select Run Script")),
                UpdateRunStep,
                @event.originalMousePosition + Vector2.up * 35.0f,
                a => { },
                new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top,
                                             SearcherWindow.Alignment.Horizontal.Left)
                );
        }
Beispiel #12
0
        internal static void ShowValues(string title, IEnumerable <string> values, Vector2 position,
                                        Action <string, int> callback)
        {
            var items    = values.Select(v => new SearcherItem(v)).ToList();
            var database = SearcherDatabase.Create(items, "", false);
            var searcher = new Searcher.Searcher(database, new SimpleSearcherAdapter(title));

            SearcherWindow.Show(EditorWindow.focusedWindow, searcher, item =>
            {
                if (item == null)
                {
                    return(false);
                }

                callback(item.Name, item.Id);
                return(true);
            }, position, null);
        }
Beispiel #13
0
        void AddDropdownCallbackDelegate(Rect buttonRect, ReorderableList list)
        {
            var database = TypeSearcherDatabase.Populate <IBuildStep>(
                type => !type.HasAttribute <HideInInspector>(),
                type => BuildStep.GetName(type),
                type => BuildStep.GetCategory(type));
            var searcher     = new Searcher(database, new AddTypeSearcherAdapter("Add Build Step"));
            var editorWindow = EditorWindow.focusedWindow;

            SearcherWindow.Show(
                editorWindow,
                searcher,
                AddStep,
                buttonRect.min + Vector2.up * 35.0f,
                a => { },
                new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top,
                                             SearcherWindow.Alignment.Horizontal.Left)
                );
        }
 void ShowSearcher(MouseDownEvent e)
 {
     if (NodeModel is SetVariableNodeModel model)
     {
         SearcherWindow.Show(EditorWindow.focusedWindow, ((VSGraphModel)model.GraphModel).GraphVariableModels.Where(g => GraphBuilder.GetVariableType(g) == GraphBuilder.VariableType.Variable)
                             .Select(v => (SearcherItem) new VariableSearcherItem(v)).ToList(), "Pick a variable to set", item =>
         {
             var variableSearcherItem = (item as VariableSearcherItem);
             if (variableSearcherItem == null)
             {
                 return(true);
             }
             model.DeclarationModel = variableSearcherItem.declarationModel;
             model.DefineNode();
             Store.Dispatch(new RefreshUIAction(UpdateFlags.GraphTopology));
             return(true);
         }, Event.current.mousePosition);
     }
 }
Beispiel #15
0
        void OnPickTargetButton(EventBase eventBase)
        {
            var items = DebuggerTracer.GetTargets(m_Store.GetState().currentTracingFrame, (m_Store.GetState().CurrentGraphModel?.AssetModel as Object)?.GetInstanceID() ?? -1)
                        .Select(x => (SearcherItem) new EntitySearcherItem(x)).ToList();

            SearcherWindow.Show(EditorWindow.focusedWindow, items, "Entities", i =>
            {
                if (i == null)
                {
                    return(true);
                }
                var t = ((EntitySearcherItem)i).Entity;
                m_Store.GetState().currentTracingTarget = t.EntityIndex;
                UpdateTracingMenu();
                return(true);
            }, eventBase.originalMousePosition);
            eventBase.StopPropagation();
            eventBase.PreventDefault();
        }
Beispiel #16
0
        void OnPickTargetButton(EventBase eventBase)
        {
            State     state         = m_Store.GetState();
            IDebugger debugger      = state.CurrentGraphModel.Stencil.Debugger;
            var       targetIndices = debugger.GetDebuggingTargets(state.CurrentGraphModel);
            var       items         = targetIndices == null ? null : targetIndices.Select(x =>
                                                                                          (SearcherItem) new TargetSearcherItem(x, debugger.GetTargetLabel(state.CurrentGraphModel, x))).ToList();

            if (items == null || !items.Any())
            {
                items = new List <SearcherItem> {
                    new SearcherItem("<No Object found>")
                }
            }
            ;

            SearcherWindow.Show(EditorWindow.focusedWindow, items, "Entities", i =>
            {
                if (i == null || !(i is TargetSearcherItem targetSearcherItem))
                {
                    return(true);
                }
                state.CurrentTracingTarget = targetSearcherItem.Target;
                UpdateTracingMenu();
                return(true);
            }, eventBase.originalMousePosition);
            eventBase.StopPropagation();
            eventBase.PreventDefault();
        }

        void OnFrameCounterKeyDown(KeyDownEvent evt)
        {
            if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)
            {
                int frame = m_CurrentFrameTextField.value;

                frame = Math.Max(0, Math.Min(frame, Time.frameCount));
                m_Store.GetState().CurrentTracingFrame = frame;
                m_Store.GetState().CurrentTracingStep  = -1;
                UpdateTracingMenu();
            }
        }
Beispiel #17
0
        internal static void ShowEnumValues(string title, Type enumType, Vector2 position, Action <Enum, int> callback)
        {
            var items = Enum.GetValues(enumType)
                        .Cast <Enum>()
                        .Select(v => new EnumValuesAdapter.EnumValueSearcherItem(v) as SearcherItem)
                        .ToList();
            var database = SearcherDatabase.Create(items, "", false);
            var searcher = new Searcher.Searcher(database, new EnumValuesAdapter(title));

            SearcherWindow.Show(EditorWindow.focusedWindow, searcher, item =>
            {
                if (item == null)
                {
                    return(false);
                }

                callback(((EnumValuesAdapter.EnumValueSearcherItem)item).value, 0);
                return(true);
            }, position, null);
        }
        static void PromptSearcher <T>(List <SearcherDatabase> databases, SearcherFilter filter,
                                       ISearcherAdapter adapter, Vector2 position, Action <T> callback) where T : ISearcherItemDataProvider
        {
            ApplyDatabasesFilter <T>(databases, filter);
            var searcher = new Searcher.Searcher(databases, adapter)
            {
                SortComparison = k_GraphElementSort
            };

            SearcherWindow.Show(EditorWindow.focusedWindow, searcher, item =>
            {
                if (item is T dataProvider)
                {
                    callback(dataProvider);
                    return(true);
                }

                return(false);
            }, position, null);
        }
Beispiel #19
0
        private void DumpFrameTrace()
        {
            var state             = m_Store.GetState();
            var currentGraphModel = state?.CurrentGraphModel;
            var debugger          = currentGraphModel?.Stencil?.Debugger;

            if (state == null || debugger == null)
            {
                return;
            }

            if (debugger.GetTracingSteps(currentGraphModel, state.CurrentTracingFrame, state.CurrentTracingTarget,
                                         out var stepList))
            {
                try
                {
                    var searcherItems = stepList.Select(MakeStepItem).ToList();
                    SearcherWindow.Show(EditorWindow.focusedWindow, searcherItems, "Steps", item =>
                    {
                        if (item != null)
                        {
                            state.CurrentTracingStep = ((StepSearcherItem)item).Index;
                        }
                        return(true);
                    }, Vector2.zero);
                }
                catch (Exception e)
                {
                    UnityEngine.Debug.LogException(e);
                }
            }
            else
            {
                Debug.Log("No frame data");
            }

            SearcherItem MakeStepItem(TracingStep step, int i)
            {
                return(new StepSearcherItem(step, i));
            }
        }
Beispiel #20
0
        static void PromptSearcher <T>(List <SearcherDatabase> databases, SearcherFilter filter,
                                       ISearcherAdapter adapter, Vector2 position, Action <T> callback) where T : ISearcherItemDataProvider
        {
            ApplyDatabasesFilter <T>(databases, filter);
            var searcher = new Searcher.Searcher(databases, adapter)
            {
                SortComparison = k_GraphElementSort
            };
            var ctx = typeof(T) == typeof(GraphNodeModelSearcherItem) ? SearcherContext.Graph : SearcherContext.Stack;

            SearcherWindow.Show(EditorWindow.focusedWindow, searcher, item =>
            {
                if (item is T dataProvider)
                {
                    callback(dataProvider);
                    return(true);
                }

                return(false);
            }, position, e => AnalyticsDataDelegate(e, ctx));
        }
Beispiel #21
0
        internal static void FindInGraph(
            EditorWindow host,
            VSGraphModel graph,
            Action <FindInGraphAdapter.FindSearcherItem> highlightDelegate,
            Action <FindInGraphAdapter.FindSearcherItem> selectionDelegate
            )
        {
            var items = graph.GetAllNodes()
                        .Where(x => !string.IsNullOrEmpty(x.Title))
                        .Select(MakeFindItems)
                        .ToList();
            var database = SearcherDatabase.Create(items, "", false);
            var searcher = new Searcher.Searcher(database, new FindInGraphAdapter(highlightDelegate));
            var position = new Vector2(host.rootVisualElement.layout.center.x, 0);

            SearcherWindow.Show(host, searcher, item =>
            {
                selectionDelegate(item as FindInGraphAdapter.FindSearcherItem);
                return(true);
            },
                                position, null, k_FindAlignment);
        }
Beispiel #22
0
        public SetVariableNode(SetVariableNodeModel model, Store store, GraphView builderGraphView)
            : base(model, store, builderGraphView)
        {
            // make it clear the ux is not final
            this.Q("title").style.backgroundColor = new StyleColor(new Color32(147, 15, 109, 255));
            this.Q <Label>("title-label").text    = "Set ";

            var pill  = new Pill();
            var label = pill.Q <Label>("title-label");

            label.text = model.DeclarationModel?.Name ?? "<Pick a variable>";

            var pillContainer = new VisualElement();

            pillContainer.AddToClassList("token");
            pillContainer.style.justifyContent = Justify.Center;
            pillContainer.style.flexGrow       = 1;
            pillContainer.Add(pill);

            titleContainer.Insert(1, pillContainer);
            titleContainer.styleSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(UICreationHelper.templatePath + "Token.uss"));

            pill.RegisterCallback <MouseDownEvent>(_ =>
            {
                SearcherWindow.Show(EditorWindow.focusedWindow, ((VSGraphModel)model.GraphModel).GraphVariableModels.Where(g => GraphBuilder.GetVariableType(g) == GraphBuilder.VariableType.Variable)
                                    .Select(v => (SearcherItem) new VariableSearcherItem(v)).ToList(), "Pick a variable to set", item =>
                {
                    var variableSearcherItem = (item as VariableSearcherItem);
                    if (variableSearcherItem == null)
                    {
                        return(true);
                    }
                    model.DeclarationModel = variableSearcherItem.declarationModel;
                    model.DefineNode();
                    store.Dispatch(new RefreshUIAction(UpdateFlags.GraphTopology));
                    return(true);
                }, Event.current.mousePosition);
            });
        }
Beispiel #23
0
        private void ShowSearcher(Vector2 position, int insertIndex, int insertViewIndex)
        {
            SearcherWindow.Show(EditorWindow.focusedWindow, searchItems, "Insert Line", item => {
                if (item is null)
                {
                    return(true);              // Prevent nullref when focus is lost before item is selected.
                }
                var lineText = string.Empty;
                var lineView = default(ScriptLineView);
                switch (item.Name)
                {
                case "Commands": return(false);    // Do nothing.

                case "Comment": lineText = CommentScriptLine.IdentifierLiteral; break;

                case "Label": lineText = LabelScriptLine.IdentifierLiteral; break;

                case "Generic Text":
                    var genericTextScriptLine = new GenericTextScriptLine(null, -1, string.Empty, null, true);
                    lineView = new GenericTextLineView(genericTextScriptLine, linesContainer);
                    break;

                case "Define": lineText = DefineScriptLine.IdentifierLiteral; break;

                default: lineText = CommandScriptLine.IdentifierLiteral + item.Name; break;
                }
                if (lineView is null)
                {
                    lineView = CreateLineView(lineText, -1, true);
                }
                InsertLine(lineView, insertIndex, insertViewIndex);
                ScriptLineView.SetFocused(lineView);
                lineView.Q <TextField>().Q <VisualElement>(TextInputBaseField <string> .textInputUssName).Focus();
                return(true);
            }, position);
        }
        public override void Build()
        {
            Reset();

            var targets = new List <Entity>();

            targets.AddRange(Targets.Where(e => e != Entity.Null && EntityManager.Exists(e)));

            ReSeatTargets(targets);

            if (targets.Count == 0)
            {
                return;
            }

            InspectorElement = new EntityInspectorElement(Session, ActualTargets);
            RootElement.contentContainer.Add(InspectorElement);

            var addComponentButton = new Button();

            addComponentButton.AddToClassList(UssClassNames.AddComponentButton);
            addComponentButton.text = "Add Component";
            addComponentButton.RegisterCallback <MouseUpEvent>(evt =>
            {
                using (var list = new NativeList <ComponentType>(10, Allocator.TempJob))
                    using (var map = new NativeHashMap <int, int>(10, Allocator.TempJob))
                    {
                        var container = new EntityContainer(EntityManager, ActualTargets[0], true);
                        PropertyContainer.Visit(ref container, new CommonComponentsVisitor(ActualTargets, EntityManager, list));

                        for (var i = 0; i < list.Length; ++i)
                        {
                            map.TryAdd(list[i].TypeIndex, 0);
                        }

                        var databases = new[]
                        {
                            ComponentSearcherDatabases.DynamicPopulateComponents(map),
                            ComponentSearcherDatabases.DynamicPopulateSharedComponents(map),
                            ComponentSearcherDatabases.DynamicPopulateBufferComponents(map),
                        };

                        var searcher = new Searcher(
                            databases,
                            ComponentSearcherDatabases.SearcherAdapter);


                        var editorWindow = EditorWindow.focusedWindow;
                        var button       = evt.target as Button;

                        SearcherWindow.Show(
                            editorWindow,
                            searcher,
                            AddType,
                            button.worldBound.center + Vector2.up * (button.worldBound.height - 10.0f) / 2.0f,
                            a => { },
                            new SearcherWindow.Alignment(SearcherWindow.Alignment.Vertical.Top,
                                                         SearcherWindow.Alignment.Horizontal.Center)
                            );
                    }
            });

            RootElement.contentContainer.Add(addComponentButton);
        }
Beispiel #25
0
        VisualElement MakeFieldRow(FieldModel fieldModel)
        {
            var field = new BlackboardField(null, fieldModel.Name, fieldModel.Type?.FriendlyName() ?? "<unknown>");

            field.userData = fieldModel;
            var propertyView = new VisualElement();

            var fieldRow = new BlackboardRow(field, propertyView)
            {
                userData = fieldModel
            };

            fieldRow.expanded = m_ExpandedRows.Contains(fieldModel);

            field.Add(new Button(() => DeleteField(fieldRow, fieldModel))
            {
                name = "deleteComponentIcon"
            });

            var fieldType = new Button()
            {
                text = fieldModel.Type?.FriendlyName() ?? "<unknown>"
            };

            fieldType.clickable.clicked += () =>
            {
                InitializeTypeItemsAndCache(); // delay init as the type cache seems to have a weird timing issue otherwise
                SearcherWindow.Show(this, new Searcher.Searcher(new SearcherDatabase(TypeItems), new TypeSearcherAdapter("Pick a type")), item =>
                {
                    PickTypeSearcherItem titem = item as PickTypeSearcherItem;

                    if (titem == null)
                    {
                        return(true);
                    }
                    fieldModel.Type = titem.Type;
                    fieldType.text  = titem.Type.FriendlyName();

                    if (titem.Shared)
                    {
                        SetStructType(CurrentStruct, StructType.SharedComponent);
                    }

                    SetModelDirty();

                    return(true);
                }, Event.current.mousePosition, null);
            };
            propertyView.Add(new PropertyRow("Type", fieldType));

            var toggle = new Toggle()
            {
                value = fieldModel.HideInInspector
            };

            toggle.RegisterValueChangedCallback(e =>
            {
                fieldModel.HideInInspector = e.newValue;
                SetModelDirty();
            });
            propertyView.Add(new PropertyRow("Hide in inspector", toggle));

            // TODO ugly
            if (!fieldModel.Type.IsValueType && fieldModel.Type != typeof(GameObject))
            {
                propertyView.Add(new Label("This is a reference type and requires the component to be a shared component"));
            }
            return(fieldRow);
        }
        void OnPickTargetButton(EventBase eventBase)
        {
            State     state         = m_Store.GetState();
            IDebugger debugger      = state.CurrentGraphModel.Stencil.Debugger;
            var       targetIndices = debugger.GetDebuggingTargets(state.CurrentGraphModel);
            var       items         = targetIndices == null ? null : targetIndices.Select(x =>
                                                                                          (SearcherItem) new TargetSearcherItem(x, debugger.GetTargetLabel(state.CurrentGraphModel, x))).ToList();

            if (items == null || !items.Any())
            {
                items = new List <SearcherItem> {
                    new SearcherItem("<No Object found>")
                }
            }
            ;

            SearcherWindow.Show(EditorWindow.focusedWindow, items, "Entities", i =>
            {
                if (i == null || !(i is TargetSearcherItem targetSearcherItem))
                {
                    return(true);
                }
                state.CurrentTracingTarget = targetSearcherItem.Target;
                UpdateTracingMenu();
                return(true);
            }, eventBase.originalMousePosition);
            eventBase.StopPropagation();
            eventBase.PreventDefault();
        }

        void OnFrameCounterKeyDown(KeyDownEvent evt)
        {
            if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)
            {
                int frame = m_CurrentFrameTextField.value;

                frame = Math.Max(0, Math.Min(frame, Time.frameCount));
                m_Store.GetState().CurrentTracingFrame = frame;
                m_Store.GetState().CurrentTracingStep  = -1;
                UpdateTracingMenu();
            }
        }

        void UpdateTracingMenu(bool force = true)
        {
            var state = m_Store.GetState();

            if (EditorApplication.isPlaying && state.EditorDataModel.TracingEnabled)
            {
                m_PickTargetLabel.text            = state.CurrentGraphModel?.Stencil?.Debugger?.GetTargetLabel(state.CurrentGraphModel, state.CurrentTracingTarget);
                m_PickTargetIcon.style.visibility = Visibility.Hidden;
                m_PickTargetButton.SetEnabled(true);
                if (EditorApplication.isPaused || !EditorApplication.isPlaying)
                {
                    m_FirstFrameTracingButton.SetEnabled(true);
                    m_PreviousFrameTracingButton.SetEnabled(true);
                    m_PreviousStepTracingButton.SetEnabled(true);
                    m_NextStepTracingButton.SetEnabled(true);
                    m_NextFrameTracingButton.SetEnabled(true);
                    m_LastFrameTracingButton.SetEnabled(true);
                    m_CurrentFrameTextField.SetEnabled(true);
                    m_TotalFrameLabel.SetEnabled(true);
                }
                else
                {
                    state.CurrentTracingFrame = Time.frameCount;
                    state.CurrentTracingStep  = -1;
                    m_FirstFrameTracingButton.SetEnabled(false);
                    m_PreviousFrameTracingButton.SetEnabled(false);
                    m_PreviousStepTracingButton.SetEnabled(false);
                    m_NextStepTracingButton.SetEnabled(false);
                    m_NextFrameTracingButton.SetEnabled(false);
                    m_LastFrameTracingButton.SetEnabled(false);
                    m_CurrentFrameTextField.SetEnabled(false);
                    m_TotalFrameLabel.SetEnabled(false);
                }

                if (!m_LastUpdate.IsRunning)
                {
                    m_LastUpdate.Start();
                }
                if (force || EditorApplication.isPaused || m_LastUpdate.ElapsedMilliseconds > k_UpdateIntervalMs)
                {
                    m_CurrentFrameTextField.value = state.CurrentTracingFrame;
                    m_TotalFrameLabel.text        = $"/{Time.frameCount.ToString()}";
                    if (state.CurrentTracingStep != -1)
                    {
                        m_TotalFrameLabel.text += $" [{state.CurrentTracingStep}/{state.MaxTracingStep}]";
                    }

                    m_LastUpdate.Restart();
                }
            }
            else
            {
                m_LastUpdate.Stop();
                state.CurrentTracingFrame         = Time.frameCount;
                state.CurrentTracingStep          = -1;
                m_PickTargetLabel.text            = "";
                m_PickTargetIcon.style.visibility = StyleKeyword.Null;
                m_CurrentFrameTextField.value     = 0;
                m_PickTargetButton.SetEnabled(false);
                m_CurrentFrameTextField.SetEnabled(false);
                m_TotalFrameLabel.text = "/0";
                m_TotalFrameLabel.SetEnabled(false);
                m_FirstFrameTracingButton.SetEnabled(false);
                m_PreviousFrameTracingButton.SetEnabled(false);
                m_PreviousStepTracingButton.SetEnabled(false);
                m_NextStepTracingButton.SetEnabled(false);
                m_NextFrameTracingButton.SetEnabled(false);
                m_LastFrameTracingButton.SetEnabled(false);
            }
        }

        void OnFirstFrameTracingButton()
        {
            m_Store.GetState().CurrentTracingFrame = 0;
            m_Store.GetState().CurrentTracingStep  = -1;
            UpdateTracingMenu();
        }

        void OnPreviousFrameTracingButton()
        {
            if (m_Store.GetState().CurrentTracingFrame > 0)
            {
                m_Store.GetState().CurrentTracingFrame--;
                m_Store.GetState().CurrentTracingStep = -1;
                UpdateTracingMenu();
            }
        }

        void OnPreviousStepTracingButton()
        {
            if (m_Store.GetState().CurrentTracingStep > 0)
            {
                m_Store.GetState().CurrentTracingStep--;
            }
            else
            {
                if (m_Store.GetState().CurrentTracingStep == -1)
                {
                    m_Store.GetState().CurrentTracingStep = m_Store.GetState().MaxTracingStep;
                }
                else
                {
                    if (m_Store.GetState().CurrentTracingFrame > 0)
                    {
                        m_Store.GetState().CurrentTracingFrame--;
                        m_Store.GetState().CurrentTracingStep = m_Store.GetState().MaxTracingStep;
                    }
                }
            }

            UpdateTracingMenu();
        }

        void OnNextStepTracingButton()
        {
            if (m_Store.GetState().CurrentTracingStep < m_Store.GetState().MaxTracingStep&& m_Store.GetState().CurrentTracingStep >= 0)
            {
                m_Store.GetState().CurrentTracingStep++;
            }
            else
            {
                if (m_Store.GetState().CurrentTracingStep == -1 && (m_Store.GetState().CurrentTracingFrame < Time.frameCount))
                {
                    m_Store.GetState().CurrentTracingStep = 0;
                }
                else
                {
                    if (m_Store.GetState().CurrentTracingFrame < Time.frameCount)
                    {
                        m_Store.GetState().CurrentTracingFrame++;
                        m_Store.GetState().CurrentTracingStep = 0;
                    }
                }
            }

            UpdateTracingMenu();
        }

        void OnNextFrameTracingButton()
        {
            if (m_Store.GetState().CurrentTracingFrame < Time.frameCount)
            {
                m_Store.GetState().CurrentTracingFrame++;
                m_Store.GetState().CurrentTracingStep = -1;
                UpdateTracingMenu();
            }
        }

        void OnLastFrameTracingButton()
        {
            m_Store.GetState().CurrentTracingFrame = Time.frameCount;
            m_Store.GetState().CurrentTracingStep  = -1;
            UpdateTracingMenu();
        }
    }