VisualElement MakeItem() { var element = new BuilderExplorerItem(); element.name = "unity-treeview-item-content"; element.RegisterCallback <MouseEnterEvent>((e) => { ClearHighlightOverlay(); var explorerItem = e.target as VisualElement; var documentElement = explorerItem?.GetProperty(BuilderConstants.ElementLinkedDocumentVisualElementVEPropertyName) as VisualElement; HighlightAllRelatedDocumentElements(documentElement); }); element.RegisterCallback <MouseLeaveEvent>((e) => { ClearHighlightOverlay(); }); element.RegisterCustomBuilderStyleChangeEvent(elementStyle => { var documentElement = element.GetProperty(BuilderConstants.ElementLinkedDocumentVisualElementVEPropertyName) as VisualElement; var isValidTarget = documentElement != null; if (!isValidTarget) { return; } var icon = element.Q(null, BuilderConstants.ExplorerItemIconClassName); if (icon == null) { return; } var path = documentElement.GetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName) as string; var libraryIcon = BuilderLibraryContent.GetTypeLibraryIcon(documentElement.GetType()); if (documentElement is TemplateContainer && !string.IsNullOrEmpty(path)) { libraryIcon = BuilderLibraryContent.GetUXMLAssetIcon(path); } else if (elementStyle == BuilderElementStyle.Highlighted && !EditorGUIUtility.isProSkin) { libraryIcon = BuilderLibraryContent.GetTypeDarkSkinLibraryIcon(documentElement.GetType()); } var styleBackgroundImage = icon.style.backgroundImage; styleBackgroundImage.value = new Background { texture = libraryIcon }; icon.style.backgroundImage = styleBackgroundImage; }); return(element); }
static void AddCategoriesToStack(BuilderLibraryItem sourceCategory, List <BuilderLibraryItem> 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) { var data = categoryStack[i].data; if (data.name == part) { continue; } else if (data.name != part) { categoryStack.RemoveRange(i, categoryStack.Count - i); } } if (categoryStack.Count <= i) { var newCategory = BuilderLibraryContent.CreateItem(part, null, null, null, null, null, null, fullName.GetHashCode()); if (categoryStack.Count == 0) { sourceCategory.AddChild(newCategory); } else { categoryStack[i - 1].AddChild(newCategory); } categoryStack.Add(newCategory); } } }
private void SetTypeAndIcon() { string typeName; if (currentVisualElement.typeName == nameof(TemplateContainer)) { typeName = BuilderConstants.BuilderInspectorTemplateInstance; m_Icon.style.backgroundImage = EditorGUIUtility.Load("VisualTreeAsset Icon") as Texture2D; } else { typeName = currentVisualElement.typeName; m_Icon.style.backgroundImage = BuilderLibraryContent.GetTypeLibraryLargeIcon(currentVisualElement.GetType()); } (m_TextField.labelElement as INotifyValueChanged <string>).SetValueWithoutNotify(typeName); }
public BuilderLibrary( BuilderPaneWindow paneWindow, BuilderViewport viewport, BuilderSelection selection, BuilderLibraryDragger dragger, BuilderTooltipPreview tooltipPreview) { m_PaneWindow = paneWindow; m_DocumentElement = viewport.documentRootElement; m_Selection = selection; m_Dragger = dragger; m_TooltipPreview = tooltipPreview; viewDataKey = "unity-ui-builder-library"; // Load styles. AddToClassList(k_UssClassName); styleSheets.Add(BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(BuilderConstants.LibraryUssPathNoExt + ".uss")); styleSheets.Add(EditorGUIUtility.isProSkin ? BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(BuilderConstants.LibraryUssPathNoExt + "Dark.uss") : BuilderPackageUtilities.LoadAssetAtPath <StyleSheet>(BuilderConstants.LibraryUssPathNoExt + "Light.uss")); var template = BuilderPackageUtilities.LoadAssetAtPath <VisualTreeAsset>(BuilderConstants.LibraryUssPathNoExt + ".uxml"); template.CloneTree(this); m_EditorExtensionMode = paneWindow.document.fileSettings.editorExtensionMode; m_LibraryContentContainer = this.Q <VisualElement>(k_ContentContainerName); m_HeaderButtonStrip = this.Q <ToggleButtonStrip>(); m_HeaderButtonStrip.choices = Enum.GetNames(typeof(BuilderLibraryTab)); m_HeaderButtonStrip.labels = new List <string> { BuilderConstants.LibraryStandardControlsTabName, BuilderConstants.LibraryProjectTabName }; m_HeaderButtonStrip.RegisterValueChangedCallback(e => { SwitchLibraryTab((BuilderLibraryTab)Enum.Parse(typeof(BuilderLibraryTab), e.newValue)); }); AddFocusable(m_HeaderButtonStrip); BuilderLibraryContent.RegenerateLibraryContent(); BuilderLibraryContent.OnLibraryContentUpdated += RebuildView; }
void FillItem(VisualElement element, ITreeViewItem item) { var explorerItem = element as BuilderExplorerItem; explorerItem.Clear(); // Pre-emptive cleanup. var row = explorerItem.parent.parent; row.RemoveFromClassList(BuilderConstants.ExplorerHeaderRowClassName); row.RemoveFromClassList(BuilderConstants.ExplorerItemHiddenClassName); row.RemoveFromClassList(BuilderConstants.ExplorerActiveStyleSheetClassName); // Get target element (in the document). var documentElement = (item as TreeViewItem <VisualElement>).data; documentElement.SetProperty(BuilderConstants.ElementLinkedExplorerItemVEPropertyName, explorerItem); explorerItem.SetProperty(BuilderConstants.ElementLinkedDocumentVisualElementVEPropertyName, documentElement); row.userData = documentElement; // If we have a FillItem callback (override), we call it and stop creating the rest of the item. var fillItemCallback = documentElement.GetProperty(BuilderConstants.ExplorerItemFillItemCallbackVEPropertyName) as Action <VisualElement, ITreeViewItem, BuilderSelection>; if (fillItemCallback != null) { fillItemCallback(explorerItem, item, m_Selection); return; } // Create main label container. var labelCont = new VisualElement(); labelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName); explorerItem.Add(labelCont); if (BuilderSharedStyles.IsStyleSheetElement(documentElement)) { var styleSheetAsset = documentElement.GetStyleSheet(); var styleSheetFileName = AssetDatabase.GetAssetPath(styleSheetAsset); var styleSheetAssetName = BuilderAssetUtilities.GetStyleSheetAssetName(styleSheetAsset, hasUnsavedChanges); var ssLabel = new Label(styleSheetAssetName); ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); ssLabel.AddToClassList("unity-debugger-tree-item-type"); row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName); labelCont.Add(ssLabel); // Register right-click events for context menu actions. m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem); // Register drag-and-drop events for reparenting. m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem); // Allow reparenting. explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement); if (styleSheetAsset == m_PaneWindow.document.activeStyleSheet) { row.AddToClassList(BuilderConstants.ExplorerActiveStyleSheetClassName); } return; } else if (BuilderSharedStyles.IsSelectorElement(documentElement)) { var selectorParts = BuilderSharedStyles.GetSelectorParts(documentElement); // Register right-click events for context menu actions. m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem); // Register drag-and-drop events for reparenting. m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem); foreach (var partStr in selectorParts) { if (partStr.StartsWith(BuilderConstants.UssSelectorClassNameSymbol)) { m_ClassPillTemplate.CloneTree(labelCont); var pill = labelCont.contentContainer.ElementAt(labelCont.childCount - 1); var pillLabel = pill.Q <Label>("class-name-label"); pill.name = "unity-builder-tree-class-pill"; pill.AddToClassList("unity-debugger-tree-item-pill"); pill.SetProperty(BuilderConstants.ExplorerStyleClassPillClassNameVEPropertyName, partStr); pill.userData = documentElement; // Add ellipsis if the class name is too long. var partStrShortened = BuilderNameUtilities.CapStringLengthAndAddEllipsis(partStr, BuilderConstants.ClassNameInPillMaxLength); pillLabel.text = partStrShortened; m_ClassDragger.RegisterCallbacksOnTarget(pill); } else if (partStr.StartsWith(BuilderConstants.UssSelectorNameSymbol)) { var selectorPartLabel = new Label(partStr); selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); selectorPartLabel.AddToClassList(BuilderConstants.ElementNameClassName); labelCont.Add(selectorPartLabel); } else if (partStr.StartsWith(BuilderConstants.UssSelectorPseudoStateSymbol)) { var selectorPartLabel = new Label(partStr); selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); selectorPartLabel.AddToClassList(BuilderConstants.ElementPseudoStateClassName); labelCont.Add(selectorPartLabel); } else if (partStr == BuilderConstants.SingleSpace) { var selectorPartLabel = new Label(BuilderConstants.TripleSpace); selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName); labelCont.Add(selectorPartLabel); } else { var selectorPartLabel = new Label(partStr); selectorPartLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); selectorPartLabel.AddToClassList(BuilderConstants.ElementTypeClassName); labelCont.Add(selectorPartLabel); } } // Allow reparenting. explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement); return; } if (BuilderSharedStyles.IsDocumentElement(documentElement)) { var uxmlAsset = documentElement.GetVisualTreeAsset(); var ssLabel = new Label(BuilderAssetUtilities.GetVisualTreeAssetAssetName(uxmlAsset, hasUnsavedChanges)); ssLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); ssLabel.AddToClassList("unity-debugger-tree-item-type"); row.AddToClassList(BuilderConstants.ExplorerHeaderRowClassName); labelCont.Add(ssLabel); return; } // Check if element is inside current document. if (!documentElement.IsPartOfCurrentDocument()) { row.AddToClassList(BuilderConstants.ExplorerItemHiddenClassName); } // Register drag-and-drop events for reparenting. m_ExplorerDragger.RegisterCallbacksOnTarget(explorerItem); // Allow reparenting. explorerItem.SetProperty(BuilderConstants.ExplorerItemElementLinkVEPropertyName, documentElement); // Element type label. if (string.IsNullOrEmpty(documentElement.name) || elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.TypeName)) { var typeLabel = new Label(documentElement.typeName); typeLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); typeLabel.AddToClassList(BuilderConstants.ElementTypeClassName); labelCont.Add(typeLabel); } // Element name label. var nameLabel = new Label(); nameLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); nameLabel.AddToClassList("unity-debugger-tree-item-name-label"); nameLabel.AddToClassList(BuilderConstants.ExplorerItemNameLabelClassName); nameLabel.AddToClassList(BuilderConstants.ElementNameClassName); if (!string.IsNullOrEmpty(documentElement.name)) { nameLabel.text = BuilderConstants.UssSelectorNameSymbol + documentElement.name; } labelCont.Add(nameLabel); // Textfield to rename element in hierarchy. var renameTextfield = explorerItem.CreateRenamingTextField(documentElement, nameLabel, m_Selection); labelCont.Add(renameTextfield); // Add class list. if (documentElement.classList.Count > 0 && elementInfoVisibilityState.HasFlag(BuilderExplorer.BuilderElementInfoVisibilityState.ClassList)) { foreach (var ussClass in documentElement.GetClasses()) { var classLabelCont = new VisualElement(); classLabelCont.AddToClassList(BuilderConstants.ExplorerItemLabelContClassName); explorerItem.Add(classLabelCont); var classLabel = new Label(BuilderConstants.UssSelectorClassNameSymbol + ussClass); classLabel.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); classLabel.AddToClassList(BuilderConstants.ElementClassNameClassName); classLabel.AddToClassList("unity-debugger-tree-item-classlist-label"); classLabelCont.Add(classLabel); } } // Show name of uxml file if this element is a TemplateContainer. var path = documentElement.GetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName) as string; Texture2D itemIcon; if (documentElement is TemplateContainer && !string.IsNullOrEmpty(path)) { var pathStr = Path.GetFileName(path); var label = new Label(pathStr); label.AddToClassList(BuilderConstants.ExplorerItemLabelClassName); label.AddToClassList(BuilderConstants.ElementTypeClassName); label.AddToClassList("unity-builder-explorer-tree-item-template-path"); // Just make it look a bit shaded. labelCont.Add(label); itemIcon = BuilderLibraryContent.GetUXMLAssetIcon(path); } else { itemIcon = BuilderLibraryContent.GetTypeLibraryIcon(documentElement.GetType()); } // Element icon. var icon = new VisualElement(); icon.AddToClassList(BuilderConstants.ExplorerItemIconClassName); var styleBackgroundImage = icon.style.backgroundImage; styleBackgroundImage.value = new Background { texture = itemIcon }; icon.style.backgroundImage = styleBackgroundImage; labelCont.Insert(0, icon); // Register right-click events for context menu actions. m_ContextMenuManipulator.RegisterCallbacksOnTarget(explorerItem); }
public void ImportFactoriesFromSource(BuilderLibraryItem sourceCategory) { var deferredFactories = new List <IUxmlFactory>(); var processingData = new FactoryProcessingHelper(); var emptyNamespaceControls = new List <TreeViewItem>(); 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 <BuilderLibraryItem>(); 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 = BuilderLibraryContent.CreateItem( known.uxmlName, elementType == typeof(TemplateContainer) ? nameof(TemplateContainer) : "CustomCSharpElement", elementType, () => known.Create(asset, context)); newItem.data.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(BuilderLibraryItem projectCategory, bool includePackages) { var categoryStack = new List <BuilderLibraryItem>(); var assets = AssetDatabase.FindAllAssets(m_SearchFilter); 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 = BuilderLibraryContent.CreateItem(asset.name + ".uxml", nameof(TemplateContainer), 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); var data = newItem.data; if (data.icon == null) { data.SetIcon((Texture2D)EditorGUIUtility.IconContent("VisualTreeAsset Icon").image); } data.hasPreview = true; if (categoryStack.Count == 0) { projectCategory.AddChild(newItem); } else { categoryStack.Last().AddChild(newItem); } } }