diff --git a/CHANGELOG.md b/CHANGELOG.md index 63cae0b..8937174 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 +## [3.0.0-preview.4] - 2020-01-31 +## [2.1.0-preview.4] +## [1.5.0-preview.4] +### Changes +- Fixed Input Field issue where scrolling events could prevent OnEndEdit event from firing. See [forum post](https://forum.unity.com/threads/mouse-wheel-on-multiline-input-field-with-no-scrollbar-hangs-input-field-stops-event-firing.794607/) for details. +- Improved Input Field handling of Vertical Scrollbar in conjunction with the ResetOnDeActivation property. Using the Vertical Scrollbar no longer triggers OnEndEdit event. +- Fixed potential Missing Component Exception that could occur when a TMP_SubMeshUI object is created. +- Fixed MissingReferenceException when deleting a TMP prefab that is part of a nested prefab. Case #1207793 +- Improved handling of allocations of newly created text objects with large amount of text. As a result of these revisions, allocations will potentially be reduce by 10X. See #1205923 +- Fixed potential Null Reference Exception with the TMP DropDown that could occur when using the experimental Editor "Enter Play Mode" feature. Case #1207915 +- Fixed potential issue with the assignment of sub text object materials. +- Add support for hiding the soft keyboard for Switch in the TMP Input Field. +- Fixed incorrect Preferred Height when Word Wrapping is disabled on text objects. See [forum post](https://forum.unity.com/threads/incorrect-wordwrapping-preferredsize-textmespro-2-1-preview-3.812376/) for details. +- Added support for the new Selected state and color to the TMP Input Field. Case #1210496 +- Fixed additional instances of TMP Resource Importer window being created when deleting the "TextMesh Pro" folder just after having imported them. Case #1205848 +- Added public ITextPreprocessor textPreprocessor; property to allow setting the text preprocessor for a given text component. + ## [3.0.0-preview.3] - 2019-12-16 ## [2.1.0-preview.3] ## [1.5.0-preview.3] diff --git a/Scripts/Editor/TMPro_CreateObjectMenu.cs b/Scripts/Editor/TMPro_CreateObjectMenu.cs index 18c4052..00b340e 100644 --- a/Scripts/Editor/TMPro_CreateObjectMenu.cs +++ b/Scripts/Editor/TMPro_CreateObjectMenu.cs @@ -72,7 +72,7 @@ static void CreateTextMeshProGuiObjectPerform(MenuCommand menuCommand) GameObject go = TMP_DefaultControls.CreateText(GetStandardResources()); // Override text color and font size - TextMeshProUGUI textComponent = go.GetComponent(); + TextMeshProUGUI textComponent = go.GetComponent(); if (textComponent.m_isWaitingOnResourceLoad == false) { diff --git a/Scripts/Runtime/TMP_Dropdown.cs b/Scripts/Runtime/TMP_Dropdown.cs index 31efaa7..1e42e39 100644 --- a/Scripts/Runtime/TMP_Dropdown.cs +++ b/Scripts/Runtime/TMP_Dropdown.cs @@ -438,10 +438,10 @@ protected TMP_Dropdown() { } protected override void Awake() { -#if UNITY_EDITOR - if (!Application.isPlaying) - return; -#endif +//#if UNITY_EDITOR +// if (!Application.isPlaying) +// return; +//#endif m_AlphaTweenRunner = new TweenRunner(); m_AlphaTweenRunner.Init(this); @@ -1157,4 +1157,4 @@ private void OnSelectItem(Toggle toggle) Hide(); } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TMP_FontFeatureTable.cs b/Scripts/Runtime/TMP_FontFeatureTable.cs index 1e500d8..633a84e 100644 --- a/Scripts/Runtime/TMP_FontFeatureTable.cs +++ b/Scripts/Runtime/TMP_FontFeatureTable.cs @@ -15,7 +15,7 @@ public class TMP_FontFeatureTable /// /// List that contains the glyph pair adjustment records. /// - internal List glyphPairAdjustmentRecords + public List glyphPairAdjustmentRecords { get { return m_GlyphPairAdjustmentRecords; } set { m_GlyphPairAdjustmentRecords = value; } diff --git a/Scripts/Runtime/TMP_InputField.cs b/Scripts/Runtime/TMP_InputField.cs index 3a1fe07..89046d8 100644 --- a/Scripts/Runtime/TMP_InputField.cs +++ b/Scripts/Runtime/TMP_InputField.cs @@ -423,6 +423,7 @@ public bool shouldHideSoftKeyboard case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerARM: case RuntimePlatform.Stadia: + case RuntimePlatform.Switch: return m_HideSoftKeyboard; default: return true; @@ -440,6 +441,7 @@ public bool shouldHideSoftKeyboard case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerARM: case RuntimePlatform.Stadia: + case RuntimePlatform.Switch: SetPropertyUtility.SetStruct(ref m_HideSoftKeyboard, value); break; default: @@ -462,6 +464,7 @@ private bool isKeyboardUsingEvents() case RuntimePlatform.Android: case RuntimePlatform.IPhonePlayer: case RuntimePlatform.tvOS: + case RuntimePlatform.Switch: return false; default: return true; @@ -732,7 +735,7 @@ public bool resetOnDeActivation private bool m_SelectionStillActive = false; private bool m_ReleaseSelection = false; - private GameObject m_SelectedObject; + private GameObject m_PreviouslySelectedObject; /// /// Controls whether the original text is restored when pressing "ESC". @@ -1417,19 +1420,36 @@ protected virtual void LateUpdate() { GameObject selectedObject = EventSystem.current != null ? EventSystem.current.currentSelectedGameObject : null; + if (selectedObject == null && m_ResetOnDeActivation) + { + ReleaseSelection(); + return; + } + if (selectedObject != null && selectedObject != this.gameObject) { - if (selectedObject != m_SelectedObject) + if (selectedObject != m_PreviouslySelectedObject) { - m_SelectedObject = selectedObject; + m_PreviouslySelectedObject = selectedObject; - // Release current selection of the newly selected object is another Input Field - if (selectedObject.GetComponent() != null) + // Special handling for Vertical Scrollbar + if (m_VerticalScrollbar && selectedObject == m_VerticalScrollbar.gameObject) { - // Release selection - m_SelectionStillActive = false; - MarkGeometryAsDirty(); - m_SelectedObject = null; + // Do not release selection + return; + } + else + { + // Release selection for all objects when ResetOnDeActivation is true + if (m_ResetOnDeActivation) + { + ReleaseSelection(); + return; + } + + // Release current selection of selected object is another Input Field + if (selectedObject.GetComponent() != null) + ReleaseSelection(); } } @@ -1456,9 +1476,7 @@ protected virtual void LateUpdate() //if (caretRectTrans != null) // caretRectTrans.localPosition = Vector3.zero; - m_SelectionStillActive = false; - - MarkGeometryAsDirty(); + ReleaseSelection(); return; } @@ -2120,7 +2138,12 @@ public virtual void OnUpdateSelected(BaseEventData eventData) /// public virtual void OnScroll(PointerEventData eventData) { - if (m_TextComponent.preferredHeight < m_TextViewport.rect.height) return; + // Return if Single Line + if (m_LineType == LineType.SingleLine) + return; + + if (m_TextComponent.preferredHeight < m_TextViewport.rect.height) + return; float scrollDirection = -eventData.scrollDelta.y; @@ -2130,9 +2153,6 @@ public virtual void OnScroll(PointerEventData eventData) AdjustTextPositionRelativeToViewport(m_ScrollPosition); - // Disable focus until user re-selected the input field. - m_AllowInput = false; - if (m_VerticalScrollbar) { m_IsUpdatingScrollbarValues = true; @@ -3948,7 +3968,13 @@ public void OnControlClick() public void ReleaseSelection() { m_SelectionStillActive = false; + m_ReleaseSelection = false; + m_PreviouslySelectedObject = null; + MarkGeometryAsDirty(); + + SendOnEndEdit(); + SendOnEndTextSelection(); } public void DeactivateInputField(bool clearSelection = false) @@ -3983,18 +4009,11 @@ public void DeactivateInputField(bool clearSelection = false) //m_StringPosition = m_StringSelectPosition = 0; //m_CaretPosition = m_CaretSelectPosition = 0; //m_TextComponent.rectTransform.localPosition = m_DefaultTransformPosition; - - //if (caretRectTrans != null) - // caretRectTrans.localPosition = Vector3.zero; - - m_SelectionStillActive = false; - m_ReleaseSelection = false; - m_SelectedObject = null; + + if (m_VerticalScrollbar == null) + ReleaseSelection(); } - SendOnEndEdit(); - SendOnEndTextSelection(); - inputSystem.imeCompositionMode = IMECompositionMode.Auto; } @@ -4173,7 +4192,7 @@ void SetToCustom(CharacterValidation characterValidation) protected override void DoStateTransition(SelectionState state, bool instant) { if (m_HasDoneFocusTransition) - state = SelectionState.Highlighted; + state = SelectionState.Selected; else if (state == SelectionState.Pressed) m_HasDoneFocusTransition = true; @@ -4329,4 +4348,4 @@ public static bool SetClass(ref T currentValue, T newValue) where T : class return true; } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TMP_PackageResourceImporter.cs b/Scripts/Runtime/TMP_PackageResourceImporter.cs index 2e0d53e..7d904c4 100644 --- a/Scripts/Runtime/TMP_PackageResourceImporter.cs +++ b/Scripts/Runtime/TMP_PackageResourceImporter.cs @@ -160,11 +160,17 @@ public class TMP_PackageResourceImporterWindow : EditorWindow [SerializeField] TMP_PackageResourceImporter m_ResourceImporter; + static TMP_PackageResourceImporterWindow m_ImporterWindow; + public static void ShowPackageImporterWindow() { - var window = GetWindow(); - window.titleContent = new GUIContent("TMP Importer"); - window.Focus(); + if (m_ImporterWindow == null) + { + m_ImporterWindow = GetWindow(); + m_ImporterWindow.titleContent = new GUIContent("TMP Importer"); + } + + m_ImporterWindow.Focus(); } void OnEnable() diff --git a/Scripts/Runtime/TMP_SubMeshUI.cs b/Scripts/Runtime/TMP_SubMeshUI.cs index f46ad9d..4b62a9e 100644 --- a/Scripts/Runtime/TMP_SubMeshUI.cs +++ b/Scripts/Runtime/TMP_SubMeshUI.cs @@ -8,6 +8,7 @@ namespace TMPro { [ExecuteAlways] + [RequireComponent(typeof(CanvasRenderer))] public class TMP_SubMeshUI : MaskableGraphic, IClippable, IMaskable, IMaterialModifier { /// @@ -274,9 +275,13 @@ protected override void OnEnable() protected override void OnDisable() { //Debug.Log("*** SubObject OnDisable() ***"); + //base.OnDisable(); //m_canvasRenderer.Clear(); - TMP_UpdateRegistry.UnRegisterCanvasElementForRebuild(this); + //TMP_UpdateRegistry.UnRegisterCanvasElementForRebuild(this); + + if (canvasRenderer != null) + canvasRenderer.Clear(); if (m_MaskMaterial != null) { @@ -289,8 +294,6 @@ protected override void OnDisable() TMP_MaterialManager.ReleaseFallbackMaterial(m_fallbackMaterial); m_fallbackMaterial = null; } - - base.OnDisable(); } @@ -518,6 +521,8 @@ public override Material GetModifiedMaterial(Material baseMaterial) m_MaskMaterial = mat; } + else if (m_MaskMaterial != null) + TMP_MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); return mat; } diff --git a/Scripts/Runtime/TMP_Text.cs b/Scripts/Runtime/TMP_Text.cs index 9180168..00e6154 100644 --- a/Scripts/Runtime/TMP_Text.cs +++ b/Scripts/Runtime/TMP_Text.cs @@ -131,12 +131,17 @@ public virtual string text [SerializeField] [TextArea(5, 10)] protected string m_text; - + /// - /// Reference to potential text preprocessor component. + /// The ITextPreprocessor component referenced by the text object (if any) /// + public ITextPreprocessor textPreprocessor + { + get { return m_TextPreprocessor; } + set { m_TextPreprocessor = value; } + } [SerializeField] - protected ITextPreprocessor m_TextPreProcessor; + protected ITextPreprocessor m_TextPreprocessor; /// /// @@ -1470,8 +1475,15 @@ internal enum TextInputSources { Text = 0, SetText = 1, SetCharArray = 2, String protected Matrix4x4 m_FXMatrix; protected bool m_isFXMatrixSet; + /// + /// Array containing the Unicode characters to be parsed. + /// + protected UnicodeChar[] m_InternalParsingBuffer = new UnicodeChar[8]; - protected UnicodeChar[] m_TextParsingBuffer; // This array holds the characters to be processed by GenerateMesh(); + /// + /// The number of Unicode characters that have been parsed and contained in the m_InternalParsingBuffer + /// + protected int m_InternalParsingBufferSize; protected struct UnicodeChar { @@ -1848,19 +1860,19 @@ protected void ParseInputText() { case TextInputSources.String: case TextInputSources.Text: - if (m_TextPreProcessor != null) - StringToCharArray(m_TextPreProcessor.PreprocessText(m_text), ref m_TextParsingBuffer); + if (m_TextPreprocessor != null) + m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_TextPreprocessor.PreprocessText(m_text), ref m_InternalParsingBuffer); else - StringToCharArray(m_text, ref m_TextParsingBuffer); + m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_text, ref m_InternalParsingBuffer); break; case TextInputSources.SetText: - SetTextArrayToCharArray(m_input_CharArray, ref m_TextParsingBuffer); + m_InternalParsingBufferSize = CharArrayToInternalParsingBuffer(m_input_CharArray, ref m_InternalParsingBuffer); break; case TextInputSources.SetCharArray: break; } - SetArraySizes(m_TextParsingBuffer); + SetArraySizes(m_InternalParsingBuffer); ////Profiler.EndSample(); } @@ -1984,7 +1996,7 @@ public void SetText(StringBuilder text) m_text = text.ToString(); #endif - StringBuilderToIntArray(text, ref m_TextParsingBuffer); + m_InternalParsingBufferSize = StringBuilderToInternalParsingBuffer(text, ref m_InternalParsingBuffer); m_isInputParsingRequired = true; m_havePropertiesChanged = true; @@ -1995,23 +2007,56 @@ public void SetText(StringBuilder text) } + /// + /// Set the text using a char array. + /// + /// + public void SetText(char[] text) + { + SetCharArray(text); + } + + + /// + /// Set the text using a char array with specified starting character and length. + /// + /// Source char array that contains the Unicode characters + /// The starting character index in the array. + /// The number of characters to be set. + public void SetText(char[] text, int start, int length) + { + SetCharArray(text, start, length); + } + + /// /// Character array containing the text to be displayed. /// /// public void SetCharArray(char[] sourceText) { - // Initialize internal character buffer if necessary - if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; + int characterCount = sourceText == null ? 0 : sourceText.Length; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - if (sourceText == null || sourceText.Length == 0) + if (characterCount == 0) m_text = string.Empty; else m_text = new string(sourceText); #endif + // Early exit if string is null or empty + if (characterCount == 0) + { + m_InternalParsingBuffer[0].unicode = 0; + m_InternalParsingBufferSize = 0; + return; + } + + // Make sure parsing buffer is large enough to handle the required text. + if (m_InternalParsingBuffer.Length < characterCount) + ResizeInternalArray(ref m_InternalParsingBuffer, characterCount); + // Clear Style stacks. for (int i = 0; i < m_TextStyleStacks.Length; i++) m_TextStyleStacks[i].SetDefault(0); @@ -2021,7 +2066,7 @@ public void SetCharArray(char[] sourceText) // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex); for (int i = 0; sourceText != null && i < sourceText.Length; i++) { @@ -2030,30 +2075,30 @@ public void SetCharArray(char[] sourceText) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r LineFeed - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 13; + m_InternalParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 9; + m_InternalParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 11; + m_InternalParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2065,9 +2110,9 @@ public void SetCharArray(char[] sourceText) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2075,9 +2120,9 @@ public void SetCharArray(char[] sourceText) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 160; + m_InternalParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2088,7 +2133,7 @@ public void SetCharArray(char[] sourceText) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2098,7 +2143,7 @@ public void SetCharArray(char[] sourceText) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2106,9 +2151,9 @@ public void SetCharArray(char[] sourceText) } } - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; + m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2116,11 +2161,12 @@ public void SetCharArray(char[] sourceText) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 0; + m_InternalParsingBuffer[writeIndex].unicode = 0; + m_InternalParsingBufferSize = writeIndex; m_inputSource = TextInputSources.SetCharArray; m_isInputParsingRequired = true; @@ -2138,24 +2184,37 @@ public void SetCharArray(char[] sourceText) /// public void SetCharArray(char[] sourceText, int start, int length) { - // Initialize internal character buffer if necessary - if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; + int characterCount = 0; + + // Range check + if (sourceText != null) + { + start = Mathf.Clamp(start, 0, sourceText.Length); + length = Mathf.Clamp(length, 0, start + length < sourceText.Length ? length : sourceText.Length - start); + + characterCount = length; + } #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - if (sourceText == null || sourceText.Length == 0 || length == 0) - { + if (characterCount == 0) m_text = string.Empty; - start = 0; - length = 0; - } else - { - // TODO: Add potential range check on start + length relative to array size. m_text = new string(sourceText, start, length); - } #endif + // Early exit if string is null or empty + if (characterCount == 0) + { + m_InternalParsingBuffer[0].unicode = 0; + m_InternalParsingBufferSize = 0; + return; + } + + // Make sure parsing buffer is large enough to handle the required text. + if (m_InternalParsingBuffer.Length < characterCount) + ResizeInternalArray(ref m_InternalParsingBuffer, characterCount); + // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) m_TextStyleStacks[j].SetDefault(0); @@ -2165,7 +2224,7 @@ public void SetCharArray(char[] sourceText, int start, int length) // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex); int i = start; int end = start + length; @@ -2176,30 +2235,30 @@ public void SetCharArray(char[] sourceText, int start, int length) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r Carriage Return - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 13; + m_InternalParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 9; + m_InternalParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 11; + m_InternalParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2211,9 +2270,9 @@ public void SetCharArray(char[] sourceText, int start, int length) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2221,9 +2280,9 @@ public void SetCharArray(char[] sourceText, int start, int length) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 160; + m_InternalParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2234,7 +2293,7 @@ public void SetCharArray(char[] sourceText, int start, int length) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2244,7 +2303,7 @@ public void SetCharArray(char[] sourceText, int start, int length) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2252,9 +2311,9 @@ public void SetCharArray(char[] sourceText, int start, int length) } } - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; + m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2262,11 +2321,11 @@ public void SetCharArray(char[] sourceText, int start, int length) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 0; + m_InternalParsingBuffer[writeIndex].unicode = 0; m_inputSource = TextInputSources.SetCharArray; m_havePropertiesChanged = true; @@ -2285,7 +2344,7 @@ public void SetCharArray(char[] sourceText, int start, int length) public void SetCharArray(int[] sourceText, int start, int length) { // Initialize internal character buffer if necessary - if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; + if (m_InternalParsingBuffer == null) m_InternalParsingBuffer = new UnicodeChar[8]; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. @@ -2310,7 +2369,7 @@ public void SetCharArray(int[] sourceText, int start, int length) // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex); int end = start + length; for (int i = start; i < end && i < sourceText.Length; i++) @@ -2320,30 +2379,30 @@ public void SetCharArray(int[] sourceText, int start, int length) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r LineFeed - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 13; + m_InternalParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 9; + m_InternalParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 11; + m_InternalParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2355,9 +2414,9 @@ public void SetCharArray(int[] sourceText, int start, int length) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 10; + m_InternalParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2365,9 +2424,9 @@ public void SetCharArray(int[] sourceText, int start, int length) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 160; + m_InternalParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2378,7 +2437,7 @@ public void SetCharArray(int[] sourceText, int start, int length) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2388,7 +2447,7 @@ public void SetCharArray(int[] sourceText, int start, int length) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2396,9 +2455,9 @@ public void SetCharArray(int[] sourceText, int start, int length) } } - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; + m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2406,11 +2465,11 @@ public void SetCharArray(int[] sourceText, int start, int length) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); - if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); + if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - m_TextParsingBuffer[writeIndex].unicode = 0; + m_InternalParsingBuffer[writeIndex].unicode = 0; m_inputSource = TextInputSources.SetCharArray; m_havePropertiesChanged = true; @@ -2426,14 +2485,34 @@ public void SetCharArray(int[] sourceText, int start, int length) /// Copies Content of formatted SetText() to charBuffer. ///
/// - /// - protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] charBuffer) + /// + protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeChar[] internalParsingArray) { - //Debug.Log("SetText Array to Char called."); - if (sourceText == null || m_charArray_Length == 0) - return; + int characterCount = sourceText == null ? 0 : sourceText.Length; + + #if UNITY_EDITOR + // Create new string to be displayed in the Input Text Box of the Editor Panel. + // This results in allocations in the Unity Editor only + if (characterCount == 0) + m_text = string.Empty; + else + m_text = new string(sourceText); + #endif - if (charBuffer == null) charBuffer = new UnicodeChar[8]; + // Early exit if string is null or empty + if (characterCount == 0) + { + if (internalParsingArray != null) + internalParsingArray[0].unicode = 0; + + return 0; + } + + // Make sure parsing buffer is large enough to handle the required text. + if (internalParsingArray == null) + internalParsingArray = new UnicodeChar[characterCount]; + else if (internalParsingArray.Length < characterCount) + ResizeInternalArray(ref internalParsingArray, characterCount); // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) @@ -2444,16 +2523,16 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); for (int i = 0; i < m_charArray_Length; i++) { // Handle UTF-32 in the input text (string). if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1])) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); i += 1; writeIndex += 1; continue; @@ -2464,9 +2543,9 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 10; + internalParsingArray[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2474,9 +2553,9 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 160; + internalParsingArray[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2487,7 +2566,7 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) { i = srcOffset; continue; @@ -2497,7 +2576,7 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2505,9 +2584,9 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char } } - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = sourceText[i]; + internalParsingArray[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2515,11 +2594,13 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 0; + internalParsingArray[writeIndex].unicode = 0; + + return writeIndex; } @@ -2527,16 +2608,25 @@ protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] char /// Method to store the content of a string into an integer array. ///
/// - /// - protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer) + /// + protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] internalParsingArray) { - if (sourceText == null) + int characterCount = sourceText == null ? 0 : sourceText.Length; + + // Early exit if string is null or empty + if (characterCount == 0) { - charBuffer[0].unicode = 0; - return; + if (internalParsingArray != null) + internalParsingArray[0].unicode = 0; + + return 0; } - if (charBuffer == null) charBuffer = new UnicodeChar[8]; + // Allocate internal buffers that are large enough to handle the required text. + if (internalParsingArray == null) + internalParsingArray = new UnicodeChar[characterCount]; + else if (internalParsingArray.Length < characterCount) + ResizeInternalArray(ref internalParsingArray, characterCount); // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) @@ -2547,7 +2637,7 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref charBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); for (int i = 0; i < sourceText.Length; i++) { @@ -2558,11 +2648,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer case 85: // \U00000000 for UTF-32 Unicode if (sourceText.Length > i + 9) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = GetUTF32(sourceText, i + 2); - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 10; + internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2); + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 10; i += 9; writeIndex += 1; @@ -2574,21 +2664,21 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer if (sourceText.Length <= i + 2) break; - if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = sourceText[i + 1]; - charBuffer[writeIndex + 1].unicode = sourceText[i + 2]; + internalParsingArray[writeIndex].unicode = sourceText[i + 1]; + internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2]; i += 2; writeIndex += 2; continue; case 110: // \n LineFeed if (!m_parseCtrlCharacters) break; - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 10; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 10; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2596,11 +2686,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer case 114: // \r if (!m_parseCtrlCharacters) break; - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 13; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 13; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2608,11 +2698,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer case 116: // \t Tab if (!m_parseCtrlCharacters) break; - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 9; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 9; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2620,11 +2710,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer case 117: // \u0000 for UTF-16 Unicode if (sourceText.Length > i + 5) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = GetUTF16(sourceText, i + 2); - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 6; + internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2); + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 6; i += 5; writeIndex += 1; @@ -2634,11 +2724,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer case 118: // \v Vertical tab used as soft line break if (!m_parseCtrlCharacters) break; - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 11; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 11; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2649,11 +2739,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer // Handle UTF-32 in the input text (string). // Not sure this is needed // if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1])) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 2; + internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 2; i += 1; writeIndex += 1; @@ -2665,11 +2755,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 10; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 10; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; writeIndex += 1; i += 3; @@ -2678,11 +2768,11 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 160; - charBuffer[writeIndex].stringIndex = i; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = 160; + internalParsingArray[writeIndex].stringIndex = i; + internalParsingArray[writeIndex].length = 1; writeIndex += 1; i += 5; @@ -2694,7 +2784,7 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) { i = srcOffset; continue; @@ -2704,18 +2794,18 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); i += 7; continue; } } - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = sourceText[i]; - charBuffer[writeIndex].stringIndex = writeIndex; - charBuffer[writeIndex].length = 1; + internalParsingArray[writeIndex].unicode = sourceText[i]; + internalParsingArray[writeIndex].stringIndex = writeIndex; + internalParsingArray[writeIndex].length = 1; writeIndex += 1; } @@ -2724,11 +2814,12 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref charBuffer, ref writeIndex); + InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 0; + internalParsingArray[writeIndex].unicode = 0; + return writeIndex; } @@ -2736,22 +2827,35 @@ protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer /// Copy contents of StringBuilder into int array. ///
/// Text to copy. - /// Array to store contents. - protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar[] charBuffer) + /// Array to store contents. + protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref UnicodeChar[] internalParsingArray) { - if (sourceText == null) - { - charBuffer[0].unicode = 0; - return; - } - - if (charBuffer == null) charBuffer = new UnicodeChar[8]; + int characterCount = sourceText == null ? 0 : sourceText.Length; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - m_text = sourceText.ToString(); + // This results in allocations in the Unity Editor only + if (characterCount == 0) + m_text = string.Empty; + else + m_text = sourceText.ToString(); #endif + // Early exit if string is null or empty + if (characterCount == 0) + { + if (internalParsingArray != null) + internalParsingArray[0].unicode = 0; + + return 0; + } + + // Make sure parsing buffer is large enough to handle the required text. + if (internalParsingArray == null) + internalParsingArray = new UnicodeChar[characterCount]; + else if (internalParsingArray.Length < characterCount) + ResizeInternalArray(ref internalParsingArray, characterCount); + // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) m_TextStyleStacks[j].SetDefault(0); @@ -2761,7 +2865,7 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref charBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); for (int i = 0; i < sourceText.Length; i++) { @@ -2772,9 +2876,9 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar case 85: // \U00000000 for UTF-32 Unicode if (sourceText.Length > i + 9) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = GetUTF32(sourceText, i + 2); + internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2); i += 9; writeIndex += 1; continue; @@ -2783,49 +2887,49 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar case 92: // \ escape if (sourceText.Length <= i + 2) break; - if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = sourceText[i + 1]; - charBuffer[writeIndex + 1].unicode = sourceText[i + 2]; + internalParsingArray[writeIndex].unicode = sourceText[i + 1]; + internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2]; i += 2; writeIndex += 2; continue; case 110: // \n LineFeed - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 10; + internalParsingArray[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 13; + internalParsingArray[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 9; + internalParsingArray[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 117: // \u0000 for UTF-16 Unicode if (sourceText.Length > i + 5) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = GetUTF16(sourceText, i + 2); + internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2); i += 5; writeIndex += 1; continue; } break; case 118: // \v Vertical tab used as soft line break - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 11; + internalParsingArray[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2835,9 +2939,9 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar // Handle UTF-32 in the input text (string). if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1])) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); i += 1; writeIndex += 1; continue; @@ -2848,9 +2952,9 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 10; + internalParsingArray[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2858,9 +2962,9 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 160; + internalParsingArray[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2871,7 +2975,7 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) { i = srcOffset; continue; @@ -2881,7 +2985,7 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2889,9 +2993,9 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar } } - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = sourceText[i]; + internalParsingArray[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2899,11 +3003,12 @@ protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref charBuffer, ref writeIndex); + InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); + if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - charBuffer[writeIndex].unicode = 0; + internalParsingArray[writeIndex].unicode = 0; + return writeIndex; } @@ -4300,6 +4405,12 @@ int GetTagHashCode(ref StringBuilder text, int index, out int closeIndex) System.Array.Resize(ref array, size); } + void ResizeInternalArray(ref T[] array, int size) + { + size = Mathf.NextPowerOfTwo(size + 1); + + System.Array.Resize(ref array, size); + } private readonly float[] k_Power = { 5e-1f, 5e-2f, 5e-3f, 5e-4f, 5e-5f, 5e-6f, 5e-7f, 5e-8f, 5e-9f, 5e-10f }; // Used by FormatText to enable rounding and avoid using Mathf.Pow. @@ -4380,9 +4491,9 @@ protected void AddIntToCharArray(double number, ref int index, int precision) /// /// Method used to determine the number of visible characters and required buffer allocations. /// - /// + /// /// - protected virtual int SetArraySizes(UnicodeChar[] chars) { return 0; } + protected virtual int SetArraySizes(UnicodeChar[] unicodeChars) { return 0; } /// @@ -4446,8 +4557,8 @@ public Vector2 GetPreferredValues(string text) { m_isCalculatingPreferredValues = true; - StringToCharArray(text, ref m_TextParsingBuffer); - SetArraySizes(m_TextParsingBuffer); + StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); + SetArraySizes(m_InternalParsingBuffer); Vector2 margin = k_LargePositiveVector2; @@ -4470,8 +4581,8 @@ public Vector2 GetPreferredValues(string text, float width, float height) { m_isCalculatingPreferredValues = true; - StringToCharArray(text, ref m_TextParsingBuffer); - SetArraySizes(m_TextParsingBuffer); + StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); + SetArraySizes(m_InternalParsingBuffer); Vector2 margin = new Vector2(width, height); @@ -4567,7 +4678,7 @@ protected float GetPreferredHeight() } m_AutoSizeIterationCount = 0; - float preferredHeight = CalculatePreferredValues(fontSize, margin, !m_enableAutoSizing, true).y; + float preferredHeight = CalculatePreferredValues(fontSize, margin, !m_enableAutoSizing, m_enableWordWrapping).y; m_isPreferredHeightDirty = false; @@ -4592,7 +4703,7 @@ protected float GetPreferredHeight(Vector2 margin) m_charWidthAdjDelta = 0; m_AutoSizeIterationCount = 0; - float preferredHeight = CalculatePreferredValues(fontSize, margin, true, true).y; + float preferredHeight = CalculatePreferredValues(fontSize, margin, true, m_enableWordWrapping).y; //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight); @@ -4676,7 +4787,7 @@ protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector } // Early exit if we don't have any Text to generate. - if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) + if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == (char)0) { return Vector2.zero; } @@ -4782,9 +4893,9 @@ protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector m_AutoSizeIterationCount += 1; // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) { - charCode = m_TextParsingBuffer[i].unicode; + charCode = m_InternalParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -4795,7 +4906,7 @@ protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector int endTagIndex; // Check if Tag is valid. If valid, skip to the end of the validated tag. - if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_InternalParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -5338,7 +5449,7 @@ protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector // If End of Text if (charCode == 0x03) - i = m_TextParsingBuffer.Length; + i = m_InternalParsingBuffer.Length; } #endregion Check for Linefeed or Last Character @@ -6583,7 +6694,7 @@ protected void GetSpecialCharacters(TMP_FontAsset fontAsset) m_cached_Underline_Character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(95,fontAsset, false, m_FontStyleInternal, (FontWeight)m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (m_cached_Underline_Character == null) - { + { if (!TMP_Settings.warningsDisabled) Debug.LogWarning("The character used for Underline and Strikethrough is not available in font asset [" + fontAsset.name + "].", this); } @@ -6595,7 +6706,7 @@ protected void GetSpecialCharacters(TMP_FontAsset fontAsset) m_cached_Ellipsis_Character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(8230, fontAsset, false, m_FontStyleInternal, (FontWeight)m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (m_cached_Ellipsis_Character == null) - { + { if (!TMP_Settings.warningsDisabled) Debug.LogWarning("The character used for Ellipsis is not available in font asset [" + fontAsset.name + "].", this); } diff --git a/Scripts/Runtime/TMP_TextInfo.cs b/Scripts/Runtime/TMP_TextInfo.cs index 67c5e5d..d1bce41 100644 --- a/Scripts/Runtime/TMP_TextInfo.cs +++ b/Scripts/Runtime/TMP_TextInfo.cs @@ -48,6 +48,16 @@ public TMP_TextInfo() meshInfo = new TMP_MeshInfo[1]; } + internal TMP_TextInfo(int characterCount) + { + characterInfo = new TMP_CharacterInfo[characterCount]; + wordInfo = new TMP_WordInfo[16]; + linkInfo = new TMP_LinkInfo[0]; + lineInfo = new TMP_LineInfo[2]; + pageInfo = new TMP_PageInfo[4]; + + meshInfo = new TMP_MeshInfo[1]; + } public TMP_TextInfo(TMP_Text textComponent) { @@ -261,12 +271,12 @@ public static void Resize (ref T[] array, int size) /// public static void Resize(ref T[] array, int size, bool isBlockAllocated) { - //if (size <= array.Length) return; - if (isBlockAllocated) size = size > 1024 ? size + 256 : Mathf.NextPowerOfTwo(size); if (size == array.Length) return; + //Debug.Log("Resizing TextInfo from [" + array.Length + "] to [" + size + "]"); + Array.Resize(ref array, size); } diff --git a/Scripts/Runtime/TMPro_Private.cs b/Scripts/Runtime/TMPro_Private.cs index adc56a1..1cb20c8 100644 --- a/Scripts/Runtime/TMPro_Private.cs +++ b/Scripts/Runtime/TMPro_Private.cs @@ -122,8 +122,8 @@ protected override void Awake() LoadFontAsset(); // Allocate our initial buffers. - if (m_TextParsingBuffer == null) - m_TextParsingBuffer = new UnicodeChar[m_max_characters]; + if (m_InternalParsingBuffer == null) + m_InternalParsingBuffer = new UnicodeChar[m_max_characters]; m_cached_TextElement = new TMP_Character(); m_isFirstAllocation = true; @@ -170,9 +170,6 @@ protected override void OnEnable() m_isRegisteredForEvents = true; } - // Get reference to potential ITextPreprocessor components - m_TextPreProcessor = GetComponent(); - // Register text object for internal updates if (m_IsTextObjectScaleStatic == false) TMP_UpdateManager.RegisterTextObjectForUpdate(this); @@ -300,6 +297,13 @@ protected override void OnValidate() /// The affected GameObject void OnPrefabInstanceUpdate(GameObject go) { + // Remove Callback if this prefab has been deleted. + if (this == null) + { + UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabInstanceUpdate; + return; + } + if (go == this.gameObject) { TMP_SubMesh[] subTextObjects = GetComponentsInChildren(); @@ -961,7 +965,7 @@ void SetPerspectiveCorrection() // This function parses through the Char[] to determine how many characters will be visible. It then makes sure the arrays are large enough for all those characters. - protected override int SetArraySizes(UnicodeChar[] chars) + protected override int SetArraySizes(UnicodeChar[] unicodeChars) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP SetArraySizes()"); @@ -989,7 +993,12 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_materialReferenceIndexLookup.Clear(); MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup); - if (m_textInfo == null) m_textInfo = new TMP_TextInfo(); + // Set allocations for the text object's TextInfo + if (m_textInfo == null) + m_textInfo = new TMP_TextInfo(m_InternalParsingBufferSize); + else if (m_textInfo.characterInfo.Length < m_InternalParsingBufferSize) + TMP_TextInfo.Resize(ref m_textInfo.characterInfo, m_InternalParsingBufferSize, false); + m_textElementType = TMP_TextElementType.Character; // Clear Linked Text object if we have one. @@ -997,13 +1006,13 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_linkedTextComponent.text = string.Empty; // Parsing XML tags in the text - for (int i = 0; i < chars.Length && chars[i].unicode != 0; i++) + for (int i = 0; i < unicodeChars.Length && unicodeChars[i].unicode != 0; i++) { //Make sure the characterInfo array can hold the next text element. if (m_textInfo.characterInfo == null || m_totalCharacterCount >= m_textInfo.characterInfo.Length) TMP_TextInfo.Resize(ref m_textInfo.characterInfo, m_totalCharacterCount + 1, true); - int unicode = chars[i].unicode; + int unicode = unicodeChars[i].unicode; // PARSE XML TAGS #region PARSE XML TAGS @@ -1013,9 +1022,9 @@ protected override int SetArraySizes(UnicodeChar[] chars) int endTagIndex; // Check if Tag is Valid - if (ValidateHtmlTag(chars, i + 1, out endTagIndex)) + if (ValidateHtmlTag(unicodeChars, i + 1, out endTagIndex)) { - int tagStartIndex = chars[i].stringIndex; + int tagStartIndex = unicodeChars[i].stringIndex; i = endTagIndex; if ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold) @@ -1033,7 +1042,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].textElement = m_currentSpriteAsset.spriteCharacterTable[m_spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; m_textInfo.characterInfo[m_totalCharacterCount].index = tagStartIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].stringIndex - tagStartIndex + 1; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].stringIndex - tagStartIndex + 1; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1122,8 +1131,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAsset; m_textInfo.characterInfo[m_totalCharacterCount].textElement = spriteAsset.spriteCharacterTable[spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1178,8 +1187,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAsset; m_textInfo.characterInfo[m_totalCharacterCount].textElement = spriteAsset.spriteCharacterTable[spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1217,7 +1226,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) int srcGlyph = unicode; // Try replacing the missing glyph character by TMP Settings Missing Glyph or Square (9633) character. - unicode = chars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; + unicode = unicodeChars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; // Check for the missing glyph character in the currently assigned font asset and its fallbacks character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); @@ -1239,7 +1248,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) if (character == null) { // Use Space (32) Glyph from the currently assigned font asset. - unicode = chars[i].unicode = 32; + unicode = unicodeChars[i].unicode = 32; character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) Debug.LogWarning("Character with ASCII value of " + srcGlyph + " was not found in the Font Asset Glyph Table. It was replaced by a space.", this); @@ -1262,8 +1271,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].isUsingAlternateTypeface = isUsingAlternativeTypeface; m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; if (isUsingFallbackOrAlternativeTypeface) { @@ -1358,17 +1367,9 @@ protected override int SetArraySizes(UnicodeChar[] chars) // Check if the material has changed. if (m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetInstanceID() != m_materialReferences[i].material.GetInstanceID()) { - bool isDefaultMaterial = m_materialReferences[i].isDefaultMaterial; - - m_subTextObjects[i].isDefaultMaterial = isDefaultMaterial; - - // Assign new material if we are not using the default material or if the font asset has changed. - if (!isDefaultMaterial || m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID() != m_materialReferences[i].material.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) - { - m_subTextObjects[i].sharedMaterial = m_materialReferences[i].material; - m_subTextObjects[i].fontAsset = m_materialReferences[i].fontAsset; - m_subTextObjects[i].spriteAsset = m_materialReferences[i].spriteAsset; - } + m_subTextObjects[i].sharedMaterial = m_materialReferences[i].material; + m_subTextObjects[i].fontAsset = m_materialReferences[i].fontAsset; + m_subTextObjects[i].spriteAsset = m_materialReferences[i].spriteAsset; } // Check if we need to use a Fallback Material @@ -1614,7 +1615,7 @@ protected override void GenerateTextMesh() m_textInfo.Clear(); // Early exit if we don't have any Text to generate. - if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) + if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == (char)0) { // Clear mesh and upload changes to the mesh. ClearMesh(true); @@ -1790,9 +1791,9 @@ protected override void GenerateTextMesh() #endif // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) { - charCode = m_TextParsingBuffer[i].unicode; + charCode = m_InternalParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -1807,7 +1808,7 @@ protected override void GenerateTextMesh() int endTagIndex; // Check if Tag is valid. If valid, skip to the end of the validated tag. - if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_InternalParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -1989,7 +1990,7 @@ protected override void GenerateTextMesh() m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; // Re-calculate font scale as the font asset may have changed. - if (isInjectingCharacter && m_TextParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) + if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) m_fontScale = m_textInfo.characterInfo[m_characterCount - 1].scale; else m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); @@ -3164,7 +3165,7 @@ protected override void GenerateTextMesh() // If End of Text if (charCode == 0x03) - i = m_TextParsingBuffer.Length; + i = m_InternalParsingBuffer.Length; #if TMP_PROFILE_ON Profiler.EndSample(); @@ -4399,4 +4400,4 @@ void UpdateSDFScale(float scaleDelta) } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TMPro_UGUI_Private.cs b/Scripts/Runtime/TMPro_UGUI_Private.cs index a6fa632..76f50a4 100644 --- a/Scripts/Runtime/TMPro_UGUI_Private.cs +++ b/Scripts/Runtime/TMPro_UGUI_Private.cs @@ -112,8 +112,8 @@ protected override void Awake() LoadFontAsset(); // Allocate our initial buffers. - if (m_TextParsingBuffer == null) - m_TextParsingBuffer = new UnicodeChar[m_max_characters]; + if (m_InternalParsingBuffer == null) + m_InternalParsingBuffer = new UnicodeChar[m_max_characters]; m_cached_TextElement = new TMP_Character(); m_isFirstAllocation = true; @@ -126,9 +126,6 @@ protected override void Awake() m_subTextObjects[i + 1] = subTextObjects[i]; } - // Get reference to potential text preprocessor component - m_TextPreProcessor = GetComponent(); - // Set flags to ensure our text is parsed and redrawn. m_isInputParsingRequired = true; m_havePropertiesChanged = true; @@ -313,6 +310,13 @@ protected override void OnValidate() /// The affected GameObject void OnPrefabInstanceUpdate(GameObject go) { + // Remove Callback if this prefab has been deleted. + if (this == null) + { + UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabInstanceUpdate; + return; + } + if (go == this.gameObject) { TMP_SubMeshUI[] subTextObjects = GetComponentsInChildren(); @@ -1008,7 +1012,7 @@ void SetMeshArrays(int size) // This function parses through the Char[] to determine how many characters will be visible. It then makes sure the arrays are large enough for all those characters. - protected override int SetArraySizes(UnicodeChar[] chars) + protected override int SetArraySizes(UnicodeChar[] unicodeChars) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP SetArraySizes()"); @@ -1036,7 +1040,12 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_materialReferenceIndexLookup.Clear(); MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup); - if (m_textInfo == null) m_textInfo = new TMP_TextInfo(); + // Set allocations for the text object's TextInfo + if (m_textInfo == null) + m_textInfo = new TMP_TextInfo(m_InternalParsingBufferSize); + else if (m_textInfo.characterInfo.Length < m_InternalParsingBufferSize) + TMP_TextInfo.Resize(ref m_textInfo.characterInfo, m_InternalParsingBufferSize, false); + m_textElementType = TMP_TextElementType.Character; // Clear Linked Text object if we have one. @@ -1046,15 +1055,14 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_linkedTextComponent.ClearMesh(); } - // Parsing XML tags in the text - for (int i = 0; i < chars.Length && chars[i].unicode != 0; i++) + for (int i = 0; i < unicodeChars.Length && unicodeChars[i].unicode != 0; i++) { //Make sure the characterInfo array can hold the next text element. if (m_textInfo.characterInfo == null || m_totalCharacterCount >= m_textInfo.characterInfo.Length) TMP_TextInfo.Resize(ref m_textInfo.characterInfo, m_totalCharacterCount + 1, true); - int unicode = chars[i].unicode; + int unicode = unicodeChars[i].unicode; // PARSE XML TAGS #region PARSE XML TAGS @@ -1064,9 +1072,9 @@ protected override int SetArraySizes(UnicodeChar[] chars) int endTagIndex; // Check if Tag is Valid - if (ValidateHtmlTag(chars, i + 1, out endTagIndex)) + if (ValidateHtmlTag(unicodeChars, i + 1, out endTagIndex)) { - int tagStartIndex = chars[i].stringIndex; + int tagStartIndex = unicodeChars[i].stringIndex; i = endTagIndex; if ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold) m_isUsingBold = true; @@ -1083,7 +1091,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].textElement = m_currentSpriteAsset.spriteCharacterTable[m_spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; m_textInfo.characterInfo[m_totalCharacterCount].index = tagStartIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].stringIndex - tagStartIndex + 1; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].stringIndex - tagStartIndex + 1; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1172,8 +1180,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAsset; m_textInfo.characterInfo[m_totalCharacterCount].textElement = spriteAsset.spriteCharacterTable[spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1228,8 +1236,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAsset; m_textInfo.characterInfo[m_totalCharacterCount].textElement = spriteAsset.spriteCharacterTable[spriteIndex]; m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1267,7 +1275,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) int srcGlyph = unicode; // Try replacing the missing glyph character by TMP Settings Missing Glyph or Square (9633) character. - unicode = chars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; + unicode = unicodeChars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; // Check for the missing glyph character in the currently assigned font asset and its fallbacks character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); @@ -1289,7 +1297,7 @@ protected override int SetArraySizes(UnicodeChar[] chars) if (character == null) { // Use Space (32) Glyph from the currently assigned font asset. - unicode = chars[i].unicode = 32; + unicode = unicodeChars[i].unicode = 32; character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) Debug.LogWarning("Character with ASCII value of " + srcGlyph + " was not found in the Font Asset Glyph Table. It was replaced by a space.", this); @@ -1312,8 +1320,8 @@ protected override int SetArraySizes(UnicodeChar[] chars) m_textInfo.characterInfo[m_totalCharacterCount].isUsingAlternateTypeface = isUsingAlternativeTypeface; m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; - m_textInfo.characterInfo[m_totalCharacterCount].index = chars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].length; + m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; if (isUsingFallbackOrAlternativeTypeface) { @@ -1412,17 +1420,9 @@ protected override int SetArraySizes(UnicodeChar[] chars) // Check if the material has changed. if (m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetInstanceID() != m_materialReferences[i].material.GetInstanceID()) { - bool isDefaultMaterial = m_materialReferences[i].isDefaultMaterial; - - m_subTextObjects[i].isDefaultMaterial = isDefaultMaterial; - - // Assign new material if we are not using the default material or if the font asset has changed. - if (!isDefaultMaterial || m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID() != m_materialReferences[i].material.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) - { - m_subTextObjects[i].sharedMaterial = m_materialReferences[i].material; - m_subTextObjects[i].fontAsset = m_materialReferences[i].fontAsset; - m_subTextObjects[i].spriteAsset = m_materialReferences[i].spriteAsset; - } + m_subTextObjects[i].sharedMaterial = m_materialReferences[i].material; + m_subTextObjects[i].fontAsset = m_materialReferences[i].fontAsset; + m_subTextObjects[i].spriteAsset = m_materialReferences[i].spriteAsset; } // Check if we need to use a Fallback Material @@ -1707,7 +1707,7 @@ protected override void GenerateTextMesh() m_textInfo.Clear(); // Early exit if we don't have any Text to generate. - if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) + if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == (char)0) { // Clear mesh and upload changes to the mesh. ClearMesh(); @@ -1883,9 +1883,9 @@ protected override void GenerateTextMesh() #endif // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) { - charCode = m_TextParsingBuffer[i].unicode; + charCode = m_InternalParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -1900,7 +1900,7 @@ protected override void GenerateTextMesh() int endTagIndex; // Check if Tag is valid. If valid, skip to the end of the validated tag. - if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_InternalParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -2082,7 +2082,7 @@ protected override void GenerateTextMesh() m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; // Re-calculate font scale as the font asset may have changed. - if (isInjectingCharacter && m_TextParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) + if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) m_fontScale = m_textInfo.characterInfo[m_characterCount - 1].scale; else m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); @@ -3257,7 +3257,7 @@ protected override void GenerateTextMesh() // If End of Text if (charCode == 0x03) - i = m_TextParsingBuffer.Length; + i = m_InternalParsingBuffer.Length; #if TMP_PROFILE_ON Profiler.EndSample(); @@ -4524,4 +4524,4 @@ void UpdateSDFScale(float scaleDelta) } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TextMeshPro.cs b/Scripts/Runtime/TextMeshPro.cs index d715cc3..bbfd883 100644 --- a/Scripts/Runtime/TextMeshPro.cs +++ b/Scripts/Runtime/TextMeshPro.cs @@ -12,6 +12,7 @@ namespace TMPro [RequireComponent(typeof(MeshFilter))] [AddComponentMenu("Mesh/TextMeshPro - Text")] [ExecuteAlways] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.textmeshpro@3.0")] public partial class TextMeshPro : TMP_Text, ILayoutElement { // Public Properties and Serializable Properties @@ -327,8 +328,8 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT /// public override TMP_TextInfo GetTextInfo(string text) { - StringToCharArray(text, ref m_TextParsingBuffer); - SetArraySizes(m_TextParsingBuffer); + StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); + SetArraySizes(m_InternalParsingBuffer); m_renderMode = TextRenderFlags.DontRender; @@ -555,4 +556,4 @@ public void CalculateLayoutInputVertical() m_isCalculateSizeRequired = false; } } -} \ No newline at end of file +} diff --git a/Scripts/Runtime/TextMeshProUGUI.cs b/Scripts/Runtime/TextMeshProUGUI.cs index 8209786..9cc30cb 100644 --- a/Scripts/Runtime/TextMeshProUGUI.cs +++ b/Scripts/Runtime/TextMeshProUGUI.cs @@ -12,6 +12,7 @@ namespace TMPro [RequireComponent(typeof(CanvasRenderer))] [AddComponentMenu("UI/TextMeshPro - Text (UI)", 11)] [ExecuteAlways] + [HelpURL("https://docs.unity3d.com/Packages/com.unity.textmeshpro@3.0")] public partial class TextMeshProUGUI : TMP_Text, ILayoutElement { /// @@ -283,10 +284,6 @@ public override Material GetModifiedMaterial(Material baseMaterial) m_ShouldRecalculateStencil = false; } - // Release masking material - //if (m_MaskMaterial != null) - // MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); - if (m_stencilID > 0) { mat = TMP_MaterialManager.GetStencilMaterial(baseMaterial, m_stencilID); @@ -295,6 +292,8 @@ public override Material GetModifiedMaterial(Material baseMaterial) m_MaskMaterial = mat; } + else if (m_MaskMaterial != null) + TMP_MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); return mat; } @@ -544,8 +543,8 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT /// public override TMP_TextInfo GetTextInfo(string text) { - StringToCharArray(text, ref m_TextParsingBuffer); - SetArraySizes(m_TextParsingBuffer); + StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); + SetArraySizes(m_InternalParsingBuffer); m_renderMode = TextRenderFlags.DontRender; @@ -695,4 +694,4 @@ public void UpdateFontAsset() } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index b863d18..9058483 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.textmeshpro", "displayName": "TextMeshPro", - "version": "3.0.0-preview.3", + "version": "3.0.0-preview.4", "unity": "2020.1", "unityRelease": "0a10", "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.", @@ -18,7 +18,7 @@ }, "repository": { "type": "git", - "url": "git@github.cds.internal.unity3d.com:unity/com.unity.textmeshpro.git", - "revision": "895ca4d54934dd808230501a874a9ce1c2652746" + "url": "https://github.cds.internal.unity3d.com/unity/com.unity.textmeshpro.git", + "revision": "79cfd8d984f00e1770f92552ecb34b9f4ff4b756" } }