/// <summary> /// Writes text from the input parameter to the textholder parameter /// with characteristics based on the parameters. Has a typewriter ' /// effect. /// </summary> /// <param name="inputText"> /// The input string to display. /// </param> /// <param name="textHolder"> /// The TextMeshProUGUI component to write to. /// </param> /// <param name="textColour"> /// The text color to be displayed</param> /// <param name="textFont"> /// The text font to be displayed /// </param> /// <param name="charDelay"> /// The time in seconds between the display of each character in the /// input string (typewriter delay) /// </param> /// <param name="delayBeforeNextBlock"> /// The time in seconds before the next dialogue item is displayed /// </param> /// <param name="waitForTime"> /// If true, the dialogue will wait for the delay before displaying the /// next dialogue. If false, the dialogue will wait for the next key /// pressed. /// </param> /// <param name="textSize"> /// The size of the text to display. /// </param> /// <returns> /// IEnumerator that can be placed in a Quoratine to write the text. /// </returns> protected IEnumerator WriteText(string inputText, TextMeshProUGUI textHolder, Color textColour, TMPro.TMP_FontAsset textFont, float charDelay, float delayBeforeNextBlock, bool waitForTime, float textSize) { textHolder.font = textFont; textHolder.color = textColour; textHolder.fontSize = textSize; for (int i = 0; i < inputText.Length; i++) { if (SkipWriting && !waitForTime) { break; } textHolder.text += inputText[i]; PlayTypingSound(); yield return(new WaitForSeconds(charDelay)); } if (SkipWriting) { textHolder.text = inputText; } if (waitForTime) { yield return(new WaitForSeconds(delayBeforeNextBlock)); } Finished = true; }
/// <summary> /// Function to add a new material reference and returning its index in the material reference array. /// </summary> /// <param name="material"></param> /// <param name="fontAsset"></param> /// <param name="materialReferences"></param> /// <param name="materialReferenceIndexLookup"></param> /// <returns></returns> public static int AddMaterialReference(Material material, TMP_FontAsset fontAsset, MaterialReference[] materialReferences, Dictionary<int, int> materialReferenceIndexLookup) { int materialID = material.GetInstanceID(); int index = 0; if (materialReferenceIndexLookup.TryGetValue(materialID, out index)) { return index; } else { index = materialReferenceIndexLookup.Count; // Add new reference index materialReferenceIndexLookup[materialID] = index; materialReferences[index].index = index; materialReferences[index].fontAsset = fontAsset; materialReferences[index].spriteAsset = null; materialReferences[index].material = material; materialReferences[index].isDefaultMaterial = materialID == fontAsset.material.GetInstanceID() ? true : false; //materialReferences[index].padding = 0; materialReferences[index].referenceCount = 0; return index; } }
private void LoadFonts() { TMPro.TMP_FontAsset[] fonts = Resources.FindObjectsOfTypeAll(typeof(TMPro.TMP_FontAsset)) as TMPro.TMP_FontAsset[]; for (int i = 0; i < fonts.Length; i++) { TMPro.TMP_FontAsset font = fonts[i]; fontsDictionary.Add(font.name, font); } }
/// <summary> /// Constructor for new Material Reference. /// </summary> /// <param name="index"></param> /// <param name="fontAsset"></param> /// <param name="spriteAsset"></param> /// <param name="material"></param> /// <param name="padding"></param> public MaterialReference(int index, TMP_FontAsset fontAsset, TMP_SpriteAsset spriteAsset, Material material, float padding) { this.index = index; this.fontAsset = fontAsset; this.spriteAsset = spriteAsset; this.material = material; this.isDefaultMaterial = material.GetInstanceID() == fontAsset.material.GetInstanceID() ? true : false; this.padding = padding; this.referenceCount = 0; }
private HelpPages LoadHelpPagesForLanguage(Language lang, TMPro.TMP_FontAsset font) { var fileContents = Resources.Load <TextAsset>(string.Format("Help/{0}", lang.id)).text; var pages = HelpPageParser.Parse(fileContents); return(new HelpPages() { Font = font, Pages = pages }); }
protected virtual void OnValidate() { //Force pick references on first validate (prevent recalculate every time that unity compiles) if (_isFirstValidate) { _isFirstValidate = false; _previousFont = m_Font; _previousFontTmpPro = m_FontTMPro; _previousImageSetTextAsset = m_ImageSetTextAsset; } //Validate Name if (_previousFontTmpPro != null || _previousFont != null) { var fontName = _previousFont != null ? _previousFont.name : #if UNITY_2018_3_OR_NEWER (_previousFontTmpPro != null ? _previousFontTmpPro.faceInfo.familyName : #else (_previousFontTmpPro != null ? _previousFontTmpPro.fontInfo.Name : #endif name); if (!fontName.EndsWith(VECTOR_FONT_SUFIX)) { fontName += VECTOR_FONT_SUFIX; } if (fontName != name) { name = fontName; var path = UnityEditor.AssetDatabase.GetAssetPath(this); if (!string.IsNullOrEmpty(path)) { UnityEditor.AssetDatabase.RenameAsset(path, name); UnityEditor.AssetDatabase.Refresh(); } } } //Try recalculate if invalid var v_fontChaged = false; if (_previousFont != m_Font || _previousFontTmpPro != m_FontTMPro) { _previousFont = m_Font; _previousFontTmpPro = m_FontTMPro; v_fontChaged = true; } if (_previousImageSetTextAsset != m_ImageSetTextAsset || (m_ImageSetTextAsset == null && v_fontChaged)) { _previousImageSetTextAsset = m_ImageSetTextAsset; RecreateIconSet(); } }
/// <summary> /// Constructor for new Material Reference. /// </summary> /// <param name="index"></param> /// <param name="fontAsset"></param> /// <param name="spriteAsset"></param> /// <param name="material"></param> /// <param name="padding"></param> public MaterialReference(int index, TMP_FontAsset fontAsset, TMP_SpriteAsset spriteAsset, Material material, float padding) { this.index = index; this.fontAsset = fontAsset; this.spriteAsset = spriteAsset; this.material = material; this.isDefaultMaterial = material.GetInstanceID() == fontAsset.material.GetInstanceID() ? true : false; this.isFallbackMaterial = false; this.fallbackMaterial = null; this.padding = padding; this.referenceCount = 0; }
private static TMP_FontAsset SearchForGlyphInternal(TMP_FontAsset font, int character, out TMP_Glyph glyph) { glyph = null; if (font == null) { return(null); } if (font.characterDictionary.TryGetValue(character, out glyph)) { return(font); } else if (font.fallbackFontAssets != null && font.fallbackFontAssets.Count > 0) { for (int i = 0; i < font.fallbackFontAssets.Count && glyph == null; i++) { TMP_FontAsset temp = font.fallbackFontAssets[i]; int id = temp.GetInstanceID(); // Skip over the fallback font asset in the event it is null or if already searched. if (temp == null || k_searchedFontAssets.Contains(id)) { continue; } // Add to list of font assets already searched. k_searchedFontAssets.Add(id); temp = SearchForGlyphInternal(temp, character, out glyph); if (temp != null) { return(temp); } } } return(null); }
internal static Material GetFallbackMaterial(TMP_FontAsset fontAsset, Material sourceMaterial, int atlasIndex) { int sourceMaterialID = sourceMaterial.GetInstanceID(); Texture tex = fontAsset.atlasTextures[atlasIndex]; int texID = tex.GetInstanceID(); long key = (long)sourceMaterialID << 32 | (long)(uint)texID; FallbackMaterial fallback; if (m_fallbackMaterials.TryGetValue(key, out fallback)) { return(fallback.fallbackMaterial); } // Create new material from the source material and assign relevant atlas texture Material fallbackMaterial = new Material(sourceMaterial); fallbackMaterial.SetTexture(ShaderUtilities.ID_MainTex, tex); fallbackMaterial.hideFlags = HideFlags.HideAndDontSave; #if UNITY_EDITOR fallbackMaterial.name += " + " + tex.name; #endif fallback = new FallbackMaterial(); fallback.baseID = sourceMaterialID; fallback.baseMaterial = fontAsset.material; fallback.fallbackID = key; fallback.fallbackMaterial = fallbackMaterial; fallback.count = 0; m_fallbackMaterials.Add(key, fallback); m_fallbackMaterialLookup.Add(fallbackMaterial.GetInstanceID(), key); #if TMP_DEBUG_MODE ListFallbackMaterials(); #endif return(fallbackMaterial); }
private static TMP_FontAsset SearchForGlyphInternal(TMP_FontAsset font, int character, out TMP_Glyph glyph) { glyph = null; if (font == null) { return(null); } if (font.characterDictionary.TryGetValue(character, out glyph)) { return(font); } if (font.fallbackFontAssets != null && font.fallbackFontAssets.Count > 0) { for (int i = 0; i < font.fallbackFontAssets.Count; i++) { if (glyph != null) { break; } TMP_FontAsset tMP_FontAsset = font.fallbackFontAssets[i]; if (tMP_FontAsset == null) { continue; } int instanceID = tMP_FontAsset.GetInstanceID(); if (!k_searchedFontAssets.Contains(instanceID)) { k_searchedFontAssets.Add(instanceID); tMP_FontAsset = SearchForGlyphInternal(tMP_FontAsset, character, out glyph); if (tMP_FontAsset != null) { return(tMP_FontAsset); } } } } return(null); }
private void ResetFontAssetData(TMP_FontAsset font) { Dictionary <uint, int> charRefDictionary; if (!m_FontCharacterLookupDictionary.TryGetValue(font, out charRefDictionary)) { return; } m_CharTryAddCharacters.Clear(); foreach (var kv in charRefDictionary) { m_CharTryAddCharacters.Add((char)kv.Key); } HashSet <char> nonexistentCharacters; if (!m_CharNonexistentCharacters.TryGetValue(font, out nonexistentCharacters)) { nonexistentCharacters = new HashSet <char>(); m_CharNonexistentCharacters.Add(font, nonexistentCharacters); } // 重设的话,要把所有用到的文本组件刷一下,不然会有残留影像 font.ClearFontAssetData(); m_CharMissingCharacters.Clear(); bool ret = font.TryAddCharacters(m_CharTryAddCharacters, m_CharMissingCharacters); MissingCharactersToNonexistent(font, nonexistentCharacters, charRefDictionary); foreach (var kv in m_TextOldCharacterDictionary) { if (kv.Key) { kv.Key.SetVerticesDirty(); } } }
public static void CreateFontAssetVariant() { Object target = Selection.activeObject; // Make sure the selection is a font file if (target == null || target.GetType() != typeof(TMP_FontAsset)) { Debug.LogWarning("A Font file must first be selected in order to create a Font Asset."); return; } TMP_FontAsset sourceFontAsset = (TMP_FontAsset)target; string sourceFontFilePath = AssetDatabase.GetAssetPath(target); string folderPath = Path.GetDirectoryName(sourceFontFilePath); string assetName = Path.GetFileNameWithoutExtension(sourceFontFilePath); string newAssetFilePathWithName = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + " - Variant.asset"); // Set Texture and Material reference to the source font asset. TMP_FontAsset fontAsset = ScriptableObject.Instantiate <TMP_FontAsset>(sourceFontAsset); AssetDatabase.CreateAsset(fontAsset, newAssetFilePathWithName); fontAsset.atlasPopulationMode = AtlasPopulationMode.Static; // Initialize array for the font atlas textures. fontAsset.atlasTextures = sourceFontAsset.atlasTextures; fontAsset.material = sourceFontAsset.material; // Not sure if this is still necessary in newer versions of Unity. EditorUtility.SetDirty(fontAsset); AssetDatabase.SaveAssets(); }
/// <summary> /// Function to check if a certain font asset is contained in the material reference array. /// </summary> /// <param name="materialReferences"></param> /// <param name="fontAsset"></param> /// <returns></returns> public static bool Contains(MaterialReference[] materialReferences, TMP_FontAsset fontAsset) { int id = fontAsset.GetInstanceID(); for (int i = 0; i < materialReferences.Length && materialReferences[i].fontAsset != null; i++) { if (materialReferences[i].fontAsset.GetInstanceID() == id) return true; } return false; }
/// <summary> /// /// </summary> /// <returns></returns> protected TMP_FontAsset GetAlternativeFontAsset() { bool isItalic = (m_style & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic; TMP_FontAsset fontAsset = null; int weightIndex = m_fontWeightInternal / 100; if (isItalic) fontAsset = m_currentFontAsset.fontWeights[weightIndex].italicTypeface; else fontAsset = m_currentFontAsset.fontWeights[weightIndex].regularTypeface; if (fontAsset == null) return m_currentFontAsset; m_currentFontAsset = fontAsset; return m_currentFontAsset; }
// Event received when font asset properties are changed in Font Inspector void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) { if (font == m_fontAsset) { //Debug.Log("ON_FONT_PROPERTY_CHANGED event received."); m_havePropertiesChanged = true; m_hasFontAssetChanged = true; SetVerticesDirty(); } }
/// <summary> /// Function to extract all the characters from a font asset. /// </summary> /// <param name="fontAsset"></param> /// <returns></returns> public static string GetCharacters(TMP_FontAsset fontAsset) { string characters = string.Empty; for (int i = 0; i < fontAsset.m_glyphInfoList.Count; i++) { characters += (char)fontAsset.m_glyphInfoList[i].id; } return characters; }
static void CreateFontAssetFromSelectedObject(Object target) { Font sourceFont = (Font)target; string sourceFontFilePath = AssetDatabase.GetAssetPath(target); string folderPath = Path.GetDirectoryName(sourceFontFilePath); string assetName = Path.GetFileNameWithoutExtension(sourceFontFilePath); string newAssetFilePathWithName = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + " SDF.asset"); // Initialize FontEngine FontEngine.InitializeFontEngine(); // Load Font Face if (FontEngine.LoadFontFace(sourceFont, 90) != FontEngineError.Success) { Debug.LogWarning("Unable to load font face for [" + sourceFont.name + "]. Make sure \"Include Font Data\" is enabled in the Font Import Settings.", sourceFont); return; } // Create new Font Asset TMP_FontAsset fontAsset = ScriptableObject.CreateInstance<TMP_FontAsset>(); AssetDatabase.CreateAsset(fontAsset, newAssetFilePathWithName); fontAsset.version = "1.1.0"; fontAsset.faceInfo = FontEngine.GetFaceInfo(); // Set font reference and GUID fontAsset.m_SourceFontFileGUID = AssetDatabase.AssetPathToGUID(sourceFontFilePath); fontAsset.m_SourceFontFile_EditorRef = sourceFont; fontAsset.atlasPopulationMode = AtlasPopulationMode.Dynamic; // Default atlas resolution is 1024 x 1024. int atlasWidth = fontAsset.atlasWidth = 1024; int atlasHeight = fontAsset.atlasHeight = 1024; int atlasPadding = fontAsset.atlasPadding = 9; fontAsset.atlasRenderMode = GlyphRenderMode.SDFAA; // Initialize array for the font atlas textures. fontAsset.atlasTextures = new Texture2D[1]; // Create atlas texture of size zero. Texture2D texture = new Texture2D(0, 0, TextureFormat.Alpha8, false); texture.name = assetName + " Atlas"; fontAsset.atlasTextures[0] = texture; AssetDatabase.AddObjectToAsset(texture, fontAsset); // Add free rectangle of the size of the texture. int packingModifier = ((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP ? 0 : 1; fontAsset.freeGlyphRects = new List<GlyphRect>() { new GlyphRect(0, 0, atlasWidth - packingModifier, atlasHeight - packingModifier) }; fontAsset.usedGlyphRects = new List<GlyphRect>(); // Create new Material and Add it as Sub-Asset Shader default_Shader = Shader.Find("TextMeshPro/Distance Field"); Material tmp_material = new Material(default_Shader); tmp_material.name = texture.name + " Material"; tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture); tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth); tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight); tmp_material.SetFloat(ShaderUtilities.ID_GradientScale, atlasPadding + packingModifier); tmp_material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle); tmp_material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle); fontAsset.material = tmp_material; AssetDatabase.AddObjectToAsset(tmp_material, fontAsset); // Add Font Asset Creation Settings fontAsset.creationSettings = new FontAssetCreationSettings(fontAsset.m_SourceFontFileGUID, fontAsset.faceInfo.pointSize, 0, atlasPadding, 0, 1024, 1024, 7, string.Empty, (int)GlyphRenderMode.SDFAA); // Not sure if this is still necessary in newer versions of Unity. EditorUtility.SetDirty(fontAsset); AssetDatabase.SaveAssets(); }
/// <summary> /// Returns the text element (character) for the given unicode value taking into consideration the requested font style and weight. /// Function searches the source font asset, its list of font assets assigned as alternative typefaces and potentially its fallbacks. /// The font asset out parameter contains a reference to the font asset containing the character. /// The typeface type indicates whether the returned font asset is the source font asset, an alternative typeface or fallback font asset. /// </summary> /// <param name="unicode">The unicode value of the requested character</param> /// <param name="sourceFontAsset">The font asset to be searched</param> /// <param name="includeFallbacks">Include the fallback font assets in the search</param> /// <param name="fontStyle">The font style</param> /// <param name="fontWeight">The font weight</param> /// <param name="type">Indicates if the OUT font asset is an alternative typeface or fallback font asset</param> /// <param name="fontAsset">The font asset that contains the requested character</param> /// <returns></returns> public static TMP_Character GetCharacterFromFontAsset(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { if (includeFallbacks) { if (k_SearchedFontAssets == null) { k_SearchedFontAssets = new List <int>(); } else { k_SearchedFontAssets.Clear(); } } return(GetCharacterFromFontAsset_Internal(unicode, sourceFontAsset, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset)); }
/// <summary> /// /// </summary> /// <param name="fontAsset"></param> internal static void RegisterFontAssetForDefinitionRefresh(TMP_FontAsset fontAsset) { instance.InternalRegisterFontAssetForDefinitionRefresh(fontAsset); }
private void AddMissingCharacters(TMP_FontAsset font) { font = GetNextDynamicFontAsset(font); if (font == null) { return; } Dictionary <uint, int> charRefDictionary; if (!m_FontCharacterLookupDictionary.TryGetValue(font, out charRefDictionary)) { charRefDictionary = new Dictionary <uint, int>(); m_FontCharacterLookupDictionary.Add(font, charRefDictionary); } HashSet <char> nonexistentCharacters; if (!m_CharNonexistentCharacters.TryGetValue(font, out nonexistentCharacters)) { nonexistentCharacters = new HashSet <char>(); m_CharNonexistentCharacters.Add(font, nonexistentCharacters); } m_CharTryAddCharacters.Clear(); m_CharMissingCharacters2.Clear(); foreach (var charMissingCharacter in m_CharMissingCharacters) { // 如果已经被使用过,则使用计数+1 int count; if (charRefDictionary.TryGetValue((uint)charMissingCharacter, out count)) { count++; charRefDictionary[charMissingCharacter] = count; continue; } // 无法生成的字符,不计算 if (nonexistentCharacters.Contains(charMissingCharacter)) { m_CharMissingCharacters2.Add(charMissingCharacter); continue; } count = 1; charRefDictionary.Add(charMissingCharacter, count); // 优化,如果此字符已经动态生成,就不再放到生成串里 if (!(font.characterLookupTable != null && font.HasCharacter(charMissingCharacter))) { m_CharTryAddCharacters.Add(charMissingCharacter); } } if (m_CharTryAddCharacters.Count > 0 && font.characterLookupTable != null) { m_CharMissingCharacters.Clear(); bool ret = font.TryAddCharacters(m_CharTryAddCharacters, m_CharMissingCharacters); MissingCharactersToNonexistent(font, nonexistentCharacters, charRefDictionary); foreach (var charMissingCharacter in m_CharMissingCharacters) { m_CharMissingCharacters2.Add(charMissingCharacter); } if (!ret) { ResetFontAssetData(font); } m_CharMissingCharacters.Clear(); foreach (var charMissingCharacter in m_CharMissingCharacters2) { m_CharMissingCharacters.Add(charMissingCharacter); } } // 判断下一级回调 if (m_CharMissingCharacters.Count > 0) { AddMissingCharacters(font); } }
/// <summary> /// Internal Function returning the Font Asset corresponding to the provided hash code. /// </summary> /// <param name="hashCode"></param> /// <param name="fontAsset"></param> /// <returns></returns> private bool TryGetFontAssetInternal(int hashCode, out TMP_FontAsset fontAsset) { fontAsset = null; if (m_FontAssetReferenceLookup.TryGetValue(hashCode, out fontAsset)) { return true; } return false; }
/// <summary> /// Add new Font Asset reference to dictionary. /// </summary> /// <param name="fontAsset"></param> private void AddFontAssetInternal(TMP_FontAsset fontAsset) { if (m_FontAssetReferenceLookup.ContainsKey(fontAsset.hashCode)) return; // Add reference to the font asset. m_FontAssetReferenceLookup.Add(fontAsset.hashCode, fontAsset); // Add reference to the font material. m_FontMaterialReferenceLookup.Add(fontAsset.materialHashCode, fontAsset.material); }
/// <summary> /// Add new material reference and return the index of this new reference in the materialReferences array. /// </summary> /// <param name="material"></param> /// <param name="materialHashCode"></param> /// <param name="fontAsset"></param> //public int AddMaterial(Material material, int materialHashCode, TMP_FontAsset fontAsset) //{ // if (!m_MaterialReferenceLookup.ContainsKey(materialHashCode)) // { // int index = m_MaterialReferenceLookup.Count; // materialReferences[index].fontAsset = fontAsset; // materialReferences[index].material = material; // materialReferences[index].isDefaultMaterial = material.GetInstanceID() == fontAsset.material.GetInstanceID() ? true : false; // materialReferences[index].index = index; // materialReferences[index].referenceCount = 0; // m_MaterialReferenceLookup[materialHashCode] = index; // // Compute Padding value and store it // // TODO // int fontAssetHashCode = fontAsset.hashCode; // if (!m_FontAssetReferenceLookup.ContainsKey(fontAssetHashCode)) // m_FontAssetReferenceLookup.Add(fontAssetHashCode, fontAsset); // m_countInternal += 1; // return index; // } // else // { // return m_MaterialReferenceLookup[materialHashCode]; // } //} /// <summary> /// Add new material reference and return the index of this new reference in the materialReferences array. /// </summary> /// <param name="material"></param> /// <param name="materialHashCode"></param> /// <param name="spriteAsset"></param> /// <returns></returns> //public int AddMaterial(Material material, int materialHashCode, TMP_SpriteAsset spriteAsset) //{ // if (!m_MaterialReferenceLookup.ContainsKey(materialHashCode)) // { // int index = m_MaterialReferenceLookup.Count; // materialReferences[index].fontAsset = materialReferences[0].fontAsset; // materialReferences[index].spriteAsset = spriteAsset; // materialReferences[index].material = material; // materialReferences[index].isDefaultMaterial = true; // materialReferences[index].index = index; // materialReferences[index].referenceCount = 0; // m_MaterialReferenceLookup[materialHashCode] = index; // int spriteAssetHashCode = spriteAsset.hashCode; // if (!m_SpriteAssetReferenceLookup.ContainsKey(spriteAssetHashCode)) // m_SpriteAssetReferenceLookup.Add(spriteAssetHashCode, spriteAsset); // m_countInternal += 1; // return index; // } // else // { // return m_MaterialReferenceLookup[materialHashCode]; // } //} /// <summary> /// Function to check if the font asset is already referenced. /// </summary> /// <param name="font"></param> /// <returns></returns> public bool Contains(TMP_FontAsset font) { if (m_FontAssetReferenceLookup.ContainsKey(font.hashCode)) return true; return false; }
/// <summary> /// Function returning the Font Asset corresponding to the provided hash code. /// </summary> /// <param name="hashCode"></param> /// <param name="fontAsset"></param> /// <returns></returns> public static bool TryGetFontAsset(int hashCode, out TMP_FontAsset fontAsset) { return MaterialReferenceManager.instance.TryGetFontAssetInternal(hashCode, out fontAsset); }
/// <summary> /// Add new font asset reference to dictionary. /// </summary> /// <param name="fontAsset"></param> public static void AddFontAsset(TMP_FontAsset fontAsset) { MaterialReferenceManager.instance.AddFontAssetInternal(fontAsset); }
// Event received when font asset properties are changed in Font Inspector void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) { if (MaterialReference.Contains(m_materialReferences, font)) { //Debug.Log("ON_FONT_PROPERTY_CHANGED event received."); m_isInputParsingRequired = true; m_havePropertiesChanged = true; //SetLayoutDirty(); SetVerticesDirty(); } }
/// <summary> /// Method used to find and cache references to the Underline and Ellipsis characters. /// </summary> /// <param name=""></param> protected void GetSpecialCharacters(TMP_FontAsset fontAsset) { // Check & Assign Underline Character for use with the Underline tag. if (!fontAsset.characterDictionary.TryGetValue(95, out m_cached_Underline_GlyphInfo)) //95 { // Check fallback fonts // TODO } // Check & Assign Underline Character for use with the Underline tag. if (!fontAsset.characterDictionary.TryGetValue(8230, out m_cached_Ellipsis_GlyphInfo)) //95 { // Check fallback fonts // TODO } }
/// <summary> /// Returns the text element (character) for the given unicode value taking into consideration the requested font style and weight. /// Function searches the provided list of font assets, the list of font assets assigned as alternative typefaces to them as well as their fallbacks. /// The font asset out parameter contains a reference to the font asset containing the character. /// The typeface type indicates whether the returned font asset is the source font asset, an alternative typeface or fallback font asset. /// </summary> /// <param name="unicode">The unicode value of the requested character</param> /// <param name="fontAssets">The list of font assets to search</param> /// <param name="includeFallbacks">Determines if the fallback of each font assets on the list will be searched</param> /// <param name="fontStyle">The font style</param> /// <param name="fontWeight">The font weight</param> /// <param name="type">Determines if the OUT font asset is an alternative typeface or fallback font asset</param> /// <param name="fontAsset">The font asset that contains the requested character</param> /// <returns></returns> public static TMP_Character GetCharacterFromFontAssets(uint unicode, List <TMP_FontAsset> fontAssets, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { isAlternativeTypeface = false; // Make sure font asset list is valid if (fontAssets == null || fontAssets.Count == 0) { fontAsset = null; return(null); } if (includeFallbacks) { if (k_SearchedFontAssets == null) { k_SearchedFontAssets = new List <int>(); } else { k_SearchedFontAssets.Clear(); } } int fontAssetCount = fontAssets.Count; for (int i = 0; i < fontAssetCount; i++) { if (fontAssets[i] == null) { continue; } TMP_Character characterData = GetCharacterFromFontAsset_Internal(unicode, fontAssets[i], includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset); if (characterData != null) { return(characterData); } } fontAsset = null; return(null); }
/// <summary> /// Restore the State of various variables used in the mesh creation loop. /// </summary> /// <param name="state"></param> /// <returns></returns> protected int RestoreWordWrappingState(ref WordWrapState state) { int index = state.previous_WordBreak; // Multi Font & Material support related m_currentFontAsset = state.currentFontAsset; m_currentSpriteAsset = state.currentSpriteAsset; m_currentMaterial = state.currentMaterial; m_currentMaterialIndex = state.currentMaterialIndex; m_characterCount = state.total_CharacterCount + 1; m_visibleCharacterCount = state.visible_CharacterCount; m_visibleSpriteCount = state.visible_SpriteCount; m_textInfo.linkCount = state.visible_LinkCount; m_firstCharacterOfLine = state.firstCharacterIndex; m_firstVisibleCharacterOfLine = state.firstVisibleCharacterIndex; m_lastVisibleCharacterOfLine = state.lastVisibleCharIndex; m_style = state.fontStyle; m_fontScale = state.fontScale; m_fontScaleMultiplier = state.fontScaleMultiplier; //m_maxFontScale = state.maxFontScale; m_currentFontSize = state.currentFontSize; m_xAdvance = state.xAdvance; m_maxAscender = state.maxAscender; m_maxDescender = state.maxDescender; m_maxLineAscender = state.maxLineAscender; m_maxLineDescender = state.maxLineDescender; m_startOfLineAscender = state.previousLineAscender; m_preferredWidth = state.preferredWidth; m_preferredHeight = state.preferredHeight; m_meshExtents = state.meshExtents; m_lineNumber = state.lineNumber; m_lineOffset = state.lineOffset; m_baselineOffset = state.baselineOffset; //m_lineJustification = state.alignment; m_htmlColor = state.vertexColor; tag_NoParsing = state.tagNoParsing; // XML Tag Stack m_colorStack = state.colorStack; m_sizeStack = state.sizeStack; m_fontWeightStack = state.fontWeightStack; m_styleStack = state.styleStack; m_materialReferenceStack = state.materialReferenceStack; if (m_lineNumber < m_textInfo.lineInfo.Length) m_textInfo.lineInfo[m_lineNumber] = state.lineInfo; return index; }
/// <summary> /// Internal function returning the text element character for the given unicode value taking into consideration the font style and weight. /// Function searches the source font asset, list of font assets assigned as alternative typefaces and list of fallback font assets. /// </summary> private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { fontAsset = null; isAlternativeTypeface = false; TMP_Character characterData = null; #region FONT WEIGHT AND FONT STYLE HANDLING // Determine if a font weight or style is used. If so check if an alternative typeface is assigned for the given weight and / or style. bool isItalic = (fontStyle & FontStyles.Italic) == FontStyles.Italic; if (isItalic || fontWeight != FontWeight.Regular) { // Get reference to the font weight pairs of the given font asset. TMP_FontWeightPair[] fontWeights = sourceFontAsset.fontWeightTable; int fontWeightIndex = 4; switch (fontWeight) { case FontWeight.Thin: fontWeightIndex = 1; break; case FontWeight.ExtraLight: fontWeightIndex = 2; break; case FontWeight.Light: fontWeightIndex = 3; break; case FontWeight.Regular: fontWeightIndex = 4; break; case FontWeight.Medium: fontWeightIndex = 5; break; case FontWeight.SemiBold: fontWeightIndex = 6; break; case FontWeight.Bold: fontWeightIndex = 7; break; case FontWeight.Heavy: fontWeightIndex = 8; break; case FontWeight.Black: fontWeightIndex = 9; break; } fontAsset = isItalic ? fontWeights[fontWeightIndex].italicTypeface : fontWeights[fontWeightIndex].regularTypeface; if (fontAsset != null) { if (fontAsset.characterLookupTable.TryGetValue(unicode, out characterData)) { isAlternativeTypeface = true; return(characterData); } else if (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { if (fontAsset.TryAddCharacterInternal(unicode, out characterData)) { isAlternativeTypeface = true; return(characterData); } // Check if the source font file contains the requested character. //if (TryGetCharacterFromFontFile(unicode, fontAsset, out characterData)) //{ // isAlternativeTypeface = true; // return characterData; //} // If we find the requested character, we add it to the font asset character table // and return its character data. // We also add this character to the list of characters we will need to add to the font atlas. // We assume the font atlas has room otherwise this font asset should not be marked as dynamic. // Alternatively, we could also add multiple pages of font atlas textures (feature consideration). } // At this point, we were not able to find the requested character in the alternative typeface // so we check the source font asset and its potential fallbacks. } } #endregion // Search the source font asset for the requested character. if (sourceFontAsset.characterLookupTable.TryGetValue(unicode, out characterData)) { // We were able to locate the requested character in the given font asset. fontAsset = sourceFontAsset; return(characterData); } else if (sourceFontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { if (sourceFontAsset.TryAddCharacterInternal(unicode, out characterData)) { fontAsset = sourceFontAsset; return(characterData); } //// Check if the source font file contains the requested character. //if (TryGetCharacterFromFontFile(unicode, sourceFontAsset, out characterData)) //{ // fontAsset = sourceFontAsset; // //fontAsset.AddCharacterToRasterList(unicode); // return characterData; //} // If we find the requested character, we add it to the font asset character table // and return its character data. // We also add this character to the list of characters we will need to add to the font atlas. // We assume the font atlas has room otherwise this font asset should not be marked as dynamic. // Alternatively, we could also add multiple pages of font atlas textures (feature consideration) } // Search fallback font assets if we still don't have a valid character and include fallback is set to true. if (characterData == null && includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null) { // Get reference to the list of fallback font assets. List <TMP_FontAsset> fallbackFontAssets = sourceFontAsset.fallbackFontAssetTable; int fallbackCount = fallbackFontAssets.Count; if (fallbackFontAssets != null && fallbackCount > 0) { for (int i = 0; i < fallbackCount && characterData == null; i++) { TMP_FontAsset temp = fallbackFontAssets[i]; if (temp == null) { continue; } int id = temp.GetInstanceID(); // Skip over the fallback font asset in the event it is null or if already searched. if (k_SearchedFontAssets.Contains(id)) { continue; } // Add to list of font assets already searched. k_SearchedFontAssets.Add(id); characterData = GetCharacterFromFontAsset_Internal(unicode, temp, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset); if (characterData != null) { return(characterData); } } } } return(null); }
static void ScanProjectFile(AssetFileRecord fileRecord) { if (m_CancelScanProcess) { return; } // Read the asset data file string assetDataFile; bool hasDataFileChanged = false; try { assetDataFile = File.ReadAllText(m_ProjectPath + "/" + fileRecord.assetFilePath); } catch { // Continue to the next asset if we can't read the current one. return; } // Check if asset file references any text components. if (assetDataFile.Contains(k_TextMeshProScriptID) || assetDataFile.Contains(k_TextMeshProUGUIScriptID)) { float characterSpacingValue = 0; float newCharacterSpacingValue = 0; float wordSpacingValue = 0; float newWordSpacingValue = 0; float lineSpacingValue = 0; float newLineSpacingValue = 0; float paragraphSpacingValue = 0; float newParagraphSpacingValue = 0; float fontSize = 0; float samplingPointSize = 0; float faceScale = 1; List <string> lines = assetDataFile.Split('\n').ToList(); int serializedVersionInsertionIndex = 0; int readingFlag = 0; // Read through each lines of the asset file for (int i = 0; i < lines.Count; i++) { string line = lines[i]; // Track potential line index to insert serializedVersion property if (line.Contains("MonoBehaviour:")) { serializedVersionInsertionIndex = i + 1; continue; } // Read until we find the line that contains a reference to a text component if (readingFlag == 0 && (line.Contains(k_TextMeshProScriptID) || line.Contains(k_TextMeshProUGUIScriptID))) { // Check if spacing values for this component have already been converted if (lines[serializedVersionInsertionIndex].Contains(" m_SerializedVersion: 1")) { readingFlag = 0; continue; } lines.Insert(serializedVersionInsertionIndex, " m_SerializedVersion: 1"); readingFlag = 1; continue; } // Keep reading until we find the font asset property field. if (readingFlag == 1) { // Check for font asset property if (line.Contains(k_FontAssetProperty)) { int guidIndex = line.IndexOf("guid: ", StringComparison.InvariantCulture); if (guidIndex != -1) { string guid = line.Substring(guidIndex + 6, 32); TMP_FontAsset fontAsset = AssetDatabase.LoadAssetAtPath <TMP_FontAsset>(AssetDatabase.GUIDToAssetPath(guid)); if (fontAsset != null) { samplingPointSize = fontAsset.faceInfo.pointSize; faceScale = fontAsset.faceInfo.scale; } } readingFlag = 2; continue; } } // Read font size property if (readingFlag == 2) { if (line.Contains(k_FontSizeProperty)) { fontSize = float.Parse(line.Split(':')[1], NumberStyles.Float, CultureInfo.InvariantCulture); readingFlag = 3; continue; } } // Check for the spacing properties that need to be converted if (readingFlag == 3) { // Read character spacing if (line.Contains(k_CharacterSpacingProperty)) { characterSpacingValue = float.Parse(line.Split(':')[1], NumberStyles.Float, CultureInfo.InvariantCulture); if (characterSpacingValue != 0) { // Convert character spacing value. newCharacterSpacingValue = characterSpacingValue * faceScale / (samplingPointSize * 0.01f); lines[i] = lines[i].Replace(k_CharacterSpacingProperty + characterSpacingValue, k_CharacterSpacingProperty + newCharacterSpacingValue); hasDataFileChanged = true; } continue; } // Read word spacing if (line.Contains(k_WordSpacingProperty)) { // Get the character spacing value wordSpacingValue = float.Parse(line.Split(':')[1], NumberStyles.Float, CultureInfo.InvariantCulture); if (wordSpacingValue != 0) { // Convert character spacing value. newWordSpacingValue = wordSpacingValue * faceScale / (samplingPointSize * 0.01f); lines[i] = lines[i].Replace(k_WordSpacingProperty + wordSpacingValue, k_WordSpacingProperty + newWordSpacingValue); hasDataFileChanged = true; } continue; } // Read line spacing if (line.Contains(k_LineSpacingProperty)) { // Get the value of line spacing value lineSpacingValue = float.Parse(line.Split(':')[1], NumberStyles.Float, CultureInfo.InvariantCulture); if (lineSpacingValue != 0) { // Convert line spacing value. newLineSpacingValue = lineSpacingValue / (fontSize * 0.01f) * fontSize / samplingPointSize * faceScale; lines[i] = lines[i].Replace(k_LineSpacingProperty + lineSpacingValue, k_LineSpacingProperty + newLineSpacingValue); hasDataFileChanged = true; } continue; } // Read paragraph spacing if (line.Contains(k_ParagraphSpacingProperty)) { // Get the value of line spacing value paragraphSpacingValue = float.Parse(line.Split(':')[1], NumberStyles.Float, CultureInfo.InvariantCulture); if (paragraphSpacingValue != 0) { // Convert line spacing value. newParagraphSpacingValue = paragraphSpacingValue / (fontSize * 0.01f) * fontSize / samplingPointSize * faceScale; lines[i] = lines[i].Replace(k_ParagraphSpacingProperty + paragraphSpacingValue, k_ParagraphSpacingProperty + newParagraphSpacingValue); hasDataFileChanged = true; } readingFlag = 4; continue; } } // Done reading text component serialized data. if (readingFlag == 4 && line.Contains("---")) { readingFlag = 0; string characterSpacingFormat = $"{(characterSpacingValue == 0 ? " " : $"{characterSpacingValue,10:F}{newCharacterSpacingValue,10:F}")}"; string wordSpacingFormat = $"{(wordSpacingValue == 0 ? " " : $"{wordSpacingValue,10:F}{newWordSpacingValue,10:F}")}"; string lineSpacingFormat = $"{(lineSpacingValue == 0 ? " " : $"{lineSpacingValue,10:F}{newLineSpacingValue,10:F}")}"; string paragraphSpacingFormat = $"{(paragraphSpacingValue == 0 ? " " : $"{paragraphSpacingValue,10:F}{newParagraphSpacingValue,10:F}")}"; if (characterSpacingValue != 0 || lineSpacingValue != 0) { m_ProjectScanResults += $"{fileRecord.assetFilePath,-100}" + characterSpacingFormat + wordSpacingFormat + lineSpacingFormat + paragraphSpacingFormat + "\n"; } // Update asset data file assetDataFile = string.Join("\n", lines); newCharacterSpacingValue = 0; newWordSpacingValue = 0; newLineSpacingValue = 0; newParagraphSpacingValue = 0; } } } // Check if asset file is a font asset // if (assetDataFile.Contains(k_FontAssetScriptID)) // { // float samplingPointSize; // float normalSpacing; // float newNormalSpacing; // float boldSpacing; // float newBoldSpacing; // } if (hasDataFileChanged) { AssetModificationRecord modifiedAsset; modifiedAsset.assetFilePath = fileRecord.assetFilePath; modifiedAsset.assetDataFile = assetDataFile; m_ModifiedAssetList.Add(modifiedAsset); } }
/// <summary> /// /// </summary> /// <param name="hashcode"></param> /// <param name="fontAsset"></param> /// <returns></returns> public static bool TryGetFontAsset(int hashcode, out TMP_FontAsset fontAsset) { fontAsset = null; return(s_FontAssetReferenceLookup.TryGetValue(hashcode, out fontAsset)); }
/// <summary> /// Function returning the Font Asset corresponding to the provided hash code. /// </summary> /// <param name="hashCode"></param> /// <param name="fontAsset"></param> /// <returns></returns> public static bool TryGetFontAsset(int hashCode, out TMP_FontAsset fontAsset) { return(MaterialReferenceManager.instance.TryGetFontAssetInternal(hashCode, out fontAsset)); }
/// <summary> /// Function which returns an array that contains all the characters from a font asset. /// </summary> /// <param name="fontAsset"></param> /// <returns></returns> public static int[] GetCharactersArray(TMP_FontAsset fontAsset) { int[] characters = new int[fontAsset.m_glyphInfoList.Count]; for (int i = 0; i < fontAsset.m_glyphInfoList.Count; i++) { characters[i] = fontAsset.m_glyphInfoList[i].id; } return characters; }
static void ParseFnt(string filename) { var txt = File.ReadAllText(filename); var common = Regex.Matches(txt, "^common lineHeight=([0-9]+) base=([0-9]+) scaleW=([0-9]+) scaleH=([0-9]+)", RegexOptions.Multiline) .OfType <Match>() .Select(m => m.Groups.OfType <Group>().Select(g => g.Value).Skip(1).Select(x => int.Parse(x)).ToArray()) .First(); var page = Regex.Matches(txt, "^page id=0 file=\"([^\"]+)\"", RegexOptions.Multiline) .OfType <Match>() .Select(m => m.Groups[1].Value) .First(); // Create and set the material var atlas = AssetDatabase.LoadAssetAtPath <Texture2D>(BuildFilenameInSamePath(filename, page)); var materialFilename = BuildFilenameWithExtension(BuildFilenameInSamePath(filename, page), "mat"); Material material = AssetDatabase.LoadAssetAtPath <Material>(materialFilename); bool matWasCreated = false; if (material == null) { var shader = AssetDatabase.LoadAssetAtPath <Shader>("Assets/TextMesh Pro/Resources/Shaders/TMP_Sprite.shader"); material = new Material(shader); matWasCreated = true; } material.SetTexture("_MainTex", atlas); if (matWasCreated) { AssetDatabase.CreateAsset(material, materialFilename); } else { AssetDatabase.SaveAssets(); } var fntFilename = BuildFilenameWithExtension(filename, "asset"); bool fntWasCreated = false; var fnt = AssetDatabase.LoadAssetAtPath <TMPro.TMP_FontAsset>(fntFilename); if (fnt == null) { fnt = new TMPro.TMP_FontAsset(); fntWasCreated = true; } // Create the atlas asset fnt.atlas = atlas; fnt.material = AssetDatabase.LoadAssetAtPath <Material>(materialFilename); // Build the face and glyphs fnt.AddFaceInfo(new TMPro.FaceInfo() { AtlasWidth = fnt.atlas.width, AtlasHeight = fnt.atlas.height, Baseline = common[1], Ascender = common[3], Descender = 0, CharacterCount = 42, LineHeight = common[0], Name = Path.GetFileNameWithoutExtension(page), Scale = 1, PointSize = 24, Padding = 4 }); fnt.AddGlyphInfo( Regex.Matches(txt, "^char id=([0-9]+) x=([0-9]+) y=([0-9]+) width=([0-9]+) height=([0-9]+) xoffset=([0-9]+) yoffset=([0-9]+) xadvance=([0-9]+) page=([0-9]+) chnl=([0-9]+)", RegexOptions.Multiline) .OfType <Match>() .Select(m => m.Groups.OfType <Group>().Select(g => g.Value).Skip(1).Select(x => int.Parse(x)).ToArray()) .Select(i => new TMPro.TMP_Glyph() { id = i[0], x = i[1], y = i[2], width = i[3], height = i[4], xOffset = i[5], yOffset = i[6], xAdvance = i[7], scale = 1 }).ToArray() ); if (fntWasCreated) { AssetDatabase.CreateAsset(fnt, fntFilename); } else { AssetDatabase.SaveAssets(); } }
/// <summary> /// Method to calculate the preferred width and height of the text object. /// </summary> /// <returns></returns> protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector2 marginSize) { //Debug.Log("*** CalculatePreferredValues() ***"); // ***** Frame: " + Time.frameCount); ////Profiler.BeginSample("TMP Generate Text - Phase I"); // Early exit if no font asset was assigned. This should not be needed since Arial SDF will be assigned by default. if (m_fontAsset == null || m_fontAsset.characterDictionary == null) { Debug.LogWarning("Can't Generate Mesh! No Font Asset has been assigned to Object ID: " + this.GetInstanceID()); return Vector2.zero; } // Early exit if we don't have any Text to generate. if (m_char_buffer == null || m_char_buffer.Length == 0 || m_char_buffer[0] == (char)0) { return Vector2.zero; } m_currentFontAsset = m_fontAsset; m_currentMaterial = m_sharedMaterial; m_currentMaterialIndex = 0; m_materialReferenceStack.SetDefault(new MaterialReference(0, m_currentFontAsset, null, m_currentMaterial, m_padding)); // Total character count is computed when the text is parsed. int totalCharacterCount = m_totalCharacterCount; // m_VisibleCharacters.Count; if (m_internalCharacterInfo == null || totalCharacterCount > m_internalCharacterInfo.Length) { m_internalCharacterInfo = new TMP_CharacterInfo[totalCharacterCount > 1024 ? totalCharacterCount + 256 : Mathf.NextPowerOfTwo(totalCharacterCount)]; } // Calculate the scale of the font based on selected font size and sampling point size. m_fontScale = (defaultFontSize / m_currentFontAsset.fontInfo.PointSize * (m_isOrthographic ? 1 : 0.1f)); m_fontScaleMultiplier = 1; // baseScale is calculated based on the font asset assigned to the text object. float baseScale = (defaultFontSize / m_fontAsset.fontInfo.PointSize * m_fontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); float currentElementScale = m_fontScale; m_currentFontSize = defaultFontSize; m_sizeStack.SetDefault(m_currentFontSize); int charCode = 0; // Holds the character code of the currently being processed character. m_style = m_fontStyle; // Set the default style. float bold_xAdvance_multiplier = 1; // Used to increase spacing between character when style is bold. m_baselineOffset = 0; // Used by subscript characters. m_styleStack.Clear(); m_lineOffset = 0; // Amount of space between lines (font line spacing + m_linespacing). m_lineHeight = 0; float lineGap = m_currentFontAsset.fontInfo.LineHeight - (m_currentFontAsset.fontInfo.Ascender - m_currentFontAsset.fontInfo.Descender); m_cSpacing = 0; // Amount of space added between characters as a result of the use of the <cspace> tag. m_monoSpacing = 0; float lineOffsetDelta = 0; m_xAdvance = 0; // Used to track the position of each character. float maxXAdvance = 0; // Used to determine Preferred Width. tag_LineIndent = 0; // Used for indentation of text. tag_Indent = 0; m_indentStack.SetDefault(0); tag_NoParsing = false; //m_isIgnoringAlignment = false; m_characterCount = 0; // Total characters in the char[] // Tracking of line information m_firstCharacterOfLine = 0; m_maxLineAscender = -Mathf.Infinity; m_maxLineDescender = Mathf.Infinity; m_lineNumber = 0; float marginWidth = marginSize.x; //float marginHeight = marginSize.y; m_marginLeft = 0; m_marginRight = 0; m_width = -1; // Used by Unity's Auto Layout system. float renderedWidth = 0; float renderedHeight = 0; // Tracking of the highest Ascender m_maxAscender = 0; m_maxDescender = 0; // Initialize struct to track states of word wrapping bool isFirstWord = true; bool isLastBreakingChar = false; WordWrapState savedLineState = new WordWrapState(); SaveWordWrappingState(ref savedLineState, 0, 0); WordWrapState savedWordWrapState = new WordWrapState(); int wrappingIndex = 0; //int loopCountA = 0; int endTagIndex = 0; // Parse through Character buffer to read HTML tags and begin creating mesh. for (int i = 0; m_char_buffer[i] != 0; i++) { charCode = m_char_buffer[i]; m_textElementType = TMP_TextElementType.Character; m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; m_currentFontAsset = m_materialReferences[m_currentMaterialIndex].fontAsset; int prev_MaterialIndex = m_currentMaterialIndex; // Parse Rich Text Tag #region Parse Rich Text Tag if (m_isRichText && charCode == 60) // '<' { m_isParsingText = true; // Check if Tag is valid. If valid, skip to the end of the validated tag. if (ValidateHtmlTag(m_char_buffer, i + 1, out endTagIndex)) { i = endTagIndex; // Continue to next character or handle the sprite element if (m_textElementType == TMP_TextElementType.Character) continue; } } #endregion End Parse Rich Text Tag m_isParsingText = false; // Handle Font Styles like LowerCase, UpperCase and SmallCaps. #region Handling of LowerCase, UpperCase and SmallCaps Font Styles float smallCapsMultiplier = 1.0f; if (m_textElementType == TMP_TextElementType.Character) { if ((m_style & FontStyles.UpperCase) == FontStyles.UpperCase) { // If this character is lowercase, switch to uppercase. if (char.IsLower((char)charCode)) charCode = char.ToUpper((char)charCode); } else if ((m_style & FontStyles.LowerCase) == FontStyles.LowerCase) { // If this character is uppercase, switch to lowercase. if (char.IsUpper((char)charCode)) charCode = char.ToLower((char)charCode); } else if ((m_fontStyle & FontStyles.SmallCaps) == FontStyles.SmallCaps || (m_style & FontStyles.SmallCaps) == FontStyles.SmallCaps) { if (char.IsLower((char)charCode)) { smallCapsMultiplier = 0.8f; charCode = char.ToUpper((char)charCode); } } } #endregion // Look up Character Data from Dictionary and cache it. #region Look up Character Data if (m_textElementType == TMP_TextElementType.Sprite) { TMP_Sprite sprite = m_currentSpriteAsset.spriteInfoList[m_spriteIndex]; if (sprite == null) continue; // Sprites are assigned in the E000 Private Area + sprite Index charCode = 57344 + m_spriteIndex; m_cached_TextElement = sprite; // Adjust the offset relative to the pivot point. //sprite.xOffset += sprite.pivot.x; //sprite.yOffset += sprite.pivot.y; currentElementScale = m_fontAsset.fontInfo.Ascender / sprite.height * sprite.scale * baseScale; m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Sprite; m_currentMaterialIndex = prev_MaterialIndex; } else if (m_textElementType == TMP_TextElementType.Character) { m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement; m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset; m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; // Re-calculate font scale as the font asset may have changed. m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f); currentElementScale = m_fontScale * m_fontScaleMultiplier; m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character; //padding = m_currentMaterialIndex == 0 ? m_padding : m_subTextObjects[m_currentMaterialIndex].padding; } #endregion // Store some of the text object's information m_internalCharacterInfo[m_characterCount].character = (char)charCode; // Handle Kerning if Enabled. #region Handle Kerning if (m_enableKerning && m_characterCount >= 1) { int prev_charCode = m_internalCharacterInfo[m_characterCount - 1].character; KerningPairKey keyValue = new KerningPairKey(prev_charCode, charCode); KerningPair pair; m_currentFontAsset.kerningDictionary.TryGetValue(keyValue.key, out pair); if (pair != null) { m_xAdvance += pair.XadvanceOffset * currentElementScale; } } #endregion // Handle Mono Spacing #region Handle Mono Spacing float monoAdvance = 0; if (m_monoSpacing != 0) { monoAdvance = (m_monoSpacing / 2 - (m_cached_TextElement.width / 2 + m_cached_TextElement.xOffset) * currentElementScale); m_xAdvance += monoAdvance; } #endregion // Set Padding based on selected font style #region Handle Style Padding if ((m_style & FontStyles.Bold) == FontStyles.Bold || (m_fontStyle & FontStyles.Bold) == FontStyles.Bold) // Checks for any combination of Bold Style. { //style_padding = m_currentFontAsset.boldStyle * 2; bold_xAdvance_multiplier = 1 + m_currentFontAsset.boldSpacing * 0.01f; } else { //style_padding = m_currentFontAsset.normalStyle * 2; bold_xAdvance_multiplier = 1.0f; } #endregion Handle Style Padding //m_internalTextInfo.characterInfo[m_characterCount].scale = currentElementScale; //m_internalTextInfo.characterInfo[m_characterCount].origin = m_xAdvance; m_internalCharacterInfo[m_characterCount].baseLine = 0 - m_lineOffset + m_baselineOffset; // Compute and save text element Ascender and maximum line Ascender. float elementAscender = m_currentFontAsset.fontInfo.Ascender * (m_textElementType == TMP_TextElementType.Character ? currentElementScale : baseScale) + m_baselineOffset; /* float elementAscenderII = */ m_internalCharacterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; m_maxLineAscender = elementAscender > m_maxLineAscender ? elementAscender : m_maxLineAscender; // Compute and save text element Descender and maximum line Descender. float elementDescender = m_currentFontAsset.fontInfo.Descender * (m_textElementType == TMP_TextElementType.Character ? currentElementScale : baseScale) + m_baselineOffset; float elementDescenderII = m_internalCharacterInfo[m_characterCount].descender = elementDescender - m_lineOffset; m_maxLineDescender = elementDescender < m_maxLineDescender ? elementDescender : m_maxLineDescender; // Adjust maxLineAscender and maxLineDescender if style is superscript or subscript if ((m_style & FontStyles.Subscript) == FontStyles.Subscript || (m_style & FontStyles.Superscript) == FontStyles.Superscript) { float baseAscender = (elementAscender - m_baselineOffset) / m_currentFontAsset.fontInfo.SubSize; elementAscender = m_maxLineAscender; m_maxLineAscender = baseAscender > m_maxLineAscender ? baseAscender : m_maxLineAscender; float baseDescender = (elementDescender - m_baselineOffset) / m_currentFontAsset.fontInfo.SubSize; elementDescender = m_maxLineDescender; m_maxLineDescender = baseDescender < m_maxLineDescender ? baseDescender : m_maxLineDescender; } if (m_lineNumber == 0) m_maxAscender = m_maxAscender > elementAscender ? m_maxAscender : elementAscender; //if (m_lineOffset == 0) pageAscender = pageAscender > elementAscender ? pageAscender : elementAscender; // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN. #region Handle Visible Characters if (charCode == 9 || !char.IsWhiteSpace((char)charCode) || m_textElementType == TMP_TextElementType.Sprite) { //m_internalTextInfo.characterInfo[m_characterCount].isVisible = true; // Check if Character exceeds the width of the Text Container #region Handle Line Breaking, Text Auto-Sizing and Horizontal Overflow float width = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - m_marginLeft - m_marginRight, m_width) : marginWidth + 0.0001f - m_marginLeft - m_marginRight; //m_internalTextInfo.lineInfo[m_lineNumber].width = width; //m_internalTextInfo.lineInfo[m_lineNumber].marginLeft = m_marginLeft; if (m_xAdvance + m_cached_TextElement.xAdvance * currentElementScale > width) { // Word Wrapping #region Handle Word Wrapping if (enableWordWrapping && m_characterCount != m_firstCharacterOfLine) { // Check if word wrapping is still possible #region Line Breaking Check if (wrappingIndex == savedWordWrapState.previous_WordBreak || isFirstWord) { // Word wrapping is no longer possible, now breaking up individual words. if (m_isCharacterWrappingEnabled == false) { m_isCharacterWrappingEnabled = true; } else isLastBreakingChar = true; //m_recursiveCount += 1; //if (m_recursiveCount > 20) //{ //Debug.Log("Recursive count exceeded!"); //continue; //} } #endregion // Restore to previously stored state of last valid (space character or linefeed) i = RestoreWordWrappingState(ref savedWordWrapState); wrappingIndex = i; // Used to detect when line length can no longer be reduced. // Check if Line Spacing of previous line needs to be adjusted. if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == 0) { //Debug.Log("(1) Adjusting Line Spacing on line #" + m_lineNumber); float offsetDelta = m_maxLineAscender - m_startOfLineAscender; AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); m_lineOffset += offsetDelta; savedWordWrapState.lineOffset = m_lineOffset; savedWordWrapState.previousLineAscender = m_maxLineAscender; // TODO - Add check for character exceeding vertical bounds } //m_isNewPage = false; // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well. float lineAscender = m_maxLineAscender - m_lineOffset; float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; m_firstCharacterOfLine = m_characterCount; // Store first character of the next line. // Compute Preferred Width & Height renderedWidth += m_xAdvance; if (m_enableWordWrapping) renderedHeight = m_maxAscender - m_maxDescender; else renderedHeight = Mathf.Max(renderedHeight, lineAscender - lineDescender); // Store the state of the line before starting on the new line. SaveWordWrappingState(ref savedLineState, i, m_characterCount - 1); m_lineNumber += 1; //isStartOfNewLine = true; // Check to make sure Array is large enough to hold a new line. //if (m_lineNumber >= m_internalTextInfo.lineInfo.Length) // ResizeLineExtents(m_lineNumber); // Apply Line Spacing based on scale of the last character of the line. if (m_lineHeight == 0) { float ascender = m_internalCharacterInfo[m_characterCount].ascender - m_internalCharacterInfo[m_characterCount].baseLine; lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacing + m_lineSpacingDelta) * baseScale; m_lineOffset += lineOffsetDelta; m_startOfLineAscender = ascender; } else m_lineOffset += m_lineHeight + m_lineSpacing * baseScale; m_maxLineAscender = -Mathf.Infinity; m_maxLineDescender = Mathf.Infinity; m_xAdvance = 0 + tag_Indent; continue; } #endregion End Word Wrapping } #endregion End Check for Characters Exceeding Width of Text Container } #endregion Handle Visible Characters // Check if Line Spacing of previous line needs to be adjusted. #region Adjust Line Spacing if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == 0 && !m_isNewPage) { //Debug.Log("Inline - Adjusting Line Spacing on line #" + m_lineNumber); //float gap = 0; // Compute gap. float offsetDelta = m_maxLineAscender - m_startOfLineAscender; AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); elementDescenderII -= offsetDelta; m_lineOffset += offsetDelta; m_startOfLineAscender += offsetDelta; savedWordWrapState.lineOffset = m_lineOffset; savedWordWrapState.previousLineAscender = m_startOfLineAscender; } #endregion // Handle xAdvance & Tabulation Stops. Tab stops at every 25% of Font Size. #region XAdvance, Tabulation & Stops if (charCode == 9) { m_xAdvance += m_currentFontAsset.fontInfo.TabWidth * currentElementScale; } else if (m_monoSpacing != 0) m_xAdvance += (m_monoSpacing - monoAdvance + ((m_characterSpacing + m_currentFontAsset.normalSpacingOffset) * currentElementScale) + m_cSpacing); else { m_xAdvance += ((m_cached_TextElement.xAdvance * bold_xAdvance_multiplier + m_characterSpacing + m_currentFontAsset.normalSpacingOffset) * currentElementScale + m_cSpacing); } // Store xAdvance information //m_internalTextInfo.characterInfo[m_characterCount].xAdvance = m_xAdvance; #endregion Tabulation & Stops // Handle Carriage Return #region Carriage Return if (charCode == 13) { maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + m_xAdvance); renderedWidth = 0; m_xAdvance = 0 + tag_Indent; } #endregion Carriage Return // Handle Line Spacing Adjustments + Word Wrapping & special case for last line. #region Check for Line Feed and Last Character if (charCode == 10 || m_characterCount == totalCharacterCount - 1) { // Check if Line Spacing of previous line needs to be adjusted. if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == 0) { //Debug.Log("(2) Adjusting Line Spacing on line #" + m_lineNumber); float offsetDelta = m_maxLineAscender - m_startOfLineAscender; AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); elementDescenderII -= offsetDelta; m_lineOffset += offsetDelta; } // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well. //float lineAscender = m_maxLineAscender - m_lineOffset; float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; m_firstCharacterOfLine = m_characterCount + 1; // Store PreferredWidth paying attention to linefeed and last character of text. if (charCode == 10 && m_characterCount != totalCharacterCount - 1) { maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + m_xAdvance); renderedWidth = 0; } else renderedWidth = Mathf.Max(maxXAdvance, renderedWidth + m_xAdvance); renderedHeight = m_maxAscender - m_maxDescender; // Add new line if not last lines or character. if (charCode == 10) { // Store the state of the line before starting on the new line. SaveWordWrappingState(ref savedLineState, i, m_characterCount); // Store the state of the last Character before the new line. SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount); m_lineNumber += 1; // Apply Line Spacing if (m_lineHeight == 0) { lineOffsetDelta = 0 - m_maxLineDescender + elementAscender + (lineGap + m_lineSpacing + m_paragraphSpacing + m_lineSpacingDelta) * baseScale; m_lineOffset += lineOffsetDelta; } else m_lineOffset += m_lineHeight + (m_lineSpacing + m_paragraphSpacing) * baseScale; m_maxLineAscender = -Mathf.Infinity; m_maxLineDescender = Mathf.Infinity; m_startOfLineAscender = elementAscender; m_xAdvance = 0 + tag_LineIndent + tag_Indent; } } #endregion Check for Linefeed or Last Character // Save State of Mesh Creation for handling of Word Wrapping #region Save Word Wrapping State if (m_enableWordWrapping || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis) { if ((charCode == 9 || charCode == 32) && !m_isNonBreakingSpace) { // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored // for Word Wrapping. SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount); m_isCharacterWrappingEnabled = false; isFirstWord = false; } else if (charCode > 0x2e80 && charCode < 0x9fff) { if (m_currentFontAsset.lineBreakingInfo.leadingCharacters.ContainsKey(charCode) == false && (m_characterCount < totalCharacterCount - 1 && m_currentFontAsset.lineBreakingInfo.followingCharacters.ContainsKey(m_internalCharacterInfo[m_characterCount + 1].character) == false)) { SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount); m_isCharacterWrappingEnabled = false; isFirstWord = false; } } else if ((isFirstWord || m_isCharacterWrappingEnabled == true || isLastBreakingChar)) SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount); } #endregion Save Word Wrapping State m_characterCount += 1; } m_isCharacterWrappingEnabled = false; // Adjust Preferred Width and Height to account for Margins. renderedWidth += m_margin.x > 0 ? m_margin.x : 0; renderedWidth += m_margin.z > 0 ? m_margin.z : 0; renderedHeight += m_margin.y > 0 ? m_margin.y : 0; renderedHeight += m_margin.w > 0 ? m_margin.w : 0; ////Profiler.EndSample(); return new Vector2(renderedWidth, renderedHeight); }
public bool Contains(TMP_FontAsset font) { return(this.m_FontAssetReferenceLookup.ContainsKey(font.hashCode)); }
/// <summary> /// Method used to find and cache references to the Underline and Ellipsis characters. /// </summary> /// <param name=""></param> protected void GetSpecialCharacters(TMP_FontAsset fontAsset) { // Check & Assign Underline Character for use with the Underline tag. if (!fontAsset.characterDictionary.TryGetValue(95, out m_cached_Underline_GlyphInfo)) //95 { // Check fallback fonts // TODO if (m_settings == null && !m_settings.warningsDisabled) Debug.LogWarning("Underscore character wasn't found in the current Font Asset. No characters assigned for Underline.", this); } // Check & Assign Underline Character for use with the Underline tag. if (!fontAsset.characterDictionary.TryGetValue(8230, out m_cached_Ellipsis_GlyphInfo)) //95 { // Check fallback fonts // TODO if (m_settings == null && !m_settings.warningsDisabled) Debug.LogWarning("Ellipsis character wasn't found in the current Font Asset. No characters assigned for Underline.", this); } }
private bool TryGetFontAssetInternal(int hashCode, out TMP_FontAsset fontAsset) { fontAsset = null; return(this.m_FontAssetReferenceLookup.TryGetValue(hashCode, out fontAsset)); }
/// <summary> /// Function to identify and validate the rich tag. Returns the position of the > if the tag was valid. /// </summary> /// <param name="chars"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <returns></returns> protected bool ValidateHtmlTag(int[] chars, int startIndex, out int endIndex) { int tagCharCount = 0; byte attributeFlag = 0; TagUnits tagUnits = TagUnits.Pixels; TagType tagType = TagType.None; int attributeIndex = 0; m_xmlAttribute[attributeIndex].nameHashCode = 0; m_xmlAttribute[attributeIndex].valueType = TagType.None; m_xmlAttribute[attributeIndex].valueHashCode = 0; m_xmlAttribute[attributeIndex].valueStartIndex = 0; m_xmlAttribute[attributeIndex].valueLength = 0; m_xmlAttribute[attributeIndex].valueDecimalIndex = 0; endIndex = startIndex; bool isTagSet = false; bool isValidHtmlTag = false; for (int i = startIndex; i < chars.Length && chars[i] != 0 && tagCharCount < m_htmlTag.Length && chars[i] != 60; i++) { if (chars[i] == 62) // ASCII Code of End HTML tag '>' { isValidHtmlTag = true; endIndex = i; m_htmlTag[tagCharCount] = (char)0; break; } m_htmlTag[tagCharCount] = (char)chars[i]; tagCharCount += 1; if (attributeFlag == 1) { if (m_xmlAttribute[attributeIndex].valueStartIndex == 0) { // Check for attribute type if (chars[i] == 43 || chars[i] == 45 || char.IsDigit((char)chars[i])) { tagType = TagType.NumericalValue; m_xmlAttribute[attributeIndex].valueType = TagType.NumericalValue; m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1; m_xmlAttribute[attributeIndex].valueLength += 1; } else if (chars[i] == 35) { tagType = TagType.ColorValue; m_xmlAttribute[attributeIndex].valueType = TagType.ColorValue; m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1; m_xmlAttribute[attributeIndex].valueLength += 1; } else if (chars[i] != 34) { tagType = TagType.StringValue; m_xmlAttribute[attributeIndex].valueType = TagType.StringValue; m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1; m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ chars[i]; m_xmlAttribute[attributeIndex].valueLength += 1; } } else { if (tagType == TagType.NumericalValue) { if (chars[i] == 46) // '.' Decimal Point Index m_xmlAttribute[attributeIndex].valueDecimalIndex = tagCharCount - 1; // Check for termination of numerical value. if (chars[i] == 112 || chars[i] == 101 || chars[i] == 37 || chars[i] == 32) { attributeFlag = 2; tagType = TagType.None; attributeIndex += 1; m_xmlAttribute[attributeIndex].nameHashCode = 0; m_xmlAttribute[attributeIndex].valueType = TagType.None; m_xmlAttribute[attributeIndex].valueHashCode = 0; m_xmlAttribute[attributeIndex].valueStartIndex = 0; m_xmlAttribute[attributeIndex].valueLength = 0; m_xmlAttribute[attributeIndex].valueDecimalIndex = 0; if (chars[i] == 101) tagUnits = TagUnits.FontUnits; else if (chars[i] == 37) tagUnits = TagUnits.Percentage; } else if (attributeFlag != 2) { m_xmlAttribute[attributeIndex].valueLength += 1; } } else if (tagType == TagType.ColorValue) { if (chars[i] != 32) { m_xmlAttribute[attributeIndex].valueLength += 1; } else { attributeFlag = 2; tagType = TagType.None; attributeIndex += 1; m_xmlAttribute[attributeIndex].nameHashCode = 0; m_xmlAttribute[attributeIndex].valueType = TagType.None; m_xmlAttribute[attributeIndex].valueHashCode = 0; m_xmlAttribute[attributeIndex].valueStartIndex = 0; m_xmlAttribute[attributeIndex].valueLength = 0; m_xmlAttribute[attributeIndex].valueDecimalIndex = 0; } } else if (tagType == TagType.StringValue) { // Compute HashCode value for the named tag. if (chars[i] != 34) { m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ chars[i]; m_xmlAttribute[attributeIndex].valueLength += 1; } else { //m_xmlAttribute[attributeIndex].valueHashCode = -1; attributeFlag = 2; tagType = TagType.None; attributeIndex += 1; m_xmlAttribute[attributeIndex].nameHashCode = 0; m_xmlAttribute[attributeIndex].valueType = TagType.None; m_xmlAttribute[attributeIndex].valueHashCode = 0; m_xmlAttribute[attributeIndex].valueStartIndex = 0; m_xmlAttribute[attributeIndex].valueLength = 0; m_xmlAttribute[attributeIndex].valueDecimalIndex = 0; } } } } if (chars[i] == 61) // '=' attributeFlag = 1; // Compute HashCode for the name of the attribute if (attributeFlag == 0 && chars[i] == 32) { if (isTagSet) return false; isTagSet = true; attributeFlag = 2; tagType = TagType.None; attributeIndex += 1; m_xmlAttribute[attributeIndex].nameHashCode = 0; m_xmlAttribute[attributeIndex].valueType = TagType.None; m_xmlAttribute[attributeIndex].valueHashCode = 0; m_xmlAttribute[attributeIndex].valueStartIndex = 0; m_xmlAttribute[attributeIndex].valueLength = 0; m_xmlAttribute[attributeIndex].valueDecimalIndex = 0; } if (attributeFlag == 0) m_xmlAttribute[attributeIndex].nameHashCode = (m_xmlAttribute[attributeIndex].nameHashCode << 3) - m_xmlAttribute[attributeIndex].nameHashCode + chars[i]; if (attributeFlag == 2 && chars[i] == 32) attributeFlag = 0; } if (!isValidHtmlTag) { return false; } //Debug.Log("Tag is [" + m_htmlTag.ArrayToString() + "]. Tag HashCode: " + m_xmlAttribute[0].nameHashCode + " Tag Value HashCode: " + m_xmlAttribute[0].valueHashCode + " Attribute 1 HashCode: " + m_xmlAttribute[1].nameHashCode + " Value HashCode: " + m_xmlAttribute[1].valueHashCode); //for (int i = 0; i < attributeIndex + 1; i++) // Debug.Log("Tag [" + i + "] with HashCode: " + m_xmlAttribute[i].nameHashCode + " has value of [" + new string(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) + "] Numerical Value: " + ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength, m_xmlAttribute[i].valueDecimalIndex)); // Special handling of the NoParsing tag if (tag_NoParsing && m_xmlAttribute[0].nameHashCode != 53822163) return false; else if (m_xmlAttribute[0].nameHashCode == 53822163) { tag_NoParsing = false; return true; } // Color <#FF00FF> if (m_htmlTag[0] == 35 && tagCharCount == 7) // if Tag begins with # and contains 7 characters. { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); return true; } // Color <#FF00FF00> with alpha else if (m_htmlTag[0] == 35 && tagCharCount == 9) // if Tag begins with # and contains 9 characters. { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); return true; } else { float value = 0; switch (m_xmlAttribute[0].nameHashCode) { case 98: // <b> m_style |= FontStyles.Bold; m_fontWeightInternal = 700; m_fontWeightStack.Add(700); return true; case 427: // </b> if ((m_fontStyle & FontStyles.Bold) != FontStyles.Bold) { m_style &= ~FontStyles.Bold; m_fontWeightInternal = m_fontWeightStack.Remove(); } return true; case 105: // <i> m_style |= FontStyles.Italic; return true; case 434: // </i> m_style &= ~FontStyles.Italic; return true; case 115: // <s> m_style |= FontStyles.Strikethrough; return true; case 444: // </s> if ((m_fontStyle & FontStyles.Strikethrough) != FontStyles.Strikethrough) m_style &= ~FontStyles.Strikethrough; return true; case 117: // <u> m_style |= FontStyles.Underline; return true; case 446: // </u> if ((m_fontStyle & FontStyles.Underline) != FontStyles.Underline) m_style &= ~FontStyles.Underline; return true; case 6552: // <sub> m_fontScaleMultiplier = m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1; m_baselineOffset = m_currentFontAsset.fontInfo.SubscriptOffset * m_fontScale * m_fontScaleMultiplier; m_style |= FontStyles.Subscript; return true; case 22673: // </sub> if ((m_style & FontStyles.Subscript) == FontStyles.Subscript) { // Check to make sure we are not also using Superscript if ((m_style & FontStyles.Superscript) == FontStyles.Superscript) { m_fontScaleMultiplier = m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1; m_baselineOffset = m_currentFontAsset.fontInfo.SuperscriptOffset * m_fontScale * m_fontScaleMultiplier; } else { m_baselineOffset = 0; m_fontScaleMultiplier = 1; } m_style &= ~FontStyles.Subscript; } return true; case 6566: // <sup> m_fontScaleMultiplier = m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1; m_baselineOffset = m_currentFontAsset.fontInfo.SuperscriptOffset * m_fontScale * m_fontScaleMultiplier; m_style |= FontStyles.Superscript; return true; case 22687: // </sup> if ((m_style & FontStyles.Superscript) == FontStyles.Superscript) { // Check to make sure we are not also using Superscript if ((m_style & FontStyles.Subscript) == FontStyles.Subscript) { m_fontScaleMultiplier = m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1; m_baselineOffset = m_currentFontAsset.fontInfo.SubscriptOffset * m_fontScale * m_fontScaleMultiplier; } else { m_baselineOffset = 0; m_fontScaleMultiplier = 1; } m_style &= ~FontStyles.Superscript; } return true; case -330774850: // <font-weight> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; if ((m_fontStyle & FontStyles.Bold) == FontStyles.Bold) { // Nothing happens since Bold is forced on the text. //m_fontWeight = 700; return true; } // Remove bold style m_style &= ~FontStyles.Bold; switch ((int)value) { case 100: m_fontWeightInternal = 100; break; case 200: m_fontWeightInternal = 200; break; case 300: m_fontWeightInternal = 300; break; case 400: m_fontWeightInternal = 400; break; case 500: m_fontWeightInternal = 500; break; case 600: m_fontWeightInternal = 600; break; case 700: m_fontWeightInternal = 700; m_style |= FontStyles.Bold; break; case 800: m_fontWeightInternal = 800; break; case 900: m_fontWeightInternal = 900; break; } m_fontWeightStack.Add(m_fontWeightInternal); return true; case -1885698441: // </font-weight> m_fontWeightInternal = m_fontWeightStack.Remove(); return true; case 6380: // <pos=000.00px> <pos=0em> <pos=50%> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999) return false; switch (tagUnits) { case TagUnits.Pixels: m_xAdvance = value; //m_isIgnoringAlignment = true; return true; case TagUnits.FontUnits: m_xAdvance = value * m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; //m_isIgnoringAlignment = true; return true; case TagUnits.Percentage: m_xAdvance = m_marginWidth * value / 100; //m_isIgnoringAlignment = true; return true; } return false; case 22501: // </pos> m_isIgnoringAlignment = false; return true; case 16034505: // <voffset> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: m_baselineOffset = value; return true; case TagUnits.FontUnits: m_baselineOffset = value * m_fontScale * m_fontAsset.fontInfo.Ascender; return true; case TagUnits.Percentage: //m_baselineOffset = m_marginHeight * val / 100; return false; } return false; case 54741026: // </voffset> m_baselineOffset = 0; return true; case 43991: // <page> // This tag only works when Overflow - Page mode is used. if (m_overflowMode == TextOverflowModes.Page) { m_xAdvance = 0 + tag_LineIndent + tag_Indent; //m_textInfo.lineInfo[m_lineNumber].marginLeft = m_xAdvance; m_lineOffset = 0; m_pageNumber += 1; m_isNewPage = true; } return true; case 43969: // <nobr> m_isNonBreakingSpace = true; return true; case 156816: // </nobr> m_isNonBreakingSpace = false; return true; case 45545: // <size=> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: if (m_htmlTag[5] == 43) // <size=+00> { m_currentFontSize = m_fontSize + value; m_sizeStack.Add(m_currentFontSize); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; } else if (m_htmlTag[5] == 45) // <size=-00> { m_currentFontSize = m_fontSize + value; m_sizeStack.Add(m_currentFontSize); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; } else // <size=00.0> { m_currentFontSize = value; m_sizeStack.Add(m_currentFontSize); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; } case TagUnits.FontUnits: m_currentFontSize = m_fontSize * value; m_sizeStack.Add(m_currentFontSize); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; case TagUnits.Percentage: m_currentFontSize = m_fontSize * value / 100; m_sizeStack.Add(m_currentFontSize); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; } return false; case 158392: // </size> m_currentFontSize = m_sizeStack.Remove(); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; case 41311: // <font=xx> //Debug.Log("Font name: \"" + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength) + "\" HashCode: " + m_xmlAttribute[0].valueHashCode + " Material Name: \"" + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength) + "\" Hashcode: " + m_xmlAttribute[1].valueHashCode); int fontHashCode = m_xmlAttribute[0].valueHashCode; int materialAttributeHashCode = m_xmlAttribute[1].nameHashCode; int materialHashCode = m_xmlAttribute[1].valueHashCode; // Special handling for <font=default> or <font=Default> if (fontHashCode == 764638571 || fontHashCode == 523367755) { m_currentFontAsset = m_materialReferences[0].fontAsset; m_currentMaterial = m_materialReferences[0].material; m_currentMaterialIndex = 0; //Debug.Log("<font=Default> assigning Font Asset [" + m_currentFontAsset.name + "] with Material [" + m_currentMaterial.name + "]."); m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); m_materialReferenceStack.Add(m_materialReferences[0]); return true; } TMP_FontAsset tempFont; Material tempMaterial; // HANDLE NEW FONT ASSET if (MaterialReferenceManager.TryGetFontAsset(fontHashCode, out tempFont)) { //if (tempFont != m_currentFontAsset) //{ // //Debug.Log("Assigning Font Asset: " + tempFont.name); // m_currentFontAsset = tempFont; // m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); //} } else { // Load Font Asset tempFont = Resources.Load<TMP_FontAsset>("Fonts & Materials/" + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength)); if (tempFont == null) return false; // Add new reference to the font asset as well as default material to the MaterialReferenceManager MaterialReferenceManager.AddFontAsset(tempFont); } // HANDLE NEW MATERIAL if (materialAttributeHashCode == 0 && materialHashCode == 0) { // No material specified then use default font asset material. m_currentMaterial = tempFont.material; m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup); m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]); } else if (materialAttributeHashCode == 103415287) // using material attribute { if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial)) { m_currentMaterial = tempMaterial; m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup); m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]); } else { // Load new material tempMaterial = Resources.Load<Material>("Fonts & Materials/" + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength)); if (tempMaterial == null) return false; // Add new reference to this material in the MaterialReferenceManager MaterialReferenceManager.AddFontMaterial(materialHashCode, tempMaterial); m_currentMaterial = tempMaterial; m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup); m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]); } } else return false; m_currentFontAsset = tempFont; m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; case 154158: // </font> MaterialReference materialReference = m_materialReferenceStack.Remove(); m_currentFontAsset = materialReference.fontAsset; m_currentMaterial = materialReference.material; m_currentMaterialIndex = materialReference.index; m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f)); return true; case 320078: // <space=000.00> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: m_xAdvance += value; return true; case TagUnits.FontUnits: m_xAdvance += value * m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; return true; case TagUnits.Percentage: // Not applicable return false; } return false; case 276254: // <alpha=#FF> if (m_xmlAttribute[0].valueLength != 3) return false; m_htmlColor.a = (byte)(HexToInt(m_htmlTag[7]) * 16 + HexToInt(m_htmlTag[8])); return true; case 1750458: // <a name=" "> return false; case 426: // </a> return true; case 43066: // <link="name"> if (m_isParsingText) { tag_LinkInfo.textComponent = this; tag_LinkInfo.hashCode = m_xmlAttribute[0].valueHashCode; tag_LinkInfo.linkTextfirstCharacterIndex = m_characterCount; tag_LinkInfo.linkIdFirstCharacterIndex = startIndex + m_xmlAttribute[0].valueStartIndex; tag_LinkInfo.linkIdLength = m_xmlAttribute[0].valueLength; } return true; case 155913: // </link> if (m_isParsingText) { tag_LinkInfo.linkTextLength = m_characterCount - tag_LinkInfo.linkTextfirstCharacterIndex; int size = m_textInfo.linkInfo.Length; if (m_textInfo.linkCount + 1 > size) TMP_TextInfo.Resize(ref m_textInfo.linkInfo, size + 1); m_textInfo.linkInfo[m_textInfo.linkCount] = tag_LinkInfo; m_textInfo.linkCount += 1; } return true; case 275917: // <align=> switch (m_xmlAttribute[0].valueHashCode) { case 3774683: // <align=left> m_lineJustification = TextAlignmentOptions.Left; return true; case 136703040: // <align=right> m_lineJustification = TextAlignmentOptions.Right; return true; case -458210101: // <align=center> m_lineJustification = TextAlignmentOptions.Center; return true; case -523808257: // <align=justified> m_lineJustification = TextAlignmentOptions.Justified; return true; } return false; case 1065846: // </align> m_lineJustification = m_textAlignment; return true; case 327550: // <width=xx> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: m_width = value; break; case TagUnits.FontUnits: return false; //break; case TagUnits.Percentage: m_width = m_marginWidth * value / 100; break; } return true; case 1117479: // </width> m_width = -1; return true; case 322689: // <style="name"> TMP_Style style = TMP_StyleSheet.Instance.GetStyle(m_xmlAttribute[0].valueHashCode); if (style == null) return false; m_styleStack.Add(style.hashCode); //// Parse Style Macro for (int i = 0; i < style.styleOpeningTagArray.Length; i++) { if (style.styleOpeningTagArray[i] == 60) ValidateHtmlTag(style.styleOpeningTagArray, i + 1, out i); } return true; case 1112618: // </style> style = TMP_StyleSheet.Instance.GetStyle(m_xmlAttribute[0].valueHashCode); if (style == null) { // Get style from the Style Stack int styleHashCode = m_styleStack.Remove(); style = TMP_StyleSheet.Instance.GetStyle(styleHashCode); } if (style == null) return false; //// Parse Style Macro for (int i = 0; i < style.styleClosingTagArray.Length; i++) { if (style.styleClosingTagArray[i] == 60) ValidateHtmlTag(style.styleClosingTagArray, i + 1, out i); } return true; case 281955: // <color=#FF00FF> or <color=#FF00FF00> // <color=#FF00FF> 3 Hex pairs if (m_htmlTag[6] == 35 && tagCharCount == 13) { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); return true; } // <color=#FF00FF00> 4 Hex pairs else if (m_htmlTag[6] == 35 && tagCharCount == 15) { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); return true; } // <color=name> switch (m_xmlAttribute[0].valueHashCode) { case 125395: // <color=red> m_htmlColor = Color.red; m_colorStack.Add(m_htmlColor); return true; case 3573310: // <color=blue> m_htmlColor = Color.blue; m_colorStack.Add(m_htmlColor); return true; case 117905991: // <color=black> m_htmlColor = Color.black; m_colorStack.Add(m_htmlColor); return true; case 121463835: // <color=green> m_htmlColor = Color.green; m_colorStack.Add(m_htmlColor); return true; case 140357351: // <color=white> m_htmlColor = Color.white; m_colorStack.Add(m_htmlColor); return true; case 26556144: // <color=orange> m_htmlColor = new Color32(255, 128, 0, 255); m_colorStack.Add(m_htmlColor); return true; case -36881330: // <color=purple> m_htmlColor = new Color32(160, 32, 240, 255); m_colorStack.Add(m_htmlColor); return true; case 554054276: // <color=yellow> m_htmlColor = Color.yellow; m_colorStack.Add(m_htmlColor); return true; } return false; case 1983971: // <cspace=xx.x> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: m_cSpacing = value; break; case TagUnits.FontUnits: m_cSpacing = value; m_cSpacing *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: return false; } return true; case 7513474: // </cspace> m_cSpacing = 0; return true; case 2152041: // <mspace=xx.x> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: m_monoSpacing = value; break; case TagUnits.FontUnits: m_monoSpacing = value; m_monoSpacing *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: return false; } return true; case 7681544: // </mspace> m_monoSpacing = 0; return true; case 280416: // <class="name"> return false; case 1071884: // </color> m_htmlColor = m_colorStack.Remove(); return true; case 2068980: // <indent=10px> <indent=10em> <indent=50%> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: tag_Indent = value; break; case TagUnits.FontUnits: tag_Indent = value; tag_Indent *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: tag_Indent = m_marginWidth * value / 100; break; } m_indentStack.Add(tag_Indent); m_xAdvance = tag_Indent; return true; case 7598483: // </indent> tag_Indent = m_indentStack.Remove(); //m_xAdvance = tag_Indent; return true; case 1109386397: // <line-indent> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; switch (tagUnits) { case TagUnits.Pixels: tag_LineIndent = value; break; case TagUnits.FontUnits: tag_LineIndent = value; tag_LineIndent *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: tag_LineIndent = m_marginWidth * value / 100; break; } m_xAdvance += tag_LineIndent; return true; case -445537194: // </line-indent> tag_LineIndent = 0; return true; case 2246877: // <sprite=x> int spriteAssetHashCode = m_xmlAttribute[0].valueHashCode; TMP_SpriteAsset tempSpriteAsset; // CHECK TAG FORMAT if (m_xmlAttribute[0].valueType == TagType.None || m_xmlAttribute[0].valueType == TagType.NumericalValue) { // No Sprite Asset specified if (m_defaultSpriteAsset == null) { // Load TMP Settings if (m_settings == null) m_settings = TMP_Settings.LoadDefaultSettings(); if (m_settings != null && m_settings.spriteAsset != null) m_defaultSpriteAsset = m_settings.spriteAsset; else m_defaultSpriteAsset = Resources.Load<TMP_SpriteAsset>("Sprite Assets/Default Sprite Asset"); } m_currentSpriteAsset = m_defaultSpriteAsset; // No valid sprite asset available if (m_currentSpriteAsset == null) return false; } else { // A Sprite Asset has been specified if (MaterialReferenceManager.TryGetSpriteAsset(spriteAssetHashCode, out tempSpriteAsset)) { m_currentSpriteAsset = tempSpriteAsset; } else { // Load Sprite Asset if (tempSpriteAsset == null) { tempSpriteAsset = Resources.Load<TMP_SpriteAsset>("Sprites/" + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength)); } if (tempSpriteAsset == null) return false; //Debug.Log("Loading & assigning new Sprite Asset: " + tempSpriteAsset.name); MaterialReferenceManager.AddSpriteAsset(spriteAssetHashCode, tempSpriteAsset); m_currentSpriteAsset = tempSpriteAsset; } } if (m_xmlAttribute[0].valueType == TagType.NumericalValue) { int index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (index == -9999) return false; m_spriteIndex = index; } else if (m_xmlAttribute[1].nameHashCode == 43347) // <sprite name=""> { //Debug.Log("Name attribute [" + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength) + "]."); int index = m_currentSpriteAsset.GetSpriteIndex(m_xmlAttribute[1].valueHashCode); if (index == -1) return false; m_spriteIndex = index; } else if (m_xmlAttribute[1].nameHashCode == 295562) // <sprite index=xx> { int index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength, m_xmlAttribute[1].valueDecimalIndex); if (index == -9999) return false; m_spriteIndex = index; // Check to make sure sprite index is valid if (m_spriteIndex > m_currentSpriteAsset.spriteInfoList.Count - 1) return false; } else { return false; } // Material HashCode for the Sprite Asset is the Sprite Asset Hash Code m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentSpriteAsset.material, m_currentSpriteAsset, m_materialReferences, m_materialReferenceIndexLookup); //m_materialReferenceStack.Add(m_materialReferenceManager.materialReferences[m_currentMaterialIndex]); m_spriteColor = s_colorWhite; m_tintSprite = false; // Handle Tint Attribute if (m_xmlAttribute[1].nameHashCode == 45819) m_tintSprite = ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength, m_xmlAttribute[1].valueDecimalIndex) != 0; else if (m_xmlAttribute[2].nameHashCode == 45819) m_tintSprite = ConvertToFloat(m_htmlTag, m_xmlAttribute[2].valueStartIndex, m_xmlAttribute[2].valueLength, m_xmlAttribute[2].valueDecimalIndex) != 0; // Handle Color Attribute if (m_xmlAttribute[1].nameHashCode == 281955) m_spriteColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength); else if (m_xmlAttribute[2].nameHashCode == 281955) m_spriteColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[2].valueStartIndex, m_xmlAttribute[2].valueLength); m_xmlAttribute[1].nameHashCode = 0; m_xmlAttribute[2].nameHashCode = 0; m_textElementType = TMP_TextElementType.Sprite; return true; case 730022849: // <lowercase> m_style |= FontStyles.LowerCase; return true; case -1668324918: // </lowercase> m_style &= ~FontStyles.LowerCase; return true; case 13526026: // <allcaps> case 781906058: // <uppercase> m_style |= FontStyles.UpperCase; return true; case 52232547: // </allcaps> case -1616441709: // </uppercase> m_style &= ~FontStyles.UpperCase; return true; case 766244328: // <smallcaps> m_style |= FontStyles.SmallCaps; return true; case -1632103439: // </smallcaps> m_style &= ~FontStyles.SmallCaps; return true; case 2109854: // <margin=00.0> <margin=00em> <margin=50%> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); // px if (value == -9999 || value == 0) return false; m_marginLeft = value; switch (tagUnits) { case TagUnits.Pixels: // Default behavior break; case TagUnits.FontUnits: m_marginLeft *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginLeft / 100; break; } m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0; m_marginRight = m_marginLeft; return true; case 7639357: // </margin> m_marginLeft = 0; m_marginRight = 0; return true; case 1100728678: // <margin-left=xx.x> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); // px if (value == -9999 || value == 0) return false; m_marginLeft = value; switch (tagUnits) { case TagUnits.Pixels: // Default behavior break; case TagUnits.FontUnits: m_marginLeft *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginLeft / 100; break; } m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0; return true; case -884817987: // <margin-right=xx.x> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); // px if (value == -9999 || value == 0) return false; m_marginRight = value; switch (tagUnits) { case TagUnits.Pixels: // Default behavior break; case TagUnits.FontUnits: m_marginRight *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize; break; case TagUnits.Percentage: m_marginRight = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginRight / 100; break; } m_marginRight = m_marginRight >= 0 ? m_marginRight : 0; return true; case 1109349752: // <line-height=xx.x> value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength, m_xmlAttribute[0].valueDecimalIndex); if (value == -9999 || value == 0) return false; m_lineHeight = value; switch (tagUnits) { case TagUnits.Pixels: //m_lineHeight *= m_isOrthographic ? 1 : 0.1f; break; case TagUnits.FontUnits: m_lineHeight *= m_fontAsset.fontInfo.LineHeight * m_fontScale; break; case TagUnits.Percentage: m_lineHeight = m_fontAsset.fontInfo.LineHeight * m_lineHeight / 100 * m_fontScale; break; } return true; case -445573839: // </line-height> m_lineHeight = 0; return true; case 15115642: // <noparse> tag_NoParsing = true; return true; case 1913798: // <action> // TODO return false; case 7443301: // </action> // TODO return false; } } return false; }
public static bool TryGetFontAsset(int hashCode, out TMP_FontAsset fontAsset) { return(instance.TryGetFontAssetInternal(hashCode, out fontAsset)); }
public static void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) { FONT_PROPERTY_EVENT.Call(isChanged, font); }
public static void AddFontAsset(TMP_FontAsset fontAsset) { instance.AddFontAssetInternal(fontAsset); }