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 ProcessMatchedRules(VisualElement element, List <SelectorMatchRecord> matchingSelectors) { matchingSelectors.Sort(SelectorMatchRecord.Compare); Int64 matchingRulesHash = element.fullTypeName.GetHashCode(); // Let current DPI contribute to the hash so cache is invalidated when this changes matchingRulesHash = (matchingRulesHash * 397) ^ currentPixelsPerPoint.GetHashCode(); int oldVariablesHash = m_StyleMatchingContext.variableContext.GetVariableHash(); int customPropertiesCount = 0; foreach (var record in matchingSelectors) { StyleRule rule = record.complexSelector.rule; int specificity = record.complexSelector.specificity; matchingRulesHash = (matchingRulesHash * 397) ^ rule.GetHashCode(); matchingRulesHash = (matchingRulesHash * 397) ^ specificity; if (rule.customPropertiesCount > 0) { customPropertiesCount += rule.customPropertiesCount; ProcessMatchedVariables(record.sheet, rule); } } int variablesHash = customPropertiesCount > 0 ? m_ProcessVarContext.GetVariableHash() : oldVariablesHash; matchingRulesHash = (matchingRulesHash * 397) ^ variablesHash; if (oldVariablesHash != variablesHash) { StyleVariableContext ctx; if (!StyleCache.TryGetValue(variablesHash, out ctx)) { ctx = new StyleVariableContext(m_ProcessVarContext); StyleCache.SetValue(variablesHash, ctx); } m_StyleMatchingContext.variableContext = ctx; } element.variableContext = m_StyleMatchingContext.variableContext; VisualElementStylesData resolvedStyles; if (StyleCache.TryGetValue(matchingRulesHash, out resolvedStyles)) { element.SetSharedStyles(resolvedStyles); } else { resolvedStyles = new VisualElementStylesData(isShared: true); foreach (var record in matchingSelectors) { m_StylePropertyReader.SetContext(record.sheet, record.complexSelector, m_StyleMatchingContext.variableContext); resolvedStyles.ApplyProperties(m_StylePropertyReader, m_StyleMatchingContext.inheritedStyle); } resolvedStyles.ApplyLayoutValues(); StyleCache.SetValue(matchingRulesHash, resolvedStyles); element.SetSharedStyles(resolvedStyles); } }
private VisualElement CloneSetupRecursively(VisualElementAsset root, Dictionary <int, List <VisualElementAsset> > idToChildren, CreationContext context) { VisualElement ve = Create(root, context); // 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 && 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 (inlineSheet == null) { Debug.LogWarning("VisualElementAsset has a RuleIndex but no inlineStyleSheet"); } else { StyleRule r = inlineSheet.rules[root.ruleIndex]; var stylesData = new VisualElementStylesData(false); ve.SetInlineStyles(stylesData); s_StylePropertyReader.SetInlineContext(inlineSheet, r, root.ruleIndex); stylesData.ApplyProperties(s_StylePropertyReader, null); } } var templateAsset = root as TemplateAsset; List <VisualElementAsset> children; if (idToChildren.TryGetValue(root.id, out children)) { children.Sort(CompareForOrder); foreach (VisualElementAsset childVea in children) { // this will fill the slotInsertionPoints mapping VisualElement childVe = CloneSetupRecursively(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); }