From f6d1bcd28d68ddbd0036fdf7f30b5ffe035ee6a7 Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity.com> Date: Sat, 14 Mar 2020 00:00:00 +0100 Subject: [PATCH] com.unity.textmeshpro@1.5.0-preview.8 ## [1.5.0-preview.8] - 2020-03-14 ## [2.1.0-preview.8] ## [3.0.0-preview.8] ### Changes - Fixed a minor issue where the preferred width of a text object can be incorrect when using multiple font assets, fallbacks and sprites in the same line of text. - Added Alpha Fade Speed property to the TMP_DropDown inspector. - Minor improvements to the LogWarning related to missing characters in a font asset or fallback being replaced by a space character. - Fixed text object geometry not getting clipped when object is outside of RectMask2D. - Improved search for potential missing character to include the primary font asset and potential fallbacks when the current font asset is not the primary. - Ignorable / Synthesized characters in font assets will only be created if they do not exist in the source font file. - Trying to use Text Overflow Ellipsis mode when no Ellipsis character is available in the primary font asset or potential fallbacks will now issue a warning and switch Text Overflow mode to Truncate. - Added <color=lightblue> and <color=grey> to pre-defined rich text tag colors. - Fixed compatibility issue when using TexturePacker - JSON (Array) mode and the TMP Sprite Asset Importer to create SpriteAssets. - Simple fix to prevent the underline rich text tag becoming visible in the TMP Input Field when in IME composition mode with Rich Text disabled on the TMP Input Field. This is a temporary fix until a more robust and flexible solution is implemented. Case #1219969 - Sub Text Objects which are created when the text requires the use of a fallback font asset or sprite asset will now use HideFlags.DontSave to prevent them from being save with Prefabs as they are created on demand. - Fix incorrect material reference when current font asset is not the primary or a fallback that is missing a character which is present in the primary font asset. --- CHANGELOG.md | 17 ++ Scripts/Editor/TMP_DropdownEditor.cs | 5 +- Scripts/Editor/TMP_SpriteAssetImporter.cs | 10 +- Scripts/Runtime/TMP_FontAsset.cs | 289 ++++++++++-------- Scripts/Runtime/TMP_FontAssetUtilities.cs | 7 +- Scripts/Runtime/TMP_InputField.cs | 7 +- Scripts/Runtime/TMP_SelectionCaret.cs | 2 +- .../Runtime/TMP_SpriteAssetImportFormats.cs | 16 +- Scripts/Runtime/TMP_SubMesh.cs | 17 +- Scripts/Runtime/TMP_SubMeshUI.cs | 3 +- Scripts/Runtime/TMP_Text.cs | 21 +- Scripts/Runtime/TMPro_Private.cs | 43 ++- Scripts/Runtime/TMPro_UGUI_Private.cs | 45 ++- Scripts/Runtime/TextMeshProUGUI.cs | 24 +- package.json | 6 +- 15 files changed, 335 insertions(+), 177 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84c9cd..c2c00e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ # Changelog These are the release notes for the TextMesh Pro UPM package which was first introduced with Unity 2018.1. Please see the following link for the Release Notes for prior versions of TextMesh Pro. http://digitalnativestudios.com/forum/index.php?topic=1363.0 +## [1.5.0-preview.8] - 2020-03-14 +## [2.1.0-preview.8] +## [3.0.0-preview.8] +### Changes +- Fixed a minor issue where the preferred width of a text object can be incorrect when using multiple font assets, fallbacks and sprites in the same line of text. +- Added Alpha Fade Speed property to the TMP_DropDown inspector. +- Minor improvements to the LogWarning related to missing characters in a font asset or fallback being replaced by a space character. +- Fixed text object geometry not getting clipped when object is outside of RectMask2D. +- Improved search for potential missing character to include the primary font asset and potential fallbacks when the current font asset is not the primary. +- Ignorable / Synthesized characters in font assets will only be created if they do not exist in the source font file. +- Trying to use Text Overflow Ellipsis mode when no Ellipsis character is available in the primary font asset or potential fallbacks will now issue a warning and switch Text Overflow mode to Truncate. +- Added <color=lightblue> and <color=grey> to pre-defined rich text tag colors. +- Fixed compatibility issue when using TexturePacker - JSON (Array) mode and the TMP Sprite Asset Importer to create SpriteAssets. +- Simple fix to prevent the underline rich text tag becoming visible in the TMP Input Field when in IME composition mode with Rich Text disabled on the TMP Input Field. This is a temporary fix until a more robust and flexible solution is implemented. Case #1219969 +- Sub Text Objects which are created when the text requires the use of a fallback font asset or sprite asset will now use HideFlags.DontSave to prevent them from being save with Prefabs as they are created on demand. +- Fix incorrect material reference when current font asset is not the primary or a fallback that is missing a character which is present in the primary font asset. + ## [1.5.0-preview.7] - 2020-03-07 ## [2.1.0-preview.7] ## [3.0.0-preview.7] diff --git a/Scripts/Editor/TMP_DropdownEditor.cs b/Scripts/Editor/TMP_DropdownEditor.cs index 7a5f49a..48f8e2b 100644 --- a/Scripts/Editor/TMP_DropdownEditor.cs +++ b/Scripts/Editor/TMP_DropdownEditor.cs @@ -17,6 +17,7 @@ public class DropdownEditor : SelectableEditor SerializedProperty m_ItemImage; SerializedProperty m_OnSelectionChanged; SerializedProperty m_Value; + SerializedProperty m_AlphaFadeSpeed; SerializedProperty m_Options; protected override void OnEnable() @@ -30,6 +31,7 @@ protected override void OnEnable() m_ItemImage = serializedObject.FindProperty("m_ItemImage"); m_OnSelectionChanged = serializedObject.FindProperty("m_OnValueChanged"); m_Value = serializedObject.FindProperty("m_Value"); + m_AlphaFadeSpeed = serializedObject.FindProperty("m_AlphaFadeSpeed"); m_Options = serializedObject.FindProperty("m_Options"); } @@ -46,9 +48,10 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_ItemText); EditorGUILayout.PropertyField(m_ItemImage); EditorGUILayout.PropertyField(m_Value); + EditorGUILayout.PropertyField(m_AlphaFadeSpeed); EditorGUILayout.PropertyField(m_Options); EditorGUILayout.PropertyField(m_OnSelectionChanged); serializedObject.ApplyModifiedProperties(); } } -} \ No newline at end of file +} diff --git a/Scripts/Editor/TMP_SpriteAssetImporter.cs b/Scripts/Editor/TMP_SpriteAssetImporter.cs index 59eeaf5..72d8277 100644 --- a/Scripts/Editor/TMP_SpriteAssetImporter.cs +++ b/Scripts/Editor/TMP_SpriteAssetImporter.cs @@ -142,7 +142,7 @@ void DrawEditorPanel() /// - /// + /// /// /// /// @@ -151,6 +151,8 @@ private static void PopulateSpriteTables(TexturePacker_JsonArray.SpriteDataObjec { List importedSprites = spriteDataObject.frames; + float atlasHeight = spriteDataObject.meta.size.h; + for (int i = 0; i < importedSprites.Count; i++) { TexturePacker_JsonArray.Frame spriteData = importedSprites[i]; @@ -159,7 +161,7 @@ private static void PopulateSpriteTables(TexturePacker_JsonArray.SpriteDataObjec spriteGlyph.index = (uint)i; spriteGlyph.metrics = new GlyphMetrics((int)spriteData.frame.w, (int)spriteData.frame.h, -spriteData.frame.w * spriteData.pivot.x, spriteData.frame.h * spriteData.pivot.y, (int)spriteData.frame.w); - spriteGlyph.glyphRect = new GlyphRect((int)spriteData.frame.x, (int)spriteData.frame.y, (int)spriteData.frame.w, (int)spriteData.frame.h); + spriteGlyph.glyphRect = new GlyphRect((int)spriteData.frame.x, (int)(atlasHeight - spriteData.frame.h - spriteData.frame.y), (int)spriteData.frame.w, (int)spriteData.frame.h); spriteGlyph.scale = 1.0f; spriteGlyphTable.Add(spriteGlyph); @@ -174,7 +176,7 @@ private static void PopulateSpriteTables(TexturePacker_JsonArray.SpriteDataObjec /// - /// + /// /// /// void SaveSpriteAsset(string filePath) @@ -237,4 +239,4 @@ void SetEditorWindowSize() } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TMP_FontAsset.cs b/Scripts/Runtime/TMP_FontAsset.cs index a3e0a55..49b0df7 100644 --- a/Scripts/Runtime/TMP_FontAsset.cs +++ b/Scripts/Runtime/TMP_FontAsset.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; - +using UnityEditor; #if UNITY_EDITOR && UNITY_2018_4_OR_NEWER #if !(UNITY_2018_4_0 || UNITY_2018_4_1 || UNITY_2018_4_2 || UNITY_2018_4_3 || UNITY_2018_4_4) using UnityEditor.TextCore.LowLevel; @@ -692,100 +692,49 @@ internal void InitializeGlyphPaidAdjustmentRecordsLookupDictionary() internal void AddSynthesizedCharactersAndFaceMetrics() { - if (m_CharacterLookupDictionary.ContainsKey(9) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, m_FaceInfo.tabWidth * tabSize), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(9, new TMP_Character(9, glyph)); - } + Profiler.BeginSample("TMP.AddSynthesizedCharacters"); - // Add Linefeed LF char(10), VT char(11) and Carriage Return CR char(13) - if (m_CharacterLookupDictionary.ContainsKey(10) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(10, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(10, new TMP_Character(10, glyph)); + if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) + FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize); - if (!m_CharacterLookupDictionary.ContainsKey(11)) - m_CharacterLookupDictionary.Add(11, new TMP_Character(11, glyph)); + // Only characters not present in the source font file will be synthesized. - if (!m_CharacterLookupDictionary.ContainsKey(13)) - m_CharacterLookupDictionary.Add(13, new TMP_Character(13, glyph)); + // Non visible and control characters with no metrics + // Add End of Text \u0003 + AddSynthesizedCharacter(0x03, true); - if (!m_CharacterLookupDictionary.ContainsKey(3)) - m_CharacterLookupDictionary.Add(3, new TMP_Character(3, glyph)); - } + // Add Tab \u0009 + AddSynthesizedCharacter(0x09, true); - // Add Non Breaking Space \u00A0 - if (m_CharacterLookupDictionary.ContainsKey(0x00A0) == false) - { - TMP_Character character; - if (m_CharacterLookupDictionary.TryGetValue(0x0020, out character)) - m_CharacterLookupDictionary.Add(0x00A0, new TMP_Character(0x00A0, character.glyph)); - } + // Add Line Feed (LF) \u000A + AddSynthesizedCharacter(0x0A); - // Add Soft Hyphen \u00AD - if (m_CharacterLookupDictionary.ContainsKey(0x00AD) == false) - { - TMP_Character character; - if (m_CharacterLookupDictionary.TryGetValue(0x002D, out character)) - m_CharacterLookupDictionary.Add(0x00AD, new TMP_Character(0x00AD, character.glyph)); - } + // Add Vertical Tab (VT) \u000B + AddSynthesizedCharacter(0x0B); + + // Add Carriage Return (CR) \u000D + AddSynthesizedCharacter(0x0D); // Add Arabic Letter Mark \u061C - if (m_CharacterLookupDictionary.ContainsKey(0x061C) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x061C, new TMP_Character(0x061C, glyph)); - } + AddSynthesizedCharacter(0x061C); - // Add Zero Width Space \u200B - if (m_CharacterLookupDictionary.ContainsKey(0x200B) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x200B, new TMP_Character(0x200B, glyph)); - } + // Add Zero Width Space \u2000B + AddSynthesizedCharacter(0x200B); // Add Left-To-Right Mark \u200E - if (m_CharacterLookupDictionary.ContainsKey(0x200E) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x200E, new TMP_Character(0x200E, glyph)); - } + AddSynthesizedCharacter(0x200E); // Add Right-To-Left Mark \u200F - if (m_CharacterLookupDictionary.ContainsKey(0x200F) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x200F, new TMP_Character(0x200F, glyph)); - } + AddSynthesizedCharacter(0x200F); // Add Line Separator \u2028 - if (m_CharacterLookupDictionary.ContainsKey(0x2028) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x2028, new TMP_Character(0x2028, glyph)); - } - - // Add Line Separator \u2029 - if (m_CharacterLookupDictionary.ContainsKey(0x2029) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x2029, new TMP_Character(0x2029, glyph)); - } + AddSynthesizedCharacter(0x2028); - // Add Zero Width Non-Breaking Space \u2060 - if (m_CharacterLookupDictionary.ContainsKey(0x2060) == false) - { - Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); - m_CharacterLookupDictionary.Add(0x2060, new TMP_Character(0x2060, glyph)); - } + // Add Paragraph Separator \u2029 + AddSynthesizedCharacter(0x2029); - // Add Non-Breaking Hyphen \u2011 - if (m_CharacterLookupDictionary.ContainsKey(0x2011) == false) - { - TMP_Character character; - if (m_CharacterLookupDictionary.TryGetValue(0x002D, out character)) - m_CharacterLookupDictionary.Add(0x2011, new TMP_Character(0x2011, character.glyph)); - } + // Add Word Joiner / Zero Width Non-Breaking Space \u2060 + AddSynthesizedCharacter(0x2060); // Set Cap Line using the capital letter 'X' if (m_FaceInfo.capLine == 0 && m_CharacterLookupDictionary.ContainsKey('X')) @@ -800,8 +749,43 @@ internal void AddSynthesizedCharactersAndFaceMetrics() uint glyphIndex = m_CharacterLookupDictionary['x'].glyphIndex; m_FaceInfo.meanLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; } + + Profiler.EndSample(); } + void AddSynthesizedCharacter(uint unicode, bool addImmediately = false) + { + // Check if unicode is already present in the font asset + if (m_CharacterLookupDictionary.ContainsKey(unicode)) + return; + + Glyph glyph; + + if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) + { + // Check if unicode is present in font file + if (FontEngine.GetGlyphIndex(unicode) != 0) + { + if (addImmediately == false) + return; + + //Debug.Log("Adding Unicode [" + unicode.ToString("X4") + "]."); + + GlyphLoadFlags glyphLoadFlags = ((GlyphRasterModes)m_AtlasRenderMode & GlyphRasterModes.RASTER_MODE_NO_HINTING) == GlyphRasterModes.RASTER_MODE_NO_HINTING ? GlyphLoadFlags.LOAD_NO_BITMAP | GlyphLoadFlags.LOAD_NO_HINTING : GlyphLoadFlags.LOAD_NO_BITMAP; + + if (FontEngine.TryGetGlyphWithUnicodeValue(unicode, glyphLoadFlags, out glyph)) + m_CharacterLookupDictionary.Add(unicode, new TMP_Character(unicode, glyph)); + + return; + } + } + + //Debug.Log("Synthesizing Unicode [" + unicode.ToString("X4") + "]."); + + // Synthesize and add missing glyph and character + glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); + m_CharacterLookupDictionary.Add(unicode, new TMP_Character(unicode, glyph)); + } /// /// Sort the Character table by Unicode values. @@ -1420,11 +1404,29 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i // Skip missing glyphs if (glyphIndex == 0) { - // Add character to list of missing characters. - s_MissingCharacterList.Add(unicode); + // Special handling for characters with potential alternative glyph representations + switch (unicode) + { + case 0xA0: // Non Breaking Space + // Use Space + glyphIndex = FontEngine.GetGlyphIndex(0x20); + break; + case 0xAD: // Soft Hyphen + case 0x2011: // Non Breaking Hyphen + // Use Hyphen Minus + glyphIndex = FontEngine.GetGlyphIndex(0x2D); + break; + } - isMissingCharacters = true; - continue; + // Skip to next character if no potential alternative glyph representation is present in font file. + if (glyphIndex == 0) + { + // Add character to list of missing characters. + s_MissingCharacterList.Add(unicode); + + isMissingCharacters = true; + continue; + } } TMP_Character character = new TMP_Character(unicode, glyphIndex); @@ -1614,11 +1616,29 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo // Skip missing glyphs if (glyphIndex == 0) { - // Add character to list of missing characters. - s_MissingCharacterList.Add(unicode); + // Special handling for characters with potential alternative glyph representations + switch (unicode) + { + case 0xA0: // Non Breaking Space + // Use Space + glyphIndex = FontEngine.GetGlyphIndex(0x20); + break; + case 0xAD: // Soft Hyphen + case 0x2011: // Non Breaking Hyphen + // Use Hyphen Minus + glyphIndex = FontEngine.GetGlyphIndex(0x2D); + break; + } - isMissingCharacters = true; - continue; + // Skip to next character if no potential alternative glyph representation is present in font file. + if (glyphIndex == 0) + { + // Add character to list of missing characters. + s_MissingCharacterList.Add(unicode); + + isMissingCharacters = true; + continue; + } } TMP_Character character = new TMP_Character(unicode, glyphIndex); @@ -1904,10 +1924,28 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) uint glyphIndex = FontEngine.GetGlyphIndex(unicode); if (glyphIndex == 0) { - m_MissingUnicodesFromFontFile.Add(unicode); + // Special handling for characters with potential alternative glyph representations + switch (unicode) + { + case 0xA0: // Non Breaking Space + // Use Space + glyphIndex = FontEngine.GetGlyphIndex(0x20); + break; + case 0xAD: // Soft Hyphen + case 0x2011: // Non Breaking Hyphen + // Use Hyphen Minus + glyphIndex = FontEngine.GetGlyphIndex(0x2D); + break; + } - Profiler.EndSample(); - return false; + // Return if no potential alternative glyph representation is present in font file. + if (glyphIndex == 0) + { + m_MissingUnicodesFromFontFile.Add(unicode); + + Profiler.EndSample(); + return false; + } } // Check if glyph is already contained in the font asset as the same glyph might be referenced by multiple characters. @@ -2086,10 +2124,28 @@ internal bool TryGetCharacter_and_QueueRenderToTexture(uint unicode, out TMP_Cha uint glyphIndex = FontEngine.GetGlyphIndex(unicode); if (glyphIndex == 0) { - m_MissingUnicodesFromFontFile.Add(unicode); + // Special handling for characters with potential alternative glyph representations + switch (unicode) + { + case 0xA0: // Non Breaking Space + // Use Space + glyphIndex = FontEngine.GetGlyphIndex(0x20); + break; + case 0xAD: // Soft Hyphen + case 0x2011: // Non Breaking Hyphen + // Use Hyphen Minus + glyphIndex = FontEngine.GetGlyphIndex(0x2D); + break; + } - Profiler.EndSample(); - return false; + // Return if no potential alternative glyph representation is present in font file. + if (glyphIndex == 0) + { + m_MissingUnicodesFromFontFile.Add(unicode); + + Profiler.EndSample(); + return false; + } } // Check if glyph is already contained in the font asset as the same glyph might be referenced by multiple characters. @@ -2388,11 +2444,11 @@ internal void UpdateGlyphAdjustmentRecords() Profiler.BeginSample("TMP.UpdateGlyphAdjustmentRecords"); // TODO: This copying of glyph index from list to array is temporary and will be replaced once an updated version of the FontEngine is released. - // Copy glyph index to array CopyListDataToArray(m_GlyphIndexList, ref k_GlyphIndexArray); // Get glyph pair adjustment records from font file. GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentTable(k_GlyphIndexArray); + // TODO: The GetGlyphPairAdjustmentTable will be replaced by the more efficient GetGlyphPairAdjustmentRecords once the updated version of the FontEngine is released. //GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentRecords(m_GlyphIndexListNewlyAdded, m_GlyphIndexList); // Clear newly added glyph list @@ -2566,23 +2622,16 @@ internal void UpdateGlyphAdjustmentRecords(List newGlyphIndexes, ListElement type void CopyListDataToArray(List srcList, ref T[] dstArray) { - // Make sure destination array is appropriately sized. - if (dstArray == null || dstArray.Length < srcList.Count + 1) - { - int newSize = Mathf.NextPowerOfTwo(srcList.Count + 1); + int size = srcList.Count; - if (dstArray == null) - dstArray = new T[newSize]; - else - Array.Resize(ref dstArray, newSize); - } + // Make sure destination array is appropriately sized. + if (dstArray == null) + dstArray = new T[size]; + else + Array.Resize(ref dstArray, size); - int count = srcList.Count; - for (int i = 0; i < count; i++) + for (int i = 0; i < size; i++) dstArray[i] = srcList[i]; - - // Terminate last array element with default value - dstArray[count] = default(T); } /// @@ -2605,15 +2654,13 @@ public void ClearFontAssetData(bool setAtlasSizeToZero = false) // Clear atlas textures ClearAtlasTextures(setAtlasSizeToZero); + ReadFontAssetDefinition(); + #if UNITY_EDITOR - if (UnityEditor.EditorUtility.IsPersistent(this)) - { - TMP_EditorResourceManager.RegisterResourceForReimport(this); - } + // Makes the changes to the font asset persistent. + TMP_EditorResourceManager.RegisterResourceForUpdate(this); #endif - ReadFontAssetDefinition(); - Profiler.EndSample(); } @@ -2641,13 +2688,6 @@ internal void UpdateFontAssetData() // Add glyphs TryAddCharacters(unicodeCharacters, true); - #if UNITY_EDITOR - if (UnityEditor.EditorUtility.IsPersistent(this)) - { - TMP_EditorResourceManager.RegisterResourceForReimport(this); - } - #endif - Profiler.EndSample(); } @@ -2702,9 +2742,16 @@ internal void ClearAtlasTextures(bool setAtlasSizeToZero = false) { Texture2D texture = m_AtlasTextures[i]; - if (i > 0) + if (i > 0 && texture != null) + { DestroyImmediate(texture, true); + #if UNITY_EDITOR + if (UnityEditor.EditorUtility.IsPersistent(this)) + TMP_EditorResourceManager.RegisterResourceForReimport(this); + #endif + } + if (texture == null) continue; diff --git a/Scripts/Runtime/TMP_FontAssetUtilities.cs b/Scripts/Runtime/TMP_FontAssetUtilities.cs index 5e77c9d..bd501c1 100644 --- a/Scripts/Runtime/TMP_FontAssetUtilities.cs +++ b/Scripts/Runtime/TMP_FontAssetUtilities.cs @@ -119,7 +119,8 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM return characterData; } - else if (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) + + if (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { if (fontAsset.TryAddCharacterInternal(unicode, out characterData)) { @@ -158,7 +159,8 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM return characterData; } - else if (sourceFontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) + + if (sourceFontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { if (sourceFontAsset.TryAddCharacterInternal(unicode, out characterData)) { @@ -168,7 +170,6 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM } // Unable to add character and glyph to font asset - } // Search fallback font assets if we still don't have a valid character and include fallback is set to true. diff --git a/Scripts/Runtime/TMP_InputField.cs b/Scripts/Runtime/TMP_InputField.cs index 3abd3a1..04ef0a9 100644 --- a/Scripts/Runtime/TMP_InputField.cs +++ b/Scripts/Runtime/TMP_InputField.cs @@ -1048,6 +1048,7 @@ protected override void OnEnable() { m_TextComponent.RegisterDirtyVerticesCallback(MarkGeometryAsDirty); m_TextComponent.RegisterDirtyVerticesCallback(UpdateLabel); + m_TextComponent.ignoreClipping = true; // Cache reference to Vertical Scrollbar RectTransform and add listener. if (m_VerticalScrollbar != null) @@ -1072,6 +1073,7 @@ protected override void OnDisable() { m_TextComponent.UnregisterDirtyVerticesCallback(MarkGeometryAsDirty); m_TextComponent.UnregisterDirtyVerticesCallback(UpdateLabel); + m_TextComponent.ignoreClipping = false; if (m_VerticalScrollbar != null) m_VerticalScrollbar.onValueChanged.RemoveListener(OnScrollbarValueChange); @@ -3129,7 +3131,10 @@ protected void UpdateLabel() // Handle selections Delete(); - fullText = text.Substring(0, m_StringPosition) + "" + compositionString + "" + text.Substring(m_StringPosition); + if (m_RichText) + fullText = text.Substring(0, m_StringPosition) + "" + compositionString + "" + text.Substring(m_StringPosition); + else + fullText = text.Substring(0, m_StringPosition) + compositionString + text.Substring(m_StringPosition); m_IsCompositionActive = true; diff --git a/Scripts/Runtime/TMP_SelectionCaret.cs b/Scripts/Runtime/TMP_SelectionCaret.cs index 6242b8a..33b12ef 100644 --- a/Scripts/Runtime/TMP_SelectionCaret.cs +++ b/Scripts/Runtime/TMP_SelectionCaret.cs @@ -30,7 +30,7 @@ public override void Cull(Rect clipRect, bool validRect) protected override void UpdateGeometry() { - // Function overridden as Caret and text Selection Highlight is controlled by the Input Field. + // Function overridden as Caret and text Selection Highlight is controlled by the Input Field. } } } diff --git a/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs b/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs index c543510..a5d6413 100644 --- a/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs +++ b/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs @@ -1,5 +1,4 @@ using UnityEngine; -using System.Collections; using System.Collections.Generic; @@ -49,10 +48,23 @@ public struct Frame public Vector2 pivot; } + [System.Serializable] + public struct Meta + { + public string app; + public string version; + public string image; + public string format; + public SpriteSize size; + public float scale; + public string smartupdate; + } + [System.Serializable] public class SpriteDataObject { public List frames; + public Meta meta; } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TMP_SubMesh.cs b/Scripts/Runtime/TMP_SubMesh.cs index a0b2b81..12cd915 100644 --- a/Scripts/Runtime/TMP_SubMesh.cs +++ b/Scripts/Runtime/TMP_SubMesh.cs @@ -2,7 +2,7 @@ using System; using System.Collections; -#pragma warning disable 0109 // Disable warning due to conflict between Unity Editor DLL and Runtime DLL related to .renderer property being available in one but not the other. +#pragma warning disable 0109 // Disable warning due to conflict between Unity Editor DLL and Runtime DLL related to .renderer property being available in one but not the other. namespace TMPro { @@ -178,7 +178,7 @@ public Mesh mesh private Mesh m_mesh; /// - /// + /// /// //public BoxCollider boxCollider //{ @@ -414,6 +414,7 @@ void ON_TMP_SETTINGS_CHANGED() public static TMP_SubMesh AddSubTextObject(TextMeshPro textComponent, MaterialReference materialReference) { GameObject go = new GameObject("TMP SubMesh [" + materialReference.material.name + "]", typeof(TMP_SubMesh)); + go.hideFlags = HideFlags.DontSave; TMP_SubMesh subMesh = go.GetComponent(); @@ -457,7 +458,7 @@ Material GetMaterial(Material mat) m_sharedMaterial = m_material; - // Compute and Set new padding values for this new material. + // Compute and Set new padding values for this new material. m_padding = GetPaddingForMaterial(); SetVerticesDirty(); @@ -506,7 +507,7 @@ void SetSharedMaterial(Material mat) // Assign new material. m_sharedMaterial = mat; - // Compute and Set new padding values for this new material. + // Compute and Set new padding values for this new material. m_padding = GetPaddingForMaterial(); SetMaterialDirty(); @@ -542,7 +543,7 @@ public void UpdateMeshPadding(bool isExtraPadding, bool isUsingBold) /// - /// + /// /// public void SetVerticesDirty() { @@ -559,7 +560,7 @@ public void SetVerticesDirty() /// - /// + /// /// public void SetMaterialDirty() { @@ -574,7 +575,7 @@ public void SetMaterialDirty() /// - /// + /// /// protected void UpdateMaterial() { @@ -598,7 +599,7 @@ protected void UpdateMaterial() } /// - /// + /// /// //public void UpdateColliders(int vertexCount) //{ diff --git a/Scripts/Runtime/TMP_SubMeshUI.cs b/Scripts/Runtime/TMP_SubMeshUI.cs index cd6ad3b..438182b 100644 --- a/Scripts/Runtime/TMP_SubMeshUI.cs +++ b/Scripts/Runtime/TMP_SubMeshUI.cs @@ -210,6 +210,7 @@ public TMP_Text textComponent public static TMP_SubMeshUI AddSubTextObject(TextMeshProUGUI textComponent, MaterialReference materialReference) { GameObject go = new GameObject("TMP UI SubObject [" + materialReference.material.name + "]", typeof(RectTransform)); + go.hideFlags = HideFlags.DontSave; go.transform.SetParent(textComponent.transform, false); go.layer = textComponent.gameObject.layer; @@ -636,7 +637,7 @@ public void SetPivotDirty() /// public override void Cull(Rect clipRect, bool validRect) { - if (validRect) + if (validRect && m_TextComponent.ignoreClipping) { canvasRenderer.cull = false; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); diff --git a/Scripts/Runtime/TMP_Text.cs b/Scripts/Runtime/TMP_Text.cs index 78e5d41..740d529 100644 --- a/Scripts/Runtime/TMP_Text.cs +++ b/Scripts/Runtime/TMP_Text.cs @@ -1697,6 +1697,12 @@ protected virtual void SetShaderDepth() { } /// protected virtual void SetCulling() { } + /// + /// Used to prevent clipping of text objects using nested RectMasks unless the compounded clip rect is no longer valid. + /// This is used by the TMP Input Field to prevent clipping when the RectTransform of the text ends up outside of the viewport RectMask. + /// + internal bool ignoreClipping; + /// /// Get the padding value for the currently assigned material /// @@ -5408,8 +5414,6 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m if (charCode == 60) charCode = 57344 + m_spriteIndex; - m_currentFontAsset = m_fontAsset; - // The sprite scale calculations are based on the font asset assigned to the text object. if (m_currentSpriteAsset.faceInfo.pointSize > 0) { @@ -7256,11 +7260,6 @@ protected void GetEllipsisSpecialCharacter(TMP_FontAsset fontAsset) m_Ellipsis.material = tempFontAsset.material; m_Ellipsis.materialIndex = 0; } - else - { - if (!TMP_Settings.warningsDisabled) - Debug.LogWarning("The character used for Ellipsis is not available in font asset [" + fontAsset.name + "].", this); - } } @@ -8899,10 +8898,18 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI m_htmlColor = Color.red; m_colorStack.Add(m_htmlColor); return true; + case -992792864: // + m_htmlColor = new Color32(173, 216, 230, 255); + m_colorStack.Add(m_htmlColor); + return true; case 3573310: // m_htmlColor = Color.blue; m_colorStack.Add(m_htmlColor); return true; + case 3680713: // + m_htmlColor = new Color32(128, 128, 128, 255); + m_colorStack.Add(m_htmlColor); + return true; case 117905991: // m_htmlColor = Color.black; m_colorStack.Add(m_htmlColor); diff --git a/Scripts/Runtime/TMPro_Private.cs b/Scripts/Runtime/TMPro_Private.cs index 6c145d2..635094d 100644 --- a/Scripts/Runtime/TMPro_Private.cs +++ b/Scripts/Runtime/TMPro_Private.cs @@ -1035,6 +1035,13 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_materialReferences[m_Ellipsis.materialIndex].referenceCount = 0; } } + else + { + m_overflowMode = TextOverflowModes.Truncate; + + if (!TMP_Settings.warningsDisabled) + Debug.LogWarning("The character used for Ellipsis is not available in font asset [" + m_currentFontAsset.name + "] or any potential fallbacks. Switching Text Overflow mode to Truncate.", this); + } } #endregion @@ -1143,6 +1150,30 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_currentFontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } + // Search for the glyph in the primary font asset if not the current font asset + if (character == null) + { + if (m_currentFontAsset.instanceID != m_fontAsset.instanceID) + { + // Search primary font asset + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_fontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + + // Use material and index of primary font asset. + if (character != null) + { + m_currentMaterialIndex = 0; + m_currentMaterial = m_materialReferences[0].material; + } + + // Search list of potential fallback font assets assigned to the primary font asset. + if (character == null) + { + if (m_fontAsset.m_FallbackFontAssetTable != null && m_fontAsset.m_FallbackFontAssetTable.Count > 0) + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + } + } + // Search for the glyph in the Sprite Asset assigned to the text object. if (character == null) { @@ -1290,11 +1321,11 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) { - string formatWarning = srcGlyph > 0xFFFF - ? "The character with Unicode value \\U{0:X8} was not found in {1}'s Glyph Table. It was replaced by a space in text object {2}." - : "The character with Unicode value \\u{0:X4} was not found in {1}'s Glyph Table. It was replaced by a space in text object {2}."; + string formattedWarning = srcGlyph > 0xFFFF + ? string.Format("The character with Unicode value \\U{0:X8} was not found in the [{1}] font asset or any potential fallbacks. It was replaced by a space in the text object [{2}].", srcGlyph, m_fontAsset.name, this.name) + : string.Format("The character with Unicode value \\u{0:X4} was not found in the [{1}] font asset or any potential fallbacks. It was replaced by a space in the text object [{2}].", srcGlyph, m_fontAsset.name, this.name); - Debug.LogWarningFormat(formatWarning, srcGlyph, m_fontAsset.name, this); + Debug.LogWarning(formattedWarning, this); } } } @@ -1318,7 +1349,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; - if (isUsingFallbackOrAlternativeTypeface) + if (isUsingFallbackOrAlternativeTypeface && m_currentFontAsset.instanceID != m_fontAsset.instanceID) { // Create Fallback material instance matching current material preset if necessary if (TMP_Settings.matchMaterialPreset) @@ -3056,7 +3087,7 @@ protected override void GenerateTextMesh() marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; } - float textHeight = m_maxAscender - m_ElementDescender + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); // m_maxAscender - (m_maxLineDescender - m_lineOffset); + float textHeight = m_maxAscender - m_ElementDescender + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? m_Ellipsis.character.m_Glyph.metrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * scale; float widthOfTextAreaForEllipsis = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - marginLeft - marginRight, m_width) : marginWidth + 0.0001f - marginLeft - marginRight; diff --git a/Scripts/Runtime/TMPro_UGUI_Private.cs b/Scripts/Runtime/TMPro_UGUI_Private.cs index 66839e7..99f6b1d 100644 --- a/Scripts/Runtime/TMPro_UGUI_Private.cs +++ b/Scripts/Runtime/TMPro_UGUI_Private.cs @@ -1088,6 +1088,13 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_materialReferences[m_Ellipsis.materialIndex].referenceCount = 0; } } + else + { + m_overflowMode = TextOverflowModes.Truncate; + + if (!TMP_Settings.warningsDisabled) + Debug.LogWarning("The character used for Ellipsis is not available in font asset [" + m_currentFontAsset.name + "] or any potential fallbacks. Switching Text Overflow mode to Truncate.", this); + } } #endregion @@ -1192,13 +1199,37 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) #region LOOKUP GLYPH character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - // Search for the glyph in the list of fallback assigned to the primary font asset. + // Search for the glyph in the list of fallback assigned to the current font asset. if (character == null) { if (m_currentFontAsset.m_FallbackFontAssetTable != null && m_currentFontAsset.m_FallbackFontAssetTable.Count > 0) character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_currentFontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } + // Search for the glyph in the primary font asset if not the current font asset + if (character == null) + { + if (m_currentFontAsset.instanceID != m_fontAsset.instanceID) + { + // Search primary font asset + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_fontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + + // Use material and index of primary font asset. + if (character != null) + { + m_currentMaterialIndex = 0; + m_currentMaterial = m_materialReferences[0].material; + } + + // Search list of potential fallback font assets assigned to the primary font asset. + if (character == null) + { + if (m_fontAsset.m_FallbackFontAssetTable != null && m_fontAsset.m_FallbackFontAssetTable.Count > 0) + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + } + } + // Search for the glyph in the Sprite Asset assigned to the text object. if (character == null) { @@ -1346,11 +1377,11 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) { - string formatWarning = srcGlyph > 0xFFFF - ? "The character with Unicode value \\U{0:X8} was not found in {1}'s Glyph Table. It was replaced by a space in text object {2}." - : "The character with Unicode value \\u{0:X4} was not found in {1}'s Glyph Table. It was replaced by a space in text object {2}."; + string formattedWarning = srcGlyph > 0xFFFF + ? string.Format("The character with Unicode value \\U{0:X8} was not found in the [{1}] font asset or any potential fallbacks. It was replaced by a space in the text object [{2}].", srcGlyph, m_fontAsset.name, this.name) + : string.Format("The character with Unicode value \\u{0:X4} was not found in the [{1}] font asset or any potential fallbacks. It was replaced by a space in the text object [{2}].", srcGlyph, m_fontAsset.name, this.name); - Debug.LogWarningFormat(formatWarning, srcGlyph, m_fontAsset.name, this); + Debug.LogWarning(formattedWarning, this); } } } @@ -1374,7 +1405,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; - if (isUsingFallbackOrAlternativeTypeface) + if (isUsingFallbackOrAlternativeTypeface && m_currentFontAsset.instanceID != m_fontAsset.instanceID) { // Create Fallback material instance matching current material preset if necessary if (TMP_Settings.matchMaterialPreset) @@ -3154,7 +3185,7 @@ protected override void GenerateTextMesh() marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; } - float textHeight = m_maxAscender - m_ElementDescender + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); // m_maxAscender - (m_maxLineDescender - m_lineOffset); + float textHeight = m_maxAscender - m_ElementDescender + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? m_Ellipsis.character.m_Glyph.metrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * scale; float widthOfTextAreaForEllipsis = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - marginLeft - marginRight, m_width) : marginWidth + 0.0001f - marginLeft - marginRight; diff --git a/Scripts/Runtime/TextMeshProUGUI.cs b/Scripts/Runtime/TextMeshProUGUI.cs index 52454ab..ecab674 100644 --- a/Scripts/Runtime/TextMeshProUGUI.cs +++ b/Scripts/Runtime/TextMeshProUGUI.cs @@ -79,7 +79,7 @@ public override Mesh mesh public void CalculateLayoutInputHorizontal() { //Debug.Log("*** CalculateLayoutHorizontal() ***"); // at Frame: " + Time.frameCount); // called on Object ID " + GetInstanceID()); - + //// Check if object is active if (!this.gameObject.activeInHierarchy) return; @@ -101,7 +101,7 @@ public void CalculateLayoutInputHorizontal() public void CalculateLayoutInputVertical() { //Debug.Log("*** CalculateLayoutInputVertical() ***"); // at Frame: " + Time.frameCount); // called on Object ID " + GetInstanceID()); - + //// Check if object is active if (!this.gameObject.activeInHierarchy) // || IsRectTransformDriven == false) return; @@ -140,7 +140,7 @@ public override void SetVerticesDirty() /// - /// + /// /// public override void SetLayoutDirty() { @@ -160,7 +160,7 @@ public override void SetLayoutDirty() /// - /// + /// /// public override void SetMaterialDirty() { @@ -184,7 +184,7 @@ public override void SetMaterialDirty() /// - /// + /// /// public override void SetAllDirty() { @@ -228,7 +228,7 @@ IEnumerator DelayedMaterialRebuild() /// - /// + /// /// /// public override void Rebuild(CanvasUpdate update) @@ -270,7 +270,7 @@ private void UpdateSubObjectPivot() /// - /// + /// /// /// /// @@ -300,7 +300,7 @@ public override Material GetModifiedMaterial(Material baseMaterial) /// - /// + /// /// protected override void UpdateMaterial() { @@ -344,7 +344,7 @@ public Vector4 maskOffset } - //public override Material defaultMaterial + //public override Material defaultMaterial //{ // get { Debug.Log("Default Material called."); return m_sharedMaterial; } //} @@ -399,7 +399,7 @@ public override void Cull(Rect clipRect, bool validRect) { //Debug.Log("***** Cull (" + clipRect + ", " + validRect + ") Cull: " + m_canvasRenderer.cull + " *****"); - if (validRect) + if (validRect && ignoreClipping) { m_canvasRenderer.cull = false; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); @@ -426,7 +426,7 @@ public override void Cull(Rect clipRect, bool validRect) /* /// - /// Sets the mask type + /// Sets the mask type /// public MaskingTypes mask { @@ -689,7 +689,7 @@ public override void UpdateVertexData() public void UpdateFontAsset() - { + { LoadFontAsset(); } diff --git a/package.json b/package.json index 15a2141..1e76aa2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.textmeshpro", "displayName": "TextMeshPro", - "version": "1.5.0-preview.7", + "version": "1.5.0-preview.8", "unity": "2018.3", "description": "TextMeshPro is the ultimate text solution for Unity. It's the perfect replacement for Unity's UI Text and the legacy Text Mesh.\n\nPowerful and easy to use, TextMeshPro (also known as TMP) uses Advanced Text Rendering techniques along with a set of custom shaders; delivering substantial visual quality improvements while giving users incredible flexibility when it comes to text styling and texturing.\n\nTextMeshPro provides Improved Control over text formatting and layout with features like character, word, line and paragraph spacing, kerning, justified text, Links, over 30 Rich Text Tags available, support for Multi Font & Sprites, Custom Styles and more.\n\nGreat performance. Since the geometry created by TextMeshPro uses two triangles per character just like Unity's text components, this improved visual quality and flexibility comes at no additional performance cost.", "keywords": [ @@ -14,9 +14,9 @@ "category": "Text Rendering", "dependencies": {}, "repository": { - "footprint": "a5c559ea6c1d68ebbb03641b12b8637c8408cfb3", + "footprint": "b7c92170340265a4df546a3cbf496f74800249df", "type": "git", "url": "https://github.cds.internal.unity3d.com/unity/com.unity.textmeshpro.git", - "revision": "b28ea54edbf8a098c0e560c7d0d1c70b36122aef" + "revision": "5b7f0f0a256afd59f753efd7b22b0a2f8fcc6e85" } }