static void GenerateProjectContentTrees()
        {
            ProjectContentTree           = new List <ITreeViewItem>();
            ProjectContentTreeNoPackages = new List <ITreeViewItem>();

            var fromProjectCategory = new BuilderLibraryTreeItem(BuilderConstants.LibraryAssetsSectionHeaderName, null, null, null)
            {
                IsHeader = true
            };

            s_ProjectAssetsScanner.ImportUxmlFromProject(fromProjectCategory, true);
            ProjectContentTree.Add(fromProjectCategory);

            var fromProjectCategoryNoPackages = new BuilderLibraryTreeItem(BuilderConstants.LibraryAssetsSectionHeaderName, null, null, null)
            {
                IsHeader = true
            };

            s_ProjectAssetsScanner.ImportUxmlFromProject(fromProjectCategoryNoPackages, false);
            ProjectContentTreeNoPackages.Add(fromProjectCategoryNoPackages);

            var customControlsCategory = new BuilderLibraryTreeItem(BuilderConstants.LibraryCustomControlsSectionHeaderName, null, null, null)
            {
                IsHeader = true
            };

            s_ProjectAssetsScanner.ImportFactoriesFromSource(customControlsCategory);
            if (customControlsCategory.hasChildren)
            {
                ProjectContentTree.Add(customControlsCategory);
                ProjectContentTreeNoPackages.Add(customControlsCategory);
            }
        }
        protected override bool StartDrag(VisualElement target, Vector2 mousePosition, VisualElement pill)
        {
            m_LibraryItem =
                target.GetProperty(BuilderConstants.LibraryItemLinkedManipulatorVEPropertyName)
                as BuilderLibraryTreeItem;
            if (m_LibraryItem == null)
            {
                return(false);
            }

            var isCurrentDocumentVisualTreeAsset = m_LibraryItem.sourceAsset == paneWindow.document.visualTreeAsset;

            if (isCurrentDocumentVisualTreeAsset)
            {
                return(false);
            }

            m_MadeElement = m_LibraryItem.makeVisualElementCallback?.Invoke();
            if (m_MadeElement == null)
            {
                return(false);
            }

            m_TooltipPreview.Disable();

            return(true);
        }
Example #3
0
        public void ImportUxmlFromProject(BuilderLibraryTreeItem projectCategory, bool includePackages)
        {
            var assets        = AssetDatabase.FindAllAssets(m_SearchFilter);
            var categoryStack = new List <BuilderLibraryTreeItem>();

            foreach (var asset in assets)
            {
                var assetPath  = AssetDatabase.GetAssetPath(asset.instanceID);
                var prettyPath = assetPath;
                prettyPath = Path.GetDirectoryName(prettyPath);
                prettyPath = prettyPath.ConvertSeparatorsToUnity();
                if (prettyPath.StartsWith("Packages/") && !includePackages)
                {
                    continue;
                }

                if (prettyPath.StartsWith(BuilderConstants.UIBuilderPackageRootPath))
                {
                    continue;
                }

                var split = prettyPath.Split('/');
                AddCategoriesToStack(projectCategory, categoryStack, split);

                var vta     = asset.pptrValue as VisualTreeAsset;
                var newItem = new BuilderLibraryTreeItem(asset.name + ".uxml", null, typeof(TemplateContainer),
                                                         () =>
                {
                    if (vta == null)
                    {
                        return(null);
                    }

                    var tree = vta.CloneTree();
                    tree.SetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName, assetPath);
                    tree.name = vta.name;
                    return(tree);
                },
                                                         (inVta, inParent, ve) =>
                {
                    var vea = inVta.AddTemplateInstance(inParent, assetPath) as VisualElementAsset;
                    vea.AddProperty("name", vta.name);
                    ve.SetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName, vta);
                    return(vea);
                },
                                                         null, vta);
                newItem.SetIcon((Texture2D)EditorGUIUtility.IconContent("UxmlScript Icon").image);
                newItem.HasPreview = true;

                if (categoryStack.Count == 0)
                {
                    projectCategory.AddChild(newItem);
                }
                else
                {
                    categoryStack.Last().AddChild(newItem);
                }
            }
        }
        protected void AddItemToTheDocument(BuilderLibraryTreeItem item)
        {
            // If this is the uxml file entry of the currently open file, don't allow
            // the user to instantiate it (infinite recursion) or re-open it.
            var  listOfOpenDocuments   = m_PaneWindow.document.openUXMLFiles;
            bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.name);

            if (isCurrentDocumentOpen)
            {
                return;
            }

            if (m_PaneWindow.document.WillCauseCircularDependency(item.sourceAsset))
            {
                BuilderDialogsUtility.DisplayDialog(BuilderConstants.InvalidWouldCauseCircularDependencyMessage,
                                                    BuilderConstants.InvalidWouldCauseCircularDependencyMessageDescription, null);
                return;
            }

            var newElement = item.makeVisualElementCallback?.Invoke();

            if (newElement == null)
            {
                return;
            }

            if (item.makeElementAssetCallback != null && newElement is TemplateContainer tempContainer)
            {
                if (!BuilderAssetUtilities.ValidateAsset(item.sourceAsset, item.sourceAssetPath))
                {
                    return;
                }
            }

            var activeVTARootElement = m_DocumentRootElement.Query().Where(e => e.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset).First();

            if (activeVTARootElement == null)
            {
                Debug.LogError("UI Builder has a bug. Could not find document root element for currently active open UXML document.");
                return;
            }
            activeVTARootElement.Add(newElement);

            if (item.makeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    m_PaneWindow.document, newElement, item.makeElementAssetCallback);
            }

            m_Selection.NotifyOfHierarchyChange();
            m_Selection.Select(null, newElement);
        }
Example #5
0
        internal static TreeViewItemData <BuilderLibraryTreeItem> CreateItem(string name, string iconName, Type type, Func <VisualElement> makeVisualElementCallback,
                                                                             Func <VisualTreeAsset, VisualElementAsset, VisualElement, VisualElementAsset> makeElementAssetCallback = null, List <TreeViewItemData <BuilderLibraryTreeItem> > children = null, VisualTreeAsset asset = null,
                                                                             int id = default, bool isHeader = false, bool isEditorOnly = false)
        {
            var itemId = BuilderLibraryTreeItem.GetItemId(name, type, asset, id);
            var data   = new BuilderLibraryTreeItem(name, iconName, type, makeVisualElementCallback, makeElementAssetCallback, asset)
            {
                isHeader = isHeader, isEditorOnly = isEditorOnly
            };

            return(new TreeViewItemData <BuilderLibraryTreeItem>(itemId, data, children));
        }
Example #6
0
        protected void AddItemToTheDocument(BuilderLibraryTreeItem item)
        {
            // If this is the uxml file entry of the currently open file, don't allow
            // the user to instantiate it (infinite recursion) or re-open it.
            var  listOfOpenDocuments   = m_PaneWindow.document.openUXMLFiles;
            bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.name);

            if (isCurrentDocumentOpen)
            {
                return;
            }

            var newElement = item.makeVisualElementCallback?.Invoke();

            if (newElement == null)
            {
                return;
            }

            var activeVTARootElement = m_DocumentRootElement.Query().Where(e => e.GetVisualTreeAsset() == m_PaneWindow.document.visualTreeAsset).First();

            if (activeVTARootElement == null)
            {
                Debug.LogError("UI Builder has a bug. Could not find document root element for currently active open UXML document.");
                return;
            }
            activeVTARootElement.Add(newElement);

            if (item.makeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    m_PaneWindow.document, newElement, item.makeElementAssetCallback);
            }

            // TODO: ListView bug. Does not refresh selection pseudo states after a
            // call to Refresh().
            m_Selection.NotifyOfHierarchyChange();
            schedule.Execute(() =>
            {
                m_Selection.Select(null, newElement);
            }).ExecuteLater(200);
        }
        static void AddCategoriesToStack(BuilderLibraryTreeItem sourceCategory, List <BuilderLibraryTreeItem> categoryStack, string[] split)
        {
            if (categoryStack.Count > split.Length)
            {
                categoryStack.RemoveRange(split.Length, categoryStack.Count - split.Length);
            }

            string fullName = string.Empty;

            for (int i = 0; i < split.Length; ++i)
            {
                var part = split[i];
                fullName += part;
                if (categoryStack.Count > i)
                {
                    if (categoryStack[i].name == part)
                    {
                        continue;
                    }
                    else if (categoryStack[i].name != part)
                    {
                        categoryStack.RemoveRange(i, categoryStack.Count - i);
                    }
                }

                if (categoryStack.Count <= i)
                {
                    var newCategory = new BuilderLibraryTreeItem(part,
                                                                 null, null, null,
                                                                 null, new List <TreeViewItem <string> >(),
                                                                 null, fullName.GetHashCode());

                    if (categoryStack.Count == 0)
                    {
                        sourceCategory.AddChild(newCategory);
                    }
                    else
                    {
                        categoryStack[i - 1].AddChild(newCategory);
                    }

                    categoryStack.Add(newCategory);
                }
            }
        }
        protected override bool StartDrag(VisualElement target, Vector2 mousePosition, VisualElement pill)
        {
            m_LibraryItem =
                target.GetProperty(BuilderConstants.LibraryItemLinkedManipulatorVEPropertyName)
                as BuilderLibraryTreeItem;
            if (m_LibraryItem == null)
            {
                return(false);
            }

            var isCurrentDocumentVisualTreeAsset = m_LibraryItem.sourceAsset == paneWindow.document.visualTreeAsset;

            if (isCurrentDocumentVisualTreeAsset)
            {
                return(false);
            }

            var madeElement = m_LibraryItem.makeVisualElementCallback?.Invoke();

            if (madeElement == null)
            {
                return(false);
            }

            pill.Clear();

            madeElement.AddToClassList(s_BeingDraggedClassName);
            pill.Add(madeElement);

            if (madeElement.GetType() == typeof(VisualElement))
            {
                madeElement.AddToClassList(s_EmptyVisualElementClassName);
            }

            var overlay = new VisualElement();

            overlay.name = s_OverlayName;
            overlay.AddToClassList(s_OverlayClassName);
            pill.Add(overlay);

            m_TooltipPreview.Disable();

            return(true);
        }
Example #9
0
        protected void AddItemToTheDocument(BuilderLibraryTreeItem item)
        {
            // If this is the uxml file entry of the currently open file, don't allow
            // the user to instantiate it (infinite recursion) or re-open it.
            var  listOfOpenDocuments   = m_PaneWindow.document.openUXMLFiles;
            bool isCurrentDocumentOpen = listOfOpenDocuments.Any(doc => doc.uxmlFileName == item.Name);

            if (isCurrentDocumentOpen)
            {
                return;
            }

            var newElement = item.MakeVisualElementCallback?.Invoke();

            if (newElement == null)
            {
                return;
            }

            m_DocumentElement.Add(newElement);

            if (item.MakeElementAssetCallback == null)
            {
                BuilderAssetUtilities.AddElementToAsset(m_PaneWindow.document, newElement);
            }
            else
            {
                BuilderAssetUtilities.AddElementToAsset(
                    m_PaneWindow.document, newElement, item.MakeElementAssetCallback);
            }

            // TODO: ListView bug. Does not refresh selection pseudo states after a
            // call to Refresh().
            m_Selection.NotifyOfHierarchyChange();
            schedule.Execute(() =>
            {
                m_Selection.Select(null, newElement);
            }).ExecuteLater(200);
        }
            public LibraryPlainViewItem(BuilderLibraryTreeItem libraryTreeItem)
            {
                m_TreeItem = libraryTreeItem;
                var template = BuilderPackageUtilities.LoadAssetAtPath <VisualTreeAsset>(BuilderConstants.LibraryUIPath + "/BuilderLibraryPlainViewItem.uxml");

                template.CloneTree(this);

                var styleSheet = BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(BuilderConstants.LibraryUIPath + "/BuilderLibraryPlainViewItem.uss");

                styleSheets.Add(styleSheet);

                content = ElementAt(0);
                if (m_TreeItem == null)
                {
                    content.AddToClassList(k_PlainViewNoHoverVariantUssClassName);
                    content.Clear();
                    return;
                }

                this.Q <Label>().text = m_TreeItem.data;
                m_Icon = this.Q <VisualElement>("icon");
                SetIcon(m_TreeItem.largeIcon);
            }
 protected void LinkToTreeViewItem(VisualElement element, BuilderLibraryTreeItem libraryTreeItem)
 {
     element.userData = libraryTreeItem;
     element.SetProperty(BuilderConstants.LibraryItemLinkedManipulatorVEPropertyName, libraryTreeItem);
 }
        static List <ITreeViewItem> GenerateControlsItemsTree()
        {
            var controlsTree   = new List <ITreeViewItem>();
            var containersItem = new BuilderLibraryTreeItem(BuilderConstants.LibraryContainersSectionHeaderName, null, null, null)
            {
                IsHeader = true
            };
            IList <ITreeViewItem> containersItemList = new List <ITreeViewItem>
            {
                new BuilderLibraryTreeItem("VisualElement", "VisualElement", typeof(VisualElement), () =>
                {
                    var ve              = new VisualElement();
                    var veMinSizeChild  = new VisualElement();
                    veMinSizeChild.name = BuilderConstants.SpecialVisualElementInitialMinSizeName;
                    veMinSizeChild.AddToClassList(BuilderConstants.SpecialVisualElementInitialMinSizeClassName);
                    ve.Add(veMinSizeChild);
                    return(ve);
                },
                                           (inVta, inParent, ve) =>
                {
                    var vea = new VisualElementAsset(typeof(VisualElement).ToString());
                    VisualTreeAssetUtilities.InitializeElement(vea);
                    inVta.AddElement(inParent, vea);
                    return(vea);
                }),
                new BuilderLibraryTreeItem("ScrollView", "ScrollView", typeof(ScrollView), () => new ScrollView()),
                new BuilderLibraryTreeItem("ListView", "ListView", typeof(ListView), () => new ListView()),
                new BuilderLibraryTreeItem("IMGUI Container", "VisualElement", typeof(IMGUIContainer), () => new IMGUIContainer()),
            };

            containersItem.AddChildren(containersItemList);
            controlsTree.Add(containersItem);

            var controlsItem = new BuilderLibraryTreeItem(BuilderConstants.LibraryControlsSectionHeaderName, null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("Label", nameof(Label), typeof(Label), () => new Label("Label")),
                new BuilderLibraryTreeItem("Button", nameof(Button), typeof(Button), () => new Button {
                    text = "Button"
                }),
                new BuilderLibraryTreeItem("Toggle", nameof(Toggle), typeof(Toggle), () => new Toggle("Toggle")),
                new BuilderLibraryTreeItem("Scroller", nameof(Scroller), typeof(Scroller), () => new Scroller(0, 100, (v) => { }, SliderDirection.Horizontal)
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Text Field", nameof(TextField), typeof(TextField), () => new TextField("Text Field")
                {
                    value = "filler text"
                }),
                new BuilderLibraryTreeItem("Foldout", nameof(Foldout), typeof(Foldout), () => new Foldout {
                    text = "Foldout"
                }),
                new BuilderLibraryTreeItem("Slider", nameof(Slider), typeof(Slider), () => new Slider("Slider", 0, 100)
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Min-Max Slider", nameof(MinMaxSlider), typeof(MinMaxSlider), () => new MinMaxSlider("Min/Max Slider", 0, 20, -10, 40)
                {
                    value = new Vector2(10, 12)
                }),
            })
            {
                IsHeader = true
            };

            var numericFields = new BuilderLibraryTreeItem("Numeric Fields", null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("Integer", nameof(IntegerField), typeof(IntegerField), () => new IntegerField("Int Field")
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Float", nameof(FloatField), typeof(FloatField), () => new FloatField("Float Field")
                {
                    value = 42.2f
                }),
                new BuilderLibraryTreeItem("Long", nameof(LongField), typeof(LongField), () => new LongField("Long Field")
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Min-Max Slider", nameof(MinMaxSlider), typeof(MinMaxSlider), () => new MinMaxSlider("Min/Max Slider", 0, 20, -10, 40)
                {
                    value = new Vector2(10, 12)
                }),
                new BuilderLibraryTreeItem("Slider", nameof(Slider), typeof(Slider), () => new Slider("Slider", 0, 100)
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Progress Bar", nameof(ProgressBar), typeof(ProgressBar), () => new ProgressBar()
                {
                    title = "my-progress", value = 22
                }),
                new BuilderLibraryTreeItem("Vector2", nameof(Vector2Field), typeof(Vector2Field), () => new Vector2Field("Vec2 Field")),
                new BuilderLibraryTreeItem("Vector3", nameof(Vector3Field), typeof(Vector3Field), () => new Vector3Field("Vec3 Field")),
                new BuilderLibraryTreeItem("Vector4", nameof(Vector4Field), typeof(Vector4Field), () => new Vector4Field("Vec4 Field")),
                new BuilderLibraryTreeItem("Rect", nameof(RectField), typeof(RectField), () => new RectField("Rect")),
                new BuilderLibraryTreeItem("Bounds", nameof(BoundsField), typeof(BoundsField), () => new BoundsField("Bounds")),
                new BuilderLibraryTreeItem("Slider (Int)", nameof(SliderInt), typeof(SliderInt), () => new SliderInt("SliderInt", 0, 100)
                {
                    value = 42
                }),
                new BuilderLibraryTreeItem("Vector2 (Int)", nameof(Vector2IntField), typeof(Vector2IntField), () => new Vector2IntField("Vector2Int")),
                new BuilderLibraryTreeItem("Vector3 (Int)", nameof(Vector3IntField), typeof(Vector3IntField), () => new Vector3IntField("Vector3Int")),
                new BuilderLibraryTreeItem("Rect (Int)", nameof(RectIntField), typeof(RectIntField), () => new RectIntField("RectInt")),
                new BuilderLibraryTreeItem("Bounds (Int)", nameof(BoundsIntField), typeof(BoundsIntField), () => new BoundsIntField("BoundsInt")),
                new BuilderLibraryTreeItem("Object Field", nameof(ObjectField), typeof(ObjectField), () => new ObjectField("Object Field")
                {
                    value = new Texture2D(10, 10)
                    {
                        name = "new_texture"
                    }
                }),
            })
            {
                IsEditorOnly = true, IsHeader = true
            };

            var valueFields = new BuilderLibraryTreeItem("Value Fields", null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("Color", nameof(ColorField), typeof(ColorField), () => new ColorField("Color")
                {
                    value = Color.cyan
                }),
                new BuilderLibraryTreeItem("Curve", nameof(CurveField), typeof(CurveField), () => new CurveField("Curve")
                {
                    value = new AnimationCurve(new Keyframe(0, 0), new Keyframe(5, 8), new Keyframe(10, 4))
                }),
                new BuilderLibraryTreeItem("Gradient", nameof(GradientField), typeof(GradientField), () => new GradientField("Gradient")
                {
                    value = new Gradient()
                    {
                        colorKeys = new[]
                        {
                            new GradientColorKey(Color.red, 0),
                            new GradientColorKey(Color.blue, 10),
                            new GradientColorKey(Color.green, 20)
                        }
                    }
                })
            })
            {
                IsEditorOnly = true, IsHeader = true
            };

            var choiceFields = new BuilderLibraryTreeItem("Choice Fields", null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("Enum", nameof(EnumField), typeof(EnumField), () => new EnumField("Enum", TextAlignment.Center)),

                // No UXML support for PopupField.
                //new LibraryTreeItem("Popup", () => new PopupField<string>("Normal Field", choices, 0)),

                new BuilderLibraryTreeItem("Tag", nameof(TagField), typeof(TagField), () => new TagField("Tag", "Player")),
                new BuilderLibraryTreeItem("Mask", nameof(MaskField), typeof(MaskField), () => new MaskField("Mask")),
                new BuilderLibraryTreeItem("Layer", nameof(LayerField), typeof(LayerField), () => new LayerField("Layer")),
                new BuilderLibraryTreeItem("LayerMask", nameof(LayerMaskField), typeof(LayerMaskField), () => new LayerMaskField("LayerMask"))
            })
            {
                IsEditorOnly = true, IsHeader = true
            };

            var toolbar = new BuilderLibraryTreeItem("Toolbar", null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("Toolbar", "ToolbarElement", typeof(Toolbar), () => new Toolbar()),
                new BuilderLibraryTreeItem("Toolbar Menu", "ToolbarElement", typeof(ToolbarMenu), () => new ToolbarMenu()),
                new BuilderLibraryTreeItem("Toolbar Button", "ToolbarElement", typeof(ToolbarButton), () => new ToolbarButton {
                    text = "Button"
                }),
                new BuilderLibraryTreeItem("Toolbar Spacer", "ToolbarElement", typeof(ToolbarSpacer), () => new ToolbarSpacer()),
                new BuilderLibraryTreeItem("Toolbar Toggle", "ToolbarElement", typeof(ToolbarToggle), () => new ToolbarToggle {
                    label = "Toggle"
                }),
#if UNITY_2019_3_OR_NEWER
                new BuilderLibraryTreeItem("Toolbar Breadcrumbs", "ToolbarElement", typeof(ToolbarBreadcrumbs), () => new ToolbarBreadcrumbs()),
#endif
                new BuilderLibraryTreeItem("Toolbar Search Field", "ToolbarElement", typeof(ToolbarSearchField), () => new ToolbarSearchField()),
                new BuilderLibraryTreeItem("Toolbar Popup Search Field", "ToolbarElement", typeof(ToolbarPopupSearchField), () => new ToolbarPopupSearchField()),
            })
            {
                IsEditorOnly = true, IsHeader = true
            };

            var inspectors = new BuilderLibraryTreeItem("Inspectors", null, null, null, null, new List <TreeViewItem <string> >
            {
                new BuilderLibraryTreeItem("PropertyField", nameof(PropertyField), typeof(PropertyField), () => new PropertyField())
            })
            {
                IsEditorOnly = true, IsHeader = true
            };

            controlsTree.Add(controlsItem);
            controlsTree.Add(numericFields);
            controlsTree.Add(valueFields);
            controlsTree.Add(choiceFields);
            controlsTree.Add(toolbar);
            controlsTree.Add(inspectors);

            return(controlsTree);
        }
        public void ImportFactoriesFromSource(BuilderLibraryTreeItem sourceCategory)
        {
            var deferredFactories      = new List <IUxmlFactory>();
            var processingData         = new FactoryProcessingHelper();
            var emptyNamespaceControls = new List <ITreeViewItem>();

            foreach (var factories in VisualElementFactoryRegistry.factories)
            {
                if (factories.Value.Count == 0)
                {
                    continue;
                }

                var factory = factories.Value[0];
                if (!ProcessFactory(factory, processingData))
                {
                    // Could not process the factory now, because it depends on a yet unprocessed factory.
                    // Defer its processing.
                    deferredFactories.Add(factory);
                }
            }

            List <IUxmlFactory> deferredFactoriesCopy;

            do
            {
                deferredFactoriesCopy = new List <IUxmlFactory>(deferredFactories);
                foreach (var factory in deferredFactoriesCopy)
                {
                    deferredFactories.Remove(factory);
                    if (!ProcessFactory(factory, processingData))
                    {
                        // Could not process the factory now, because it depends on a yet unprocessed factory.
                        // Defer its processing again.
                        deferredFactories.Add(factory);
                    }
                }
            }while (deferredFactoriesCopy.Count > deferredFactories.Count);

            if (deferredFactories.Count > 0)
            {
                Debug.Log("Some factories could not be processed because their base type is missing.");
            }

            var categoryStack = new List <BuilderLibraryTreeItem>();

            foreach (var known in processingData.knownTypes.Values)
            {
                var split = known.uxmlNamespace.Split('.');
                if (split.Length == 0)
                {
                    continue;
                }

                // Avoid adding our own internal factories (like Package Manager templates).
                if (!Unsupported.IsDeveloperMode() && split.Length > 0 && s_NameSpacesToAvoid.Contains(split[0]))
                {
                    continue;
                }

                // Avoid adding UI Builder's own types, even in internal mode.
                if (split.Length >= 3 && split[0] == "Unity" && split[1] == "UI" && split[2] == "Builder")
                {
                    continue;
                }

                var asset     = new VisualElementAsset(known.uxmlQualifiedName);
                var slots     = new Dictionary <string, VisualElement>();
                var overrides = new List <TemplateAsset.AttributeOverride>();
                var vta       = ScriptableObject.CreateInstance <VisualTreeAsset>();
                var context   = new CreationContext(slots, overrides, vta, null);

                Type elementType = null;
                var  factoryType = known.GetType();
                while (factoryType != null && elementType == null)
                {
                    if (factoryType.IsGenericType && factoryType.GetGenericTypeDefinition() == typeof(UxmlFactory <,>))
                    {
                        elementType = factoryType.GetGenericArguments()[0];
                    }
                    else
                    {
                        factoryType = factoryType.BaseType;
                    }
                }

                var newItem = new BuilderLibraryTreeItem(
                    known.uxmlName, "CustomCSharpElement", elementType, () => known.Create(asset, context));
                newItem.hasPreview = true;

                if (string.IsNullOrEmpty(split[0]))
                {
                    emptyNamespaceControls.Add(newItem);
                }
                else
                {
                    AddCategoriesToStack(sourceCategory, categoryStack, split);
                    if (categoryStack.Count == 0)
                    {
                        sourceCategory.AddChild(newItem);
                    }
                    else
                    {
                        categoryStack.Last().AddChild(newItem);
                    }
                }
            }

            sourceCategory.AddChildren(emptyNamespaceControls);
        }
        public void ImportUxmlFromProject(BuilderLibraryTreeItem projectCategory, bool includePackages)
        {
            var assets        = AssetDatabase.FindAllAssets(m_SearchFilter);
            var categoryStack = new List <BuilderLibraryTreeItem>();

            foreach (var asset in assets)
            {
                var assetPath  = AssetDatabase.GetAssetPath(asset.instanceID);
                var prettyPath = assetPath;
                prettyPath = Path.GetDirectoryName(prettyPath);
                prettyPath = prettyPath.ConvertSeparatorsToUnity();
                if (prettyPath.StartsWith("Packages/") && !includePackages)
                {
                    continue;
                }

                if (prettyPath.StartsWith(BuilderConstants.UIBuilderPackageRootPath))
                {
                    continue;
                }

                // Check to make sure the asset is actually writable.
                var packageInfo = PackageInfo.FindForAssetPath(assetPath);
                if (packageInfo != null && packageInfo.source != PackageSource.Embedded && packageInfo.source != PackageSource.Local)
                {
                    continue;
                }

                // Anoter way to check the above. Leaving it here for references in case the above stops working.
                //AssetDatabase.GetAssetFolderInfo(assetPath, out bool isRoot, out bool isImmutable);
                //if (isImmutable)
                //continue;

                var split = prettyPath.Split('/');
                AddCategoriesToStack(projectCategory, categoryStack, split);

                var vta     = asset.pptrValue as VisualTreeAsset;
                var newItem = new BuilderLibraryTreeItem(asset.name + ".uxml", null, typeof(TemplateContainer),
                                                         () =>
                {
                    if (vta == null)
                    {
                        return(null);
                    }

                    var tree = vta.CloneTree();
                    tree.SetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName, assetPath);
                    tree.name = vta.name;
                    return(tree);
                },
                                                         (inVta, inParent, ve) =>
                {
                    var vea = inVta.AddTemplateInstance(inParent, assetPath) as VisualElementAsset;
                    vea.AddProperty("name", vta.name);
                    ve.SetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName, vta);
                    return(vea);
                },
                                                         null, vta);
                newItem.SetIcon((Texture2D)EditorGUIUtility.IconContent("UxmlScript Icon").image);
                newItem.hasPreview = true;

                if (categoryStack.Count == 0)
                {
                    projectCategory.AddChild(newItem);
                }
                else
                {
                    categoryStack.Last().AddChild(newItem);
                }
            }
        }