public static List <string> GetStyleSheetPaths(this VisualElementAsset vea) { return(vea.stylesheetPaths); }
private static bool ParseAttributes(XElement elt, VisualElementAsset res, StyleSheetBuilder ssb, VisualTreeAsset vta, VisualElementAsset parent) { // underscore means "unnamed element but it would not look pretty in the project window without one" res.name = "_" + res.GetType().Name; bool startedRule = false; foreach (XAttribute xattr in elt.Attributes()) { string attrName = xattr.Name.LocalName; // start with special cases switch (attrName) { case "name": res.name = xattr.Value; continue; case "text": res.text = xattr.Value; continue; case "class": res.classes = xattr.Value.Split(' '); continue; case "contentContainer": if (vta.contentContainerId != 0) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateContentContainer, null, Error.Level.Fatal, elt); continue; } vta.contentContainerId = res.id; continue; case k_SlotDefinitionAttr: if (String.IsNullOrEmpty(xattr.Value)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotDefinitionHasEmptyName, null, Error.Level.Fatal, elt); } else if (!vta.AddSlotDefinition(xattr.Value, res.id)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateSlotDefinition, xattr.Value, Error.Level.Fatal, elt); } continue; case k_SlotUsageAttr: var templateAsset = parent as TemplateAsset; if (!(templateAsset != null)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageInNonTemplate, parent, Error.Level.Fatal, elt); continue; } if (string.IsNullOrEmpty(xattr.Value)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageHasEmptyName, null, Error.Level.Fatal, elt); continue; } templateAsset.AddSlotUsage(xattr.Value, res.id); continue; case "style": ExCSS.StyleSheet parsed = new Parser().Parse("* { " + xattr.Value + " }"); if (parsed.Errors.Count != 0) { logger.LogError( ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, parsed.Errors.Aggregate("", (s, error) => s + error.ToString() + "\n"), Error.Level.Warning, xattr); continue; } if (parsed.StyleRules.Count != 1) { logger.LogError( ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, "Expected one style rule, found " + parsed.StyleRules.Count, Error.Level.Warning, xattr); continue; } ssb.BeginRule(-1); startedRule = true; StyleSheetImportErrors errors = new StyleSheetImportErrors(); foreach (Property prop in parsed.StyleRules[0].Declarations) { ssb.BeginProperty(prop.Name); StyleSheetImporterImpl.VisitValue(errors, ssb, prop.Term); ssb.EndProperty(); } // Don't call ssb.EndRule() here, it's done in LoadXml to get the rule index at the same time ! continue; case "pickingMode": if (!Enum.IsDefined(typeof(PickingMode), xattr.Value)) { Debug.LogErrorFormat("Could not parse value of '{0}', because it isn't defined in the PickingMode enum.", xattr.Value); continue; } res.pickingMode = (PickingMode)Enum.Parse(typeof(PickingMode), xattr.Value); continue; } res.AddProperty(xattr.Name.LocalName, xattr.Value); } return(startedRule); }
public static void InitializeElement(VisualElementAsset vea) { vea.classes = new string[0]; vea.orderInDocument = -1; vea.ruleIndex = -1; }
bool ParseAttributes(XElement elt, VisualElementAsset res, VisualTreeAsset vta, VisualElementAsset parent) { bool startedRule = false; foreach (XAttribute xattr in elt.Attributes()) { string attrName = xattr.Name.LocalName; // start with special cases switch (attrName) { case k_ClassAttr: res.AddProperty(xattr.Name.LocalName, xattr.Value); res.classes = xattr.Value.Split(' '); continue; case "content-container": case "contentContainer": res.AddProperty(xattr.Name.LocalName, xattr.Value); if (attrName == "contentContainer") { } if (vta.contentContainerId != 0) { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.DuplicateContentContainer, null, elt); continue; } vta.contentContainerId = res.id; continue; case k_SlotDefinitionAttr: LogWarning(vta, ImportErrorType.Syntax, ImportErrorCode.SlotsAreExperimental, null, elt); if (String.IsNullOrEmpty(xattr.Value)) { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.SlotDefinitionHasEmptyName, null, elt); } else if (!vta.AddSlotDefinition(xattr.Value, res.id)) { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.DuplicateSlotDefinition, xattr.Value, elt); } continue; case k_SlotUsageAttr: LogWarning(vta, ImportErrorType.Syntax, ImportErrorCode.SlotsAreExperimental, null, elt); var templateAsset = parent as TemplateAsset; if (templateAsset == null) { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.SlotUsageInNonTemplate, parent, elt); continue; } if (string.IsNullOrEmpty(xattr.Value)) { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.SlotUsageHasEmptyName, null, elt); continue; } templateAsset.AddSlotUsage(xattr.Value, res.id); continue; case k_StyleAttr: res.AddProperty(xattr.Name.LocalName, xattr.Value); ExCSS.StyleSheet parsed = new Parser().Parse("* { " + xattr.Value + " }"); if (parsed.Errors.Count != 0) { LogWarning( vta, ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, parsed.Errors.Aggregate("", (s, error) => s + error.ToString() + "\n"), xattr); continue; } if (parsed.StyleRules.Count != 1) { LogWarning( vta, ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, "Expected one style rule, found " + parsed.StyleRules.Count, xattr); continue; } m_Builder.BeginRule(-1); startedRule = true; m_CurrentLine = ((IXmlLineInfo)xattr).LineNumber; foreach (Property prop in parsed.StyleRules[0].Declarations) { m_Builder.BeginProperty(prop.Name); VisitValue(prop.Term); m_Builder.EndProperty(); } // Don't call m_Builder.EndRule() here, it's done in LoadXml to get the rule index at the same time ! continue; } res.AddProperty(xattr.Name.LocalName, xattr.Value); } return(startedRule); }
private static bool ParseAttributes(XElement elt, VisualElementAsset res, StyleSheetBuilder ssb, VisualTreeAsset vta, VisualElementAsset parent) { res.name = "_" + res.GetType().Name; bool result = false; foreach (XAttribute current in elt.Attributes()) { string localName = current.Name.LocalName; switch (localName) { case "name": res.name = current.Value; continue; case "text": res.text = current.Value; continue; case "class": res.classes = current.Value.Split(new char[] { ' ' }); continue; case "contentContainer": if (vta.contentContainerId != 0) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateContentContainer, null, UIElementsViewImporter.Error.Level.Fatal, elt); continue; } vta.contentContainerId = res.id; continue; case "slot-name": if (string.IsNullOrEmpty(current.Value)) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotDefinitionHasEmptyName, null, UIElementsViewImporter.Error.Level.Fatal, elt); } else if (!vta.AddSlotDefinition(current.Value, res.id)) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateSlotDefinition, current.Value, UIElementsViewImporter.Error.Level.Fatal, elt); } continue; case "slot": { TemplateAsset templateAsset = parent as TemplateAsset; if (templateAsset == null) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageInNonTemplate, parent, UIElementsViewImporter.Error.Level.Fatal, elt); continue; } if (string.IsNullOrEmpty(current.Value)) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageHasEmptyName, null, UIElementsViewImporter.Error.Level.Fatal, elt); continue; } templateAsset.AddSlotUsage(current.Value, res.id); continue; } case "style": { StyleSheet styleSheet = new Parser().Parse("* { " + current.Value + " }"); if (styleSheet.Errors.Count != 0) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, styleSheet.Errors.Aggregate("", (string s, StylesheetParseError error) => s + error.ToString() + "\n"), UIElementsViewImporter.Error.Level.Warning, current); continue; } if (styleSheet.StyleRules.Count != 1) { UIElementsViewImporter.logger.LogError(ImportErrorType.Semantic, ImportErrorCode.InvalidCssInStyleAttribute, "Expected one style rule, found " + styleSheet.StyleRules.Count, UIElementsViewImporter.Error.Level.Warning, current); continue; } ssb.BeginRule(-1); result = true; StyleSheetImportErrors errors = new StyleSheetImportErrors(); foreach (Property current2 in styleSheet.StyleRules[0].Declarations) { ssb.BeginProperty(current2.Name); StyleSheetImporterImpl.VisitValue(errors, ssb, current2.Term); ssb.EndProperty(); } continue; } case "pickingMode": if (!Enum.IsDefined(typeof(PickingMode), current.Value)) { Debug.LogErrorFormat("Could not parse value of '{0}', because it isn't defined in the PickingMode enum.", new object[] { current.Value }); continue; } res.pickingMode = (PickingMode)Enum.Parse(typeof(PickingMode), current.Value); continue; } res.AddProperty(current.Name.LocalName, current.Value); } return(result); }
static void AppendElementNonStyleAttributes(VisualElementAsset vea, StringBuilder stringBuilder, bool writingToFile) { AppendElementAttributes(vea, stringBuilder, writingToFile, "class", "style"); }
void ImportFactoriesFromSource(LibraryTreeItem sourceCategory) { List <IUxmlFactory> deferredFactories = new List <IUxmlFactory>(); FactoryProcessingHelper processingData = new FactoryProcessingHelper(); 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 <LibraryTreeItem>(); foreach (var known in processingData.knownTypes.Values) { var split = known.uxmlNamespace.Split('.'); // Avoid adding our own internal factories (like Package Manager templates). if (!Unsupported.IsDeveloperMode() && split.Count() > 0 && s_NameSpacesToAvoid.Contains(split[0])) { continue; } AddCategoriesToStack(sourceCategory, categoryStack, split); 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); var newItem = new LibraryTreeItem( known.uxmlName, () => known.Create(asset, context)); if (categoryStack.Count == 0) { sourceCategory.AddChild(newItem); } else { categoryStack.Last().AddChild(newItem); } } }
public static void Select(this VisualElementAsset vea) { vea.SetAttributeValue( BuilderConstants.SelectedVisualElementAssetAttributeName, BuilderConstants.SelectedVisualElementAssetAttributeValue); }
public static void Deselect(this VisualElementAsset vea) { vea.SetAttributeValue( BuilderConstants.SelectedVisualElementAssetAttributeName, string.Empty); }
static void GenerateUXMLRecursive( VisualTreeAsset vta, string vtaPath, VisualElementAsset root, Dictionary <int, List <VisualElementAsset> > idToChildren, StringBuilder stringBuilder, int depth, bool omitUnsavedUss, bool writingToFile) { Indent(stringBuilder, depth); stringBuilder.Append("<"); AppendElementTypeName(root, stringBuilder); // Add all non-style attributes. AppendElementNonStyleAttributes(root, stringBuilder, writingToFile); // Add style classes to class attribute. if (root.classes != null && root.classes.Length > 0) { stringBuilder.Append(" class=\""); for (int i = 0; i < root.classes.Length; i++) { if (i > 0) { stringBuilder.Append(" "); } stringBuilder.Append(root.classes[i]); } stringBuilder.Append("\""); } // Add inline StyleSheet attribute. if (root.ruleIndex != -1) { if (vta.inlineSheet == null) { Debug.LogWarning("VisualElementAsset has a RuleIndex but no inlineStyleSheet"); } else { StyleRule r = vta.inlineSheet.rules[root.ruleIndex]; if (r.properties != null && r.properties.Length > 0) { var ruleBuilder = new StringBuilder(); var exportOptions = new UssExportOptions(); exportOptions.propertyIndent = string.Empty; StyleSheetToUss.ToUssString(vta.inlineSheet, exportOptions, r, ruleBuilder); var ruleStr = ruleBuilder.ToString(); AppendElementAttribute("style", ruleStr, stringBuilder); } } } // If we have no children, avoid adding the full end tag and just end the open tag. bool hasChildTags = false; // Add special children. #if UNITY_2019_3_OR_NEWER2 var styleSheets = root.stylesheets; if (styleSheets != null && styleSheets.Count > 0) { bool newLineAdded = false; foreach (var styleSheet in styleSheets) { var path = AssetDatabase.GetAssetPath(styleSheet); ProcessStyleSheetPath( vtaPath, path, stringBuilder, depth, omitUnsavedUss, ref newLineAdded, ref hasChildTags); } } #else var styleSheetPaths = root.GetStyleSheetPaths(); if (styleSheetPaths != null && styleSheetPaths.Count > 0) { bool newLineAdded = false; foreach (var path in styleSheetPaths) { ProcessStyleSheetPath( vtaPath, path, stringBuilder, depth, omitUnsavedUss, ref newLineAdded, ref hasChildTags); } } #endif var templateAsset = root as TemplateAsset; if (templateAsset != null && templateAsset.attributeOverrides != null && templateAsset.attributeOverrides.Count > 0) { if (!hasChildTags) { stringBuilder.Append(">\n"); } var overridesMap = new Dictionary <string, List <TemplateAsset.AttributeOverride> >(); foreach (var attributeOverride in templateAsset.attributeOverrides) { if (!overridesMap.ContainsKey(attributeOverride.m_ElementName)) { overridesMap.Add(attributeOverride.m_ElementName, new List <TemplateAsset.AttributeOverride>()); } overridesMap[attributeOverride.m_ElementName].Add(attributeOverride); } foreach (var attributeOverridePair in overridesMap) { var elementName = attributeOverridePair.Key; var overrides = attributeOverridePair.Value; Indent(stringBuilder, depth + 1); stringBuilder.Append("<AttributeOverrides"); AppendElementAttribute("element-name", elementName, stringBuilder); foreach (var attributeOverride in overrides) { AppendElementAttribute(attributeOverride.m_AttributeName, attributeOverride.m_Value, stringBuilder); } stringBuilder.Append(" />\n"); } hasChildTags = true; } // Iterate through child elements. List <VisualElementAsset> children; if (idToChildren != null && idToChildren.TryGetValue(root.id, out children) && children.Count > 0) { if (!hasChildTags) { stringBuilder.Append(">\n"); } children.Sort(VisualTreeAssetUtilities.CompareForOrder); foreach (VisualElementAsset childVea in children) { GenerateUXMLRecursive( vta, vtaPath, childVea, idToChildren, stringBuilder, depth + 1, omitUnsavedUss, writingToFile); } hasChildTags = true; } if (hasChildTags) { Indent(stringBuilder, depth); stringBuilder.Append("</"); AppendElementTypeName(root, stringBuilder); stringBuilder.Append(">\n"); } else { stringBuilder.Append(" />\n"); } }
public static bool IsSelected(this VisualElementAsset vea) { var value = vea.GetAttributeValue(BuilderConstants.SelectedVisualElementAssetAttributeName); return(value == BuilderConstants.SelectedVisualElementAssetAttributeValue); }
public static void RemoveStyleSheetPath(this VisualElementAsset vea, string styleSheetPath) { vea.GetStyleSheetPaths().RemoveAll((s) => s == styleSheetPath); }
public static void RemoveStyleSheet(this VisualElementAsset vea, StyleSheet styleSheet) { vea.stylesheets.RemoveAll((s) => s == styleSheet); }
public static void ClearStyleSheets(this VisualElementAsset vea) { vea.stylesheets.Clear(); vea.GetStyleSheetPaths().Clear(); }
static List <TreeViewItem> GenerateControlsItemsTree() { var containersItem = CreateItem(BuilderConstants.LibraryContainersSectionHeaderName, null, null, null, id: 1, isHeader: true); var controlsTree = new List <TreeViewItem>(); IList <TreeViewItem> containersItemList = new List <TreeViewItem> { CreateItem("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); }), CreateItem("ScrollView", "ScrollView", typeof(ScrollView), () => new ScrollView()), CreateItem("ListView", "ListView", typeof(ListView), () => new ListView()), CreateItem("GroupBox", "VisualElement", typeof(GroupBox), () => new GroupBox()), }; containersItem.AddChildren(containersItemList); controlsTree.Add(containersItem); var editorContainersItemList = CreateItem(BuilderConstants.LibraryEditorContainersSectionHeaderName, null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("IMGUI Container", "VisualElement", typeof(IMGUIContainer), () => new IMGUIContainer()), }, id: 2, isEditorOnly: true, isHeader: true); var controlsItem = CreateItem(BuilderConstants.LibraryControlsSectionHeaderName, null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("Label", nameof(Label), typeof(Label), () => new Label("Label")), CreateItem("Button", nameof(Button), typeof(Button), () => new Button { text = "Button" }), CreateItem("Toggle", nameof(Toggle), typeof(Toggle), () => new Toggle("Toggle")), CreateItem("Scroller", nameof(Scroller), typeof(Scroller), () => new Scroller(0, 100, (v) => {}, SliderDirection.Horizontal) { value = 42 }), CreateItem("Text Field", nameof(TextField), typeof(TextField), () => new TextField("Text Field") { value = "filler text" }), CreateItem("Foldout", nameof(Foldout), typeof(Foldout), () => new Foldout { text = "Foldout" }), CreateItem("Slider", nameof(Slider), typeof(Slider), () => new Slider("Slider", 0, 100) { value = 42 }), CreateItem("Slider (Int)", nameof(SliderInt), typeof(SliderInt), () => new SliderInt("SliderInt", 0, 100) { value = 42 }), CreateItem("Min-Max Slider", nameof(MinMaxSlider), typeof(MinMaxSlider), () => new MinMaxSlider("Min/Max Slider", 0, 20, -10, 40) { value = new Vector2(10, 12) }), CreateItem("Progress Bar", nameof(ProgressBar), typeof(ProgressBar), () => new ProgressBar() { title = "my-progress", value = 22 }), CreateItem("Dropdown", "Dropdown", typeof(DropdownField), () => new DropdownField("Dropdown")), CreateItem("Enum", nameof(EnumField), typeof(EnumField), () => new EnumField("Enum", TextAlignment.Center)), CreateItem("Radio Button", nameof(RadioButton), typeof(RadioButton), () => new RadioButton("Radio Button")), CreateItem("Radio Button Group", nameof(RadioButtonGroup), typeof(RadioButtonGroup), () => new RadioButtonGroup("Radio Button Group")), }, isHeader: true); var numericFields = CreateItem("Numeric Fields", null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("Integer", nameof(IntegerField), typeof(IntegerField), () => new IntegerField("Int Field") { value = 42 }), CreateItem("Float", nameof(FloatField), typeof(FloatField), () => new FloatField("Float Field") { value = 42.2f }), CreateItem("Long", nameof(LongField), typeof(LongField), () => new LongField("Long Field") { value = 42 }), CreateItem("Double", nameof(DoubleField), typeof(DoubleField), () => new DoubleField("Double Field") { value = 42.2 }), CreateItem("Hash128", nameof(Hash128Field), typeof(Hash128Field), () => new Hash128Field("Hash128 Field") { value = Hash128.Compute("42") }), CreateItem("Vector2", nameof(Vector2Field), typeof(Vector2Field), () => new Vector2Field("Vec2 Field")), CreateItem("Vector3", nameof(Vector3Field), typeof(Vector3Field), () => new Vector3Field("Vec3 Field")), CreateItem("Vector4", nameof(Vector4Field), typeof(Vector4Field), () => new Vector4Field("Vec4 Field")), CreateItem("Rect", nameof(RectField), typeof(RectField), () => new RectField("Rect")), CreateItem("Bounds", nameof(BoundsField), typeof(BoundsField), () => new BoundsField("Bounds")), CreateItem("Vector2 (Int)", nameof(Vector2IntField), typeof(Vector2IntField), () => new Vector2IntField("Vector2Int")), CreateItem("Vector3 (Int)", nameof(Vector3IntField), typeof(Vector3IntField), () => new Vector3IntField("Vector3Int")), CreateItem("Rect (Int)", nameof(RectIntField), typeof(RectIntField), () => new RectIntField("RectInt")), CreateItem("Bounds (Int)", nameof(BoundsIntField), typeof(BoundsIntField), () => new BoundsIntField("BoundsInt")), }, isHeader: true); var valueFields = CreateItem("Value Fields", null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("Color", nameof(ColorField), typeof(ColorField), () => new ColorField("Color") { value = Color.cyan }), CreateItem("Curve", nameof(CurveField), typeof(CurveField), () => new CurveField("Curve") { value = new AnimationCurve(new Keyframe(0, 0), new Keyframe(5, 8), new Keyframe(10, 4)) }), CreateItem("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 = CreateItem("Choice Fields", null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { // No UXML support for PopupField. //new LibraryTreeItem("Popup", () => new PopupField<string>("Normal Field", choices, 0)), CreateItem("Tag", nameof(TagField), typeof(TagField), () => new TagField("Tag", "Player")), CreateItem("Mask", nameof(MaskField), typeof(MaskField), () => new MaskField("Mask")), CreateItem("Layer", nameof(LayerField), typeof(LayerField), () => new LayerField("Layer")), CreateItem("LayerMask", nameof(LayerMaskField), typeof(LayerMaskField), () => new LayerMaskField("LayerMask")) }, isEditorOnly: true, isHeader: true); var toolbar = CreateItem("Toolbar", null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("Toolbar", "ToolbarElement", typeof(Toolbar), () => new Toolbar()), CreateItem("Toolbar Menu", "ToolbarElement", typeof(ToolbarMenu), () => new ToolbarMenu()), CreateItem("Toolbar Button", "ToolbarElement", typeof(ToolbarButton), () => new ToolbarButton { text = "Button" }), CreateItem("Toolbar Spacer", "ToolbarElement", typeof(ToolbarSpacer), () => new ToolbarSpacer()), CreateItem("Toolbar Toggle", "ToolbarElement", typeof(ToolbarToggle), () => new ToolbarToggle { label = "Toggle" }), CreateItem("Toolbar Breadcrumbs", "ToolbarElement", typeof(ToolbarBreadcrumbs), () => new ToolbarBreadcrumbs()), CreateItem("Toolbar Search Field", "ToolbarElement", typeof(ToolbarSearchField), () => new ToolbarSearchField()), CreateItem("Toolbar Popup Search Field", "ToolbarElement", typeof(ToolbarPopupSearchField), () => new ToolbarPopupSearchField()), }, isEditorOnly: true, isHeader: true); var inspectors = CreateItem("Inspectors", null, null, null, null, new List <TreeViewItemData <BuilderLibraryTreeItem> > { CreateItem("Object Field", nameof(ObjectField), typeof(ObjectField), () => new ObjectField("Object Field") { value = new Texture2D(10, 10) { name = "new_texture" } }), CreateItem("PropertyField", nameof(PropertyField), typeof(PropertyField), () => new PropertyField()) }, isEditorOnly: true, isHeader: true); controlsTree.Add(editorContainersItemList); controlsTree.Add(controlsItem); controlsTree.Add(numericFields); controlsTree.Add(valueFields); controlsTree.Add(choiceFields); controlsTree.Add(toolbar); controlsTree.Add(inspectors); return(controlsTree); }
public static bool HasParent(this VisualElementAsset vea) { return(vea.parentId != 0); }
static void GenerateUXMLRecursive( VisualTreeAsset vta, string vtaPath, VisualElementAsset root, Dictionary <int, List <VisualElementAsset> > idToChildren, StringBuilder stringBuilder, int depth, bool writingToFile) { Indent(stringBuilder, depth); stringBuilder.Append(BuilderConstants.UxmlOpenTagSymbol); AppendElementTypeName(root, stringBuilder); // Add all non-style attributes. AppendElementNonStyleAttributes(root, stringBuilder, writingToFile); // Add style classes to class attribute. if (root.classes != null && root.classes.Length > 0) { stringBuilder.Append(" class=\""); for (int i = 0; i < root.classes.Length; i++) { if (i > 0) { stringBuilder.Append(" "); } stringBuilder.Append(root.classes[i]); } stringBuilder.Append("\""); } // Add inline StyleSheet attribute. if (root.ruleIndex != -1) { if (vta.inlineSheet == null) { Debug.LogWarning("VisualElementAsset has a RuleIndex but no inlineStyleSheet"); } else { StyleRule r = vta.inlineSheet.rules[root.ruleIndex]; if (r.properties != null && r.properties.Length > 0) { var ruleBuilder = new StringBuilder(); var exportOptions = new UssExportOptions(); exportOptions.propertyIndent = string.Empty; StyleSheetToUss.ToUssString(vta.inlineSheet, exportOptions, r, ruleBuilder); var ruleStr = ruleBuilder.ToString(); // Need to remove newlines here before we give it to // AppendElementAttribute() so we don't add " " everywhere. ruleStr = ruleStr.Replace("\n", " "); ruleStr = ruleStr.Replace("\r", ""); ruleStr = ruleStr.Trim(); AppendElementAttribute("style", ruleStr, stringBuilder); } } } // If we have no children, avoid adding the full end tag and just end the open tag. bool hasChildTags = false; // Add special children. var styleSheets = root.GetStyleSheets(); var styleSheetPaths = root.GetStyleSheetPaths(); if (styleSheetPaths != null && styleSheetPaths.Count > 0) { Assert.IsNotNull(styleSheets); Assert.AreEqual(styleSheetPaths.Count, styleSheets.Count); bool newLineAdded = false; for (var i = 0; i < styleSheetPaths.Count; ++i) { var styleSheet = styleSheets[i]; var styleSheetPath = styleSheetPaths[i]; ProcessStyleSheetPath( vtaPath, styleSheet, styleSheetPath, stringBuilder, depth, ref newLineAdded, ref hasChildTags); } } var templateAsset = root as TemplateAsset; if (templateAsset != null && templateAsset.attributeOverrides != null && templateAsset.attributeOverrides.Count > 0) { if (!hasChildTags) { stringBuilder.Append(BuilderConstants.UxmlCloseTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } var overridesMap = new Dictionary <string, List <TemplateAsset.AttributeOverride> >(); foreach (var attributeOverride in templateAsset.attributeOverrides) { if (!overridesMap.ContainsKey(attributeOverride.m_ElementName)) { overridesMap.Add(attributeOverride.m_ElementName, new List <TemplateAsset.AttributeOverride>()); } overridesMap[attributeOverride.m_ElementName].Add(attributeOverride); } foreach (var attributeOverridePair in overridesMap) { var elementName = attributeOverridePair.Key; var overrides = attributeOverridePair.Value; Indent(stringBuilder, depth + 1); stringBuilder.Append(BuilderConstants.UxmlOpenTagSymbol + "AttributeOverrides"); AppendElementAttribute("element-name", elementName, stringBuilder); foreach (var attributeOverride in overrides) { AppendElementAttribute(attributeOverride.m_AttributeName, attributeOverride.m_Value, stringBuilder); } stringBuilder.Append(" " + BuilderConstants.UxmlCloseTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } hasChildTags = true; } // Iterate through child elements. List <VisualElementAsset> children; if (idToChildren != null && idToChildren.TryGetValue(root.id, out children) && children.Count > 0) { if (!hasChildTags) { stringBuilder.Append(BuilderConstants.UxmlCloseTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } children.Sort(VisualTreeAssetUtilities.CompareForOrder); foreach (var childVea in children) { GenerateUXMLRecursive( vta, vtaPath, childVea, idToChildren, stringBuilder, depth + 1, writingToFile); } hasChildTags = true; } // Iterate through Uxml Objects var entry = vta.GetUxmlObjectEntry(root.id); if (entry.uxmlObjectAssets != null && entry.uxmlObjectAssets.Count > 0) { if (!hasChildTags) { stringBuilder.Append(BuilderConstants.UxmlCloseTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } foreach (var childVea in entry.uxmlObjectAssets) { GenerateUXMLRecursive( vta, vtaPath, childVea, idToChildren, stringBuilder, depth + 1, writingToFile); } hasChildTags = true; } if (hasChildTags) { Indent(stringBuilder, depth); stringBuilder.Append(BuilderConstants.UxmlOpenTagSymbol + "/"); AppendElementTypeName(root, stringBuilder); stringBuilder.Append(BuilderConstants.UxmlCloseTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } else { stringBuilder.Append(" " + BuilderConstants.UxmlEndTagSymbol); stringBuilder.Append(BuilderConstants.newlineCharFromEditorSettings); } }
public static void SetAttributeValue(this VisualElementAsset vea, string attributeName, string attributeValue) { vea.AddProperty(attributeName, attributeValue); }
public static void SetVisualElementAsset(this VisualElement element, VisualElementAsset vea) { element.SetProperty(BuilderConstants.ElementLinkedVisualElementAssetVEPropertyName, vea); }
static VisualElement CloneSetupRecursively(VisualTreeAsset vta, VisualElementAsset root, Dictionary <int, List <VisualElementAsset> > idToChildren, CreationContext context) { #if UNITY_2019_3_OR_NEWER var resolvedSheets = new List <StyleSheet>(); foreach (var sheetPath in root.stylesheetPaths) { resolvedSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(sheetPath)); } root.stylesheets = resolvedSheets; #endif var ve = VisualTreeAsset.Create(root, context); // Linking the new element with its VisualElementAsset. // All this copied code for this one line! ve.SetProperty(BuilderConstants.ElementLinkedVisualElementAssetVEPropertyName, root); // context.target is the created templateContainer if (root.id == context.visualTreeAsset.contentContainerId) { if (context.target is TemplateContainer) { ((TemplateContainer)context.target).SetContentContainer(ve); } else { Debug.LogError( "Trying to clone a VisualTreeAsset with a custom content container into a element which is not a template container"); } } // if the current element had a slot-name attribute, put it in the resulting slot mapping string slotName; if (context.slotInsertionPoints != null && vta.TryGetSlotInsertionPoint(root.id, out slotName)) { context.slotInsertionPoints.Add(slotName, ve); } if (root.classes != null) { for (int i = 0; i < root.classes.Length; i++) { ve.AddToClassList(root.classes[i]); } } if (root.ruleIndex != -1) { if (vta.inlineSheet == null) { Debug.LogWarning("VisualElementAsset has a RuleIndex but no inlineStyleSheet"); } else { var rule = vta.inlineSheet.rules[root.ruleIndex]; #if UNITY_2020_1_OR_NEWER ve.SetInlineRule(vta.inlineSheet, rule); #elif UNITY_2019_3_OR_NEWER var stylesData = new VisualElementStylesData(false); ve.SetInlineStyles(stylesData); s_StylePropertyReader.SetInlineContext(vta.inlineSheet, rule, root.ruleIndex); stylesData.ApplyProperties(s_StylePropertyReader, null); #else var stylesData = new VisualElementStylesData(false); ve.SetInlineStyles(stylesData); var propIds = StyleSheetCache.GetPropertyIDs(vta.inlineSheet, root.ruleIndex); stylesData.ApplyRule(vta.inlineSheet, Int32.MaxValue, rule, propIds); #endif } } var templateAsset = root as TemplateAsset; if (templateAsset != null) { var templatePath = vta.GetPathFromTemplateName(templateAsset.templateAlias); ve.SetProperty(BuilderConstants.LibraryItemLinkedTemplateContainerPathVEPropertyName, templatePath); var instancedTemplateVTA = vta.ResolveTemplate(templateAsset.templateAlias); if (instancedTemplateVTA != null) { ve.SetProperty(BuilderConstants.ElementLinkedInstancedVisualTreeAssetVEPropertyName, instancedTemplateVTA); } } List <VisualElementAsset> children; if (idToChildren.TryGetValue(root.id, out children)) { children.Sort(VisualTreeAssetUtilities.CompareForOrder); foreach (VisualElementAsset childVea in children) { // this will fill the slotInsertionPoints mapping VisualElement childVe = CloneSetupRecursively(vta, childVea, idToChildren, context); if (childVe == null) { continue; } // if the parent is not a template asset, just add the child to whatever hierarchy we currently have // if ve is a scrollView (with contentViewport as contentContainer), this will go to the right place if (templateAsset == null) { ve.Add(childVe); continue; } int index = templateAsset.slotUsages == null ? -1 : templateAsset.slotUsages.FindIndex(u => u.assetId == childVea.id); if (index != -1) { VisualElement parentSlot; string key = templateAsset.slotUsages[index].slotName; Assert.IsFalse(String.IsNullOrEmpty(key), "a lost name should not be null or empty, this probably points to an importer or serialization bug"); if (context.slotInsertionPoints == null || !context.slotInsertionPoints.TryGetValue(key, out parentSlot)) { Debug.LogErrorFormat("Slot '{0}' was not found. Existing slots: {1}", key, context.slotInsertionPoints == null ? String.Empty : String.Join(", ", System.Linq.Enumerable.ToArray(context.slotInsertionPoints.Keys))); ve.Add(childVe); } else { parentSlot.Add(childVe); } } else { ve.Add(childVe); } } } if (templateAsset != null && context.slotInsertionPoints != null) { context.slotInsertionPoints.Clear(); } return(ve); }
void RefreshTreeView() { Clear(); var choices = new List <string> { "First", "Second", "Third" }; LibraryTreeItem.ResetNextId(); var items = new List <ITreeViewItem>(); var unityItem = new LibraryTreeItem("Unity", () => null); unityItem.isHeader = true; IList <ITreeViewItem> unityItemList = new List <ITreeViewItem>() { new LibraryTreeItem("VisualElement", () => { var ve = new VisualElement(); var veMinSizeChild = new VisualElement(); veMinSizeChild.name = BuilderConstants.SpecialVisualElementInitialMinSizeName; veMinSizeChild.AddToClassList(BuilderConstants.SpecialVisualElementInitialMinSizeClassName); ve.Add(veMinSizeChild); return(ve); }, (inVta, inParent) => { var vea = new VisualElementAsset(typeof(VisualElement).ToString()); VisualTreeAssetUtilities.InitializeElement(vea); inVta.AddElement(inParent, vea); return(vea); }), new LibraryTreeItem("Button", () => new Button() { text = "Button" }), new LibraryTreeItem("Scroller", () => new Scroller(0, 100, (v) => { }, SliderDirection.Horizontal) { value = 42 }), new LibraryTreeItem("Toggle", () => new Toggle("Toggle")), new LibraryTreeItem("Label", () => new Label("Label")), new LibraryTreeItem("Text Field", () => new TextField("Text Field") { value = "filler text" }), new LibraryTreeItem("Object Field", () => new ObjectField("Object Field") { value = new Texture2D(10, 10) { name = "new_texture" } }), new LibraryTreeItem("Foldout", () => new Foldout() { text = "Foldout" }), new LibraryTreeItem("Numeric Fields", () => null, null, new List <TreeViewItem <string> >() { new LibraryTreeItem("Integer", () => new IntegerField("Int Field") { value = 42 }), new LibraryTreeItem("Float", () => new FloatField("Float Field") { value = 42.2f }), new LibraryTreeItem("Long", () => new LongField("Long Field") { value = 42 }), new LibraryTreeItem("Min-Max Slider", () => new MinMaxSlider("Min/Max Slider", 0, 20, -10, 40) { value = new Vector2(10, 12) }), new LibraryTreeItem("Slider", () => new Slider("SliderInt", 0, 100) { value = 42 }), new LibraryTreeItem("Progress Bar", () => new ProgressBar() { title = "my-progress", value = 22 }), new LibraryTreeItem("Vector2", () => new Vector2Field("Vec2 Field")), new LibraryTreeItem("Vector3", () => new Vector3Field("Vec3 Field")), new LibraryTreeItem("Vector4", () => new Vector4Field("Vec4 Field")), new LibraryTreeItem("Rect", () => new RectField("Rect")), new LibraryTreeItem("Bounds", () => new BoundsField("Bounds")), new LibraryTreeItem("Slider (Int)", () => new SliderInt("SliderInt", 0, 100) { value = 42 }), new LibraryTreeItem("Vector2 (Int)", () => new Vector2IntField("Vector2Int")), new LibraryTreeItem("Vector3 (Int)", () => new Vector3IntField("Vector3Int")), new LibraryTreeItem("Rect (Int)", () => new RectIntField("RectInt")), new LibraryTreeItem("Bounds (Int)", () => new BoundsIntField("BoundsInt")) }), new LibraryTreeItem("Value Fields", () => null, null, new List <TreeViewItem <string> >() { new LibraryTreeItem("Color", () => new ColorField("Color") { value = Color.cyan }), new LibraryTreeItem("Curve", () => new CurveField("Curve")), new LibraryTreeItem("Gradient", () => new GradientField("Gradient")) }), new LibraryTreeItem("Choice Fields", () => null, null, new List <TreeViewItem <string> >() { new LibraryTreeItem("Enum", () => new EnumField("Enum", TextAlignment.Center)), // No UXML support for PopupField. //new LibraryTreeItem("Popup", () => new PopupField<string>("Normal Field", choices, 0)), new LibraryTreeItem("Tag", () => new TagField("Tag", "Player")), new LibraryTreeItem("Mask", () => new MaskField("Mask")), new LibraryTreeItem("Layer", () => new LayerField("Layer")), new LibraryTreeItem("LayerMask", () => new LayerMaskField("LayerMask")) }), new LibraryTreeItem("Containers", () => null, null, new List <TreeViewItem <string> >() { new LibraryTreeItem("ScrollView", () => new ScrollView()), new LibraryTreeItem("ListView", () => new ListView()) }), new LibraryTreeItem("Inspectors", () => null, null, new List <TreeViewItem <string> >() { new LibraryTreeItem("PropertyField", () => new PropertyField()) }), }; unityItem.AddChildren(unityItemList); items.Add(unityItem); // From Project var fromProjectCategory = new LibraryTreeItem("Project", () => null); fromProjectCategory.isHeader = true; items.Add(fromProjectCategory); ImportUxmlFromProject(fromProjectCategory); ImportFactoriesFromSource(fromProjectCategory); var treeView = new TreeView() { name = k_TreeViewName }; treeView.AddToClassList(k_TreeViewClassName); Add(treeView); treeView.viewDataKey = "samples-tree"; treeView.itemHeight = 20; treeView.rootItems = items; treeView.makeItem = () => MakeItem(); // This is apparently more optimal than "= MakeItem;". treeView.bindItem = (e, i) => BindItem(e, i); #if UNITY_2020_1_OR_NEWER treeView.onItemsChosen += (s) => OnItemsChosen(s); #else treeView.onItemChosen += (s) => OnItemChosen(s); #endif treeView.Refresh(); // Make sure the Hierarchy View gets focus when the pane gets focused. primaryFocusable = treeView.Q <ListView>(); // Auto-expand all items on load. foreach (var item in treeView.rootItems) { treeView.ExpandItem(item.id); } }
public static bool IsRootElement(this VisualTreeAsset vta, VisualElementAsset vea) { return(vea.parentId == vta.GetRootUXMLElementId()); }
private static bool ResolveType(XElement elt, VisualTreeAsset visualTreeAsset, out VisualElementAsset vea) { if (visualTreeAsset.AliasExists(elt.Name.LocalName)) { vea = new TemplateAsset(elt.Name.LocalName); } else { string text = (!string.IsNullOrEmpty(elt.Name.NamespaceName)) ? (elt.Name.NamespaceName + "." + elt.Name.LocalName) : elt.Name.LocalName; if (text == typeof(VisualElement).FullName) { text = typeof(VisualContainer).FullName; } vea = new VisualElementAsset(text); } return(true); }
internal static VisualElementAsset AddElement( this VisualTreeAsset vta, VisualElementAsset parent, VisualElementAsset vea) { return(VisualTreeAssetUtilities.AddElementToDocument(vta, vea, parent)); }
private static bool ResolveType(XElement elt, VisualTreeAsset visualTreeAsset, out VisualElementAsset vea) { string fullName; if (visualTreeAsset.AliasExists(elt.Name.LocalName)) { vea = new TemplateAsset(elt.Name.LocalName); } else { fullName = String.IsNullOrEmpty(elt.Name.NamespaceName) ? elt.Name.LocalName : elt.Name.NamespaceName + "." + elt.Name.LocalName; // HACK: wait for Theo's PR OR go with that if (fullName == typeof(VisualElement).FullName) { fullName = typeof(VisualContainer).FullName; } vea = new VisualElementAsset(fullName); } return(true); }
public static StyleRule GetOrCreateInlineStyleRule(this VisualTreeAsset vta, VisualElementAsset vea) { bool wasCreated; return(vta.GetOrCreateInlineStyleRule(vea, out wasCreated)); }
public static int CompareForOrder(VisualElementAsset a, VisualElementAsset b) => a.orderInDocument.CompareTo(b.orderInDocument);
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); }
void LoadXml(XElement elt, VisualElementAsset parent, VisualTreeAsset vta, int orderInDocument) { VisualElementAsset vea = ResolveType(elt, vta); if (vea == null) { return; } int parentHash; if (parent == null) { vea.parentId = 0; parentHash = vta.GetHashCode(); } else { vea.parentId = parent.id; parentHash = parent.id; } // id includes the parent id, meaning it's dependent on the whole direct hierarchy vea.id = (vta.GetNextChildSerialNumber() + 585386304) * -1521134295 + parentHash; vea.orderInDocument = orderInDocument; bool startedRule = ParseAttributes(elt, vea, vta, parent); // each vea will creates 0 or 1 style rule, with one or more properties // they don't have selectors and are directly referenced by index // it's then applied during tree cloning vea.ruleIndex = startedRule ? m_Builder.EndRule() : -1; var templateAsset = vea as TemplateAsset; if (templateAsset != null) { vta.templateAssets.Add(templateAsset); } else { vta.visualElementAssets.Add(vea); } if (elt.HasElements) { foreach (XElement child in elt.Elements()) { if (child.Name.LocalName == k_StyleReferenceNode) { LoadStyleReferenceNode(vea, child); } else if (templateAsset != null && child.Name.LocalName == k_AttributeOverridesNode) { LoadAttributeOverridesNode(templateAsset, child); } else { ++orderInDocument; LoadXml(child, vea, vta, orderInDocument); } } } }
static void AppendElementNonStyleAttributes(VisualElementAsset vea, StringBuilder stringBuilder, bool writingToFile) { // In 2019.3, je pense, "class" and "style" are now regular attributes?? AppendElementAttributes(vea, stringBuilder, writingToFile, "class", "style"); }