static void AddDependency(string assetPath, XElement templateNode, List <string> dependencies) { bool hasSrc = false; string src = null; foreach (var xAttribute in templateNode.Attributes()) { switch (xAttribute.Name.LocalName) { case k_GenericSrcAttr: hasSrc = true; src = xAttribute.Value; break; } } if (hasSrc) { string errorMessage, projectRelativePath; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, src, out errorMessage, out projectRelativePath); if (result == URIValidationResult.OK) { dependencies.Add(projectRelativePath); } } }
protected void VisitUrlFunction(PrimitiveTerm term) { string path = (string)term.Value; string projectRelativePath, errorMessage; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, path, out errorMessage, out projectRelativePath); if (result != URIValidationResult.OK) { m_Errors.AddSemanticError(ConvertErrorCode(result), errorMessage); } else { UnityEngine.Object asset = DeclareDependencyAndLoad(projectRelativePath); if (asset is Texture2D || asset is Font) { m_Builder.AddValue(asset); } else { m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidURIProjectAssetType, string.Format("Invalid asset type {0}, only Font and Texture2D are supported", asset.GetType().Name)); } } }
protected void VisitUrlFunction(PrimitiveTerm term) { string path = (string)term.Value; string projectRelativePath, errorMessage; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, path, out errorMessage, out projectRelativePath); if (result != URIValidationResult.OK) { m_Builder.AddValue(path, StyleValueType.MissingAssetReference); m_Errors.AddValidationWarning(errorMessage, m_Builder.currentProperty.line); } else { UnityEngine.Object asset = DeclareDependencyAndLoad(projectRelativePath); bool isTexture = asset is Texture2D; if (isTexture || asset is Font || asset is VectorImage) { // Looking suffixed images files only if (isTexture) { string hiResImageLocation = URIHelpers.InjectFileNameSuffix(projectRelativePath, "@2x"); if (File.Exists(hiResImageLocation)) { UnityEngine.Object hiResImage = DeclareDependencyAndLoad(hiResImageLocation); if (hiResImage is Texture2D) { m_Builder.AddValue(new ScalableImage() { normalImage = asset as Texture2D, highResolutionImage = hiResImage as Texture2D }); } else { m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidHighResolutionImage, string.Format("Invalid asset type {0}, only Texture2D is supported for variants with @2x suffix", asset.GetType().Name)); } return; } // If we didn't find an high res variant, tell ADB we depend on that potential file existing DeclareDependencyAndLoad(hiResImageLocation); } m_Builder.AddValue(asset); } else { m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidURIProjectAssetType, string.Format("Invalid asset type {0}, only Font, Texture2D and VectorImage are supported", asset.GetType().Name)); } } }
static void AddDependency(string assetPath, XElement templateNode, List <string> dependencies) { bool hasSrc = false; string src = null; foreach (var xAttribute in templateNode.Attributes()) { switch (xAttribute.Name.LocalName) { case k_GenericSrcAttr: hasSrc = true; src = xAttribute.Value; break; } } if (!hasSrc) { return; } URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, src, out string errorMessage, out string projectRelativePath); if (result != URIValidationResult.OK) { return; } switch (templateNode.Name.LocalName) { case k_TemplateNode: var templateDependencies = new HashSet <string>(); templateDependencies.Add(assetPath); if (!HasTemplateCircularDependencies(projectRelativePath, templateDependencies)) { dependencies.Add(projectRelativePath); } else { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.TemplateHasCircularDependency, projectRelativePath, Error.Level.Warning, templateNode); } break; default: dependencies.Add(projectRelativePath); break; } }
void LoadStyleReferenceNode(VisualElementAsset vea, XElement styleElt, VisualTreeAsset vta) { XAttribute pathAttr = styleElt.Attribute(k_GenericPathAttr); bool hasPath = pathAttr != null && !String.IsNullOrEmpty(pathAttr.Value); XAttribute srcAttr = styleElt.Attribute(k_GenericSrcAttr); bool hasSrc = srcAttr != null && !String.IsNullOrEmpty(srcAttr.Value); if (hasPath == hasSrc) { LogWarning(vta, ImportErrorType.Semantic, hasPath ? ImportErrorCode.StyleReferenceSrcAndPathBothSpecified : ImportErrorCode.StyleReferenceEmptyOrMissingPathOrSrcAttr, null, styleElt); return; } if (hasPath) { vea.stylesheetPaths.Add(pathAttr.Value); } else if (hasSrc) { string errorMessage, projectRelativePath; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, srcAttr.Value, out errorMessage, out projectRelativePath); if (result != URIValidationResult.OK) { LogError(vta, ImportErrorType.Semantic, ConvertErrorCode(result), errorMessage, styleElt); } else { Object asset = DeclareDependencyAndLoad(projectRelativePath); if (asset is StyleSheet) { vea.stylesheets.Add(asset as StyleSheet); } else { LogError(vta, ImportErrorType.Semantic, ImportErrorCode.ReferenceInvalidAssetType, projectRelativePath, styleElt); } } } }
static ImportErrorCode ConvertErrorCode(URIValidationResult result) { switch (result) { case URIValidationResult.InvalidURILocation: return(ImportErrorCode.ReferenceInvalidURILocation); case URIValidationResult.InvalidURIScheme: return(ImportErrorCode.ReferenceInvalidURIScheme); case URIValidationResult.InvalidURIProjectAssetPath: return(ImportErrorCode.ReferenceInvalidURIProjectAssetPath); default: throw new ArgumentOutOfRangeException(result.ToString()); } }
static protected StyleSheetImportErrorCode ConvertErrorCode(URIValidationResult result) { switch (result) { case URIValidationResult.InvalidURILocation: return(StyleSheetImportErrorCode.InvalidURILocation); case URIValidationResult.InvalidURIScheme: return(StyleSheetImportErrorCode.InvalidURIScheme); case URIValidationResult.InvalidURIProjectAssetPath: return(StyleSheetImportErrorCode.InvalidURIProjectAssetPath); default: return(StyleSheetImportErrorCode.Internal); } }
internal static (StyleSheetImportErrorCode, string) ConvertErrorCode(URIValidationResult result) { switch (result) { case URIValidationResult.InvalidURILocation: return(StyleSheetImportErrorCode.InvalidURILocation, glossary.invalidUriLocation); case URIValidationResult.InvalidURIScheme: return(StyleSheetImportErrorCode.InvalidURIScheme, glossary.invalidUriScheme); case URIValidationResult.InvalidURIProjectAssetPath: return(StyleSheetImportErrorCode.InvalidURIProjectAssetPath, glossary.invalidAssetPath); default: return(StyleSheetImportErrorCode.Internal, glossary.internalErrorWithStackTrace); } }
internal static bool HasTemplateCircularDependencies(XElement templateElement, HashSet <string> templateDependencies, string rootAssetPath) { bool hasCircularDependencies = false; var elements = templateElement.Elements(); foreach (var child in elements) { switch (child.Name.LocalName) { case k_TemplateNode: var attributes = child.Attributes(); foreach (var xAttribute in attributes) { if (xAttribute.Name.LocalName != k_GenericSrcAttr) { continue; } var src = xAttribute.Value; URIValidationResult result = URIHelpers.ValidAssetURL(rootAssetPath, src, out string errorMessage, out string projectRelativePath); hasCircularDependencies = HasTemplateCircularDependencies(projectRelativePath, templateDependencies); if (!hasCircularDependencies) { templateDependencies.Remove(projectRelativePath); } } break; default: hasCircularDependencies = HasTemplateCircularDependencies(child, templateDependencies, rootAssetPath); break; } if (hasCircularDependencies) { break; } } return(hasCircularDependencies); }
void LoadTemplateNode(VisualTreeAsset vta, XElement elt, XElement child) { bool hasPath = false; bool hasSrc = false; string name = null; string path = null; string src = null; foreach (var xAttribute in child.Attributes()) { switch (xAttribute.Name.LocalName) { case k_GenericPathAttr: hasPath = true; path = xAttribute.Value; break; case k_GenericSrcAttr: hasSrc = true; src = xAttribute.Value; break; case k_TemplateNameAttr: name = xAttribute.Value; if (String.IsNullOrEmpty(name)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.TemplateHasEmptyName, child, Error.Level.Fatal, child ); } break; default: logger.LogError(ImportErrorType.Semantic, ImportErrorCode.UnknownAttribute, xAttribute.Name.LocalName, Error.Level.Fatal, child ); break; } } if (hasPath == hasSrc) { logger.LogError(ImportErrorType.Semantic, hasPath ? ImportErrorCode.TemplateSrcAndPathBothSpecified : ImportErrorCode.TemplateMissingPathOrSrcAttribute, null, Error.Level.Fatal, elt ); return; } if (String.IsNullOrEmpty(name)) { name = Path.GetFileNameWithoutExtension(path); } if (vta.TemplateExists(name)) { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateTemplateName, name, Error.Level.Fatal, elt ); return; } if (hasPath) { vta.RegisterTemplate(name, path); } else if (hasSrc) { string errorMessage, projectRelativePath; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, src, out errorMessage, out projectRelativePath); if (result != URIValidationResult.OK) { logger.LogError(ImportErrorType.Semantic, ConvertErrorCode(result), errorMessage, Error.Level.Fatal, elt); } else { Object asset = DeclareDependencyAndLoad(projectRelativePath); if (asset is VisualTreeAsset) { vta.RegisterTemplate(name, asset as VisualTreeAsset); } else { logger.LogError(ImportErrorType.Semantic, ImportErrorCode.ReferenceInvalidAssetType, projectRelativePath, Error.Level.Fatal, elt); } } } }
protected void ImportParserStyleSheet(UnityStyleSheet asset, ParserStyleSheet styleSheet) { m_Errors.assetPath = assetPath; if (styleSheet.Errors.Count > 0) { foreach (StylesheetParseError error in styleSheet.Errors) { m_Errors.AddSyntaxError(error.ToString()); } } else { try { VisitSheet(styleSheet); } catch (Exception exc) { Debug.LogException(exc); m_Errors.AddInternalError(exc.StackTrace); } } bool success = !m_Errors.hasErrors; if (success) { m_Builder.BuildTo(asset); if (!s_StyleSheetsWithCircularImportDependencies.Contains(assetPath)) { var importDirectivesCount = styleSheet.ImportDirectives.Count; asset.imports = new UnityStyleSheet.ImportStruct[importDirectivesCount]; for (int i = 0; i < importDirectivesCount; ++i) { var importedPath = styleSheet.ImportDirectives[i].Href; string projectRelativePath, errorMessage; URIValidationResult importResult = URIHelpers.ValidAssetURL(assetPath, importedPath, out errorMessage, out projectRelativePath); UnityStyleSheet importedStyleSheet = null; if (importResult != URIValidationResult.OK) { m_Errors.AddSemanticError(ConvertErrorCode(importResult), errorMessage); } else { importedStyleSheet = DeclareDependencyAndLoad(projectRelativePath) as UnityStyleSheet; m_Context.DependsOnImportedAsset(projectRelativePath); } asset.imports[i] = new UnityStyleSheet.ImportStruct { styleSheet = importedStyleSheet, mediaQueries = styleSheet.ImportDirectives[i].Media.ToArray() }; } if (importDirectivesCount > 0) { asset.FlattenImportedStyleSheetsRecursive(); } } else { asset.imports = new UnityStyleSheet.ImportStruct[0]; var errorMsg = $"The {assetPath} contains circular @import dependencies. All @import directives will be ignored for this StyleSheet."; Debug.LogError(errorMsg); m_Errors.AddInternalError(errorMsg); } OnImportSuccess(asset); } if (!success || m_Errors.hasWarning) { OnImportError(m_Errors); } }
protected void VisitUrlFunction(PrimitiveTerm term) { string path = (string)term.Value; string projectRelativePath, subAssetPath, errorMessage; URIValidationResult result = URIHelpers.ValidAssetURL(assetPath, path, out errorMessage, out projectRelativePath, out subAssetPath); if (result != URIValidationResult.OK) { m_Builder.AddValue(path, StyleValueType.MissingAssetReference); m_Errors.AddValidationWarning(errorMessage, m_Builder.currentProperty.line); } else { UnityEngine.Object asset = DeclareDependencyAndLoad(projectRelativePath, subAssetPath); bool isTexture = asset is Texture2D; Sprite spriteAsset = asset as Sprite; if (isTexture && string.IsNullOrEmpty(subAssetPath)) { // Try to load a sprite sub-asset associated with this texture. // Sprites have extra data, such as slices and tight-meshes that // aren't stored in plain textures. spriteAsset = AssetDatabase.LoadAssetAtPath <Sprite>(projectRelativePath); } if (isTexture || spriteAsset != null || asset is Font || IsFontAssetInternal(asset) || asset is VectorImage || asset is RenderTexture) { // Looking suffixed images files only if (isTexture) { string hiResImageLocation = URIHelpers.InjectFileNameSuffix(projectRelativePath, "@2x"); if (File.Exists(hiResImageLocation)) { UnityEngine.Object hiResImage = DeclareDependencyAndLoad(hiResImageLocation); if (hiResImage is Texture2D) { m_Builder.AddValue(new ScalableImage() { normalImage = asset as Texture2D, highResolutionImage = hiResImage as Texture2D }); } else { m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidHighResolutionImage, string.Format("Invalid asset type {0}, only Texture2D is supported for variants with @2x suffix", asset.GetType().Name)); } return; } // If we didn't find an high res variant, tell ADB we depend on that potential file existing if (spriteAsset != null) { DeclareDependencyAndLoad(hiResImageLocation); } } m_Builder.AddValue(spriteAsset != null ? spriteAsset : asset); } else { m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidURIProjectAssetType, string.Format("Invalid asset type {0}, only Font, FontAssets, Sprite, Texture2D and VectorImage are supported", asset.GetType().Name)); } } }