diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e1de6a..2caf64a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,135 +1,18 @@ # 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 -## [2.1.0-preview.11] - 2020-04-22 -## [1.5.0-preview.11] -## [3.0.0-preview.11] +## [3.0.0] - 2019-10-30 ### Changes -- Fixed incorrect culling of text object by RectMask2D component when the parent Canvas Render Mode is set to Screen Space - Camera or World Space. Case #1240595 -- Added special handling to ForceMeshUpdate() when the parent Canvas is disabled. - -## [2.1.0-preview.10] - 2020-04-21 -## [1.5.0-preview.10] -## [3.0.0-preview.10] -### Changes -- Revised caching of Preferred Width and Height to further reduce the amount of time it has to be recomputed when using a complex structure of Layout components. -- Fixed potential issue when using Text Overflow Ellipsis and Truncate modes when the text contains characters using superscript, subscript or using the <voffset> tag. -- Revised culling of text objects when using a RectMask2D where the bounds of the text geometry instead of the RectTransform define the culling rect. -- Added HDR support to material preset colors. -- Fixed various formatting issues in this ChangeLog. -- Added the ability to define a unicode value for a missing sprite character in the TMP Settings. -- Added support for displaying a missing sprite character when the requested sprite character is not present in the sprite asset or potential fallback(s). This new functionality is only available when trying to reference a sprite by name. -- Sprite Characters will now have a default Unicode value of 0xFFFE (Private NonCharacter) instead of a Unicode value of 0x0 (default unicode value for missing character). -- Using the sprite asset context menu option "Update Sprite Asset" will now remap sprite characters with unicode value of 0x0 to 0xFFFE in addition to its currently functionality. -- Updating TMP Essential Resources via the "Window - TextMeshPro - Import TMP Essential Resources" menu option will no longer override existing TMP Settings. -- Minor optimization where SDF Scale on some text objects could be unnecessarily updated due to floating point rounding errors in their lossy scale. Case #1230799 -- Fixed minor issue where text objects created before importing the required TMP Essential Resources would have no default text. -- Improvements to line breaking for CJK and mixed Latin and CJK characters. See the following [forum post](https://forum.unity.com/threads/tmp-bug.852733/#post-5688274) for more details. -- Fixed potential NullReferenceException that could occur in the TMP InputField on some platforms if the InputSystem reference is null. Case #1232433 -- Added small padding to bitmap character geometry to prevent potential clipping. -- Added optimization to ignore very small RectTransform pivot changes that are usually the result of rounding errors when using Layout Components. Case #1237700 -- Sorting Layer ID and Sorting Order properties located in the Extra Settings of <TextMeshPro> text objects will now serialized when creating Editor Presets. Case #1215750 -- TextMeshProUGUI sub text objects will now be set as first sibling of their parent to prevent them from being rendered over other non text object child in the scene hierarchy. -- Fixed text objects becoming visible when set to empty or null as a result of a scale change. Case #1238408 -- Fixed useMaxVisibleDescender property now getting set properly via scripting. Case #1218526 -- Fixed SortingLayerID and SortingOrder not getting set correctly when multiple <TextMeshPro> objects are selected. Case #1171272 -- Fixed default settings getting applied to disabled text objects in the scene hierarchy whose text property was set to null. Case #1151621 -- Fixed mouse cursor flickering when hovering the Text Input Box of a text prefab with RTL enabled. Case #1206395 - -## [2.1.0-preview.8] - 2020-03-14 -## [1.5.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. - -## [2.1.0-preview.7] - 2020-03-07 -## [1.5.0-preview.7] -## [3.0.0-preview.7] -### Changes -- Reverted recent change to the TMP_SubMeshUI OnDisable() function that could result in a Missing Reference Exception in the GraphicRaycaster.cs script. See the following [forum post](https://forum.unity.com/threads/version-1-5-0-2-1-0-preview-5-now-available-for-testing.753587/page-2#post-5523412). -- Added support for Stadia for Unity 2019.3 or newer. -- Addressed warning that would appear in the console in Unity 2019.3 related to recent Preset API changes. Case #1223257 -- Fixed glyph drawing issue in the Font Asset Inspector Glyph Adjustment Table when Multi Atlas Texture is enabled and the glyph is not located in the main atlas texture or at atlasTextures[0]. -- Added support for <ZWSP> tag which is internally replaced by a zero width space or \u200B. -- Improved line breaking handling when using <NBSP> and / or <NOBR> tags where instead of breaking these line segments per character, they will break at any possible soft breaking space when these segments exceed the width of the text container. -- Improved PreferredHeight calculations and handling when using Text Auto Size. -- Fixed incorrect color being applied to the underline or strikethrough line segments when using and / or tags along with a tag while at the same time applying an Underline or Strikethrough font style on the whole text object. -- Fixed SDF Scale not getting updated when using SetText() with StringBuilder when the lossyScale of the text object changes. Case #1216007 -- Added Non Breaking Space \u00A0 and Soft Hyphen \u00AD to list of synthesized characters in the event they are not present in the source font file. -- Fixed stack overflow issue when using TMP_FontAsset.HasCharacter and TMP_FontAsset.HasCharacters function on font assets that have circular fallback references. Case #1222574 -- Fixed atlas texture not getting set correctly to IsReadable when switching a static font asset to dynamic in the Generation Settings of the Font Asset Inspector. -- Added check for RectTransform.sizeDelta change when OnRectTransformDimensionsChange() is called by the Canvas system to get around potential rounding error that erroneously trigger this callback when the RectTransform is using Stretch Anchor mode. -- As requested by a few users, TMP_FontAsset.faceInfo setter is now public instead of internal. - -## [2.1.0-preview.5] - 2020-02-25 -## [1.5.0-preview.5] -## [3.0.0-preview.5] -### Changes -- Revised SetText function formatting options to including ability to specify padding for integral part of the value. Revised format is as follows: {Arg Index:Integral Padding.Decimal Precision} Example: TMP_Text.SetText("Value = {0:000.00}", 10.375f); result in "Value = 010.38". -- Fixed issue where text objects isTextObjectScaleStatic property would be ignored when OnCanvasHierarchyChanged() is called. -- Added a Character, Glyph and Record count to those respective tables in the Font Asset Inspector. -- Fixed potential Null Reference Exception that would occur when using text Overflow Ellipsis mode with a primary font asset that doesn't contain the Ellipsis character. Case #1209771 -- Fixed a potential Editor lockup when using text Overflow Page mode. Case #1219055 -- Fixed Input Field incorrect caret vertical alignment when using the Midline / Vertical Geometry alignment option. -- Added initial / minimal support for the New Input System. Please use with caution and report any issues. -- Changes to Font Asset Generation Settings via the Font Asset Inspector will now update the existing glyphs and characters for the new settings instead of clearing them. -- Text object InternalUpdate() used to handle potential scale changes of text objects now uses willRenderCanvases event instead of onPreCull. This avoids a potential one frame delay in updating of objects and no impact on objects. Case #1216007 - -## [2.1.0-preview.4] - 2020-01-31 -## [1.5.0-preview.4] -## [3.0.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 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. - -## [2.1.0-preview.3] - 2019-12-16 -## [1.5.0-preview.3] -### Changes -- Fixed potential issue with TMP Dropdown where calling Show() and Hide() in very short interval could result in additional Blockers. Case #1194114 -- Fixed potential issues that could occur when upgrading to version 1.5.0-preview.2 or newer of the TMP package without also updating the TMP Essential Resources in the project. -- Added check and warning when trying to create a font asset whose source font file has "Incl. Font Data" disabled in the Font Import Settings. Case #1198587 and #1198112 -- Fixed Ellipsis overflow mode issue when using small caps. Case #1198392 -- Fixed potential layout issue when adding a Layout Group to the text object itself. Case #1197614 -- Fixed Font Asset Creator issue where too many adjustment records with adjustment value of zero were added to the font asset. -- Added support for Line Separator \u2028 and Paragraph Separator \u2029. -- TMP shaders have been moved from "TextMesh Pro/Resources/Shaders" folder to "TextMesh Pro/Shaders" folder. See the following [post](https://forum.unity.com/threads/version-1-5-0-2-1-0-preview-2-now-available-for-testing.753587/#post-5206853) for details. -- Added new experimental SDF and Mobile SDF Shaders that use Screen Space Derivatives (SSD) where these shaders no longer require SDF Scale to be passed via Vertex Attributes. These shaders have higher performance overhead but are more flexible. This overhead should only be noticeable on mobile platforms. -- Fixed potential text alignment issue where upgrading from package version 1.4.1 to 1.5.0-preview.2 would result in incorrect alignment on prefabs. Case #1198833 -- Added \u061C Arabic Letter Mark, \u200E Left-to-Right Mark and \u200F Right-to-Left Mark to list of control and non renderable characters. -- Fixed Missing Reference Exception that would appear when expanding the Extra Settings of a TextMeshPro Preset asset. Case #1201072 -- Fixed Missing Reference Exception that would appear when editing the Vertex Color or Color Gradient of a TMP component Preset asset. Case #1201069 -- Fixed Inspector layout issue preventing enabling or disabling the Outline, Underlay, Lighting and Glow features when selecting a Preset asset material. Case #1196963 -- Revised the Create Material Preset context menu option to issue a warning and ignore materials outside the project. Case #1200109 -- Added experimental ITextPreprocessor interface to allow users to create custom components to handle text preprocessing and shaping. This interface includes a PreprocessText(string text) function that is called when the object contains a component that inherits from this interface. -- Added support for Unity Presets in the Editor for both and components. Case #1191793 -- Optimization to ensure the TMP Update Manager only rebuilds text objects once per frame regardless of the number of cameras in the scene. +- Updated TMP Examples & Extras to remove CanvasRenderer from text objects in example scenes. +- CanvasRenderer component will now be removed from existing text objects that contains this unnecessary component. +- Editing a prefab that contains a normal component will no longer open the prefab in Canvas mode. Case #1103782 and Case #1188483 ## [2.1.0-preview.2] - 2019-10-30 ## [1.5.0-preview.2] ### Changes - Fixed Input Field issue when Read Only flag is set preventing the initial setting of the text. Also fixed Read Only flag not being respected when using IME input. - Fixed potential infinite loop when using text overflow mode ScrollRect. See Case #1188867 -- Fixed Input Field culling related issue(s) where text would be incorrectly culled. See https://forum.unity.com/threads/version-1-5-0-2-1-0-preview-1-now-available-for-testing.753587/#post-5023700 +- Fixed Input Field culling related issue(s) where text would be incorrectly culled. See https://forum.unity.com/threads/version-1-5-0-2-1-0-preview-1-now-available-for-testing.753587/#post-5023700 - Revised handling and referencing of the CanvasRenderer in anticipation of an incoming change to the MaskableGraphic class where it will no longer automatically add a CanvasRenderer to components inheriting from it. As a result, objects will no longer have a CanvasRenderer. - Fixed potential NRE when using Overflow Truncate mode with sprites. See https://forum.unity.com/threads/tmpro-stackoverflow-caused-by-tmpro-textmeshprougui-generatetextmesh.750398/page-2#post-5042822 - Fixed issue when using font weights in combination of font styles in the editor. @@ -141,7 +24,7 @@ These are the release notes for the TextMesh Pro UPM package which was first int - Fixed Fallback material not getting updated correctly when changing Generation Settings on the Fallback Font Asset. - Fixed a typo in the Font Weight section of the Font Asset Editor. - Fixed potential ArgumentOutOfRangeException in the Input Field when using Hide Mobile Input and deleting a long string. Case #1162514 -- Added "Is Scale Static" option in the Extra Settings to exclude text objects from InternalUpdate callbacks to improve performance when the object's scale is static. This InternalUpdate callback is used to track potential changes to the scale of text objects to update their SDF Scale. +- Added "Is Scale Static" option in the Extra Settings to exclude text objects from InternalUpdate callbacks to improve performance when the object's scale is static. This InternalUpdate callback is used to track potential changes to the scale of text objects to update their SDF Scale. - Added the ability to control culling modes for the TMP Shaders. This new option is available in the Debug section of the Material Inspector. New feature requires updating the TMP Essential Resources. See the following post https://forum.unity.com/threads/not-see-textmeshpro-rendering-from-the-back.767510/#post-5112461. - Fixed Material Inspector issue when toggling the Record button in the Animation window. Case #1174960 - Improved Line Breaking handling for CJK. This also addresses a few reported issues. Case #1171603 @@ -191,7 +74,7 @@ These are the release notes for the TextMesh Pro UPM package which was first int - Since the legacy TextContainer used by TMP has been deprecated, it was removed from the Layout Context Menu options. - Improved character positioning when using italic text where large angle / slant would potentially result in uneven spacing between normal and italic blocks of text. - Fixed an issue where <mspace> and <cspace> tags would not be handled correctly in conjunction with word wrapping. -- Fixed issue in the TMP_Dropdown.cs that was affecting navigation. Case 1162600. See https://forum.unity.com/threads/huge-bug-missing-a-code-line-since-1-4-0.693421/ +- Fixed issue in the TMP_Dropdown.cs that was affecting navigation. Case 1162600. See https://forum.unity.com/threads/huge-bug-missing-a-code-line-since-1-4-0.693421/ - Fixed an issue related to kerning where the glyph adjustment values did not account for the upsampling of the legacy SDF modes like SDF8 / SDF16 and SDF32. - Made the TMP_Text.text property virtual. - Fixed Material Preset of fallback materials getting modified when the TMP Settings Match Material Preset option is disabled. @@ -216,7 +99,7 @@ These are the release notes for the TextMesh Pro UPM package which was first int - Fixed potential issue related to SDF Scaling when the scale of the text object is negative. See https://forum.unity.com/threads/version-1-4-1-preview-1-with-dynamic-sdf-for-unity-2018-3-now-available.622420/page-5#post-4958240 for details. - Added validation check for Sprite Data Source file in the Sprite Asset Importer. Case #1186620 - Added warning when using Create - TextMeshPro - Sprite Asset menu when no valid texture is selected. Case #1163982 -- Fixed potential cosmetic issue in the text component inspector when using Overflow Linked mode. Case #1177640 +- Fixed potential cosmetic issue in the text component inspector when using Overflow Linked mode. Case #1177640 ## [1.4.1] - 2019-04-12 ### Changes @@ -240,13 +123,13 @@ These are the release notes for the TextMesh Pro UPM package which was first int - Fixed an issue with SDF Scale handling where the text object would not render correctly after the object scale had been set to zero. - Fixed an issue with the TMP_UpdateManager where text objects were not getting unregistered correctly. - Any changes to Font Asset Creation Settings' padding, atlas width and / or atlas height will now result in all Material Presets for the given font asset to also be updated. -- Added new section in the TMP Settings related to the new Dynamic Font System. +- Added new section in the TMP Settings related to the new Dynamic Font System. - Added new property in the Dynamic Font System section to determine if OpenType Font Features will be retrieved from source font files at runtime as new characters are added to font assets. Glyph Adjustment Data (Kerning) is the only feature currently supported. - Fix an issue where font assets created at runtime were not getting their asset version number set to "1.1.0". - Improved parsing of the text file used in the Font Asset Creator and "Characters from File" option to handle UTF16 "\u" and UTF32 "\U" escape character sequences. - Fixed a Null Reference Error (NRE) that could occur when using the <font> tag with an invalid font name followed by the <sprite> tag. - The Glyph Adjustment Table presentation and internal data structure has been changed to facilitate the future addition of OpenType font features. See https://forum.unity.com/threads/version-1-4-0-preview-with-dynamic-sdf-for-unity-2018-3-now-available.622420/#post-4206595 for more details. -- Fixed an issue with the <rotate> tag incorrectly affecting character spacing. +- Fixed an issue with the <rotate> tag incorrectly affecting character spacing. ## [1.4.0-preview.1] - 2019-01-30 ### Changes @@ -354,7 +237,7 @@ These are the release notes for the TextMesh Pro UPM package which was first int ## [1.1.0] - 2018-01-23 ### Changes -- Package version # increased to 1.1.0 which is the first release for Unity 2018.1. +- Package version # increased to 1.1.0 which is the first release for Unity 2018.1. ## [1.0.27] - 2018-01-16 ### Changes diff --git a/Editor Resources/Shaders/TMP_SDF Internal Editor.shader b/Editor Resources/Shaders/TMP_SDF Internal Editor.shader deleted file mode 100644 index baf4501..0000000 --- a/Editor Resources/Shaders/TMP_SDF Internal Editor.shader +++ /dev/null @@ -1,75 +0,0 @@ -// Simplified SDF shader: -// - No Shading Option (bevel / bump / env map) -// - No Glow Option -// - Softness is applied on both side of the outline - -Shader "Hidden/TMP/Internal/Editor/Distance Field SSD" { - - Properties{ - _FaceColor("Face Color", Color) = (1,1,1,1) - _FaceDilate("Face Dilate", Range(-1,1)) = 0 - - _OutlineColor("Outline Color", Color) = (0,0,0,1) - _OutlineWidth("Outline Thickness", Range(0,1)) = 0 - _OutlineSoftness("Outline Softness", Range(0,1)) = 0 - - _UnderlayColor("Border Color", Color) = (0,0,0,.5) - _UnderlayOffsetX("Border OffsetX", Range(-1,1)) = 0 - _UnderlayOffsetY("Border OffsetY", Range(-1,1)) = 0 - _UnderlayDilate("Border Dilate", Range(-1,1)) = 0 - _UnderlaySoftness("Border Softness", Range(0,1)) = 0 - - _WeightNormal("Weight Normal", float) = 0 - _WeightBold("Weight Bold", float) = .5 - - _ShaderFlags("Flags", float) = 0 - _ScaleRatioA("Scale RatioA", float) = 1 - _ScaleRatioB("Scale RatioB", float) = 1 - _ScaleRatioC("Scale RatioC", float) = 1 - - _MainTex("Font Atlas", 2D) = "white" {} - _TextureWidth("Texture Width", float) = 1024 - _TextureHeight("Texture Height", float) = 1024 - _GradientScale("Gradient Scale", float) = 1 - _ScaleX("Scale X", float) = 1 - _ScaleY("Scale Y", float) = 1 - _PerspectiveFilter("Perspective Correction", Range(0, 1)) = 0.875 - _Sharpness("Sharpness", Range(-1,1)) = 0 - - _VertexOffsetX("Vertex OffsetX", float) = 0 - _VertexOffsetY("Vertex OffsetY", float) = 0 - } - - SubShader - { - Tags - { - "ForceSupported" = "True" - } - - Lighting Off - Blend One OneMinusSrcAlpha - Cull Off - ZWrite Off - ZTest Always - - Pass - { - CGPROGRAM - #pragma vertex VertShader - #pragma fragment PixShader - #pragma shader_feature __ OUTLINE_ON - #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER - - #include "UnityCG.cginc" - #include "UnityUI.cginc" - #include "TMP_Properties.cginc" - - #include "TMP_SDF_SSD.cginc" - - ENDCG - } - } - - CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" -} diff --git a/Editor Resources/Shaders/TMP_SDF Internal SSD.shader b/Editor Resources/Shaders/TMP_SDF Internal SSD.shader new file mode 100644 index 0000000..7e28d74 --- /dev/null +++ b/Editor Resources/Shaders/TMP_SDF Internal SSD.shader @@ -0,0 +1,126 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "Hidden/TextMeshPro/Internal/Distance Field SSD" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0.02 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "ForceSupported" = "True" + } + + Lighting Off + Blend One OneMinusSrcAlpha + Cull Off + ZWrite Off + ZTest Always + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + + #include "UnityCG.cginc" + #include "TMP_Properties.cginc" + + sampler2D _GUIClipTexture; + uniform float4x4 unity_GUIClipTextureMatrix; + + struct vertex_t { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + + pixel_t VertShader(vertex_t input) + { + // Does not handle simulated bold correctly. + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float opacity = input.color.a; + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + // Generate UV for the Clip Texture + float3 eyePos = UnityObjectToViewPos(input.vertex); + float2 clipUV = mul(unity_GUIClipTextureMatrix, float4(eyePos.xy, 0, 1.0)); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + float2(input.texcoord0.x, input.texcoord0.y), + clipUV, + }; + + return output; + } + + half transition(half2 range, half distance) + { + return smoothstep(range.x, range.y, distance); + } + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half distanceSample = tex2D(_MainTex, input.texcoord0).a; + half smoothing = fwidth(distanceSample) * (1 - _Sharpness) + _OutlineSoftness; + half contour = 0.5 - _FaceDilate * 0.5; + half2 edgeRange = half2(contour - smoothing, contour + smoothing); + + half4 c = input.faceColor; + + half edgeTransition = transition(edgeRange, distanceSample); + c *= edgeTransition; + + c *= tex2D(_GUIClipTexture, input.clipUV).a; + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Editor Resources/Shaders/TMP_SDF Internal Editor.shader.meta b/Editor Resources/Shaders/TMP_SDF Internal SSD.shader.meta similarity index 80% rename from Editor Resources/Shaders/TMP_SDF Internal Editor.shader.meta rename to Editor Resources/Shaders/TMP_SDF Internal SSD.shader.meta index 5ba708d..7845e11 100644 --- a/Editor Resources/Shaders/TMP_SDF Internal Editor.shader.meta +++ b/Editor Resources/Shaders/TMP_SDF Internal SSD.shader.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9c442dc870b456e48b615cd8add0e9ef +guid: ce4ec0f498d1b1a4f90fe94e115b6f9a ShaderImporter: externalObjects: {} defaultTextures: [] diff --git a/Editor Resources/Shaders/TMP_SDF_SSD.cginc b/Editor Resources/Shaders/TMP_SDF_SSD.cginc deleted file mode 100644 index 0f587bd..0000000 --- a/Editor Resources/Shaders/TMP_SDF_SSD.cginc +++ /dev/null @@ -1,132 +0,0 @@ -struct vertex_t -{ - float4 position : POSITION; - float3 normal : NORMAL; - float4 color : COLOR; - float2 texcoord0 : TEXCOORD0; - float2 texcoord1 : TEXCOORD1; -}; - -struct pixel_t -{ - float4 position : SV_POSITION; - float4 faceColor : COLOR; - float4 outlineColor : COLOR1; - float2 texcoord0 : TEXCOORD0; - float4 param : TEXCOORD1; // weight, scaleRatio - float2 clipUV : TEXCOORD2; - #if (UNDERLAY_ON || UNDERLAY_INNER) - float4 texcoord2 : TEXCOORD3; - float4 underlayColor : COLOR2; - #endif -}; - -sampler2D _GUIClipTexture; -uniform float4x4 unity_GUIClipTextureMatrix; -float4 _MainTex_TexelSize; - -float4 SRGBToLinear(float4 rgba) -{ - return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); -} - -pixel_t VertShader(vertex_t input) -{ - pixel_t output; - - float bold = step(input.texcoord1.y, 0); - - float4 vert = input.position; - vert.x += _VertexOffsetX; - vert.y += _VertexOffsetY; - - float4 vPosition = UnityObjectToClipPos(vert); - - float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; - weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; - - // Generate UV for the Clip Texture - float3 eyePos = UnityObjectToViewPos(input.position); - float2 clipUV = mul(unity_GUIClipTextureMatrix, float4(eyePos.xy, 0, 1.0)); - - float4 color = input.color; - #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) - color = SRGBToLinear(input.color); - #endif - - float opacity = color.a; - #if (UNDERLAY_ON | UNDERLAY_INNER) - opacity = 1.0; - #endif - - float4 faceColor = float4(color.rgb, opacity) * _FaceColor; - faceColor.rgb *= faceColor.a; - - float4 outlineColor = _OutlineColor; - outlineColor.a *= opacity; - outlineColor.rgb *= outlineColor.a; - - output.position = vPosition; - output.faceColor = faceColor; - output.outlineColor = outlineColor; - output.texcoord0 = float2(input.texcoord0.xy); - output.param = float4(0.5 - weight, 1.3333 * _GradientScale * (_Sharpness + 1) / _MainTex_TexelSize.z , _OutlineWidth * _ScaleRatioA * 0.5, 0); - output.clipUV = clipUV; - - #if (UNDERLAY_ON || UNDERLAY_INNER) - float4 underlayColor = _UnderlayColor; - underlayColor.rgb *= underlayColor.a; - - float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _MainTex_TexelSize.z; - float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _MainTex_TexelSize.w; - - output.texcoord2 = float4(input.texcoord0 + float2(x, y), input.color.a, 0); - output.underlayColor = underlayColor; - #endif - - return output; -} - -float4 PixShader(pixel_t input) : SV_Target -{ - float d = tex2D(_MainTex, input.texcoord0.xy).a; - - float2 UV = input.texcoord0.xy; - float scale = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))) * input.param.y; - - #if (UNDERLAY_ON | UNDERLAY_INNER) - float layerScale = scale; - layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); - float layerBias = input.param.x * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); - #endif - - scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); - - float4 faceColor = input.faceColor * saturate((d - input.param.x) * scale + 0.5); - - #ifdef OUTLINE_ON - float4 outlineColor = lerp(input.faceColor, input.outlineColor, sqrt(min(1.0, input.param.z * scale * 2))); - faceColor = lerp(outlineColor, input.faceColor, saturate((d - input.param.x - input.param.z) * scale + 0.5)); - faceColor *= saturate((d - input.param.x + input.param.z) * scale + 0.5); - #endif - - #if UNDERLAY_ON - d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale; - faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - layerBias) * (1 - faceColor.a); - #endif - - #if UNDERLAY_INNER - float bias = input.param.x * scale - 0.5; - float sd = saturate(d * scale - bias - input.param.z); - d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale; - faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - layerBias)) * sd * (1 - faceColor.a); - #endif - - #if (UNDERLAY_ON | UNDERLAY_INNER) - faceColor *= input.texcoord2.z; - #endif - - faceColor *= tex2D(_GUIClipTexture, input.clipUV).a; - - return faceColor; -} diff --git a/Editor Resources/Shaders/TMP_SDF_SSD.cginc.meta b/Editor Resources/Shaders/TMP_SDF_SSD.cginc.meta deleted file mode 100644 index 3d0b3bf..0000000 --- a/Editor Resources/Shaders/TMP_SDF_SSD.cginc.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: abe6991365a27d341a10580f3b7c0f44 -ShaderImporter: - externalObjects: {} - defaultTextures: [] - nonModifiableTextures: [] - userData: - assetBundleName: - assetBundleVariant: diff --git a/Package Resources/TMP Essential Resources.unitypackage b/Package Resources/TMP Essential Resources.unitypackage index aa27eb5..002d7e2 100644 Binary files a/Package Resources/TMP Essential Resources.unitypackage and b/Package Resources/TMP Essential Resources.unitypackage differ diff --git a/Package Resources/TMP Examples & Extras.unitypackage b/Package Resources/TMP Examples & Extras.unitypackage index ea3a62b..7872a8b 100644 Binary files a/Package Resources/TMP Examples & Extras.unitypackage and b/Package Resources/TMP Examples & Extras.unitypackage differ diff --git a/Scripts/Editor/GlyphMetricsPropertyDrawer.cs b/Scripts/Editor/GlyphMetricsPropertyDrawer.cs index bcd25a6..1e1f4d1 100644 --- a/Scripts/Editor/GlyphMetricsPropertyDrawer.cs +++ b/Scripts/Editor/GlyphMetricsPropertyDrawer.cs @@ -21,10 +21,10 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten // We get Rect since a valid position may not be provided by the caller. Rect rect = new Rect(position.x, position.y, position.width, 49); - EditorGUI.LabelField(new Rect(rect.x, rect.y - 2.5f, rect.width, 18), new GUIContent("Glyph Metrics")); + EditorGUI.LabelField(rect, new GUIContent("Glyph Metrics")); - EditorGUIUtility.labelWidth = 50f; - EditorGUIUtility.fieldWidth = 15f; + EditorGUIUtility.labelWidth = 30f; + EditorGUIUtility.fieldWidth = 10f; //GUI.enabled = false; float width = (rect.width - 75f) / 2; diff --git a/Scripts/Editor/GlyphRectPropertyDrawer.cs b/Scripts/Editor/GlyphRectPropertyDrawer.cs index c9be74e..87ecf0c 100644 --- a/Scripts/Editor/GlyphRectPropertyDrawer.cs +++ b/Scripts/Editor/GlyphRectPropertyDrawer.cs @@ -21,10 +21,10 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten // We get Rect since a valid position may not be provided by the caller. Rect rect = new Rect(position.x, position.y, position.width, 49); - EditorGUI.LabelField(new Rect(rect.x, rect.y - 2.5f, rect.width, 18), new GUIContent("Glyph Rect")); + EditorGUI.LabelField(rect, new GUIContent("Glyph Rect")); - EditorGUIUtility.labelWidth = 50f; - EditorGUIUtility.fieldWidth = 20f; + EditorGUIUtility.labelWidth = 30f; + EditorGUIUtility.fieldWidth = 10f; //GUI.enabled = false; float width = (rect.width - 75f) / 4; diff --git a/Scripts/Editor/TMP_BaseEditorPanel.cs b/Scripts/Editor/TMP_BaseEditorPanel.cs index 9987c5d..dc4d128 100644 --- a/Scripts/Editor/TMP_BaseEditorPanel.cs +++ b/Scripts/Editor/TMP_BaseEditorPanel.cs @@ -30,20 +30,20 @@ public abstract class TMP_BaseEditorPanel : Editor static readonly GUIContent k_LowercaseLabel = new GUIContent("ab", "Lowercase"); static readonly GUIContent k_UppercaseLabel = new GUIContent("AB", "Uppercase"); static readonly GUIContent k_SmallcapsLabel = new GUIContent("SC", "Smallcaps"); - + static readonly GUIContent k_ColorModeLabel = new GUIContent("Color Mode", "The type of gradient to use."); static readonly GUIContent k_BaseColorLabel = new GUIContent("Vertex Color", "The base color of the text vertices."); static readonly GUIContent k_ColorPresetLabel = new GUIContent("Color Preset", "A Color Preset which override the local color settings."); static readonly GUIContent k_ColorGradientLabel = new GUIContent("Color Gradient", "The gradient color applied over the Vertex Color. Can be locally set or driven by a Gradient Asset."); static readonly GUIContent k_CorenerColorsLabel = new GUIContent("Colors", "The color composition of the gradient."); static readonly GUIContent k_OverrideTagsLabel = new GUIContent("Override Tags", "Whether the color settings override the tag."); - + static readonly GUIContent k_SpacingOptionsLabel = new GUIContent("Spacing Options (em)", "Spacing adjustments between different elements of the text. Values are in font units where a value of 1 equals 1/100em."); static readonly GUIContent k_CharacterSpacingLabel = new GUIContent("Character"); static readonly GUIContent k_WordSpacingLabel = new GUIContent("Word"); static readonly GUIContent k_LineSpacingLabel = new GUIContent("Line"); static readonly GUIContent k_ParagraphSpacingLabel = new GUIContent("Paragraph"); - + static readonly GUIContent k_AlignmentLabel = new GUIContent("Alignment", "Horizontal and vertical aligment of the text within its container."); static readonly GUIContent k_WrapMixLabel = new GUIContent("Wrap Mix (W <-> C)", "How much to favor words versus characters when distributing the text."); @@ -66,7 +66,7 @@ public abstract class TMP_BaseEditorPanel : Editor static readonly GUIContent k_KerningLabel = new GUIContent("Kerning", "Enables character specific spacing between pairs of characters."); static readonly GUIContent k_PaddingLabel = new GUIContent("Extra Padding", "Adds some padding between the characters and the edge of the text mesh. Can reduce graphical errors when displaying small text."); - + static readonly GUIContent k_LeftLabel = new GUIContent("Left"); static readonly GUIContent k_TopLabel = new GUIContent("Top"); static readonly GUIContent k_RightLabel = new GUIContent("Right"); @@ -84,14 +84,14 @@ protected struct Foldout public static bool extraSettings = false; public static bool materialInspector = true; } - + protected static int s_EventId; public int selAlignGridA; public int selAlignGridB; - + protected SerializedProperty m_TextProp; - + protected SerializedProperty m_IsRightToLeftProp; protected string m_RtlText; @@ -109,7 +109,7 @@ protected struct Foldout protected int m_StyleSelectionIndex; protected SerializedProperty m_FontStyleProp; - + protected SerializedProperty m_FontColorProp; protected SerializedProperty m_EnableVertexGradientProp; protected SerializedProperty m_FontColorGradientProp; @@ -122,7 +122,7 @@ protected struct Foldout protected SerializedProperty m_AutoSizingProp; protected SerializedProperty m_FontSizeMinProp; protected SerializedProperty m_FontSizeMaxProp; - + protected SerializedProperty m_LineSpacingMaxProp; protected SerializedProperty m_CharWidthMaxAdjProp; @@ -174,12 +174,12 @@ protected struct Foldout protected TMP_Text m_TextComponent; protected TMP_Text m_PreviousLinkedTextComponent; protected RectTransform m_RectTransform; - + protected Material m_TargetMaterial; - + protected Vector3[] m_RectCorners = new Vector3[4]; protected Vector3[] m_HandlePoints = new Vector3[4]; - + protected virtual void OnEnable() { m_TextProp = serializedObject.FindProperty("m_text"); @@ -195,7 +195,7 @@ protected virtual void OnEnable() m_AutoSizingProp = serializedObject.FindProperty("m_enableAutoSizing"); m_FontSizeMinProp = serializedObject.FindProperty("m_fontSizeMin"); m_FontSizeMaxProp = serializedObject.FindProperty("m_fontSizeMax"); - + m_LineSpacingMaxProp = serializedObject.FindProperty("m_lineSpacingMax"); m_CharWidthMaxAdjProp = serializedObject.FindProperty("m_charWidthMaxAdj"); @@ -227,13 +227,13 @@ protected virtual void OnEnable() m_ParentLinkedTextComponentProp = serializedObject.FindProperty("parentLinkedComponent"); m_EnableKerningProp = serializedObject.FindProperty("m_enableKerning"); - + m_EnableExtraPaddingProp = serializedObject.FindProperty("m_enableExtraPadding"); m_IsRichTextProp = serializedObject.FindProperty("m_isRichText"); m_CheckPaddingRequiredProp = serializedObject.FindProperty("checkPaddingRequired"); m_EnableEscapeCharacterParsingProp = serializedObject.FindProperty("m_parseCtrlCharacters"); m_UseMaxVisibleDescenderProp = serializedObject.FindProperty("m_useMaxVisibleDescender"); - + m_GeometrySortingOrderProp = serializedObject.FindProperty("m_geometrySortingOrder"); m_IsTextObjectScaleStaticProp = serializedObject.FindProperty("m_IsTextObjectScaleStatic"); @@ -325,14 +325,14 @@ public void OnSceneGUI() m_RectTransform.GetWorldCorners(m_RectCorners); Vector4 marginOffset = m_TextComponent.margin; Vector3 lossyScale = m_RectTransform.lossyScale; - + m_HandlePoints[0] = m_RectCorners[0] + m_RectTransform.TransformDirection(new Vector3(marginOffset.x * lossyScale.x, marginOffset.w * lossyScale.y, 0)); m_HandlePoints[1] = m_RectCorners[1] + m_RectTransform.TransformDirection(new Vector3(marginOffset.x * lossyScale.x, -marginOffset.y * lossyScale.y, 0)); m_HandlePoints[2] = m_RectCorners[2] + m_RectTransform.TransformDirection(new Vector3(-marginOffset.z * lossyScale.x, -marginOffset.y * lossyScale.y, 0)); m_HandlePoints[3] = m_RectCorners[3] + m_RectTransform.TransformDirection(new Vector3(-marginOffset.z * lossyScale.x, marginOffset.w * lossyScale.y, 0)); Handles.DrawSolidRectangleWithOutline(m_HandlePoints, new Color32(255, 255, 255, 0), new Color32(255, 255, 0, 255)); - + // Draw & process FreeMoveHandles // LEFT HANDLE @@ -354,7 +354,7 @@ public void OnSceneGUI() { float delta = oldTop.y - newTop.y; marginOffset.y += delta / lossyScale.y; - //Debug.Log("Top Margin H1:" + handlePoints[1] + " H2:" + handlePoints[2]); + //Debug.Log("Top Margin H1:" + handlePoints[1] + " H2:" + handlePoints[2]); hasChanged = true; } @@ -395,8 +395,6 @@ protected void DrawTextInput() Rect rect = EditorGUILayout.GetControlRect(false, 22); GUI.Label(rect, new GUIContent("Text Input"), TMP_UIStyleManager.sectionHeader); - EditorGUI.indentLevel = 0; - // If the text component is linked, disable the text input box. if (m_ParentLinkedTextComponentProp.objectReferenceValue != null) { @@ -404,47 +402,50 @@ protected void DrawTextInput() } else { - // Display RTL Toggle - float labelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 110f; - - m_IsRightToLeftProp.boolValue = EditorGUI.Toggle(new Rect(rect.width - 120, rect.y + 3, 130, 20), k_RtlToggleLabel, m_IsRightToLeftProp.boolValue); - - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_TextProp, GUIContent.none); - if (EditorGUI.EndChangeCheck()) + if (EditorGUI.EndChangeCheck() || (m_IsRightToLeftProp.boolValue && string.IsNullOrEmpty(m_RtlText))) { m_TextComponent.m_inputSource = TMP_Text.TextInputSources.Text; m_TextComponent.m_isInputParsingRequired = true; m_HavePropertiesChanged = true; + + // Handle Left to Right or Right to Left Editor + if (m_IsRightToLeftProp.boolValue) + { + m_RtlText = string.Empty; + string sourceText = m_TextProp.stringValue; + + // Reverse Text displayed in Text Input Box + for (int i = 0; i < sourceText.Length; i++) + { + m_RtlText += sourceText[sourceText.Length - i - 1]; + } + } } + // Toggle showing Rich Tags + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 110f; + m_IsRightToLeftProp.boolValue = EditorGUI.Toggle(new Rect(rect.width - 120, rect.y + 3, 130, 20), k_RtlToggleLabel, m_IsRightToLeftProp.boolValue); + EditorGUIUtility.labelWidth = labelWidth; + if (m_IsRightToLeftProp.boolValue) { - // Copy source text to RTL string - m_RtlText = string.Empty; - string sourceText = m_TextProp.stringValue; - - // Reverse Text displayed in Text Input Box - for (int i = 0; i < sourceText.Length; i++) - m_RtlText += sourceText[sourceText.Length - i - 1]; - GUILayout.Label("RTL Text Input"); - EditorGUI.BeginChangeCheck(); m_RtlText = EditorGUILayout.TextArea(m_RtlText, TMP_UIStyleManager.wrappingTextArea, GUILayout.Height(EditorGUI.GetPropertyHeight(m_TextProp) - EditorGUIUtility.singleLineHeight), GUILayout.ExpandWidth(true)); - if (EditorGUI.EndChangeCheck()) { // Convert RTL input - sourceText = string.Empty; + string sourceText = string.Empty; // Reverse Text displayed in Text Input Box for (int i = 0; i < m_RtlText.Length; i++) + { sourceText += m_RtlText[m_RtlText.Length - i - 1]; + } m_TextProp.stringValue = sourceText; } @@ -487,7 +488,7 @@ protected void DrawMainSettings() DrawWrappingOverflow(); DrawTextureMapping(); - + //EditorGUI.indentLevel -= 1; } @@ -564,9 +565,9 @@ void DrawFont() rect.x += rect.width; v7 = TMP_EditorUtility.EditorToggle(rect, (styleValue & 64) == 64, k_StrikethroughLabel, TMP_UIStyleManager.alignmentButtonRight) ? 64 : 0; // Strikethrough rect.x += rect.width; - + int selected = 0; - + EditorGUI.BeginChangeCheck(); v4 = TMP_EditorUtility.EditorToggle(rect, (styleValue & 8) == 8, k_LowercaseLabel, TMP_UIStyleManager.alignmentButtonLeft) ? 8 : 0; // Lowercase if (EditorGUI.EndChangeCheck() && v4 > 0) @@ -616,14 +617,14 @@ void DrawFont() v7 = TMP_EditorUtility.EditorToggle(rect, (styleValue & 64) == 64, k_StrikethroughLabel, TMP_UIStyleManager.alignmentButtonRight) ? 64 : 0; // Strikethrough rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight + 2f); - + rect.x += EditorGUIUtility.labelWidth; rect.width -= EditorGUIUtility.labelWidth; rect.width = Mathf.Max(25f, rect.width / 4f); int selected = 0; - + EditorGUI.BeginChangeCheck(); v4 = TMP_EditorUtility.EditorToggle(rect, (styleValue & 8) == 8, k_LowercaseLabel, TMP_UIStyleManager.alignmentButtonLeft) ? 8 : 0; // Lowercase if (EditorGUI.EndChangeCheck() && v4 > 0) @@ -661,7 +662,7 @@ void DrawFont() // FONT SIZE EditorGUI.BeginChangeCheck(); - + EditorGUI.BeginDisabledGroup(m_AutoSizingProp.boolValue); EditorGUILayout.PropertyField(m_FontSizeProp, k_FontSizeLabel, GUILayout.MaxWidth(EditorGUIUtility.labelWidth + 50f)); EditorGUI.EndDisabledGroup(); @@ -676,7 +677,7 @@ void DrawFont() } EditorGUI.indentLevel += 1; - + EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_AutoSizingProp, k_AutoSizeLabel); if (EditorGUI.EndChangeCheck()) @@ -742,13 +743,13 @@ void DrawFont() m_LineSpacingMaxProp.floatValue = Mathf.Min(0, m_LineSpacingMaxProp.floatValue); m_HavePropertiesChanged = true; } - + EditorGUI.indentLevel = previousIndent; } EditorGUI.indentLevel -= 1; - + EditorGUILayout.Space(); } @@ -757,30 +758,24 @@ void DrawColor() { // FACE VERTEX COLOR EditorGUI.BeginChangeCheck(); - Color vertexColor = EditorGUILayout.ColorField(k_BaseColorLabel, m_FontColorProp.colorValue, false, true, false); - if (EditorGUI.EndChangeCheck()) - { - m_FontColorProp.colorValue = vertexColor; - m_HavePropertiesChanged = true; - } + EditorGUILayout.PropertyField(m_FontColorProp, k_BaseColorLabel); - EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_EnableVertexGradientProp, k_ColorGradientLabel); if (EditorGUI.EndChangeCheck()) { m_HavePropertiesChanged = true; } - + EditorGUIUtility.fieldWidth = 0; if (m_EnableVertexGradientProp.boolValue) { EditorGUI.indentLevel += 1; - + EditorGUI.BeginChangeCheck(); - + EditorGUILayout.PropertyField(m_FontColorGradientPresetProp, k_ColorPresetLabel); - + SerializedObject obj = null; SerializedProperty colorMode; @@ -832,9 +827,9 @@ void DrawColor() TMP_EditorUtility.DrawColorProperty(rect, topLeft); rect.x += rect.width; - + TMP_EditorUtility.DrawColorProperty(rect, topRight); - + bottomLeft.colorValue = topLeft.colorValue; bottomRight.colorValue = topRight.colorValue; break; @@ -843,9 +838,9 @@ void DrawColor() rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2)); rect.x += EditorGUIUtility.labelWidth; - + TMP_EditorUtility.DrawColorProperty(rect, bottomLeft); - + topRight.colorValue = topLeft.colorValue; bottomRight.colorValue = bottomLeft.colorValue; break; @@ -855,13 +850,13 @@ void DrawColor() TMP_EditorUtility.DrawColorProperty(rect, topLeft); rect.x += rect.width; - + TMP_EditorUtility.DrawColorProperty(rect, topRight); rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2)); rect.x += EditorGUIUtility.labelWidth; rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f; - + TMP_EditorUtility.DrawColorProperty(rect, bottomLeft); rect.x += rect.width; @@ -869,7 +864,7 @@ void DrawColor() TMP_EditorUtility.DrawColorProperty(rect, bottomRight); break; } - + if (EditorGUI.EndChangeCheck()) { m_HavePropertiesChanged = true; @@ -882,9 +877,9 @@ void DrawColor() EditorGUI.indentLevel -= 1; } - + EditorGUILayout.PropertyField(m_OverrideHtmlColorProp, k_OverrideTagsLabel); - + EditorGUILayout.Space(); } @@ -892,9 +887,9 @@ void DrawSpacing() { // CHARACTER, LINE & PARAGRAPH SPACING EditorGUI.BeginChangeCheck(); - + Rect rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); - + EditorGUI.PrefixLabel(rect, k_SpacingOptionsLabel); int oldIndent = EditorGUI.indentLevel; @@ -902,9 +897,9 @@ void DrawSpacing() rect.x += EditorGUIUtility.labelWidth; rect.width = (rect.width - EditorGUIUtility.labelWidth - 3f) / 2f; - + EditorGUIUtility.labelWidth = Mathf.Min(rect.width * 0.55f, 80f); - + EditorGUI.PropertyField(rect, m_CharacterSpacingProp, k_CharacterSpacingLabel); rect.x += rect.width + 3f; EditorGUI.PropertyField(rect, m_WordSpacingProp, k_WordSpacingLabel); @@ -964,7 +959,7 @@ void DrawWrappingOverflow() m_HavePropertiesChanged = true; m_TextComponent.m_isInputParsingRequired = true; } - + // TEXT OVERFLOW EditorGUI.BeginChangeCheck(); @@ -978,7 +973,7 @@ void DrawWrappingOverflow() EditorGUIUtility.fieldWidth = fieldWidth; EditorGUILayout.PropertyField(m_LinkedTextComponentProp, GUIContent.none); - + EditorGUILayout.EndHorizontal(); if (GUI.changed) @@ -1087,7 +1082,7 @@ protected void DrawIsTextObjectScaleStatic() protected void DrawRichText() { EditorGUI.BeginChangeCheck(); - + EditorGUILayout.PropertyField(m_IsRichTextProp, k_RichTextLabel); if (EditorGUI.EndChangeCheck()) m_HavePropertiesChanged = true; @@ -1336,4 +1331,4 @@ protected void DrawPropertySlider(GUIContent label, SerializedProperty property) protected abstract void OnUndoRedo(); } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_BaseShaderGUI.cs b/Scripts/Editor/TMP_BaseShaderGUI.cs index 5fd33ce..112d277 100644 --- a/Scripts/Editor/TMP_BaseShaderGUI.cs +++ b/Scripts/Editor/TMP_BaseShaderGUI.cs @@ -176,9 +176,8 @@ public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] pro protected bool BeginPanel(string panel, bool expanded) { - EditorGUI.indentLevel = 0; - EditorGUILayout.BeginVertical(EditorStyles.helpBox); + Rect r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 18)); r.x += 20; r.width += 6; @@ -198,8 +197,6 @@ protected bool BeginPanel(string panel, bool expanded) protected bool BeginPanel(string panel, ShaderFeature feature, bool expanded, bool readState = true) { - EditorGUI.indentLevel = 0; - if (readState) { feature.ReadState(m_Material); @@ -286,7 +283,7 @@ void DoTexture(string name, string label, System.Type type, bool withTilingOffse { MaterialProperty property = FindProperty(name, m_Properties); m_Editor.BeginAnimatedCheck(Rect.zero, property); - + Rect rect = EditorGUILayout.GetControlRect(true, 60f); float totalWidth = rect.width; rect.width = EditorGUIUtility.labelWidth + 60f; @@ -414,7 +411,7 @@ protected void DoColor(string name, string label) { MaterialProperty property = BeginProperty(name); s_TempLabel.text = label; - Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue, false, true, true); + Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue); if (EndProperty()) { property.colorValue = value; diff --git a/Scripts/Editor/TMP_CharacterPropertyDrawer.cs b/Scripts/Editor/TMP_CharacterPropertyDrawer.cs index 98f32c7..c1f5fb9 100644 --- a/Scripts/Editor/TMP_CharacterPropertyDrawer.cs +++ b/Scripts/Editor/TMP_CharacterPropertyDrawer.cs @@ -10,7 +10,11 @@ namespace TMPro.EditorUtilities [CustomPropertyDrawer(typeof(TMP_Character))] public class TMP_CharacterPropertyDrawer : PropertyDrawer { - private string k_ColorProperty = "_Color"; + //[SerializeField] + //static Material s_InternalSDFMaterial; + + //[SerializeField] + //static Material s_InternalBitmapMaterial; int m_GlyphSelectedForEditing = -1; @@ -74,18 +78,18 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { // Get a reference to the font asset TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset; - + // Make sure new glyph index is valid. int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == prop_GlyphIndex.intValue); if (elementIndex == -1) prop_GlyphIndex.intValue = currentGlyphIndex; else - fontAsset.IsFontAssetLookupTablesDirty = true; + fontAsset.m_IsFontAssetLookupTablesDirty = true; } int glyphIndex = prop_GlyphIndex.intValue; - + // Reset glyph selection if new character has been selected. if (GUI.enabled && m_GlyphSelectedForEditing != glyphIndex) m_GlyphSelectedForEditing = -1; @@ -112,7 +116,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { // Get the index of the glyph in the font asset glyph table. int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == glyphIndex); - + if (elementIndex != -1) { SerializedProperty prop_GlyphTable = property.serializedObject.FindProperty("m_GlyphTable"); @@ -142,7 +146,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUIUtility.labelWidth = 39f; EditorGUI.PropertyField(new Rect(rect.x, rect.y + 36, 80, 18), prop_Scale, new GUIContent("Scale:")); - + // Draw Glyph (if exists) DrawGlyph(position, property); } @@ -188,7 +192,7 @@ void DrawGlyph(Rect position, SerializedProperty property) return; mat.mainTexture = atlasTexture; - mat.SetColor(k_ColorProperty, Color.white); + mat.SetColor("_Color", Color.white); } else { @@ -204,14 +208,12 @@ void DrawGlyph(Rect position, SerializedProperty property) // Draw glyph Rect glyphDrawPosition = new Rect(position.x, position.y, 48, 58); - SerializedProperty glyphRectProperty = prop_Glyph.FindPropertyRelative("m_GlyphRect"); - - int padding = fontAsset.atlasPadding; + SerializedProperty prop_GlyphRect = prop_Glyph.FindPropertyRelative("m_GlyphRect"); - int glyphOriginX = glyphRectProperty.FindPropertyRelative("m_X").intValue - padding; - int glyphOriginY = glyphRectProperty.FindPropertyRelative("m_Y").intValue - padding; - int glyphWidth = glyphRectProperty.FindPropertyRelative("m_Width").intValue + padding * 2; - int glyphHeight = glyphRectProperty.FindPropertyRelative("m_Height").intValue + padding * 2; + int glyphOriginX = prop_GlyphRect.FindPropertyRelative("m_X").intValue; + int glyphOriginY = prop_GlyphRect.FindPropertyRelative("m_Y").intValue; + int glyphWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue; + int glyphHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue; float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine; float scale = glyphDrawPosition.width / normalizedHeight; diff --git a/Scripts/Editor/TMP_DropdownEditor.cs b/Scripts/Editor/TMP_DropdownEditor.cs index 48f8e2b..7a5f49a 100644 --- a/Scripts/Editor/TMP_DropdownEditor.cs +++ b/Scripts/Editor/TMP_DropdownEditor.cs @@ -17,7 +17,6 @@ public class DropdownEditor : SelectableEditor SerializedProperty m_ItemImage; SerializedProperty m_OnSelectionChanged; SerializedProperty m_Value; - SerializedProperty m_AlphaFadeSpeed; SerializedProperty m_Options; protected override void OnEnable() @@ -31,7 +30,6 @@ 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"); } @@ -48,10 +46,9 @@ 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_EditorPanel.cs b/Scripts/Editor/TMP_EditorPanel.cs index a03494f..f430407 100644 --- a/Scripts/Editor/TMP_EditorPanel.cs +++ b/Scripts/Editor/TMP_EditorPanel.cs @@ -1,6 +1,5 @@ using UnityEngine; using UnityEditor; -using UnityEditor.Presets; namespace TMPro.EditorUtilities { @@ -12,29 +11,22 @@ public class TMP_EditorPanel : TMP_BaseEditorPanel static readonly GUIContent k_OrderInLayerLabel = new GUIContent("Order in Layer", "Renderer's order within a sorting layer."); static readonly GUIContent k_OrthographicLabel = new GUIContent("Orthographic Mode", "Should be enabled when using an orthographic camera. Instructs the shader to not perform any perspective correction."); static readonly GUIContent k_VolumetricLabel = new GUIContent("Volumetric Setup", "Use cubes rather than quads to render the text. Allows for volumetric rendering when combined with a compatible shader."); - - private static string[] k_SortingLayerNames; - bool IsPreset; - + SerializedProperty m_IsVolumetricTextProp; + SerializedProperty m_IsOrthographicProp; + Renderer m_Renderer; protected override void OnEnable() { base.OnEnable(); - // Determine if the inspected object is a Preset - IsPreset = (int)(target as Component).gameObject.hideFlags == 93; - m_IsOrthographicProp = serializedObject.FindProperty("m_isOrthographic"); - + m_IsVolumetricTextProp = serializedObject.FindProperty("m_isVolumetricText"); m_Renderer = m_TextComponent.GetComponent(); - - // Populate Sorting Layer Names - k_SortingLayerNames = SortingLayerHelper.sortingLayerNames; } protected override void DrawExtraSettings() @@ -59,7 +51,7 @@ protected override void DrawExtraSettings() DrawIsTextObjectScaleStatic(); DrawOrthographicMode(); - + DrawRichText(); DrawParsing(); @@ -84,29 +76,33 @@ protected void DrawSortingLayer() EditorGUI.BeginChangeCheck(); - TextMeshPro textComponent = (TextMeshPro)m_TextComponent; + // SORTING LAYERS + var sortingLayerNames = SortingLayerHelper.sortingLayerNames; + + var textComponent = (TextMeshPro)m_TextComponent; // Look up the layer name using the current layer ID - string oldName = IsPreset ? SortingLayer.IDToName(textComponent._SortingLayerID) : SortingLayer.IDToName(textComponent.sortingLayerID); + string oldName = SortingLayerHelper.GetSortingLayerNameFromID(textComponent.sortingLayerID); // Use the name to look up our array index into the names list - int oldLayerIndex = System.Array.IndexOf(k_SortingLayerNames, oldName); + int oldLayerIndex = System.Array.IndexOf(sortingLayerNames, oldName); // Show the pop-up for the names EditorGUIUtility.fieldWidth = 0f; - int newLayerIndex = EditorGUILayout.Popup(k_SortingLayerLabel, oldLayerIndex, k_SortingLayerNames); - + int newLayerIndex = EditorGUILayout.Popup(k_SortingLayerLabel, oldLayerIndex, sortingLayerNames); + // If the index changes, look up the ID for the new index to store as the new ID if (newLayerIndex != oldLayerIndex) - UpdateTargetsSortingLayerID(SortingLayer.NameToID(k_SortingLayerNames[newLayerIndex])); - - // Get value from internal property if target is a Preset otherwise from the public property - int oldSortingOrder = IsPreset ? textComponent._SortingOrder : textComponent.sortingOrder; - - int newSortingLayerOrder = EditorGUILayout.IntField(k_OrderInLayerLabel, oldSortingOrder); + { + textComponent.sortingLayerID = SortingLayerHelper.GetSortingLayerIDForIndex(newLayerIndex); + } + // Expose the manual sorting order + int newSortingLayerOrder = EditorGUILayout.IntField(k_OrderInLayerLabel, textComponent.sortingOrder); if (newSortingLayerOrder != textComponent.sortingOrder) - UpdateTargetsSortingOrder(newSortingLayerOrder); + { + textComponent.sortingOrder = newSortingLayerOrder; + } if (EditorGUI.EndChangeCheck()) m_HavePropertiesChanged = true; @@ -165,27 +161,5 @@ protected override void OnUndoRedo() } } } - - void UpdateTargetsSortingLayerID(int sortingLayerID) - { - for (int i = 0; i < targets.Length; i++) - { - var textComponent = (TextMeshPro)targets[i]; - - if (textComponent != null) - textComponent.sortingLayerID = sortingLayerID; - } - } - - void UpdateTargetsSortingOrder(int sortingOrder) - { - for (int i = 0; i < targets.Length; i++) - { - var textComponent = (TextMeshPro)targets[i]; - - if (textComponent != null) - textComponent.sortingOrder = sortingOrder; - } - } } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_FontAssetEditor.cs b/Scripts/Editor/TMP_FontAssetEditor.cs index 8cf9a79..bdc34e2 100644 --- a/Scripts/Editor/TMP_FontAssetEditor.cs +++ b/Scripts/Editor/TMP_FontAssetEditor.cs @@ -1,10 +1,14 @@ using UnityEngine; using UnityEditor; using UnityEditorInternal; +using System.Collections; using System.Collections.Generic; using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; + +//#if UNITY_2018_4_5_OR_NEWER using UnityEditor.TextCore.LowLevel; +//#endif namespace TMPro.EditorUtilities @@ -73,7 +77,7 @@ internal static Material internalSDFMaterial { if (s_InternalSDFMaterial == null) { - Shader shader = Shader.Find("Hidden/TMP/Internal/Editor/Distance Field SSD"); + Shader shader = Shader.Find("Hidden/TextMeshPro/Internal/Distance Field SSD"); if (shader != null) s_InternalSDFMaterial = new Material(shader); @@ -143,7 +147,7 @@ private struct Warning private string m_KerningTableSearchPattern; private List m_KerningTableSearchList; - + private bool m_isSearchDirty; private const string k_UndoRedo = "UndoRedoPerformed"; @@ -261,9 +265,6 @@ public void OnEnable() m_GlyphSearchList = new List(); m_KerningTableSearchList = new List(); - - // Sort Font Asset Tables - m_fontAsset.SortAllTables(); } @@ -381,7 +382,11 @@ public override void OnInspectorGUI() Texture2D tex = m_fontAsset.atlasTextures[i]; if (tex != null && tex.isReadable) + { + //#if UNITY_2018_4_5_OR_NEWER FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, false); + //#endif + } } Debug.Log("Atlas Population mode set to [Static]."); @@ -405,7 +410,11 @@ public override void OnInspectorGUI() Texture2D tex = m_fontAsset.atlasTextures[i]; if (tex != null && tex.isReadable == false) + { + //#if UNITY_2018_4_5_OR_NEWER FontEngineEditorUtilities.SetAtlasTextureIsReadable(tex, true); + //#endif + } } Debug.Log("Atlas Population mode set to [Dynamic]."); @@ -489,7 +498,7 @@ public override void OnInspectorGUI() } } - m_fontAsset.UpdateFontAssetData(); + m_fontAsset.ClearFontAssetData(); GUIUtility.keyboardControl = 0; isAssetDirty = true; @@ -563,7 +572,7 @@ public override void OnInspectorGUI() GUI.Label(rect, "Regular Typeface", EditorStyles.label); rect.x += rect.width; GUI.Label(rect, "Italic Typeface", EditorStyles.label); - + EditorGUI.indentLevel = 1; EditorGUILayout.PropertyField(fontWeights_prop.GetArrayElementAtIndex(1), new GUIContent("100 - Thin")); @@ -605,7 +614,7 @@ public override void OnInspectorGUI() m_materialPresets[i].SetFloat("_WeightBold", font_boldStyle_prop.floatValue); } EditorGUILayout.EndHorizontal(); - + EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(font_normalSpacing_prop, new GUIContent("Spacing Offset")); font_normalSpacing_prop.floatValue = Mathf.Clamp(font_normalSpacing_prop.floatValue, -100, 100); @@ -621,11 +630,11 @@ public override void OnInspectorGUI() GUI.changed = false; } EditorGUILayout.EndHorizontal(); - + EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(font_italicStyle_prop, new GUIContent("Italic Style")); font_italicStyle_prop.intValue = Mathf.Clamp(font_italicStyle_prop.intValue, 15, 60); - + EditorGUILayout.PropertyField(font_tabSize_prop, new GUIContent("Tab Multiple")); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); @@ -662,9 +671,7 @@ public override void OnInspectorGUI() EditorGUI.indentLevel = 0; rect = EditorGUILayout.GetControlRect(false, 24); - int characterCount = m_fontAsset.characterTable.Count; - - if (GUI.Button(rect, new GUIContent("Character Table [" + characterCount + "]" + (rect.width > 320 ? " Characters" : ""), "List of characters contained in this font asset."), TMP_UIStyleManager.sectionHeader)) + if (GUI.Button(rect, new GUIContent("Character Table", "List of characters contained in this font asset."), TMP_UIStyleManager.sectionHeader)) UI_PanelState.characterTablePanel = !UI_PanelState.characterTablePanel; GUI.Label(rect, (UI_PanelState.characterTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel); @@ -861,9 +868,7 @@ public override void OnInspectorGUI() GUIStyle glyphPanelStyle = new GUIStyle(EditorStyles.helpBox); - int glyphCount = m_fontAsset.glyphTable.Count; - - if (GUI.Button(rect, new GUIContent("Glyph Table [" + glyphCount + "]" + (rect.width > 275 ? " Glyphs" : ""), "List of glyphs contained in this font asset."), TMP_UIStyleManager.sectionHeader)) + if (GUI.Button(rect, new GUIContent("Glyph Table", "List of glyphs contained in this font asset."), TMP_UIStyleManager.sectionHeader)) UI_PanelState.glyphTablePanel = !UI_PanelState.glyphTablePanel; GUI.Label(rect, (UI_PanelState.glyphTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel); @@ -917,7 +922,7 @@ public override void OnInspectorGUI() EditorGUILayout.EndVertical(); // Display Glyph Table Elements - + if (arraySize > 0) { // Display each GlyphInfo entry using the GlyphInfo property drawer. @@ -1058,9 +1063,7 @@ public override void OnInspectorGUI() EditorGUI.indentLevel = 0; rect = EditorGUILayout.GetControlRect(false, 24); - int adjustmentPairCount = m_fontAsset.fontFeatureTable.glyphPairAdjustmentRecords.Count; - - if (GUI.Button(rect, new GUIContent("Glyph Adjustment Table [" + adjustmentPairCount + "]" + (rect.width > 340 ? " Records" : ""), "List of glyph adjustment / advanced kerning pairs."), TMP_UIStyleManager.sectionHeader)) + if (GUI.Button(rect, new GUIContent("Glyph Adjustment Table", "List of glyph adjustment / advanced kerning pairs."), TMP_UIStyleManager.sectionHeader)) UI_PanelState.fontFeatureTablePanel = !UI_PanelState.fontFeatureTablePanel; GUI.Label(rect, (UI_PanelState.fontFeatureTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel); @@ -1263,7 +1266,7 @@ public override void OnInspectorGUI() if (m_DisplayDestructiveChangeWarning == false) TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, m_fontAsset); - if (m_fontAsset.IsFontAssetLookupTablesDirty || evt_cmd == k_UndoRedo) + if (m_fontAsset.m_IsFontAssetLookupTablesDirty || evt_cmd == k_UndoRedo) m_fontAsset.ReadFontAssetDefinition(); isAssetDirty = false; @@ -1271,7 +1274,7 @@ public override void OnInspectorGUI() } - // Clear selection if mouse event was not consumed. + // Clear selection if mouse event was not consumed. GUI.enabled = true; if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0) m_SelectedAdjustmentRecord = -1; @@ -1408,7 +1411,7 @@ void DisplayPageNavigation(ref int currentPage, int arraySize, int itemsPerPage) /// - /// + /// /// /// /// @@ -1444,7 +1447,7 @@ bool AddNewGlyph(int srcIndex, int dstGlyphID) } /// - /// + /// /// /// void RemoveGlyphFromList(int index) @@ -1561,7 +1564,7 @@ void RemoveAdjustmentPairFromList(int index) } /// - /// + /// /// /// /// @@ -1608,7 +1611,7 @@ void CopyCharacterSerializedProperty(SerializedProperty source, ref SerializedPr /// - /// + /// /// /// /// @@ -1664,7 +1667,7 @@ void SearchCharacterTable(string searchPattern, ref List searchResults) searchResults.Add(i); else if (id.ToString("X").Contains(searchPattern)) searchResults.Add(i); - + // Check for potential match against decimal id //if (id.ToString().Contains(searchPattern)) // searchResults.Add(i); @@ -1714,4 +1717,4 @@ void SearchKerningTable(string searchPattern, ref List searchResults) } } } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_FontAsset_CreationMenu.cs b/Scripts/Editor/TMP_FontAsset_CreationMenu.cs index 344965c..7d5edfa 100644 --- a/Scripts/Editor/TMP_FontAsset_CreationMenu.cs +++ b/Scripts/Editor/TMP_FontAsset_CreationMenu.cs @@ -161,22 +161,15 @@ public static void CreateFontAsset() string newAssetFilePathWithName = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + " SDF.asset"); - // Initialize FontEngine - FontEngine.InitializeFontEngine(); - - // Load Font Face - if (FontEngine.LoadFontFace(sourceFont, 90) != FontEngineError.Success) - { - Debug.LogWarning("Unable to load font face for [" + sourceFont.name + "]. Make sure \"Include Font Data\" is enabled in the Font Import Settings.", sourceFont); - return; - } - - // Create new Font Asset + //// Create new TM Font Asset. TMP_FontAsset fontAsset = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(fontAsset, newAssetFilePathWithName); fontAsset.version = "1.1.0"; + // Set face information + FontEngine.InitializeFontEngine(); + FontEngine.LoadFontFace(sourceFont, 90); fontAsset.faceInfo = FontEngine.GetFaceInfo(); // Set font reference and GUID diff --git a/Scripts/Editor/TMP_GlyphPairAdjustmentRecordPropertyDrawer.cs b/Scripts/Editor/TMP_GlyphPairAdjustmentRecordPropertyDrawer.cs index 69ac6f8..fd4eb3e 100644 --- a/Scripts/Editor/TMP_GlyphPairAdjustmentRecordPropertyDrawer.cs +++ b/Scripts/Editor/TMP_GlyphPairAdjustmentRecordPropertyDrawer.cs @@ -316,7 +316,7 @@ uint GetUnicodeCharacter (string source) void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property) { - // Get a reference to the font asset + // Get a reference to the sprite texture TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset; if (fontAsset == null) @@ -324,12 +324,12 @@ void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property) Glyph glyph; - // Check if glyph is present in the atlas texture. + // Check if glyph currently exists in the atlas texture. if (!fontAsset.glyphLookupTable.TryGetValue(glyphIndex, out glyph)) return; - // Get the atlas index of the glyph and lookup its atlas texture - int atlasIndex = glyph.atlasIndex; + // Get reference to atlas texture. + int atlasIndex = fontAsset.m_AtlasTextureIndex; Texture2D atlasTexture = fontAsset.atlasTextures.Length > atlasIndex ? fontAsset.atlasTextures[atlasIndex] : null; if (atlasTexture == null) @@ -361,25 +361,18 @@ void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property) GlyphRect glyphRect = glyph.glyphRect; - int padding = fontAsset.atlasPadding; - - int glyphOriginX = glyphRect.x - padding; - int glyphOriginY = glyphRect.y - padding; - int glyphWidth = glyphRect.width + padding * 2; - int glyphHeight = glyphRect.height + padding * 2; - float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine; float scale = glyphDrawPosition.width / normalizedHeight; // Compute the normalized texture coordinates - Rect texCoords = new Rect((float)glyphOriginX / atlasTexture.width, (float)glyphOriginY / atlasTexture.height, (float)glyphWidth / atlasTexture.width, (float)glyphHeight / atlasTexture.height); + Rect texCoords = new Rect((float)glyphRect.x / atlasTexture.width, (float)glyphRect.y / atlasTexture.height, (float)glyphRect.width / atlasTexture.width, (float)glyphRect.height / atlasTexture.height); if (Event.current.type == EventType.Repaint) { - glyphDrawPosition.x += (glyphDrawPosition.width - glyphWidth * scale) / 2; - glyphDrawPosition.y += (glyphDrawPosition.height - glyphHeight * scale) / 2; - glyphDrawPosition.width = glyphWidth * scale; - glyphDrawPosition.height = glyphHeight * scale; + glyphDrawPosition.x += (glyphDrawPosition.width - glyphRect.width * scale) / 2; + glyphDrawPosition.y += (glyphDrawPosition.height - glyphRect.height * scale) / 2; + glyphDrawPosition.width = glyphRect.width * scale; + glyphDrawPosition.height = glyphRect.height * scale; // Could switch to using the default material of the font asset which would require passing scale to the shader. Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(1f, 1f, 1f), mat); @@ -388,4 +381,4 @@ void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property) } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_GlyphPropertyDrawer.cs b/Scripts/Editor/TMP_GlyphPropertyDrawer.cs index d8d3700..b92dfd6 100644 --- a/Scripts/Editor/TMP_GlyphPropertyDrawer.cs +++ b/Scripts/Editor/TMP_GlyphPropertyDrawer.cs @@ -1,4 +1,4 @@ -using UnityEngine; + using UnityEngine; using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; using UnityEditor; @@ -11,8 +11,6 @@ namespace TMPro.EditorUtilities [CustomPropertyDrawer(typeof(Glyph))] public class TMP_GlyphPropertyDrawer : PropertyDrawer { - private string k_ColorProperty = "_Color"; - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SerializedProperty prop_GlyphIndex = property.FindPropertyRelative("m_Index"); @@ -75,7 +73,7 @@ void DrawGlyph(Rect position, SerializedProperty property) return; mat.mainTexture = atlasTexture; - mat.SetColor(k_ColorProperty, Color.white); + mat.SetColor("_Color", Color.white); } else { @@ -91,14 +89,12 @@ void DrawGlyph(Rect position, SerializedProperty property) // Draw glyph from atlas texture. Rect glyphDrawPosition = new Rect(position.x, position.y + 2, 64, 80); - SerializedProperty glyphRectProperty = property.FindPropertyRelative("m_GlyphRect"); - - int padding = fontAsset.atlasPadding; + SerializedProperty prop_GlyphRect = property.FindPropertyRelative("m_GlyphRect"); - int glyphOriginX = glyphRectProperty.FindPropertyRelative("m_X").intValue - padding; - int glyphOriginY = glyphRectProperty.FindPropertyRelative("m_Y").intValue - padding; - int glyphWidth = glyphRectProperty.FindPropertyRelative("m_Width").intValue + padding * 2; - int glyphHeight = glyphRectProperty.FindPropertyRelative("m_Height").intValue + padding * 2; + int glyphOriginX = prop_GlyphRect.FindPropertyRelative("m_X").intValue; + int glyphOriginY = prop_GlyphRect.FindPropertyRelative("m_Y").intValue; + int glyphWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue; + int glyphHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue; float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine; float scale = glyphDrawPosition.width / normalizedHeight; diff --git a/Scripts/Editor/TMP_PackageUtilities.cs b/Scripts/Editor/TMP_PackageUtilities.cs index 5768525..21ca101 100644 --- a/Scripts/Editor/TMP_PackageUtilities.cs +++ b/Scripts/Editor/TMP_PackageUtilities.cs @@ -39,7 +39,7 @@ class AssetConversionData public class TMP_ProjectConversionUtility : EditorWindow { - // Create Project Files GUID Remapping Tool window + // Create Sprite Asset Editor Window [MenuItem("Window/TextMeshPro/Project Files GUID Remapping Tool", false, 2100)] static void ShowConverterWindow() { @@ -81,7 +81,7 @@ static void ShowConverterWindow() }; /// - /// + /// /// struct AssetModificationRecord { @@ -234,7 +234,7 @@ void SetEditorWindowSize() /// - /// + /// /// /// /// @@ -402,7 +402,7 @@ static void ScanProjectFileAsync(AssetFileRecord fileRecord) /// - /// + /// /// private static void ResetScanProcess() { @@ -415,7 +415,7 @@ private static void ResetScanProcess() /// - /// + /// /// private static void UpdateProjectFiles() { @@ -484,7 +484,7 @@ struct AssetModificationRecord } /// - /// + /// /// [MenuItem("Window/TextMeshPro/Import TMP Essential Resources", false, 2050)] public static void ImportProjectResourcesMenu() @@ -494,7 +494,7 @@ public static void ImportProjectResourcesMenu() /// - /// + /// /// [MenuItem("Window/TextMeshPro/Import TMP Examples and Extras", false, 2051)] public static void ImportExamplesContentMenu() @@ -511,56 +511,24 @@ private static void GetVersionInfo() /// - /// + /// /// private static void ImportExamplesAndExtras() { - string packageFullPath = TMP_EditorUtility.packageFullPath; + string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath; AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Examples & Extras.unitypackage", true); } - private static string k_SettingsFilePath; - private static byte[] k_SettingsBackup; /// - /// + /// /// private static void ImportEssentialResources() { - // Check if the TMP Settings asset is already present in the project. - string[] settings = AssetDatabase.FindAssets("t:TMP_Settings"); - - if (settings.Length > 0) - { - // Save assets just in case the TMP Setting were modified before import. - AssetDatabase.SaveAssets(); - - // Copy existing TMP Settings asset to a byte[] - k_SettingsFilePath = AssetDatabase.GUIDToAssetPath(settings[0]); - k_SettingsBackup = File.ReadAllBytes(k_SettingsFilePath); - - RegisterResourceImportCallback(); - } - - string packageFullPath = TMP_EditorUtility.packageFullPath; + string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath; AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Essential Resources.unitypackage", true); } - - private static void RegisterResourceImportCallback() - { - AssetDatabase.importPackageCompleted += ImportCallback; - } - - private static void ImportCallback(string packageName) - { - // Restore backup of TMP Settings from byte[] - File.WriteAllBytes(k_SettingsFilePath, k_SettingsBackup); - - AssetDatabase.Refresh(); - - AssetDatabase.importPackageCompleted -= ImportCallback; - } } } diff --git a/Scripts/Editor/TMP_SettingsEditor.cs b/Scripts/Editor/TMP_SettingsEditor.cs index e4b8d5c..f7bf4b7 100644 --- a/Scripts/Editor/TMP_SettingsEditor.cs +++ b/Scripts/Editor/TMP_SettingsEditor.cs @@ -44,11 +44,10 @@ internal class Styles public static readonly GUIContent getFontFeaturesAtRuntime = new GUIContent("Get Font Features at Runtime", "Determines if Glyph Adjustment Data will be retrieved from font files at runtime when new characters and glyphs are added to font assets."); public static readonly GUIContent dynamicAtlasTextureGroup = new GUIContent("Dynamic Atlas Texture Group"); - public static readonly GUIContent missingGlyphLabel = new GUIContent("Missing Character Unicode", "The character to be displayed when the requested character is not found in any font asset or fallbacks."); + public static readonly GUIContent missingGlyphLabel = new GUIContent("Replacement Character", "The character to be displayed when the requested character is not found in any font asset or fallbacks."); public static readonly GUIContent disableWarningsLabel = new GUIContent("Disable warnings", "Disable warning messages in the Console."); public static readonly GUIContent defaultSpriteAssetLabel = new GUIContent("Default Sprite Asset", "The Sprite Asset that will be assigned by default when using the tag when no Sprite Asset is specified."); - public static readonly GUIContent missingSpriteCharacterUnicodeLabel = new GUIContent("Missing Sprite Unicode", "The unicode value for the sprite character to be displayed when the requested sprite character is not found in any sprite assets or fallbacks."); public static readonly GUIContent enableEmojiSupportLabel = new GUIContent("iOS Emoji Support", "Enables Emoji support for Touch Screen Keyboards on target devices."); //public static readonly GUIContent spriteRelativeScale = new GUIContent("Relative Scaling", "Determines if the sprites will be scaled relative to the primary font asset assigned to the text object or relative to the current font asset."); @@ -75,7 +74,6 @@ internal class Styles SerializedProperty m_PropEnableRaycastTarget; SerializedProperty m_PropSpriteAsset; - SerializedProperty m_PropMissingSpriteCharacterUnicode; //SerializedProperty m_PropSpriteRelativeScaling; SerializedProperty m_PropEnableEmojiSupport; SerializedProperty m_PropSpriteAssetPath; @@ -104,8 +102,6 @@ internal class Styles SerializedProperty m_PropFollowingCharacters; SerializedProperty m_PropUseModernHangulLineBreakingRules; - private const string k_UndoRedo = "UndoRedoPerformed"; - public void OnEnable() { if (target == null) @@ -122,7 +118,6 @@ public void OnEnable() m_PropEnableRaycastTarget = serializedObject.FindProperty("m_EnableRaycastTarget"); m_PropSpriteAsset = serializedObject.FindProperty("m_defaultSpriteAsset"); - m_PropMissingSpriteCharacterUnicode = serializedObject.FindProperty("m_MissingCharacterSpriteUnicode"); //m_PropSpriteRelativeScaling = serializedObject.FindProperty("m_SpriteRelativeScaling"); m_PropEnableEmojiSupport = serializedObject.FindProperty("m_enableEmojiSupport"); m_PropSpriteAssetPath = serializedObject.FindProperty("m_defaultSpriteAssetPath"); @@ -169,7 +164,6 @@ public void OnEnable() public override void OnInspectorGUI() { serializedObject.Update(); - string evt_cmd = Event.current.commandName; float labelWidth = EditorGUIUtility.labelWidth; float fieldWidth = EditorGUIUtility.fieldWidth; @@ -265,7 +259,6 @@ public override void OnInspectorGUI() GUILayout.Label(Styles.defaultSpriteAssetLabel, EditorStyles.boldLabel); EditorGUI.indentLevel = 1; EditorGUILayout.PropertyField(m_PropSpriteAsset, Styles.defaultSpriteAssetLabel); - EditorGUILayout.PropertyField(m_PropMissingSpriteCharacterUnicode, Styles.missingSpriteCharacterUnicodeLabel); EditorGUILayout.PropertyField(m_PropEnableEmojiSupport, Styles.enableEmojiSupportLabel); //EditorGUILayout.PropertyField(m_PropSpriteRelativeScaling, Styles.spriteRelativeScale); EditorGUILayout.PropertyField(m_PropSpriteAssetPath, Styles.spriteAssetsPathLabel); @@ -320,7 +313,7 @@ public override void OnInspectorGUI() EditorGUILayout.Space(); EditorGUILayout.EndVertical(); - if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo) + if (serializedObject.ApplyModifiedProperties()) { EditorUtility.SetDirty(target); TMPro_EventManager.ON_TMP_SETTINGS_CHANGED(); diff --git a/Scripts/Editor/TMP_SpriteAssetImporter.cs b/Scripts/Editor/TMP_SpriteAssetImporter.cs index 5408c6f..3bcb0e3 100644 --- a/Scripts/Editor/TMP_SpriteAssetImporter.cs +++ b/Scripts/Editor/TMP_SpriteAssetImporter.cs @@ -52,7 +52,7 @@ void DrawEditorPanel() m_JsonFile = EditorGUILayout.ObjectField("Sprite Data Source", m_JsonFile, typeof(TextAsset), false) as TextAsset; m_SpriteDataFormat = (SpriteAssetImportFormats)EditorGUILayout.EnumPopup("Import Format", m_SpriteDataFormat); - + // Sprite Texture Selection m_SpriteAtlas = EditorGUILayout.ObjectField("Sprite Texture Atlas", m_SpriteAtlas, typeof(Texture2D), false) as Texture2D; @@ -142,7 +142,7 @@ void DrawEditorPanel() /// - /// + /// /// /// /// @@ -151,8 +151,6 @@ 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]; @@ -161,14 +159,13 @@ 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)(atlasHeight - spriteData.frame.h - spriteData.frame.y), (int)spriteData.frame.w, (int)spriteData.frame.h); + spriteGlyph.glyphRect = new GlyphRect((int)spriteData.frame.x, (int)spriteData.frame.y, (int)spriteData.frame.w, (int)spriteData.frame.h); spriteGlyph.scale = 1.0f; spriteGlyphTable.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph); spriteCharacter.name = spriteData.filename.Split('.')[0]; - spriteCharacter.unicode = 0xFFFE; spriteCharacter.scale = 1.0f; spriteCharacterTable.Add(spriteCharacter); @@ -177,7 +174,7 @@ private static void PopulateSpriteTables(TexturePacker_JsonArray.SpriteDataObjec /// - /// + /// /// /// void SaveSpriteAsset(string filePath) @@ -240,4 +237,4 @@ void SetEditorWindowSize() } } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_SpriteAssetMenu.cs b/Scripts/Editor/TMP_SpriteAssetMenu.cs index 0e46711..1e0994e 100644 --- a/Scripts/Editor/TMP_SpriteAssetMenu.cs +++ b/Scripts/Editor/TMP_SpriteAssetMenu.cs @@ -14,8 +14,14 @@ namespace TMPro.EditorUtilities public static class TMP_SpriteAssetMenu { // Add a Context Menu to the Sprite Asset Editor Panel to Create and Add a Default Material. + [MenuItem("CONTEXT/TMP_SpriteAsset/Add Default Material", true, 2200)] + static bool AddDefaultMaterialValidate(MenuCommand command) + { + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/TMP_SpriteAsset/Add Default Material", false, 2200)] - static void CopyTexture(MenuCommand command) + static void AddDefaultMaterial(MenuCommand command) { TMP_SpriteAsset spriteAsset = (TMP_SpriteAsset)command.context; @@ -28,6 +34,12 @@ static void CopyTexture(MenuCommand command) } // Add a Context Menu to the Sprite Asset Editor Panel to update existing sprite assets. + [MenuItem("CONTEXT/TMP_SpriteAsset/Update Sprite Asset", true, 2100)] + static bool UpdateSpriteAssetValidate(MenuCommand command) + { + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/TMP_SpriteAsset/Update Sprite Asset", false, 2100)] static void UpdateSpriteAsset(MenuCommand command) { @@ -40,7 +52,7 @@ static void UpdateSpriteAsset(MenuCommand command) } internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset) - { + { // Get a list of all the sprites contained in the texture referenced by the sprite asset. // This only works if the texture is set to sprite mode. string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet); @@ -98,7 +110,7 @@ internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset) spriteGlyphTable.Add(spriteGlyph); - TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph); + TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; @@ -117,14 +129,6 @@ internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset) } } - // Update Sprite Character Table to replace unicode 0x0 by 0xFFFE - for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++) - { - TMP_SpriteCharacter spriteCharacter = spriteAsset.spriteCharacterTable[i]; - if (spriteCharacter.unicode == 0) - spriteCharacter.unicode = 0xFFFE; - } - // Sort glyph table by glyph index spriteAsset.SortGlyphTable(); spriteAsset.UpdateLookupTables(); @@ -197,7 +201,7 @@ public static void CreateSpriteAsset() // Get the Sprites contained in the Sprite Sheet EditorUtility.SetDirty(spriteAsset); - + //spriteAsset.sprites = sprites; // Set source texture back to Not Readable. @@ -214,12 +218,12 @@ public static void CreateSpriteAsset() private static void PopulateSpriteTables(Texture source, ref List spriteCharacterTable, ref List spriteGlyphTable) { //Debug.Log("Creating new Sprite Asset."); - + string filePath = AssetDatabase.GetAssetPath(source); // Get all the Sprites sorted by Index Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray(); - + for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; @@ -233,7 +237,7 @@ private static void PopulateSpriteTables(Texture source, ref List UpdateSpriteInfo(TMP_SpriteAsset spriteAsset) for (int j = 0; j < ids.Length; j++ ) { if (ids[0] != 0) break; - + if (j > 0 && (ids[j] - ids[j - 1]) > 1) { id = ids[j - 1] + 1; @@ -366,6 +370,6 @@ private static List UpdateSpriteInfo(TMP_SpriteAsset spriteAsset) return spriteAsset.spriteInfoList; } - + } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMP_SubMesh_Editor.cs b/Scripts/Editor/TMP_SubMesh_Editor.cs index f668af9..b5a3cc7 100644 --- a/Scripts/Editor/TMP_SubMesh_Editor.cs +++ b/Scripts/Editor/TMP_SubMesh_Editor.cs @@ -15,15 +15,13 @@ private struct m_foldout //public static bool shadowSetting = false; //public static bool materialEditor = true; } - + private SerializedProperty fontAsset_prop; private SerializedProperty spriteAsset_prop; private TMP_SubMesh m_SubMeshComponent; private Renderer m_Renderer; - private string[] m_SortingLayerNames; - public void OnEnable() { fontAsset_prop = serializedObject.FindProperty("m_fontAsset"); @@ -32,40 +30,47 @@ public void OnEnable() m_SubMeshComponent = target as TMP_SubMesh; m_Renderer = m_SubMeshComponent.renderer; - - m_SortingLayerNames = SortingLayerHelper.sortingLayerNames; } public override void OnInspectorGUI() { EditorGUI.indentLevel = 0; - + GUI.enabled = false; EditorGUILayout.PropertyField(fontAsset_prop); EditorGUILayout.PropertyField(spriteAsset_prop); GUI.enabled = true; - + EditorGUI.BeginChangeCheck(); + // SORTING LAYERS + var sortingLayerNames = SortingLayerHelper.sortingLayerNames; + // Look up the layer name using the current layer ID - string oldName = SortingLayer.IDToName(m_Renderer.sortingLayerID); + string oldName = SortingLayerHelper.GetSortingLayerNameFromID(m_Renderer.sortingLayerID); // Use the name to look up our array index into the names list - int oldLayerIndex = System.Array.IndexOf(m_SortingLayerNames, oldName); + int oldLayerIndex = System.Array.IndexOf(sortingLayerNames, oldName); // Show the pop-up for the names - int newLayerIndex = EditorGUILayout.Popup("Sorting Layer", oldLayerIndex, m_SortingLayerNames); + int newLayerIndex = EditorGUILayout.Popup("Sorting Layer", oldLayerIndex, sortingLayerNames); // If the index changes, look up the ID for the new index to store as the new ID if (newLayerIndex != oldLayerIndex) - m_Renderer.sortingLayerID = SortingLayer.NameToID(m_SortingLayerNames[newLayerIndex]); + { + //Undo.RecordObject(renderer, "Edit Sorting Layer"); + m_Renderer.sortingLayerID = SortingLayerHelper.GetSortingLayerIDForIndex(newLayerIndex); + //EditorUtility.SetDirty(renderer); + } // Expose the manual sorting order int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", m_Renderer.sortingOrder); if (newSortingLayerOrder != m_Renderer.sortingOrder) + { + //Undo.RecordObject(renderer, "Edit Sorting Order"); m_Renderer.sortingOrder = newSortingLayerOrder; - + } } } } diff --git a/Scripts/Editor/TMPro_ContextMenus.cs b/Scripts/Editor/TMPro_ContextMenus.cs index 21410f4..7960219 100644 --- a/Scripts/Editor/TMPro_ContextMenus.cs +++ b/Scripts/Editor/TMPro_ContextMenus.cs @@ -46,18 +46,13 @@ static void DuplicateMaterial(MenuCommand command) Material source_Mat = (Material)command.context; if (!EditorUtility.IsPersistent(source_Mat)) { - Debug.LogWarning("Material is an instance and cannot be converted into a persistent asset."); + Debug.LogWarning("Material is an instance and cannot be converted into a permanent asset."); return; } - string assetPath = AssetDatabase.GetAssetPath(source_Mat).Split('.')[0]; - if (assetPath.IndexOf("Assets/", System.StringComparison.InvariantCultureIgnoreCase) == -1) - { - Debug.LogWarning("Material Preset cannot be created from a material that is located outside the project."); - return; - } - + string assetPath = AssetDatabase.GetAssetPath(source_Mat).Split('.')[0]; + Material duplicate = new Material(source_Mat); // Need to manually copy the shader keywords @@ -118,8 +113,16 @@ static void CopyMaterialProperties(MenuCommand command) } - // PASTE MATERIAL - //[MenuItem("CONTEXT/MaterialComponent/Paste Material Properties", false)] + // PASTE MATERIAL PROPERTIES + [MenuItem("CONTEXT/Material/Paste Material Properties", true)] + static bool PasteMaterialPropertiesValidate(MenuCommand command) + { + if (m_copiedProperties == null) + return false; + + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/Material/Paste Material Properties", false)] static void PasteMaterialProperties(MenuCommand command) { @@ -160,6 +163,12 @@ static void PasteMaterialProperties(MenuCommand command) // Enable Resetting of Material properties without losing unique properties of the font atlas. + [MenuItem("CONTEXT/Material/Reset", true, 2100)] + static bool ResetSettingsValidate(MenuCommand command) + { + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/Material/Reset", false, 2100)] static void ResetSettings(MenuCommand command) { @@ -236,6 +245,15 @@ static void CopyAtlas(MenuCommand command) // This function is used for debugging and fixing potentially broken font atlas links + [MenuItem("CONTEXT/Material/Paste Atlas", true, 2001)] + static bool PasteAtlasValidate(MenuCommand command) + { + if (m_copiedAtlasProperties == null && m_copiedTexture == null) + return false; + + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/Material/Paste Atlas", false, 2001)] static void PasteAtlas(MenuCommand command) { @@ -325,6 +343,12 @@ static void ForceFontAssetUpgrade(MenuCommand command) /// Clear Dynamic Font Asset data such as glyph, character and font features. /// /// + [MenuItem("CONTEXT/TMP_FontAsset/Reset", true, 100)] + static bool ClearFontAssetDataValidate(MenuCommand command) + { + return AssetDatabase.IsOpenForEdit(command.context); + } + [MenuItem("CONTEXT/TMP_FontAsset/Reset", false, 100)] static void ClearFontAssetData(MenuCommand command) { diff --git a/Scripts/Editor/TMPro_CreateObjectMenu.cs b/Scripts/Editor/TMPro_CreateObjectMenu.cs index 99b83a6..358333e 100644 --- a/Scripts/Editor/TMPro_CreateObjectMenu.cs +++ b/Scripts/Editor/TMPro_CreateObjectMenu.cs @@ -1,6 +1,5 @@ using UnityEngine; using UnityEditor; -using UnityEditor.Presets; using UnityEditor.SceneManagement; using UnityEditor.Experimental.SceneManagement; using UnityEngine.SceneManagement; @@ -20,59 +19,18 @@ public static class TMPro_CreateObjectMenu [MenuItem("GameObject/3D Object/Text - TextMeshPro", false, 30)] static void CreateTextMeshProObjectPerform(MenuCommand command) { - GameObject go = ObjectFactory.CreateGameObject("Text (TMP)"); + GameObject go = new GameObject("Text (TMP)"); // Add support for new prefab mode StageUtility.PlaceGameObjectInCurrentStage(go); - TextMeshPro textComponent = ObjectFactory.AddComponent(go); + TextMeshPro textMeshPro = go.AddComponent(); + textMeshPro.text = "Sample text"; + textMeshPro.alignment = TextAlignmentOptions.TopLeft; - if (textComponent.m_isWaitingOnResourceLoad == false) - { - // Get reference to potential Presets for component - #if UNITY_2019_3_OR_NEWER - Preset[] presets = Preset.GetDefaultPresetsForObject(textComponent); - - if (presets == null || presets.Length == 0) - { - textComponent.text = "Sample text"; - textComponent.alignment = TextAlignmentOptions.TopLeft; - } - else - { - textComponent.renderer.sortingLayerID = textComponent._SortingLayerID; - textComponent.renderer.sortingOrder = textComponent._SortingOrder; - } - #else - if (Preset.GetDefaultForObject(textComponent) == null) - { - textComponent.text = "Sample text"; - textComponent.alignment = TextAlignmentOptions.TopLeft; - } - else - { - textComponent.renderer.sortingLayerID = textComponent._SortingLayerID; - textComponent.renderer.sortingOrder = textComponent._SortingOrder; - } - #endif - - if (TMP_Settings.autoSizeTextContainer) - { - Vector2 size = textComponent.GetPreferredValues(TMP_Math.FLOAT_MAX, TMP_Math.FLOAT_MAX); - textComponent.rectTransform.sizeDelta = size; - } - else - { - textComponent.rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProTextContainerSize; - } - } - else - { - textComponent.text = "Sample text"; - textComponent.alignment = TextAlignmentOptions.TopLeft; - } + - Undo.RegisterCreatedObjectUndo(go, "Create " + go.name); + Undo.RegisterCreatedObjectUndo((Object)go, "Create " + go.name); GameObject contextObject = command.context as GameObject; if (contextObject != null) @@ -95,51 +53,16 @@ static void CreateTextMeshProGuiObjectPerform(MenuCommand menuCommand) GameObject go = TMP_DefaultControls.CreateText(GetStandardResources()); // Override text color and font size - TextMeshProUGUI textComponent = go.GetComponent(); - + TMP_Text textComponent = go.GetComponent(); + textComponent.color = Color.white; if (textComponent.m_isWaitingOnResourceLoad == false) - { - // Get reference to potential Presets for component - #if UNITY_2019_3_OR_NEWER - Preset[] presets = Preset.GetDefaultPresetsForObject(textComponent); - - if (presets == null || presets.Length == 0) - { - textComponent.fontSize = TMP_Settings.defaultFontSize; - textComponent.color = Color.white; - textComponent.text = "New Text"; - } - #else - if (Preset.GetDefaultForObject(textComponent) == null) - { - textComponent.fontSize = TMP_Settings.defaultFontSize; - textComponent.color = Color.white; - textComponent.text = "New Text"; - } - #endif - - if (TMP_Settings.autoSizeTextContainer) - { - Vector2 size = textComponent.GetPreferredValues(TMP_Math.FLOAT_MAX, TMP_Math.FLOAT_MAX); - textComponent.rectTransform.sizeDelta = size; - } - else - { - textComponent.rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProUITextContainerSize; - } - } - else - { - textComponent.fontSize = 36; - textComponent.color = Color.white; - textComponent.text = "New Text"; - } + textComponent.fontSize = TMP_Settings.defaultFontSize; PlaceUIElementRoot(go, menuCommand); } [MenuItem("GameObject/UI/Button - TextMeshPro", false, 2031)] - public static void AddButton(MenuCommand menuCommand) + static public void AddButton(MenuCommand menuCommand) { GameObject go = TMP_DefaultControls.CreateButton(GetStandardResources()); @@ -161,7 +84,7 @@ static void AddTextMeshProInputField(MenuCommand menuCommand) [MenuItem("GameObject/UI/Dropdown - TextMeshPro", false, 2036)] - public static void AddDropdown(MenuCommand menuCommand) + static public void AddDropdown(MenuCommand menuCommand) { GameObject go = TMP_DefaultControls.CreateDropdown(GetStandardResources()); PlaceUIElementRoot(go, menuCommand); @@ -178,10 +101,10 @@ public static void AddDropdown(MenuCommand menuCommand) private const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd"; private const string kMaskPath = "UI/Skin/UIMask.psd"; - private static TMP_DefaultControls.Resources s_StandardResources; + static private TMP_DefaultControls.Resources s_StandardResources; - private static TMP_DefaultControls.Resources GetStandardResources() + static private TMP_DefaultControls.Resources GetStandardResources() { if (s_StandardResources.standard == null) { @@ -294,7 +217,7 @@ private static void PlaceUIElementRoot(GameObject element, MenuCommand menuComma } - public static GameObject CreateNewUI() + static public GameObject CreateNewUI() { // Root for the UI var root = new GameObject("Canvas"); @@ -353,7 +276,7 @@ private static void CreateEventSystem(bool select, GameObject parent) // Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas. - public static GameObject GetOrCreateCanvasGameObject() + static public GameObject GetOrCreateCanvasGameObject() { GameObject selectedGo = Selection.activeGameObject; diff --git a/Scripts/Editor/TMPro_FontAssetCreatorWindow.cs b/Scripts/Editor/TMPro_FontAssetCreatorWindow.cs index a3c6c76..7b7c54a 100644 --- a/Scripts/Editor/TMPro_FontAssetCreatorWindow.cs +++ b/Scripts/Editor/TMPro_FontAssetCreatorWindow.cs @@ -83,15 +83,15 @@ public static void ShowFontAtlasCreatorWindow(TMP_FontAsset fontAsset) // Make sure TMP Essential Resources have been imported. window.CheckEssentialResources(); } - + [System.Serializable] class FontAssetCreationSettingsContainer { public List fontAssetCreationSettings; } - + FontAssetCreationSettingsContainer m_FontAssetCreationSettingsContainer; - + //static readonly string[] m_FontCreationPresets = new string[] { "Recent 1", "Recent 2", "Recent 3", "Recent 4" }; int m_FontAssetCreationSettingsCurrentIndex = 0; @@ -103,7 +103,7 @@ class FontAssetCreationSettingsContainer System.Diagnostics.Stopwatch m_StopWatch; double m_GlyphPackingGenerationTime; double m_GlyphRenderingGenerationTime; - + string[] m_FontSizingOptions = { "Auto Sizing", "Custom Size" }; int m_PointSizeSamplingMode; string[] m_FontResolutionLabels = { "8", "16","32", "64", "128", "256", "512", "1024", "2048", "4096", "8192" }; @@ -120,7 +120,7 @@ enum FontPackingModes { Fast = 0, Optimum = 4 }; int m_CharacterCount; Vector2 m_ScrollPosition; Vector2 m_OutputScrollPosition; - + bool m_IsRepaintNeeded; float m_AtlasGenerationProgress; @@ -150,7 +150,7 @@ enum FontPackingModes { Fast = 0, Optimum = 4 }; Texture2D m_FontAtlasTexture; Texture2D m_SavedFontAtlas; - // + // List m_FontGlyphTable = new List(); List m_FontCharacterTable = new List(); @@ -175,7 +175,7 @@ public void OnEnable() { // Used for Diagnostics m_StopWatch = new System.Diagnostics.Stopwatch(); - + // Set Editor window size. minSize = new Vector2(315, minSize.y); @@ -386,7 +386,7 @@ void DrawControls() { m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); } - + GUILayout.Space(5f); GUILayout.Label(m_SelectedFontAsset != null ? string.Format("Font Settings [{0}]", m_SelectedFontAsset.name) : "Font Settings", EditorStyles.boldLabel); @@ -395,7 +395,7 @@ void DrawControls() EditorGUIUtility.labelWidth = 125f; EditorGUIUtility.fieldWidth = 5f; - + // Disable Options if already generating a font atlas texture. EditorGUI.BeginDisabledGroup(m_IsProcessing); { @@ -505,7 +505,7 @@ void DrawControls() { if (m_ReferencedFontAsset != null) m_CharacterSequence = TMP_EditorUtility.GetDecimalCharacterSequence(TMP_FontAsset.GetCharactersArray(m_ReferencedFontAsset)); - + m_IsFontAtlasInvalid = true; } @@ -522,7 +522,7 @@ void DrawControls() { m_IsFontAtlasInvalid = true; } - + EditorGUILayout.EndVertical(); break; @@ -537,7 +537,7 @@ void DrawControls() { if (m_ReferencedFontAsset != null) m_CharacterSequence = TMP_EditorUtility.GetUnicodeCharacterSequence(TMP_FontAsset.GetCharactersArray(m_ReferencedFontAsset)); - + m_IsFontAtlasInvalid = true; } @@ -569,12 +569,12 @@ void DrawControls() { if (m_ReferencedFontAsset != null) m_CharacterSequence = TMP_FontAsset.GetCharacters(m_ReferencedFontAsset); - + m_IsFontAtlasInvalid = true; } EditorGUI.indentLevel = 0; - + GUILayout.Label("Custom Character List", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); m_CharacterSequence = EditorGUILayout.TextArea(m_CharacterSequence, TMP_UIStyleManager.textAreaBoxWindow, GUILayout.Height(120), GUILayout.ExpandWidth(true)); @@ -641,7 +641,7 @@ void DrawControls() { EditorGUILayout.HelpBox(m_WarningMessage, MessageType.Warning); } - + GUI.enabled = m_SourceFontFile != null && !m_IsProcessing && !m_IsGenerationDisabled; // Enable Preview if we are not already rendering a font. if (GUILayout.Button("Generate Font Atlas") && GUI.enabled) { @@ -657,7 +657,7 @@ void DrawControls() { Debug.Log("Font Asset Creator - Error [" + errorCode + "] has occurred while Initializing the FreeType Library."); } - + // Get file path of the source font file. string fontPath = AssetDatabase.GetAssetPath(m_SourceFontFile); @@ -710,20 +710,14 @@ void DrawControls() } m_CharacterCount = characterSet.Length; - + m_AtlasGenerationProgress = 0; m_IsProcessing = true; m_IsGenerationCancelled = false; - GlyphLoadFlags glyphLoadFlags = ((GlyphRasterModes)m_GlyphRenderMode & GlyphRasterModes.RASTER_MODE_HINTED) == GlyphRasterModes.RASTER_MODE_HINTED - ? GlyphLoadFlags.LOAD_RENDER - : GlyphLoadFlags.LOAD_RENDER | GlyphLoadFlags.LOAD_NO_HINTING; - - glyphLoadFlags = ((GlyphRasterModes)m_GlyphRenderMode & GlyphRasterModes.RASTER_MODE_MONO) == GlyphRasterModes.RASTER_MODE_MONO - ? glyphLoadFlags | GlyphLoadFlags.LOAD_MONOCHROME - : glyphLoadFlags; + GlyphLoadFlags glyphLoadFlags = ((GlyphRasterModes)m_GlyphRenderMode & GlyphRasterModes.RASTER_MODE_HINTED) == GlyphRasterModes.RASTER_MODE_HINTED ? GlyphLoadFlags.LOAD_RENDER : GlyphLoadFlags.LOAD_RENDER | GlyphLoadFlags.LOAD_NO_HINTING; - // + // AutoResetEvent autoEvent = new AutoResetEvent(false); // Worker thread to pack glyphs in the given texture space. @@ -938,7 +932,7 @@ void DrawControls() // Add glyphs to list of glyphs that need to be rendered. if (glyph.glyphRect.width > 0 && glyph.glyphRect.height > 0) m_GlyphsToRender.Add(glyph); - + foreach (uint unicode in m_GlyphLookupMap[glyphIndex]) { // Create new Character @@ -946,7 +940,7 @@ void DrawControls() } } - // + // foreach (Glyph glyph in m_GlyphsToPack) { foreach (uint unicode in m_GlyphLookupMap[glyph.index]) @@ -1020,7 +1014,7 @@ void DrawControls() // FONT STATUS & INFORMATION GUI.enabled = true; - + GUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(200)); m_OutputScrollPosition = EditorGUILayout.BeginScrollView(m_OutputScrollPosition); EditorGUILayout.LabelField(m_OutputFeedback, TMP_UIStyleManager.label); @@ -1029,9 +1023,9 @@ void DrawControls() // SAVE TEXTURE & CREATE and SAVE FONT XML FILE GUI.enabled = m_FontAtlasTexture != null && !m_IsProcessing; // Enable Save Button if font_Atlas is not Null. - + EditorGUILayout.BeginHorizontal(); - + if (GUILayout.Button("Save") && GUI.enabled) { if (m_SelectedFontAsset == null) @@ -1063,13 +1057,13 @@ void DrawControls() SaveNewFontAssetWithSameName(m_SelectedFontAsset); } } - + EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.EndVertical(); - + GUI.enabled = true; // Re-enable GUI if (position.height > position.width || position.width < k_TwoColumnControlsWidth) @@ -1077,7 +1071,7 @@ void DrawControls() DrawPreview(); GUILayout.Space(5); } - + EditorGUILayout.EndScrollView(); if (m_IsFontAtlasInvalid) @@ -1097,7 +1091,7 @@ void ClearGeneratedData() DestroyImmediate(m_FontAtlasTexture); m_FontAtlasTexture = null; } - + m_AtlasGenerationProgressLabel = string.Empty; m_AtlasGenerationProgress = 0; m_SavedFontAtlas = null; @@ -1130,7 +1124,7 @@ void UpdateRenderFeedbackWindow() // Report characters missing from font file missingGlyphReport += "\n\nCharacters missing from font file:"; missingGlyphReport += "\n----------------------------------------"; - + m_OutputFeedback = missingGlyphReport; for (int i = 0; i < m_MissingCharacters.Count; i++) @@ -1181,7 +1175,7 @@ void CreateFontAtlasTexture() colors[i] = new Color32(c, c, c, c); } - // Clear allocation of + // Clear allocation of m_AtlasTextureBuffer = null; if ((m_GlyphRenderMode & GlyphRenderMode.RASTER) == GlyphRenderMode.RASTER || (m_GlyphRenderMode & GlyphRenderMode.RASTER_HINTED) == GlyphRenderMode.RASTER_HINTED) @@ -1203,7 +1197,7 @@ void CreateFontAtlasTexture() void SaveNewFontAsset(Object sourceObject) { string filePath; - + // Save new Font Asset and open save file requester at Source Font File location. string saveDirectory = new FileInfo(AssetDatabase.GetAssetPath(sourceObject)).DirectoryName; @@ -1300,7 +1294,7 @@ void Save_Bitmap_FontAsset(string filePath) fontAsset.characterTable = m_FontCharacterTable; // Sort glyph and character tables. - fontAsset.SortAllTables(); + fontAsset.SortGlyphAndCharacterTables(); // Get and Add Kerning Pairs to Font Asset if (m_IncludeFontFeatures) @@ -1351,7 +1345,7 @@ void Save_Bitmap_FontAsset(string filePath) fontAsset.characterTable = m_FontCharacterTable; // Sort glyph and character tables. - fontAsset.SortAllTables(); + fontAsset.SortGlyphAndCharacterTables(); // Get and Add Kerning Pairs to Font Asset if (m_IncludeFontFeatures) @@ -1479,7 +1473,7 @@ void Save_SDF_FontAsset(string filePath) fontAsset.characterTable = m_FontCharacterTable; // Sort glyph and character tables. - fontAsset.SortAllTables(); + fontAsset.SortGlyphAndCharacterTables(); // Get and Add Kerning Pairs to Font Asset if (m_IncludeFontFeatures) @@ -1529,7 +1523,7 @@ void Save_SDF_FontAsset(string filePath) //Set Font Asset Type fontAsset.atlasRenderMode = m_GlyphRenderMode; - // Add FaceInfo to Font Asset + // Add FaceInfo to Font Asset fontAsset.faceInfo = m_FaceInfo; // Add GlyphInfo[] to Font Asset @@ -1539,7 +1533,7 @@ void Save_SDF_FontAsset(string filePath) fontAsset.characterTable = m_FontCharacterTable; // Sort glyph and character tables. - fontAsset.SortAllTables(); + fontAsset.SortGlyphAndCharacterTables(); // Get and Add Kerning Pairs to Font Asset // TODO: Check and preserve existing adjustment pairs. @@ -1723,7 +1717,7 @@ void DrawPreview() pixelRect = GUILayoutUtility.GetAspectRect(1f); } - + if (m_FontAtlasTexture != null) { EditorGUI.DrawTextureAlpha(pixelRect, m_FontAtlasTexture, ScaleMode.StretchToFill); @@ -1775,7 +1769,7 @@ public TMP_FontFeatureTable GetKerningTable() TMP_FontFeatureTable fontFeatureTable = new TMP_FontFeatureTable(); - for (int i = 0; i < adjustmentRecords.Length && adjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) + for (int i = 0; i < adjustmentRecords.Length; i++) { fontFeatureTable.glyphPairAdjustmentRecords.Add(new TMP_GlyphPairAdjustmentRecord(adjustmentRecords[i])); } @@ -1785,4 +1779,4 @@ public TMP_FontFeatureTable GetKerningTable() return fontFeatureTable; } } -} +} \ No newline at end of file diff --git a/Scripts/Editor/TMPro_SortingLayerHelper.cs b/Scripts/Editor/TMPro_SortingLayerHelper.cs index c36f9f8..4f44c53 100644 --- a/Scripts/Editor/TMPro_SortingLayerHelper.cs +++ b/Scripts/Editor/TMPro_SortingLayerHelper.cs @@ -1,32 +1,105 @@ -using UnityEngine; +/* + * Copyright (c) 2014, Nick Gravelyn. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +using UnityEngine; +using UnityEditor; +using System; +using System.Reflection; namespace TMPro { // Helpers used by the different sorting layer classes. public static class SortingLayerHelper { + private static Type _utilityType; + private static PropertyInfo _sortingLayerNamesProperty; + private static MethodInfo _getSortingLayerUserIdMethod; + + static SortingLayerHelper() + { + _utilityType = Type.GetType("UnityEditorInternal.InternalEditorUtility, UnityEditor"); + _sortingLayerNamesProperty = _utilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic); + _getSortingLayerUserIdMethod = _utilityType.GetMethod("GetSortingLayerUniqueID", BindingFlags.Static | BindingFlags.NonPublic); + } + // Gets an array of sorting layer names. + // Since this uses reflection, callers should check for 'null' which will be returned if the reflection fails. public static string[] sortingLayerNames { get { - return GetSortingLayerNames(); + if (_sortingLayerNamesProperty == null) + { + return null; + } + + return _sortingLayerNamesProperty.GetValue(null, null) as string[]; + } + } + + // Given the ID of a sorting layer, returns the sorting layer's name + public static string GetSortingLayerNameFromID(int id) + { + string[] names = sortingLayerNames; + if (names == null) + { + return null; } + + for (int i = 0; i < names.Length; i++) + { + if (GetSortingLayerIDForIndex(i) == id) + { + return names[i]; + } + } + + return null; } - static string[] GetSortingLayerNames() + // Given the name of a sorting layer, returns the ID. + public static int GetSortingLayerIDForName(string name) { - int layerCount = SortingLayer.layers.Length; + string[] names = sortingLayerNames; + if (names == null) + { + return 0; + } - string[] layerNames = new string[layerCount]; + return GetSortingLayerIDForIndex(Array.IndexOf(names, name)); + } - for (int i = 0; i < layerCount; i++) + // Helper to convert from a sorting layer INDEX to a sorting layer ID. These are not the same thing. + // IDs are based on the order in which layers were created and do not change when reordering the layers. + // Thankfully there is a private helper we can call to get the ID for a layer given its index. + public static int GetSortingLayerIDForIndex(int index) + { + if (_getSortingLayerUserIdMethod == null) { - layerNames[i] = SortingLayer.layers[i].name; + return 0; } - return layerNames; + return (int)_getSortingLayerUserIdMethod.Invoke(null, new object[] { index }); } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/ITextPreProcessor.cs b/Scripts/Runtime/ITextPreProcessor.cs deleted file mode 100644 index 5d3f57a..0000000 --- a/Scripts/Runtime/ITextPreProcessor.cs +++ /dev/null @@ -1,17 +0,0 @@ - - -namespace TMPro -{ - /// - /// Interface used for preprocessing and shaping of text. - /// - public interface ITextPreprocessor - { - /// - /// Function used for preprocessing of text - /// - /// Source text to be processed - /// Processed text - string PreprocessText(string text); - } -} diff --git a/Scripts/Runtime/ITextPreProcessor.cs.meta b/Scripts/Runtime/ITextPreProcessor.cs.meta deleted file mode 100644 index 8dd7083..0000000 --- a/Scripts/Runtime/ITextPreProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: afc31ad767318c9488de260c166cd21d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Scripts/Runtime/TMP_Character.cs b/Scripts/Runtime/TMP_Character.cs index 6b4cc83..8fc161e 100644 --- a/Scripts/Runtime/TMP_Character.cs +++ b/Scripts/Runtime/TMP_Character.cs @@ -28,24 +28,6 @@ public TMP_Character(uint unicode, Glyph glyph) m_ElementType = TextElementType.Character; this.unicode = unicode; - this.textAsset = null; - this.glyph = glyph; - this.glyphIndex = glyph.index; - this.scale = 1.0f; - } - - /// - /// Constructor for new character - /// - /// Unicode value. - /// The font asset to which this character belongs. - /// Glyph - public TMP_Character(uint unicode, TMP_FontAsset fontAsset, Glyph glyph) - { - m_ElementType = TextElementType.Character; - - this.unicode = unicode; - this.textAsset = fontAsset; this.glyph = glyph; this.glyphIndex = glyph.index; this.scale = 1.0f; @@ -61,7 +43,6 @@ internal TMP_Character(uint unicode, uint glyphIndex) m_ElementType = TextElementType.Character; this.unicode = unicode; - this.textAsset = null; this.glyph = null; this.glyphIndex = glyphIndex; this.scale = 1.0f; diff --git a/Scripts/Runtime/TMP_CharacterInfo.cs b/Scripts/Runtime/TMP_CharacterInfo.cs index 7747cbd..8e1f005 100644 --- a/Scripts/Runtime/TMP_CharacterInfo.cs +++ b/Scripts/Runtime/TMP_CharacterInfo.cs @@ -20,7 +20,7 @@ public struct TMP_Vertex } /// - /// + /// /// public struct TMP_Offset { @@ -37,7 +37,7 @@ public struct TMP_Offset public float vertical { get { return m_Top; } set { m_Top = value; m_Bottom = value; } } /// - /// + /// /// public static TMP_Offset zero { get { return k_ZeroOffset; } } @@ -53,7 +53,7 @@ public struct TMP_Offset static readonly TMP_Offset k_ZeroOffset = new TMP_Offset(0F, 0F, 0F, 0F); /// - /// + /// /// /// /// @@ -68,7 +68,7 @@ public TMP_Offset(float left, float right, float top, float bottom) } /// - /// + /// /// /// /// @@ -116,7 +116,7 @@ public bool Equals(TMP_Offset other) /// - /// + /// /// public struct HighlightState { @@ -193,15 +193,12 @@ public struct TMP_CharacterInfo public Vector3 bottomLeft; public Vector3 topRight; public Vector3 bottomRight; - public float origin; - public float xAdvance; public float ascender; public float baseLine; public float descender; - internal float adjustedAscender; - internal float adjustedDescender; + public float xAdvance; public float aspectRatio; public float scale; public Color32 color; diff --git a/Scripts/Runtime/TMP_Compatibility.cs b/Scripts/Runtime/TMP_Compatibility.cs index 8484a5c..8db0f58 100644 --- a/Scripts/Runtime/TMP_Compatibility.cs +++ b/Scripts/Runtime/TMP_Compatibility.cs @@ -7,8 +7,8 @@ namespace TMPro // Class used to convert scenes and objects saved in version 0.1.44 to the new Text Container public static class TMP_Compatibility { - public enum AnchorPositions { TopLeft, Top, TopRight, Left, Center, Right, BottomLeft, Bottom, BottomRight, BaseLine, None }; - + public enum AnchorPositions { TopLeft, Top, TopRight, Left, Center, Right, BottomLeft, Bottom, BottomRight, BaseLine, None }; + /// /// Function used to convert text alignment option enumeration format. /// diff --git a/Scripts/Runtime/TMP_DefaultControls.cs b/Scripts/Runtime/TMP_DefaultControls.cs index 45eac33..6d2b057 100644 --- a/Scripts/Runtime/TMP_DefaultControls.cs +++ b/Scripts/Runtime/TMP_DefaultControls.cs @@ -2,10 +2,6 @@ using System.Collections; using UnityEngine.UI; -#if UNITY_EDITOR -using UnityEditor; -#endif - namespace TMPro { @@ -152,19 +148,11 @@ public static GameObject CreateButton(Resources resources) public static GameObject CreateText(Resources resources) { - GameObject go = null; - #if UNITY_EDITOR - go = ObjectFactory.CreateGameObject("Text (TMP)"); - #else - go = CreateUIElementRoot("Text (TMP)", s_TextElementSize); - #endif - - TextMeshProUGUI textComponent = null; - #if UNITY_EDITOR - textComponent = ObjectFactory.AddComponent(go); - #else - textComponent = go.AddComponent(); - #endif + GameObject go = CreateUIElementRoot("Text (TMP)", s_TextElementSize); + + TextMeshProUGUI lbl = go.AddComponent(); + lbl.text = "New Text"; + SetDefaultTextValues(lbl); return go; } diff --git a/Scripts/Runtime/TMP_Dropdown.cs b/Scripts/Runtime/TMP_Dropdown.cs index 1e42e39..1841d32 100644 --- a/Scripts/Runtime/TMP_Dropdown.cs +++ b/Scripts/Runtime/TMP_Dropdown.cs @@ -348,7 +348,6 @@ public List options private List m_Items = new List(); private TweenRunner m_AlphaTweenRunner; private bool validTemplate = false; - private Coroutine m_Coroutine = null; private static OptionData s_NoOptionData = new OptionData(); @@ -438,10 +437,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); @@ -740,12 +739,6 @@ public virtual void OnCancel(BaseEventData eventData) /// public void Show() { - if (m_Coroutine != null) - { - StopCoroutine(m_Coroutine); - ImmediateDestroyDropdownList(); - } - if (!IsActive() || !IsInteractable() || m_Dropdown != null) return; @@ -1086,23 +1079,20 @@ private void SetAlpha(float alpha) /// public void Hide() { - if (m_Coroutine == null) + if (m_Dropdown != null) { - if (m_Dropdown != null) - { - AlphaFadeList(m_AlphaFadeSpeed, 0f); + AlphaFadeList(m_AlphaFadeSpeed, 0f); - // User could have disabled the dropdown during the OnValueChanged call. - if (IsActive()) - m_Coroutine = StartCoroutine(DelayedDestroyDropdownList(m_AlphaFadeSpeed)); - } + // User could have disabled the dropdown during the OnValueChanged call. + if (IsActive()) + StartCoroutine(DelayedDestroyDropdownList(m_AlphaFadeSpeed)); + } - if (m_Blocker != null) - DestroyBlocker(m_Blocker); + if (m_Blocker != null) + DestroyBlocker(m_Blocker); - m_Blocker = null; - Select(); - } + m_Blocker = null; + Select(); } private IEnumerator DelayedDestroyDropdownList(float delay) @@ -1124,11 +1114,7 @@ private void ImmediateDestroyDropdownList() if (m_Dropdown != null) DestroyDropdownList(m_Dropdown); - if (m_AlphaTweenRunner != null) - m_AlphaTweenRunner.StopTween(); - m_Dropdown = null; - m_Coroutine = null; } // Change the value and hide the dropdown. @@ -1157,4 +1143,4 @@ private void OnSelectItem(Toggle toggle) Hide(); } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/TMP_EditorResourceManager.cs b/Scripts/Runtime/TMP_EditorResourceManager.cs index b9ffa7c..cbe4871 100644 --- a/Scripts/Runtime/TMP_EditorResourceManager.cs +++ b/Scripts/Runtime/TMP_EditorResourceManager.cs @@ -12,10 +12,10 @@ public class TMP_EditorResourceManager private static TMP_EditorResourceManager s_Instance; private readonly List m_ObjectUpdateQueue = new List(); - private HashSet m_ObjectUpdateQueueLookup = new HashSet(); + private Dictionary m_ObjectUpdateQueueLookup = new Dictionary(); private readonly List m_ObjectReImportQueue = new List(); - private HashSet m_ObjectReImportQueueLookup = new HashSet(); + private Dictionary m_ObjectReImportQueueLookup = new Dictionary(); /// /// Get a singleton instance of the manager. @@ -62,10 +62,10 @@ private void InternalRegisterResourceForReimport(Object obj) { int id = obj.GetInstanceID(); - if (m_ObjectReImportQueueLookup.Contains(id)) + if (m_ObjectReImportQueueLookup.ContainsKey(id)) return; - m_ObjectReImportQueueLookup.Add(id); + m_ObjectReImportQueueLookup[id] = id; m_ObjectReImportQueue.Add(obj); return; @@ -84,10 +84,10 @@ private void InternalRegisterResourceForUpdate(Object obj) { int id = obj.GetInstanceID(); - if (m_ObjectUpdateQueueLookup.Contains(id)) + if (m_ObjectUpdateQueueLookup.ContainsKey(id)) return; - m_ObjectUpdateQueueLookup.Add(id); + m_ObjectUpdateQueueLookup[id] = id; m_ObjectUpdateQueue.Add(obj); return; diff --git a/Scripts/Runtime/TMP_FontAsset.cs b/Scripts/Runtime/TMP_FontAsset.cs index 2701012..df53236 100644 --- a/Scripts/Runtime/TMP_FontAsset.cs +++ b/Scripts/Runtime/TMP_FontAsset.cs @@ -4,10 +4,11 @@ using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; using UnityEngine.Profiling; +using System.Collections; using System.Collections.Generic; using System.Linq; -#if UNITY_EDITOR +#if UNITY_EDITOR //&& UNITY_2018_4_5_OR_NEWER using UnityEditor.TextCore.LowLevel; #endif @@ -41,7 +42,7 @@ public string version /// [SerializeField] internal string m_SourceFontFileGUID; - + #if UNITY_EDITOR /// /// Persistent reference to the source font file maintained in the editor. @@ -51,7 +52,7 @@ public string version #endif /// - /// Source font file when atlas population mode is set to dynamic. Null when the atlas population mode is set to static. + /// Source font file when atlas population mode is set to dynamic. Null when the atlas population mode is set to static. /// public Font sourceFontFile { @@ -87,7 +88,7 @@ public AtlasPopulationMode atlasPopulationMode public FaceInfo faceInfo { get { return m_FaceInfo; } - set { m_FaceInfo = value; } + internal set { m_FaceInfo = value; } } [SerializeField] internal FaceInfo m_FaceInfo; @@ -215,13 +216,9 @@ public Texture2D[] atlasTextures public int atlasTextureCount { get { return m_AtlasTextureIndex + 1; } } /// - /// + /// /// - public bool isMultiAtlasTexturesEnabled - { - get { return m_IsMultiAtlasTexturesEnabled; } - set { m_IsMultiAtlasTexturesEnabled = value; } - } + public bool isMultiAtlasTexturesEnabled { get { return m_IsMultiAtlasTexturesEnabled; } set { m_IsMultiAtlasTexturesEnabled = value; } } [SerializeField] private bool m_IsMultiAtlasTexturesEnabled; @@ -262,7 +259,7 @@ public FaceInfo_Legacy fontInfo private FaceInfo_Legacy m_fontInfo = null; /// - /// + /// /// [SerializeField] public Texture2D atlas; // Should add a property to make this read-only. @@ -317,7 +314,7 @@ public GlyphRenderMode atlasRenderMode internal KerningTable m_KerningTable = new KerningTable(); /// - /// Table containing the various font features of this font asset. + /// Table containing the various font features of this font asset. /// public TMP_FontFeatureTable fontFeatureTable { @@ -402,7 +399,8 @@ public TMP_FontWeightPair[] fontWeightTable public byte tabSize = 10; - internal bool IsFontAssetLookupTablesDirty; + private byte m_oldTabSize; + internal bool m_IsFontAssetLookupTablesDirty = false; /// /// Create new instance of a font asset using default settings. @@ -427,20 +425,14 @@ public static TMP_FontAsset CreateFontAsset(Font font) /// public static TMP_FontAsset CreateFontAsset(Font font, int samplingPointSize, int atlasPadding, GlyphRenderMode renderMode, int atlasWidth, int atlasHeight, AtlasPopulationMode atlasPopulationMode = AtlasPopulationMode.Dynamic, bool enableMultiAtlasSupport = true) { - // Initialize FontEngine - FontEngine.InitializeFontEngine(); - - // Load Font Face - if (FontEngine.LoadFontFace(font, samplingPointSize) != FontEngineError.Success) - { - Debug.LogWarning("Unable to load font face for [" + font.name + "]. Make sure \"Include Font Data\" is enabled in the Font Import Settings.", font); - return null; - } - - // Create new font asset TMP_FontAsset fontAsset = ScriptableObject.CreateInstance(); fontAsset.m_Version = "1.1.0"; + + // Set face information + FontEngine.InitializeFontEngine(); + FontEngine.LoadFontFace(font, samplingPointSize); + fontAsset.faceInfo = FontEngine.GetFaceInfo(); // Set font reference and GUID @@ -532,68 +524,10 @@ void Awake() } - public void ReadFontAssetDefinition() - { - Profiler.BeginSample("TMP.ReadFontAssetDefinition"); - - //Debug.Log("Reading Font Asset Definition for " + this.name + "."); - - // Check version number of font asset to see if it needs to be upgraded. - if (this.material != null && string.IsNullOrEmpty(m_Version)) - UpgradeFontAsset(); - - // Initialize lookup tables for characters and glyphs. - InitializeDictionaryLookupTables(); - - // Add synthesized characters and adjust face metrics - AddSynthesizedCharactersAndFaceMetrics(); - - // Adjust Font Scale for compatibility reasons - if (m_FaceInfo.scale == 0) - m_FaceInfo.scale = 1.0f; - - // Set Strikethrough Offset (if needed) - if (m_FaceInfo.strikethroughOffset == 0) - m_FaceInfo.strikethroughOffset = m_FaceInfo.capLine / 2.5f; - - // Set Padding value for legacy font assets. - if (m_AtlasPadding == 0) - { - if (material.HasProperty(ShaderUtilities.ID_GradientScale)) - m_AtlasPadding = (int)material.GetFloat(ShaderUtilities.ID_GradientScale) - 1; - } - - // Compute Hashcode for the font asset name - hashCode = TMP_TextUtilities.GetSimpleHashCode(this.name); - - // Compute Hashcode for the material name - materialHashCode = TMP_TextUtilities.GetSimpleHashCode(material.name); - - // Add reference to font asset in TMP Resource Manager - //TMP_ResourceManager.AddFontAsset(this); - - IsFontAssetLookupTablesDirty = false; - - Profiler.EndSample(); - } - - /// /// Read the various data tables of the font asset to populate its different dictionaries to allow for faster lookup of related font asset data. /// internal void InitializeDictionaryLookupTables() - { - // Initialize and populate glyph lookup dictionary - InitializeGlyphLookupDictionary(); - - // Initialize and populate character lookup dictionary - InitializeCharacterLookupDictionary(); - - // Initialize and populate character lookup dictionary - InitializeGlyphPaidAdjustmentRecordsLookupDictionary(); - } - - internal void InitializeGlyphLookupDictionary() { // Create new instance of the glyph lookup dictionary or clear the existing one. if (m_GlyphLookupDictionary == null) @@ -601,22 +535,15 @@ internal void InitializeGlyphLookupDictionary() else m_GlyphLookupDictionary.Clear(); - // Initialize or clear list of glyph indexes. + int glyphCount = m_GlyphTable.Count; + + // Initialize glyph index array or clear the existing one. if (m_GlyphIndexList == null) m_GlyphIndexList = new List(); else m_GlyphIndexList.Clear(); - // Initialize or clear list of glyph indexes. - if (m_GlyphIndexListNewlyAdded == null) - m_GlyphIndexListNewlyAdded = new List(); - else - m_GlyphIndexListNewlyAdded.Clear(); - - // - int glyphCount = m_GlyphTable.Count; - - // Add glyphs contained in the glyph table to dictionary for faster lookup. + // Add the characters contained in the character table into the dictionary for faster lookup. for (int i = 0; i < glyphCount; i++) { Glyph glyph = m_GlyphTable[i]; @@ -630,17 +557,14 @@ internal void InitializeGlyphLookupDictionary() m_GlyphIndexList.Add(index); } } - } - internal void InitializeCharacterLookupDictionary() - { // Create new instance of the character lookup dictionary or clear the existing one. if (m_CharacterLookupDictionary == null) m_CharacterLookupDictionary = new Dictionary(); else m_CharacterLookupDictionary.Clear(); - // Add the characters contained in the character table to the dictionary for faster lookup. + // Add the characters contained in the character table into the dictionary for faster lookup. for (int i = 0; i < m_CharacterTable.Count; i++) { TMP_Character character = m_CharacterTable[i]; @@ -648,24 +572,15 @@ internal void InitializeCharacterLookupDictionary() uint unicode = character.unicode; uint glyphIndex = character.glyphIndex; - // Add character along with reference to text asset and glyph if (m_CharacterLookupDictionary.ContainsKey(unicode) == false) - { m_CharacterLookupDictionary.Add(unicode, character); - character.textAsset = this; + + if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) + { character.glyph = m_GlyphLookupDictionary[glyphIndex]; } } - // Clear internal fallback references - if (FallbackSearchQueryLookup == null) - FallbackSearchQueryLookup = new HashSet(); - else - FallbackSearchQueryLookup.Clear(); - } - - internal void InitializeGlyphPaidAdjustmentRecordsLookupDictionary() - { // Upgrade Glyph Adjustment Table to the new Font Feature table and Glyph Pair Adjustment Records if (m_KerningTable != null && m_KerningTable.kerningPairs != null && m_KerningTable.kerningPairs.Count > 0) UpgradeGlyphAdjustmentTableToFontFeatureTable(); @@ -691,115 +606,103 @@ internal void InitializeGlyphPaidAdjustmentRecordsLookupDictionary() } } - internal void AddSynthesizedCharactersAndFaceMetrics() - { - Profiler.BeginSample("TMP.AddSynthesizedCharacters"); - - if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) - FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize); - - // Only characters not present in the source font file will be synthesized. - - // Non visible and control characters with no metrics - // Add End of Text \u0003 - AddSynthesizedCharacter(0x03, true); - - // Add Tab \u0009 - AddSynthesizedCharacter(0x09, true); - - // Add Line Feed (LF) \u000A - AddSynthesizedCharacter(0x0A); - // Add Vertical Tab (VT) \u000B - AddSynthesizedCharacter(0x0B); - - // Add Carriage Return (CR) \u000D - AddSynthesizedCharacter(0x0D); + /// + /// + /// + public void ReadFontAssetDefinition() + { + //Debug.Log("Reading Font Definition for " + this.name + "."); - // Add Arabic Letter Mark \u061C - AddSynthesizedCharacter(0x061C); + // Check version number of font asset to see if it needs to be upgraded. + if (this.material != null && string.IsNullOrEmpty(m_Version)) + UpgradeFontAsset(); - // Add Zero Width Space \u2000B - AddSynthesizedCharacter(0x200B); + // Initialize lookup tables for characters and glyphs. + InitializeDictionaryLookupTables(); - // Add Left-To-Right Mark \u200E - AddSynthesizedCharacter(0x200E); + // Add Tab char(9) to Dictionary. + 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)); + } - // Add Right-To-Left Mark \u200F - AddSynthesizedCharacter(0x200F); + // 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)); - // Add Line Separator \u2028 - AddSynthesizedCharacter(0x2028); + if (!m_CharacterLookupDictionary.ContainsKey(11)) + m_CharacterLookupDictionary.Add(11, new TMP_Character(11, glyph)); - // Add Paragraph Separator \u2029 - AddSynthesizedCharacter(0x2029); + if (!m_CharacterLookupDictionary.ContainsKey(13)) + m_CharacterLookupDictionary.Add(13, new TMP_Character(13, glyph)); - // Add Word Joiner / Zero Width Non-Breaking Space \u2060 - AddSynthesizedCharacter(0x2060); + if (!m_CharacterLookupDictionary.ContainsKey(3)) + m_CharacterLookupDictionary.Add(3, new TMP_Character(3, glyph)); + } - // Set Cap Line using the capital letter 'X' - if (m_FaceInfo.capLine == 0 && m_CharacterLookupDictionary.ContainsKey('X')) + // Add Zero Width Space 8203 (0x200B) + if (m_CharacterLookupDictionary.ContainsKey(8203) == false) { - uint glyphIndex = m_CharacterLookupDictionary['X'].glyphIndex; - m_FaceInfo.capLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; + Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); + m_CharacterLookupDictionary.Add(8203, new TMP_Character(8203, glyph)); } - // Set Mean Line using the lowercase letter 'x' - if (m_FaceInfo.meanLine == 0 && m_CharacterLookupDictionary.ContainsKey('x')) + // Add Zero Width Non-Breaking Space 8288 (0x2060) + if (m_CharacterLookupDictionary.ContainsKey(8288) == false) { - uint glyphIndex = m_CharacterLookupDictionary['x'].glyphIndex; - m_FaceInfo.meanLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; + Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); + m_CharacterLookupDictionary.Add(8288, new TMP_Character(8288, glyph)); } - Profiler.EndSample(); - } + // Add Non-Breaking Hyphen 8209 (0x2011) + if (m_CharacterLookupDictionary.ContainsKey(8209) == false) + { + TMP_Character character; - void AddSynthesizedCharacter(uint unicode, bool addImmediately = false) - { - // Check if unicode is already present in the font asset - if (m_CharacterLookupDictionary.ContainsKey(unicode)) - return; + if (m_CharacterLookupDictionary.TryGetValue(45, out character)) + m_CharacterLookupDictionary.Add(8209, new TMP_Character(8209, character.glyph)); + } - Glyph glyph; - if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) + // Set Cap Height + if (m_FaceInfo.capLine == 0 && m_CharacterLookupDictionary.ContainsKey(72)) { - // Check if unicode is present in font file - if (FontEngine.GetGlyphIndex(unicode) != 0) - { - if (addImmediately == false) - return; - - //Debug.Log("Adding Unicode [" + unicode.ToString("X4") + "]."); + uint glyphIndex = m_CharacterLookupDictionary[72].glyphIndex; + m_FaceInfo.capLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; + } - 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; + // Adjust Font Scale for compatibility reasons + if (m_FaceInfo.scale == 0) + m_FaceInfo.scale = 1.0f; - if (FontEngine.TryGetGlyphWithUnicodeValue(unicode, glyphLoadFlags, out glyph)) - m_CharacterLookupDictionary.Add(unicode, new TMP_Character(unicode, this, glyph)); + // Set Strikethrough Offset (if needed) + if (m_FaceInfo.strikethroughOffset == 0) + m_FaceInfo.strikethroughOffset = m_FaceInfo.capLine / 2.5f; - return; - } + // Set Padding value for legacy font assets. + if (m_AtlasPadding == 0) + { + if (material.HasProperty(ShaderUtilities.ID_GradientScale)) + m_AtlasPadding = (int)material.GetFloat(ShaderUtilities.ID_GradientScale) - 1; } - //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, this, glyph)); - } + // Compute Hashcode for the font asset name + hashCode = TMP_TextUtilities.GetSimpleHashCode(this.name); - internal HashSet FallbackSearchQueryLookup = new HashSet(); + // Compute Hashcode for the material name + materialHashCode = TMP_TextUtilities.GetSimpleHashCode(material.name); - internal void AddCharacterToLookupCache(uint unicode, TMP_Character character) - { - m_CharacterLookupDictionary.Add(unicode, character); + // Add reference to font asset in TMP Resource Manager + //TMP_ResourceManager.AddFontAsset(this); - // Add font asset to fallback references. - FallbackSearchQueryLookup.Add(character.textAsset.instanceID); + m_IsFontAssetLookupTablesDirty = false; } + /// /// Sort the Character table by Unicode values. /// @@ -818,25 +721,15 @@ internal void SortGlyphTable() m_GlyphTable = m_GlyphTable.OrderBy(c => c.index).ToList(); } - internal void SortFontFeatureTable() - { - m_FontFeatureTable.SortGlyphPairAdjustmentRecords(); - } - /// /// Sort both glyph and character tables. /// - internal void SortAllTables() + internal void SortGlyphAndCharacterTables() { SortGlyphTable(); SortCharacterTable(); - SortFontFeatureTable(); } - /// - /// HashSet of font asset instance ID used in the process of searching for through fallback font assets for a given character or characters. - /// - private static HashSet k_SearchedFontAssetLookup; /// /// Function to check if a certain character exists in the font asset. @@ -854,14 +747,31 @@ public bool HasCharacter(int character) return false; } + + /// + /// Function to check if a certain character exists in the font asset. + /// + /// + /// + public bool HasCharacter(char character) + { + if (m_CharacterLookupDictionary == null) + return false; + + if (m_CharacterLookupDictionary.ContainsKey(character)) + return true; + + return false; + } + + /// /// Function to check if a character is contained in the font asset with the option to also check through fallback font assets. /// /// /// - /// /// - public bool HasCharacter(char character, bool searchFallbacks = false, bool tryAddCharacter = false) + public bool HasCharacter(char character, bool searchFallbacks) { // Read font asset definition if it hasn't already been done. if (m_CharacterLookupDictionary == null) @@ -877,7 +787,7 @@ public bool HasCharacter(char character, bool searchFallbacks = false, bool tryA return true; // Check if font asset is dynamic and if so try to add the requested character to it. - if (tryAddCharacter && m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) + if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) { TMP_Character returnedCharacter; @@ -887,29 +797,13 @@ public bool HasCharacter(char character, bool searchFallbacks = false, bool tryA if (searchFallbacks) { - // Initialize or clear font asset lookup - if (k_SearchedFontAssetLookup == null) - k_SearchedFontAssetLookup = new HashSet(); - else - k_SearchedFontAssetLookup.Clear(); - - // Add current font asset to lookup - k_SearchedFontAssetLookup.Add(GetInstanceID()); - // Check font asset fallbacks if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) { for (int i = 0; i < fallbackFontAssetTable.Count && fallbackFontAssetTable[i] != null; i++) { - TMP_FontAsset fallback = fallbackFontAssetTable[i]; - int fallbackID = fallback.GetInstanceID(); - - // Search fallback if not already contained in lookup - if (k_SearchedFontAssetLookup.Add(fallbackID)) - { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) - return true; - } + if (fallbackFontAssetTable[i].HasCharacter_Internal(character, searchFallbacks)) + return true; } } @@ -918,30 +812,22 @@ public bool HasCharacter(char character, bool searchFallbacks = false, bool tryA { for (int i = 0; i < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[i] != null; i++) { - TMP_FontAsset fallback = TMP_Settings.fallbackFontAssets[i]; - int fallbackID = fallback.GetInstanceID(); + if (TMP_Settings.fallbackFontAssets[i].m_CharacterLookupDictionary == null) + TMP_Settings.fallbackFontAssets[i].ReadFontAssetDefinition(); - // Search fallback if not already contained in lookup - if (k_SearchedFontAssetLookup.Add(fallbackID)) - { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) - return true; - } + if (TMP_Settings.fallbackFontAssets[i].m_CharacterLookupDictionary != null && TMP_Settings.fallbackFontAssets[i].HasCharacter_Internal(character, searchFallbacks)) + return true; } } // Check TMP Settings Default Font Asset if (TMP_Settings.defaultFontAsset != null) { - TMP_FontAsset fallback = TMP_Settings.defaultFontAsset; - int fallbackID = fallback.GetInstanceID(); + if (TMP_Settings.defaultFontAsset.m_CharacterLookupDictionary == null) + TMP_Settings.defaultFontAsset.ReadFontAssetDefinition(); - // Search fallback if it has not already been searched - if (k_SearchedFontAssetLookup.Add(fallbackID)) - { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) - return true; - } + if (TMP_Settings.defaultFontAsset.m_CharacterLookupDictionary != null && TMP_Settings.defaultFontAsset.HasCharacter_Internal(character, searchFallbacks)) + return true; } } @@ -955,9 +841,8 @@ public bool HasCharacter(char character, bool searchFallbacks = false, bool tryA /// /// /// - /// /// - bool HasCharacter_Internal(uint character, bool searchFallbacks = false, bool tryAddCharacter = false) + bool HasCharacter_Internal(uint character, bool searchFallbacks) { // Read font asset definition if it hasn't already been done. if (m_CharacterLookupDictionary == null) @@ -972,30 +857,14 @@ bool HasCharacter_Internal(uint character, bool searchFallbacks = false, bool tr if (m_CharacterLookupDictionary.ContainsKey(character)) return true; - // Check if fallback is dynamic and if so try to add the requested character to it. - if (tryAddCharacter && atlasPopulationMode == AtlasPopulationMode.Dynamic) - { - TMP_Character returnedCharacter; - - if (TryAddCharacterInternal(character, out returnedCharacter)) - return true; - } - if (searchFallbacks) { // Check Font Asset Fallback fonts. - if (fallbackFontAssetTable == null || fallbackFontAssetTable.Count == 0) - return false; - - for (int i = 0; i < fallbackFontAssetTable.Count && fallbackFontAssetTable[i] != null; i++) + if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) { - TMP_FontAsset fallback = fallbackFontAssetTable[i]; - int fallbackID = fallback.GetInstanceID(); - - // Search fallback if it has not already been searched - if (k_SearchedFontAssetLookup.Add(fallbackID)) + for (int i = 0; i < fallbackFontAssetTable.Count && fallbackFontAssetTable[i] != null; i++) { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) + if (fallbackFontAssetTable[i].HasCharacter_Internal(character, searchFallbacks)) return true; } } @@ -1009,7 +878,6 @@ bool HasCharacter_Internal(uint character, bool searchFallbacks = false, bool tr /// Function to check if certain characters exists in the font asset. Function returns a list of missing characters. /// /// - /// /// public bool HasCharacters(string text, out List missingCharacters) { @@ -1034,14 +902,13 @@ public bool HasCharacters(string text, out List missingCharacters) } /// - /// + /// /// /// /// /// - /// /// - public bool HasCharacters(string text, out uint[] missingCharacters, bool searchFallbacks = false, bool tryAddCharacter = false) + public bool HasCharacters(string text, out uint[] missingCharacters, bool searchFallbacks = false) { missingCharacters = null; @@ -1054,7 +921,7 @@ public bool HasCharacters(string text, out uint[] missingCharacters, bool search return false; } - // Clear internal list of + // Clear internal list of s_MissingCharacterList.Clear(); for (int i = 0; i < text.Length; i++) @@ -1062,86 +929,55 @@ public bool HasCharacters(string text, out uint[] missingCharacters, bool search bool isMissingCharacter = true; uint character = text[i]; - if (m_CharacterLookupDictionary.ContainsKey(character)) - continue; - - // Check if fallback is dynamic and if so try to add the requested character to it. - if (tryAddCharacter && atlasPopulationMode == AtlasPopulationMode.Dynamic) - { - TMP_Character returnedCharacter; - - if (TryAddCharacterInternal(character, out returnedCharacter)) - continue; - } - - if (searchFallbacks) + if (!m_CharacterLookupDictionary.ContainsKey(character)) { - // Initialize or clear font asset lookup - if (k_SearchedFontAssetLookup == null) - k_SearchedFontAssetLookup = new HashSet(); - else - k_SearchedFontAssetLookup.Clear(); - - // Add current font asset to lookup - k_SearchedFontAssetLookup.Add(GetInstanceID()); - - // Check font asset fallbacks - if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) + if (searchFallbacks) { - for (int j = 0; j < fallbackFontAssetTable.Count && fallbackFontAssetTable[j] != null; j++) + // Check font asset fallbacks + if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) { - TMP_FontAsset fallback = fallbackFontAssetTable[j]; - int fallbackID = fallback.GetInstanceID(); - - // Search fallback if it has not already been searched - if (k_SearchedFontAssetLookup.Add(fallbackID)) + for (int j = 0; j < fallbackFontAssetTable.Count && fallbackFontAssetTable[j] != null; j++) { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter) == false) - continue; - - isMissingCharacter = false; - break; + if (fallbackFontAssetTable[j].HasCharacter_Internal(character, searchFallbacks)) + { + isMissingCharacter = false; + break; + } } } - } - // Check general fallback font assets. - if (isMissingCharacter && TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - { - for (int j = 0; j < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[j] != null; j++) + // Check general fallback font assets. + if (isMissingCharacter && TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) { - TMP_FontAsset fallback = TMP_Settings.fallbackFontAssets[j]; - int fallbackID = fallback.GetInstanceID(); - - // Search fallback if it has not already been searched - if (k_SearchedFontAssetLookup.Add(fallbackID)) + for (int j = 0; j < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[j] != null; j++) { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter) == false) - continue; - - isMissingCharacter = false; - break; + if (TMP_Settings.fallbackFontAssets[j].m_CharacterLookupDictionary == null) + TMP_Settings.fallbackFontAssets[j].ReadFontAssetDefinition(); + + if (TMP_Settings.fallbackFontAssets[j].m_CharacterLookupDictionary != null && TMP_Settings.fallbackFontAssets[j].HasCharacter_Internal(character, searchFallbacks)) + { + isMissingCharacter = false; + break; + } } } - } - - // Check TMP Settings Default Font Asset - if (isMissingCharacter && TMP_Settings.defaultFontAsset != null) - { - TMP_FontAsset fallback = TMP_Settings.defaultFontAsset; - int fallbackID = fallback.GetInstanceID(); - // Search fallback if it has not already been searched - if (k_SearchedFontAssetLookup.Add(fallbackID)) + // Check TMP Settings Default Font Asset + if (isMissingCharacter && TMP_Settings.defaultFontAsset != null) { - if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) + if (TMP_Settings.defaultFontAsset.m_CharacterLookupDictionary == null) + TMP_Settings.defaultFontAsset.ReadFontAssetDefinition(); + + if (TMP_Settings.defaultFontAsset.m_CharacterLookupDictionary != null && TMP_Settings.defaultFontAsset.HasCharacter_Internal(character, searchFallbacks)) isMissingCharacter = false; } } - } - if (isMissingCharacter) - s_MissingCharacterList.Add(character); + if (isMissingCharacter) + { + s_MissingCharacterList.Add(character); + } + } } if (s_MissingCharacterList.Count > 0) @@ -1209,23 +1045,6 @@ public static int[] GetCharactersArray(TMP_FontAsset fontAsset) return characters; } - /// - /// Internal function used to get the glyph index for the given Unicode. - /// - /// - /// - internal uint GetGlyphIndex(uint unicode) - { - // Check if glyph already exists in font asset. - if (m_CharacterLookupDictionary.ContainsKey(unicode)) - return m_CharacterLookupDictionary[unicode].glyphIndex; - - // Load font face. - if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) - return 0; - - return FontEngine.GetGlyphIndex(unicode); - } // ================================================================================ // Properties and functions related to character and glyph additions as well as @@ -1233,132 +1052,68 @@ internal uint GetGlyphIndex(uint unicode) // ================================================================================ // List and HashSet used for tracking font assets whose font atlas texture and character data needs updating. - private static List k_FontAssets_FontFeaturesUpdateQueue = new List(); - private static HashSet k_FontAssets_FontFeaturesUpdateQueueLookup = new HashSet(); - - private static List k_FontAssets_AtlasTexturesUpdateQueue = new List(); - private static HashSet k_FontAssets_AtlasTexturesUpdateQueueLookup = new HashSet(); + private static List k_FontAssetsToUpdate = new List(); + private static HashSet k_FontAssetsToUpdateLookup = new HashSet(); /// - /// + /// Determines if the font asset is already registered to be updated. /// - /// - internal static void RegisterFontAssetForFontFeatureUpdate(TMP_FontAsset fontAsset) - { - int instanceID = fontAsset.instanceID; - - if (k_FontAssets_FontFeaturesUpdateQueueLookup.Add(instanceID)) - k_FontAssets_FontFeaturesUpdateQueue.Add(fontAsset); - } + //private bool m_IsAlreadyRegisteredForUpdate; /// - /// Function called to update the font atlas texture and character data of font assets to which - /// new characters were added. + /// List of glyphs that need to be added / packed in atlas texture. /// - internal static void UpdateFontFeaturesForFontAssetsInQueue() - { - int count = k_FontAssets_FontFeaturesUpdateQueue.Count; - - for (int i = 0; i < count; i++) - k_FontAssets_FontFeaturesUpdateQueue[i].UpdateGlyphAdjustmentRecords(); - - if (count > 0) - { - k_FontAssets_FontFeaturesUpdateQueue.Clear(); - k_FontAssets_FontFeaturesUpdateQueueLookup.Clear(); - } - } + private List m_GlyphsToPack = new List(); /// - /// + /// List of glyphs that have been packed in the atlas texture and ready to be rendered. /// - /// - internal static void RegisterFontAssetForAtlasTextureUpdate(TMP_FontAsset fontAsset) - { - int instanceID = fontAsset.instanceID; - - if (k_FontAssets_AtlasTexturesUpdateQueueLookup.Add(instanceID)) - k_FontAssets_AtlasTexturesUpdateQueue.Add(fontAsset); - } + private List m_GlyphsPacked = new List(); /// - /// + /// /// - internal static void UpdateAtlasTexturesForFontAssetsInQueue() - { - int count = k_FontAssets_AtlasTexturesUpdateQueueLookup.Count; - - for (int i = 0; i < count; i++) - k_FontAssets_AtlasTexturesUpdateQueue[i].TryAddGlyphsToAtlasTextures(); - - if (count > 0) - { - k_FontAssets_AtlasTexturesUpdateQueue.Clear(); - k_FontAssets_AtlasTexturesUpdateQueueLookup.Clear(); - } - } + private List m_GlyphsToRender = new List(); /// - /// + /// List used in the process of adding new glyphs to the atlas texture. /// - //private bool m_IsAlreadyRegisteredForUpdate; + private List m_GlyphIndexList = new List(); /// - /// List of glyphs that need to be rendered and added to an atlas texture. + /// Internal static array used to avoid allocations when using the GetGlyphPairAdjustmentTable(). /// - private List m_GlyphsToRender = new List(); + internal static uint[] s_GlyphIndexArray = new uint[16]; /// - /// List of glyphs that we just rendered and added to an atlas texture. + /// /// - private List m_GlyphsRendered = new List(); + internal static List s_GlyphsToAdd = new List(16); + internal static HashSet s_GlyphsToAddLookup = new HashSet(); + + internal static List s_CharactersToAdd = new List(); + internal static HashSet s_CharactersToAddLookup = new HashSet(); /// - /// List of all the glyph indexes contained in the font asset. + /// Internal static list used to track characters that could not be added to the font asset. /// - private List m_GlyphIndexList = new List(); - - /// - /// List of glyph indexes newly added to the font asset. - /// This list is used in the process of retrieving font features. - /// - private List m_GlyphIndexListNewlyAdded = new List(); - - /// - /// - /// - internal List m_GlyphsToAdd = new List(); - internal HashSet m_GlyphsToAddLookup = new HashSet(); - - internal List m_CharactersToAdd = new List(); - internal HashSet m_CharactersToAddLookup = new HashSet(); - - /// - /// Internal list used to track characters that could not be added to the font asset. - /// - internal List s_MissingCharacterList = new List(); + internal static List s_MissingCharacterList = new List(16); /// /// Hash table used to track characters that are known to be missing from the font file. /// internal HashSet m_MissingUnicodesFromFontFile = new HashSet(); - /// - /// Internal static array used to avoid allocations when using the GetGlyphPairAdjustmentTable(). - /// - internal static uint[] k_GlyphIndexArray; - /// /// Try adding the characters from the provided string to the font asset. /// /// Array that contains the characters to add to the font asset. - /// /// Returns true if all the characters were successfully added to the font asset. Return false otherwise. - public bool TryAddCharacters(uint[] unicodes, bool includeFontFeatures = false) + public bool TryAddCharacters(uint[] unicodes) { uint[] missingUnicodes; - return TryAddCharacters(unicodes, out missingUnicodes, includeFontFeatures); + return TryAddCharacters(unicodes, out missingUnicodes); } /// @@ -1366,9 +1121,8 @@ public bool TryAddCharacters(uint[] unicodes, bool includeFontFeatures = false) /// /// Array that contains the characters to add to the font asset. /// Array containing the characters that could not be added to the font asset. - /// /// Returns true if all the characters were successfully added to the font asset. Return false otherwise. - public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool includeFontFeatures = false) + public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes) { Profiler.BeginSample("TMP.TryAddCharacters"); @@ -1378,7 +1132,9 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i if (m_AtlasPopulationMode == AtlasPopulationMode.Static) Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because its AtlasPopulationMode is set to Static.", this); else + { Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because the provided Unicode list is Null or Empty.", this); + } missingUnicodes = unicodes.ToArray(); Profiler.EndSample(); @@ -1394,10 +1150,10 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i } // Clear lists used to track which character and glyphs were added or missing. - m_GlyphsToAdd.Clear(); - m_GlyphsToAddLookup.Clear(); - m_CharactersToAdd.Clear(); - m_CharactersToAddLookup.Clear(); + s_GlyphsToAdd.Clear(); + s_GlyphsToAddLookup.Clear(); + s_CharactersToAdd.Clear(); + s_CharactersToAddLookup.Clear(); s_MissingCharacterList.Clear(); bool isMissingCharacters = false; @@ -1411,35 +1167,17 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i if (m_CharacterLookupDictionary.ContainsKey(unicode)) continue; - // Get the index of the glyph for this Unicode value. + // Get the index of the glyph for this unicode value. uint glyphIndex = FontEngine.GetGlyphIndex(unicode); // Skip missing glyphs if (glyphIndex == 0) { - // 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; - } + // Add character to list of missing characters. + s_MissingCharacterList.Add(unicode); - // 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; - } + isMissingCharacters = true; + continue; } TMP_Character character = new TMP_Character(unicode, glyphIndex); @@ -1447,25 +1185,28 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i // Check if glyph is already contained in the font asset as the same glyph might be referenced by multiple characters. if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) { - // Add a reference to the source text asset and glyph character.glyph = m_GlyphLookupDictionary[glyphIndex]; - character.textAsset = this; - m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(unicode, character); continue; } // Make sure glyph index has not already been added to list of glyphs to add. - if (m_GlyphsToAddLookup.Add(glyphIndex)) - m_GlyphsToAdd.Add(glyphIndex); + if (s_GlyphsToAddLookup.Contains(glyphIndex) == false) + { + s_GlyphsToAddLookup.Add(glyphIndex); + s_GlyphsToAdd.Add(glyphIndex); + } // Make sure unicode / character has not already been added. - if (m_CharactersToAddLookup.Add(unicode)) - m_CharactersToAdd.Add(character); + if (s_CharactersToAddLookup.Contains(unicode) == false) + { + s_CharactersToAddLookup.Add(unicode); + s_CharactersToAdd.Add(character); + } } - if (m_GlyphsToAdd.Count == 0) + if (s_GlyphsToAdd.Count == 0) { //Debug.LogWarning("No characters will be added to font asset [" + this.name + "] either because they are already present in the font asset or missing from the font file."); missingUnicodes = unicodes; @@ -1481,62 +1222,50 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i } Glyph[] glyphs; - bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); + bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(s_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); // Add new glyphs to relevant font asset data structure for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) { Glyph glyph = glyphs[i]; - uint glyphIndex = glyph.index; - glyph.atlasIndex = m_AtlasTextureIndex; // Add new glyph to glyph table. m_GlyphTable.Add(glyph); - m_GlyphLookupDictionary.Add(glyphIndex, glyph); - - m_GlyphIndexListNewlyAdded.Add(glyphIndex); - m_GlyphIndexList.Add(glyphIndex); + m_GlyphLookupDictionary.Add(glyph.index, glyph); } // Clear glyph index list to allow - m_GlyphsToAdd.Clear(); + s_GlyphsToAdd.Clear(); // Add new characters to relevant data structures as well as track glyphs that could not be added to the current atlas texture. - for (int i = 0; i < m_CharactersToAdd.Count; i++) + for (int i = 0; i < s_CharactersToAdd.Count; i++) { - TMP_Character character = m_CharactersToAdd[i]; + TMP_Character character = s_CharactersToAdd[i]; Glyph glyph; if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) { - m_GlyphsToAdd.Add(character.glyphIndex); + s_GlyphsToAdd.Add(character.glyphIndex); continue; } - // Add a reference to the source text asset and glyph character.glyph = glyph; - character.textAsset = this; - m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(character.unicode, character); // Remove character from list to add - m_CharactersToAdd.RemoveAt(i); + s_CharactersToAdd.RemoveAt(i); i -= 1; } - // Try adding missing glyphs to + // Try adding missing glyphs to if (m_IsMultiAtlasTexturesEnabled && allGlyphsAddedToTexture == false) { while (allGlyphsAddedToTexture == false) allGlyphsAddedToTexture = TryAddGlyphsToNewAtlasTexture(); } - // Get Font Features for the given characters - if (includeFontFeatures) - UpdateGlyphAdjustmentRecords(); - #if UNITY_EDITOR // Makes the changes to the font asset persistent. if (UnityEditor.EditorUtility.IsPersistent(this)) @@ -1546,9 +1275,9 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i #endif // Populate list of missing characters - for (int i = 0; i < m_CharactersToAdd.Count; i++) + for (int i = 0; i < s_CharactersToAdd.Count; i++) { - TMP_Character character = m_CharactersToAdd[i]; + TMP_Character character = s_CharactersToAdd[i]; s_MissingCharacterList.Add(character.unicode); } @@ -1566,7 +1295,6 @@ public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool i /// Try adding the characters from the provided string to the font asset. /// /// String containing the characters to add to the font asset. - /// /// Returns true if all the characters were successfully added to the font asset. Return false otherwise. public bool TryAddCharacters(string characters, bool includeFontFeatures = false) { @@ -1581,7 +1309,6 @@ public bool TryAddCharacters(string characters, bool includeFontFeatures = false /// /// String containing the characters to add to the font asset. /// String containing the characters that could not be added to the font asset. - /// /// Returns true if all the characters were successfully added to the font asset. Return false otherwise. public bool TryAddCharacters(string characters, out string missingCharacters, bool includeFontFeatures = false) { @@ -1611,10 +1338,10 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo } // Clear data structures used to track which glyph needs to be added to atlas texture. - m_GlyphsToAdd.Clear(); - m_GlyphsToAddLookup.Clear(); - m_CharactersToAdd.Clear(); - m_CharactersToAddLookup.Clear(); + s_GlyphsToAdd.Clear(); + s_GlyphsToAddLookup.Clear(); + s_CharactersToAdd.Clear(); + s_CharactersToAddLookup.Clear(); s_MissingCharacterList.Clear(); bool isMissingCharacters = false; @@ -1635,29 +1362,11 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo // Skip missing glyphs if (glyphIndex == 0) { - // 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; - } - - // 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); + // Add character to list of missing characters. + s_MissingCharacterList.Add(unicode); - isMissingCharacters = true; - continue; - } + isMissingCharacters = true; + continue; } TMP_Character character = new TMP_Character(unicode, glyphIndex); @@ -1665,25 +1374,28 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo // Check if glyph is already contained in the font asset as the same glyph might be referenced by multiple characters. if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) { - // Add a reference to the source text asset and glyph character.glyph = m_GlyphLookupDictionary[glyphIndex]; - character.textAsset = this; - m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(unicode, character); continue; } // Make sure glyph index has not already been added to list of glyphs to add. - if (m_GlyphsToAddLookup.Add(glyphIndex)) - m_GlyphsToAdd.Add(glyphIndex); + if (s_GlyphsToAddLookup.Contains(glyphIndex) == false) + { + s_GlyphsToAddLookup.Add(glyphIndex); + s_GlyphsToAdd.Add(glyphIndex); + } // Make sure unicode / character has not already been added. - if (m_CharactersToAddLookup.Add(unicode)) - m_CharactersToAdd.Add(character); + if (s_CharactersToAddLookup.Contains(unicode) == false) + { + s_CharactersToAddLookup.Add(unicode); + s_CharactersToAdd.Add(character); + } } - if (m_GlyphsToAdd.Count == 0) + if (s_GlyphsToAdd.Count == 0) { missingCharacters = characters; Profiler.EndSample(); @@ -1700,61 +1412,49 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo Glyph[] glyphs; - bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); + bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(s_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) { Glyph glyph = glyphs[i]; - uint glyphIndex = glyph.index; - glyph.atlasIndex = m_AtlasTextureIndex; // Add new glyph to glyph table. m_GlyphTable.Add(glyph); - m_GlyphLookupDictionary.Add(glyphIndex, glyph); - - m_GlyphIndexListNewlyAdded.Add(glyphIndex); - m_GlyphIndexList.Add(glyphIndex); + m_GlyphLookupDictionary.Add(glyph.index, glyph); } - // Clear glyph index list to track glyphs that were not added to the atlas texture - m_GlyphsToAdd.Clear(); + // Clear glyph index list to track glyphs that were not added to the atlas texture + s_GlyphsToAdd.Clear(); // Add new characters to relevant data structures. - for (int i = 0; i < m_CharactersToAdd.Count; i++) + for (int i = 0; i < s_CharactersToAdd.Count; i++) { - TMP_Character character = m_CharactersToAdd[i]; + TMP_Character character = s_CharactersToAdd[i]; Glyph glyph; if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) { - m_GlyphsToAdd.Add(character.glyphIndex); + s_GlyphsToAdd.Add(character.glyphIndex); continue; } - // Add a reference to the source text asset and glyph character.glyph = glyph; - character.textAsset = this; - m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(character.unicode, character); // Remove character from list to add - m_CharactersToAdd.RemoveAt(i); + s_CharactersToAdd.RemoveAt(i); i -= 1; } - // Try adding glyphs that didn't fit in the current atlas texture to new atlas texture + // Try adding glyphs that didn't fit in the current atlas texture to new atlas texture if (m_IsMultiAtlasTexturesEnabled && allGlyphsAddedToTexture == false) { while (allGlyphsAddedToTexture == false) allGlyphsAddedToTexture = TryAddGlyphsToNewAtlasTexture(); } - // Get Font Features for the given characters - if (includeFontFeatures) - UpdateGlyphAdjustmentRecords(); - #if UNITY_EDITOR // Makes the changes to the font asset persistent. if (UnityEditor.EditorUtility.IsPersistent(this)) @@ -1763,12 +1463,15 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo } #endif + // Get Font Features for the given characters + //GetFontFeatures() + missingCharacters = string.Empty; // Populate list of missing characters - for (int i = 0; i < m_CharactersToAdd.Count; i++) + for (int i = 0; i < s_CharactersToAdd.Count; i++) { - TMP_Character character = m_CharactersToAdd[i]; + TMP_Character character = s_CharactersToAdd[i]; s_MissingCharacterList.Add(character.unicode); } @@ -1780,8 +1483,6 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo } - // Functions to remove... - /* /// /// NOT USED CURRENTLY - Try adding character using Unicode value to font asset. /// @@ -1791,7 +1492,7 @@ public bool TryAddCharacters(string characters, out string missingCharacters, bo internal bool TryAddCharacter_Internal(uint unicode) { TMP_Character character = null; - + // Check if character is already contained in the character table. if (m_CharacterLookupDictionary.ContainsKey(unicode)) return true; @@ -1885,7 +1586,7 @@ internal TMP_Character AddCharacter_Internal(uint unicode, Glyph glyph) } else { - // Try packing new glyph + // Try packing new glyph if (FontEngine.TryPackGlyphInAtlas(glyph, m_AtlasPadding, GlyphPackingMode.ContactPointRule, m_AtlasRenderMode, m_AtlasWidth, m_AtlasHeight, m_FreeGlyphRects, m_UsedGlyphRects) == false) { // TODO: Add handling to create new atlas texture to fit glyph. @@ -1893,7 +1594,7 @@ internal TMP_Character AddCharacter_Internal(uint unicode, Glyph glyph) return null; } - //m_GlyphsToRender.Add(glyph); + m_GlyphsToRender.Add(glyph); } } @@ -1906,7 +1607,7 @@ internal TMP_Character AddCharacter_Internal(uint unicode, Glyph glyph) // Schedule glyph to be added to the font atlas texture //TM_FontAssetUpdateManager.RegisterFontAssetForUpdate(this); - //UpdateAtlasTexture(); // Temporary until callback system is revised. + UpdateAtlasTexture(); // Temporary until callback system is revised. //#if UNITY_EDITOR // Makes the changes to the font asset persistent. @@ -1918,7 +1619,6 @@ internal TMP_Character AddCharacter_Internal(uint unicode, Glyph glyph) return character; } - */ /// @@ -1934,7 +1634,7 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) character = null; - // Check if the Unicode character is already known to be missing from the source font file. + // Check if the unicode character is already known to be missing from the source font file. if (m_MissingUnicodesFromFontFile.Contains(unicode)) { Profiler.EndSample(); @@ -1949,37 +1649,25 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) uint glyphIndex = FontEngine.GetGlyphIndex(unicode); if (glyphIndex == 0) { - // 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; - } + m_MissingUnicodesFromFontFile.Add(unicode); - // Return if no potential alternative glyph representation is present in font file. - if (glyphIndex == 0) - { - m_MissingUnicodesFromFontFile.Add(unicode); - - Profiler.EndSample(); - return false; - } + Profiler.EndSample(); + return false; } // Check if glyph is already contained in the font asset as the same glyph might be referenced by multiple characters. if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) { - character = new TMP_Character(unicode, this, m_GlyphLookupDictionary[glyphIndex]); + character = new TMP_Character(unicode, m_GlyphLookupDictionary[glyphIndex]); m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(unicode, character); + if (TMP_Settings.getFontFeaturesAtRuntime) + { + if (k_FontAssetsToUpdateLookup.Add(instanceID)) + k_FontAssetsToUpdate.Add(this); + } + #if UNITY_EDITOR // Makes the changes to the font asset persistent. // OPTIMIZATION: This could be handled when exiting Play mode if we added any new characters to the asset. @@ -2016,10 +1704,7 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) // m_GlyphIndexList.Add(glyphIndex); // if (TMP_Settings.getFontFeaturesAtRuntime) - // { - // if (k_FontAssetsToUpdateLookup.Add(instanceID)) - // k_FontAssetsToUpdate.Add(this); - // } + // UpdateGlyphAdjustmentRecords(unicode, glyphIndex); // //Profiler.EndSample(); @@ -2049,21 +1734,23 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) { // Update glyph atlas index glyph.atlasIndex = m_AtlasTextureIndex; - + // Add new glyph to glyph table. m_GlyphTable.Add(glyph); m_GlyphLookupDictionary.Add(glyphIndex, glyph); // Add new character - character = new TMP_Character(unicode, this, glyph); + character = new TMP_Character(unicode, glyph); m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(unicode, character); m_GlyphIndexList.Add(glyphIndex); - m_GlyphIndexListNewlyAdded.Add(glyphIndex); if (TMP_Settings.getFontFeaturesAtRuntime) - RegisterFontAssetForFontFeatureUpdate(this); + { + if (k_FontAssetsToUpdateLookup.Add(instanceID)) + k_FontAssetsToUpdate.Add(this); + } #if UNITY_EDITOR // Makes the changes to the font asset persistent. @@ -2092,21 +1779,23 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) { // Update glyph atlas index glyph.atlasIndex = m_AtlasTextureIndex; - + // Add new glyph to glyph table. m_GlyphTable.Add(glyph); m_GlyphLookupDictionary.Add(glyphIndex, glyph); // Add new character - character = new TMP_Character(unicode, this, glyph); + character = new TMP_Character(unicode, glyph); m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(unicode, character); m_GlyphIndexList.Add(glyphIndex); - m_GlyphIndexListNewlyAdded.Add(glyphIndex); if (TMP_Settings.getFontFeaturesAtRuntime) - RegisterFontAssetForFontFeatureUpdate(this); + { + if (k_FontAssetsToUpdateLookup.Add(instanceID)) + k_FontAssetsToUpdate.Add(this); + } #if UNITY_EDITOR //SortGlyphTable(); @@ -2128,181 +1817,8 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) } - internal bool TryGetCharacter_and_QueueRenderToTexture(uint unicode, out TMP_Character character) - { - Profiler.BeginSample("TMP.TryAddCharacter"); - - character = null; - - // Check if the Unicode character is already known to be missing from the source font file. - if (m_MissingUnicodesFromFontFile.Contains(unicode)) - { - Profiler.EndSample(); - - return false; - } - - // Load font face. - if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) - return false; - - uint glyphIndex = FontEngine.GetGlyphIndex(unicode); - if (glyphIndex == 0) - { - // 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; - } - - // 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. - if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) - { - character = new TMP_Character(unicode, this, m_GlyphLookupDictionary[glyphIndex]); - m_CharacterTable.Add(character); - m_CharacterLookupDictionary.Add(unicode, character); - - #if UNITY_EDITOR - // Makes the changes to the font asset persistent. - // OPTIMIZATION: This could be handled when exiting Play mode if we added any new characters to the asset. - // Could also add some update registry to handle this. - //SortGlyphTable(); - if (UnityEditor.EditorUtility.IsPersistent(this)) - { - TMP_EditorResourceManager.RegisterResourceForUpdate(this); - } - #endif - - Profiler.EndSample(); - - return true; - } - - GlyphLoadFlags glyphLoadFlags = (GlyphRasterModes.RASTER_MODE_NO_HINTING & (GlyphRasterModes)m_AtlasRenderMode) == GlyphRasterModes.RASTER_MODE_NO_HINTING - ? GlyphLoadFlags.LOAD_NO_BITMAP | GlyphLoadFlags.LOAD_NO_HINTING - : GlyphLoadFlags.LOAD_NO_BITMAP; - - Glyph glyph = null; - - if (FontEngine.TryGetGlyphWithIndexValue(glyphIndex, glyphLoadFlags, out glyph)) - { - // Add new glyph to glyph table. - m_GlyphTable.Add(glyph); - m_GlyphLookupDictionary.Add(glyphIndex, glyph); - - // Add new character - character = new TMP_Character(unicode, this, glyph); - m_CharacterTable.Add(character); - m_CharacterLookupDictionary.Add(unicode, character); - - m_GlyphIndexList.Add(glyphIndex); - m_GlyphIndexListNewlyAdded.Add(glyphIndex); - - if (TMP_Settings.getFontFeaturesAtRuntime) - RegisterFontAssetForFontFeatureUpdate(this); - - // Add glyph to list of glyphs to be rendered - m_GlyphsToRender.Add(glyph); - - // Register font asset to render and add glyphs to atlas textures - RegisterFontAssetForAtlasTextureUpdate(this); - - #if UNITY_EDITOR - // Makes the changes to the font asset persistent. - // OPTIMIZATION: This could be handled when exiting Play mode if we added any new characters to the asset. - // Could also add some update registry to handle this. - //SortGlyphTable(); - if (UnityEditor.EditorUtility.IsPersistent(this)) - { - TMP_EditorResourceManager.RegisterResourceForUpdate(this); - } - #endif - - Profiler.EndSample(); - - return true; - } - - Profiler.EndSample(); - - return false; - } - - /// - /// This function requires an update to the TextCore:FontEngine - /// - internal void TryAddGlyphsToAtlasTextures() - { - /* - // Return if we don't have any glyphs to add. - if (m_GlyphsToRender.Count == 0) - return; - - Profiler.BeginSample("TMP.TryAddGlyphsToAtlasTextures"); - - // Resize the Atlas Texture to the appropriate size - if (m_AtlasTextures[m_AtlasTextureIndex].width == 0 || m_AtlasTextures[m_AtlasTextureIndex].height == 0) - { - //Debug.Log("Setting initial size of atlas texture used by font asset [" + this.name + "]."); - m_AtlasTextures[m_AtlasTextureIndex].Resize(m_AtlasWidth, m_AtlasHeight); - FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); - } - - bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToRender, m_GlyphsRendered, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex]); - - // Try adding glyphs that didn't fit in the current atlas texture to new atlas texture - if (m_IsMultiAtlasTexturesEnabled && allGlyphsAddedToTexture == false) - { - while (allGlyphsAddedToTexture == false) - { - // Create and prepare new atlas texture - SetupNewAtlasTexture(); - - // Try adding remaining glyphs in the newly created atlas texture - allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToRender, m_GlyphsRendered, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex]); - } - } - - if (allGlyphsAddedToTexture == false) - { - // TODO: Handle case when we have left over glyph to render that didn't fit in the atlas texture. - Debug.LogError("Unable to add some glyphs to atlas texture."); - } - - #if UNITY_EDITOR - // Makes the changes to the font asset persistent. - if (UnityEditor.EditorUtility.IsPersistent(this)) - { - //SortGlyphAndCharacterTables(); - TMP_EditorResourceManager.RegisterResourceForUpdate(this); - } - #endif - - Profiler.EndSample(); - */ - } - - /// - /// + /// /// /// bool TryAddGlyphsToNewAtlasTexture() @@ -2313,48 +1829,40 @@ bool TryAddGlyphsToNewAtlasTexture() Glyph[] glyphs; // Try adding remaining glyphs in the newly created atlas texture - bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); + bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(s_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); // Add new glyphs to relevant data structures. for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) { Glyph glyph = glyphs[i]; - uint glyphIndex = glyph.index; - glyph.atlasIndex = m_AtlasTextureIndex; // Add new glyph to glyph table. m_GlyphTable.Add(glyph); - m_GlyphLookupDictionary.Add(glyphIndex, glyph); - - m_GlyphIndexListNewlyAdded.Add(glyphIndex); - m_GlyphIndexList.Add(glyphIndex); + m_GlyphLookupDictionary.Add(glyph.index, glyph); } - // Clear glyph index list to allow us to track glyphs - m_GlyphsToAdd.Clear(); + // Clear glyph index list to allow us to track glyphs + s_GlyphsToAdd.Clear(); // Add new characters to relevant data structures as well as track glyphs that could not be added to the current atlas texture. - for (int i = 0; i < m_CharactersToAdd.Count; i++) + for (int i = 0; i < s_CharactersToAdd.Count; i++) { - TMP_Character character = m_CharactersToAdd[i]; + TMP_Character character = s_CharactersToAdd[i]; Glyph glyph; if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) { - m_GlyphsToAdd.Add(character.glyphIndex); + s_GlyphsToAdd.Add(character.glyphIndex); continue; } - // Add a reference to the source text asset and glyph character.glyph = glyph; - character.textAsset = this; - m_CharacterTable.Add(character); m_CharacterLookupDictionary.Add(character.unicode, character); // Remove character - m_CharactersToAdd.RemoveAt(i); + s_CharactersToAdd.RemoveAt(i); i -= 1; } @@ -2363,7 +1871,7 @@ bool TryAddGlyphsToNewAtlasTexture() /// - /// + /// /// void SetupNewAtlasTexture() { @@ -2397,18 +1905,41 @@ void SetupNewAtlasTexture() } + /// + /// Internal function used to get the glyph index for the given unicode. + /// + /// + /// + internal uint GetGlyphIndex(uint unicode) + { + // Check if glyph already exists in font asset. + if (m_CharacterLookupDictionary.ContainsKey(unicode)) + return m_CharacterLookupDictionary[unicode].glyphIndex; + + // Load font face. + if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) + return 0; + + return FontEngine.GetGlyphIndex(unicode); + } + + /// /// Not used currently /// internal void UpdateAtlasTexture() { // Return if we don't have any glyphs to add to atlas texture. + // This is possible if UpdateAtlasTexture() was called manually. + //if (m_GlyphsToPack.Count == 0) + // return; + if (m_GlyphsToRender.Count == 0) return; //Debug.Log("Updating [" + this.name + "]'s atlas texture."); - // Pack glyphs in the given atlas texture size. + // Pack glyphs in the given atlas texture size. // TODO: Packing and glyph render modes should be defined in the font asset. //FontEngine.PackGlyphsInAtlas(m_GlyphsToPack, m_GlyphsPacked, m_AtlasPadding, GlyphPackingMode.ContactPointRule, GlyphRenderMode.SDFAA, m_AtlasWidth, m_AtlasHeight, m_FreeGlyphRects, m_UsedGlyphRects); //FontEngine.RenderGlyphsToTexture(m_GlyphsPacked, m_AtlasPadding, GlyphRenderMode.SDFAA, m_AtlasTextures[m_AtlasTextureIndex]); @@ -2421,32 +1952,32 @@ internal void UpdateAtlasTexture() FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); } - //FontEngine.RenderGlyphsToTexture(m_GlyphsToRender, m_AtlasPadding, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex]); + FontEngine.RenderGlyphsToTexture(m_GlyphsToRender, m_AtlasPadding, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex]); // Apply changes to atlas texture m_AtlasTextures[m_AtlasTextureIndex].Apply(false, false); // Add glyphs that were successfully packed to the glyph table. - //for (int i = 0; i < m_GlyphsToRender.Count /* m_GlyphsPacked.Count */; i++) - //{ - // Glyph glyph = m_GlyphsToRender[i]; // m_GlyphsPacked[i]; + for (int i = 0; i < m_GlyphsToRender.Count /* m_GlyphsPacked.Count */; i++) + { + Glyph glyph = m_GlyphsToRender[i]; // m_GlyphsPacked[i]; - // // Update atlas texture index - // glyph.atlasIndex = m_AtlasTextureIndex; + // Update atlas texture index + glyph.atlasIndex = m_AtlasTextureIndex; - // m_GlyphTable.Add(glyph); - // m_GlyphLookupDictionary.Add(glyph.index, glyph); - //} + m_GlyphTable.Add(glyph); + m_GlyphLookupDictionary.Add(glyph.index, glyph); + } // Clear list of glyphs - //m_GlyphsPacked.Clear(); - //m_GlyphsToRender.Clear(); + m_GlyphsPacked.Clear(); + m_GlyphsToRender.Clear(); // Add any remaining glyphs into new atlas texture if multi texture support if enabled. - //if (m_GlyphsToPack.Count > 0) - //{ + if (m_GlyphsToPack.Count > 0) + { /* - // Create new atlas texture + // Create new atlas texture Texture2D tex = new Texture2D(m_AtlasWidth, m_AtlasHeight, TextureFormat.Alpha8, false, true); tex.SetPixels32(new Color32[m_AtlasWidth * m_AtlasHeight]); tex.Apply(); @@ -2458,161 +1989,54 @@ internal void UpdateAtlasTexture() m_AtlasTextures[m_AtlasTextureIndex] = tex; */ - //} + } #if UNITY_EDITOR // Makes the changes to the font asset persistent. - //SortAllTables(); + SortGlyphAndCharacterTables(); TMP_EditorResourceManager.RegisterResourceForUpdate(this); #endif } - /// - /// - /// - 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. - 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 - m_GlyphIndexListNewlyAdded.Clear(); - - if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) - { - Profiler.EndSample(); - return; - } - - if (m_FontFeatureTable == null) - m_FontFeatureTable = new TMP_FontFeatureTable(); - - for (int i = 0; i < pairAdjustmentRecords.Length && pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) - { - uint pairKey = pairAdjustmentRecords[i].secondAdjustmentRecord.glyphIndex << 16 | pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex; - - // Check if table already contains a pair adjustment record for this key. - if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey)) - continue; - - TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(pairAdjustmentRecords[i]); - - m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); - m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, record); - } - - Profiler.EndSample(); - } /// - /// Function used for debugging and performance testing. + /// Function called to update the font atlas texture and character data of font assets to which + /// new characters were added. /// - /// - internal void UpdateGlyphAdjustmentRecords(uint[] glyphIndexes) + public static void UpdateFontAssets() { - Profiler.BeginSample("TMP.UpdateGlyphAdjustmentRecords"); + int count = k_FontAssetsToUpdate.Count; - // Get glyph pair adjustment records from font file. - GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentTable(glyphIndexes); - - // Clear newly added glyph list - //m_GlyphIndexListNewlyAdded.Clear(); - - if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) + for (int i = 0; i < count; i++) { - Profiler.EndSample(); - return; + k_FontAssetsToUpdate[i].UpdateGlyphAdjustmentRecords(); } - if (m_FontFeatureTable == null) - m_FontFeatureTable = new TMP_FontFeatureTable(); - - for (int i = 0; i < pairAdjustmentRecords.Length && pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) + if (count > 0) { - uint pairKey = pairAdjustmentRecords[i].secondAdjustmentRecord.glyphIndex << 16 | pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex; - - // Check if table already contains a pair adjustment record for this key. - if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey)) - continue; - - TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(pairAdjustmentRecords[i]); - - m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); - m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, record); + k_FontAssetsToUpdate.Clear(); + k_FontAssetsToUpdateLookup.Clear(); } - - Profiler.EndSample(); } - /// - /// Function requires an update to the TextCore:FontEngine - /// - /// - internal void UpdateGlyphAdjustmentRecords(List glyphIndexes) + internal void UpdateGlyphAdjustmentRecords() { - /* Profiler.BeginSample("TMP.UpdateGlyphAdjustmentRecords"); - // Get glyph pair adjustment records from font file. - int recordCount; - GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentRecords(glyphIndexes, out recordCount); - - // Clear newly added glyph list - //m_GlyphIndexListNewlyAdded.Clear(); - - if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) - { - Profiler.EndSample(); - return; - } - - if (m_FontFeatureTable == null) - m_FontFeatureTable = new TMP_FontFeatureTable(); - - for (int i = 0; i < pairAdjustmentRecords.Length && pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) - { - uint pairKey = pairAdjustmentRecords[i].secondAdjustmentRecord.glyphIndex << 16 | pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex; - - // Check if table already contains a pair adjustment record for this key. - if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey)) - continue; - - TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(pairAdjustmentRecords[i]); + int glyphCount = m_GlyphIndexList.Count; - m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); - m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, record); - } + if (s_GlyphIndexArray.Length < glyphCount) + s_GlyphIndexArray = new uint[Mathf.NextPowerOfTwo(glyphCount + 1)]; - #if UNITY_EDITOR - m_FontFeatureTable.SortGlyphPairAdjustmentRecords(); - #endif + for (int i = 0; i < glyphCount; i++) + s_GlyphIndexArray[i] = m_GlyphIndexList[i]; - Profiler.EndSample(); - */ - } - - /// - /// Function requires an update to the TextCore:FontEngine - /// - /// - /// - internal void UpdateGlyphAdjustmentRecords(List newGlyphIndexes, List allGlyphIndexes) - { - /* - Profiler.BeginSample("TMP.UpdateGlyphAdjustmentRecords"); + // Clear unused array elements + Array.Clear(s_GlyphIndexArray, glyphCount, s_GlyphIndexArray.Length - glyphCount); // Get glyph pair adjustment records from font file. - GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentRecords(newGlyphIndexes, allGlyphIndexes); - - // Clear newly added glyph list - m_GlyphIndexListNewlyAdded.Clear(); + // TODO: Revise FontEngine bindings to use a more efficient function where only the new glyph index is passed. + GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentTable(s_GlyphIndexArray); if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) { @@ -2642,28 +2066,8 @@ internal void UpdateGlyphAdjustmentRecords(List newGlyphIndexes, List - /// Internal method to copy generic list data to generic array of the same type. - /// - /// Source - /// Destination - /// Element type - void CopyListDataToArray(List srcList, ref T[] dstArray) - { - int size = srcList.Count; - - // Make sure destination array is appropriately sized. - if (dstArray == null) - dstArray = new T[size]; - else - Array.Resize(ref dstArray, size); - - for (int i = 0; i < size; i++) - dstArray[i] = srcList[i]; - } /// /// Clears font asset data including the glyph and character tables and textures. @@ -2672,65 +2076,11 @@ void CopyListDataToArray(List srcList, ref T[] dstArray) /// Will set the atlas texture size to zero width and height if true. public void ClearFontAssetData(bool setAtlasSizeToZero = false) { - Profiler.BeginSample("TMP.ClearFontAssetData"); - #if UNITY_EDITOR // Record full object undo in the Editor. //UnityEditor.Undo.RecordObjects(new UnityEngine.Object[] { this, this.atlasTexture }, "Resetting Font Asset"); #endif - // Clear glyph, character and font feature tables - ClearFontAssetTables(); - - // Clear atlas textures - ClearAtlasTextures(setAtlasSizeToZero); - - ReadFontAssetDefinition(); - - //TMP_ResourceManager.RebuildFontAssetCache(instanceID); - - #if UNITY_EDITOR - // Makes the changes to the font asset persistent. - TMP_EditorResourceManager.RegisterResourceForUpdate(this); - #endif - - Profiler.EndSample(); - } - - /// - /// - /// - internal void UpdateFontAssetData() - { - Profiler.BeginSample("TMP.UpdateFontAssetData"); - - // Get list of all characters currently contained in the font asset. - uint[] unicodeCharacters = new uint[m_CharacterTable.Count]; - - for (int i = 0; i < m_CharacterTable.Count; i++) - unicodeCharacters[i] = m_CharacterTable[i].unicode; - - // Clear glyph, character and font feature tables - ClearFontAssetTables(); - - // Clear atlas textures - ClearAtlasTextures(true); - - ReadFontAssetDefinition(); - - //TMP_ResourceManager.RebuildFontAssetCache(instanceID); - - // Add glyphs - TryAddCharacters(unicodeCharacters, true); - - Profiler.EndSample(); - } - - /// - /// - /// - internal void ClearFontAssetTables() - { // Clear glyph and character tables if (m_GlyphTable != null) m_GlyphTable.Clear(); @@ -2749,75 +2099,74 @@ internal void ClearFontAssetTables() m_FreeGlyphRects.Add(new GlyphRect(0, 0, m_AtlasWidth - packingModifier, m_AtlasHeight - packingModifier)); } - if (m_GlyphsToRender != null) - m_GlyphsToRender.Clear(); + if (m_GlyphsToPack != null) + m_GlyphsToPack.Clear(); - if (m_GlyphsRendered != null) - m_GlyphsRendered.Clear(); + if (m_GlyphsPacked != null) + m_GlyphsPacked.Clear(); // Clear Glyph Adjustment Table if (m_FontFeatureTable != null && m_FontFeatureTable.m_GlyphPairAdjustmentRecords != null) m_FontFeatureTable.glyphPairAdjustmentRecords.Clear(); - } - /// - /// Internal function to clear all atlas textures. - /// - /// Set main atlas texture size to zero if true. - internal void ClearAtlasTextures(bool setAtlasSizeToZero = false) - { m_AtlasTextureIndex = 0; - // Return if we don't have any atlas textures - if (m_AtlasTextures == null) - return; - - // Clear all atlas textures - for (int i = 0; i < m_AtlasTextures.Length; i++) + // Clear atlas textures + if (m_AtlasTextures != null) { - Texture2D texture = m_AtlasTextures[i]; - - if (i > 0 && texture != null) + for (int i = 0; i < m_AtlasTextures.Length; i++) { - DestroyImmediate(texture, true); + Texture2D texture = m_AtlasTextures[i]; - #if UNITY_EDITOR - if (UnityEditor.EditorUtility.IsPersistent(this)) - TMP_EditorResourceManager.RegisterResourceForReimport(this); - #endif - } + if (i > 0) + DestroyImmediate(texture, true); - if (texture == null) - continue; + if (texture == null) + continue; - // TODO: Need texture to be readable. - if (m_AtlasTextures[i].isReadable == false) - { - #if UNITY_EDITOR - FontEngineEditorUtilities.SetAtlasTextureIsReadable(m_AtlasTextures[i], true); - #endif - } + // TODO: Need texture to be readable. + if (m_AtlasTextures[i].isReadable == false) + { + #if UNITY_EDITOR //&& UNITY_2018_4_5_OR_NEWER + FontEngineEditorUtilities.SetAtlasTextureIsReadable(m_AtlasTextures[i], true); + #else + Debug.LogWarning("Unable to reset font asset [" + this.name + "]'s atlas texture. Please make the texture [" + m_AtlasTextures[i].name + "] readable.", m_AtlasTextures[i]); + continue; + #endif + } - if (setAtlasSizeToZero) - { - texture.Resize(0, 0, TextureFormat.Alpha8, false); - } - else if (texture.width != m_AtlasWidth || texture.height != m_AtlasHeight) - { - texture.Resize(m_AtlasWidth, m_AtlasHeight, TextureFormat.Alpha8, false); - } + if (setAtlasSizeToZero) + { + texture.Resize(0, 0, TextureFormat.Alpha8, false); + } + else if (texture.width != m_AtlasWidth || texture.height != m_AtlasHeight) + { + texture.Resize(m_AtlasWidth, m_AtlasHeight, TextureFormat.Alpha8, false); + } - // Clear texture atlas - FontEngine.ResetAtlasTexture(texture); - texture.Apply(); + // Clear texture atlas + FontEngine.ResetAtlasTexture(texture); + texture.Apply(); - if (i == 0) - m_AtlasTexture = texture; + if (i == 0) + m_AtlasTexture = texture; - m_AtlasTextures[i] = texture; + m_AtlasTextures[i] = texture; + } + } + + #if UNITY_EDITOR + if (UnityEditor.EditorUtility.IsPersistent(this)) + { + TMP_EditorResourceManager.RegisterResourceForReimport(this); } + #endif + + ReadFontAssetDefinition(); } + + /// /// Internal method used to upgrade font asset to support Dynamic SDF. /// @@ -2944,7 +2293,7 @@ internal void UpgradeFontAsset() Glyph glyph = new Glyph(); uint glyphIndex = (uint)i + 1; - + //#if UNITY_EDITOR //if (m_SourceFontFile_EditorRef != null) // glyphIndex = FontEngine.GetGlyphIndex((uint)oldGlyph.id); @@ -2958,7 +2307,7 @@ internal void UpgradeFontAsset() m_GlyphTable.Add(glyph); - TMP_Character character = new TMP_Character((uint)oldGlyph.id, this, glyph); + TMP_Character character = new TMP_Character((uint)oldGlyph.id, glyph); if (oldGlyph.id == 32) isSpaceCharacterPresent = true; @@ -2972,7 +2321,7 @@ internal void UpgradeFontAsset() Debug.Log("Synthesizing Space for [" + this.name + "]"); Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, m_FaceInfo.ascentLine / 5), GlyphRect.zero, 1.0f, 0); m_GlyphTable.Add(glyph); - m_CharacterTable.Add(new TMP_Character(32, this, glyph)); + m_CharacterTable.Add(new TMP_Character(32, glyph)); } // Clear legacy glyph info list. @@ -2991,7 +2340,7 @@ internal void UpgradeFontAsset() } /// - /// + /// /// void UpgradeGlyphAdjustmentTableToFontFeatureTable() { @@ -3040,4 +2389,4 @@ void UpgradeGlyphAdjustmentTableToFontFeatureTable() } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/TMP_FontAssetUtilities.cs b/Scripts/Runtime/TMP_FontAssetUtilities.cs index a0e6439..a2d7f19 100644 --- a/Scripts/Runtime/TMP_FontAssetUtilities.cs +++ b/Scripts/Runtime/TMP_FontAssetUtilities.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; @@ -25,9 +28,9 @@ public static TMP_FontAssetUtilities instance /// - /// HashSet containing instance ID of font assets already searched. + /// List containing instance ID of font assets already searched. /// - private static HashSet k_SearchedAssets; + private static List k_SearchedFontAssets; /// @@ -41,20 +44,20 @@ public static TMP_FontAssetUtilities instance /// Include the fallback font assets in the search /// The font style /// The font weight - /// Indicates if the OUT font asset is an alternative typeface or fallback font asset + /// Indicates if the OUT font asset is an alternative typeface or fallback font asset /// The font asset that contains the requested character /// - public static TMP_Character GetCharacterFromFontAsset(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface) + public static TMP_Character GetCharacterFromFontAsset(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { if (includeFallbacks) { - if (k_SearchedAssets == null) - k_SearchedAssets = new HashSet(); + if (k_SearchedFontAssets == null) + k_SearchedFontAssets = new List(); else - k_SearchedAssets.Clear(); + k_SearchedFontAssets.Clear(); } - return GetCharacterFromFontAsset_Internal(unicode, sourceFontAsset, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface); + return GetCharacterFromFontAsset_Internal(unicode, sourceFontAsset, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset); } @@ -62,10 +65,11 @@ public static TMP_Character GetCharacterFromFontAsset(uint unicode, TMP_FontAsse /// Internal function returning the text element character for the given unicode value taking into consideration the font style and weight. /// Function searches the source font asset, list of font assets assigned as alternative typefaces and list of fallback font assets. /// - private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface) + private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { + fontAsset = null; isAlternativeTypeface = false; - TMP_Character character = null; + TMP_Character characterData = null; #region FONT WEIGHT AND FONT STYLE HANDLING // Determine if a font weight or style is used. If so check if an alternative typeface is assigned for the given weight and / or style. @@ -108,24 +112,23 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM break; } - TMP_FontAsset temp = isItalic ? fontWeights[fontWeightIndex].italicTypeface : fontWeights[fontWeightIndex].regularTypeface; + fontAsset = isItalic ? fontWeights[fontWeightIndex].italicTypeface : fontWeights[fontWeightIndex].regularTypeface; - if (temp != null) + if (fontAsset != null) { - if (temp.characterLookupTable.TryGetValue(unicode, out character)) + if (fontAsset.characterLookupTable.TryGetValue(unicode, out characterData)) { isAlternativeTypeface = true; - return character; + return characterData; } - - if (temp.atlasPopulationMode == AtlasPopulationMode.Dynamic) + else if (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { - if (temp.TryAddCharacterInternal(unicode, out character)) + if (fontAsset.TryAddCharacterInternal(unicode, out characterData)) { isAlternativeTypeface = true; - return character; + return characterData; } // Check if the source font file contains the requested character. @@ -151,17 +154,28 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM #endregion // Search the source font asset for the requested character. - if (sourceFontAsset.characterLookupTable.TryGetValue(unicode, out character)) - return character; + if (sourceFontAsset.characterLookupTable.TryGetValue(unicode, out characterData)) + { + // We were able to locate the requested character in the given font asset. + fontAsset = sourceFontAsset; - if (sourceFontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) + return characterData; + } + else if (sourceFontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic) { - if (sourceFontAsset.TryAddCharacterInternal(unicode, out character)) - return character; + if (sourceFontAsset.TryAddCharacterInternal(unicode, out characterData)) + { + fontAsset = sourceFontAsset; + + return characterData; + } + + // 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. - if (character == null && includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null) + if (characterData == null && includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null) { // Get reference to the list of fallback font assets. List fallbackFontAssets = sourceFontAsset.fallbackFontAssetTable; @@ -169,28 +183,30 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM if (fallbackFontAssets != null && fallbackCount > 0) { - for (int i = 0; i < fallbackCount; i++) + for (int i = 0; i < fallbackCount && characterData == null; i++) { TMP_FontAsset temp = fallbackFontAssets[i]; - if (temp == null) - continue; + if (temp == null) continue; - int id = temp.instanceID; + int id = temp.GetInstanceID(); - // Try adding font asset to search list. If already present skip to the next one otherwise check if it contains the requested character. - if (k_SearchedAssets.Add(id) == false) + // Skip over the fallback font asset in the event it is null or if already searched. + if (k_SearchedFontAssets.Contains(id)) continue; - // Add reference to this search query - sourceFontAsset.FallbackSearchQueryLookup.Add(id); + // Add to list of font assets already searched. + k_SearchedFontAssets.Add(id); - character = GetCharacterFromFontAsset_Internal(unicode, temp, true, fontStyle, fontWeight, out isAlternativeTypeface); + characterData = GetCharacterFromFontAsset_Internal(unicode, temp, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset); - if (character != null) - return character; + if (characterData != null) + { + return characterData; + } } } + } return null; @@ -204,156 +220,45 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM /// The typeface type indicates whether the returned font asset is the source font asset, an alternative typeface or fallback font asset. /// /// The unicode value of the requested character - /// The font asset originating the search query /// The list of font assets to search /// Determines if the fallback of each font assets on the list will be searched /// The font style /// The font weight - /// Determines if the OUT font asset is an alternative typeface or fallback font asset + /// Determines if the OUT font asset is an alternative typeface or fallback font asset + /// The font asset that contains the requested character /// - public static TMP_Character GetCharacterFromFontAssets(uint unicode, TMP_FontAsset sourceFontAsset, List fontAssets, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface) + public static TMP_Character GetCharacterFromFontAssets(uint unicode, List fontAssets, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface, out TMP_FontAsset fontAsset) { isAlternativeTypeface = false; // Make sure font asset list is valid if (fontAssets == null || fontAssets.Count == 0) + { + fontAsset = null; return null; + } if (includeFallbacks) { - if (k_SearchedAssets == null) - k_SearchedAssets = new HashSet(); + if (k_SearchedFontAssets == null) + k_SearchedFontAssets = new List(); else - k_SearchedAssets.Clear(); + k_SearchedFontAssets.Clear(); } int fontAssetCount = fontAssets.Count; for (int i = 0; i < fontAssetCount; i++) { - TMP_FontAsset fontAsset = fontAssets[i]; - - if (fontAsset == null) continue; - - // Add reference to this search query - sourceFontAsset.FallbackSearchQueryLookup.Add(fontAsset.instanceID); - - TMP_Character character = GetCharacterFromFontAsset_Internal(unicode, fontAsset, includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface); - - if (character != null) - return character; - } - - return null; - } - - // ===================================================================== - // SPRITE ASSET - Functions - // ===================================================================== - - /// - /// - /// - /// - /// - /// - /// - public static TMP_SpriteCharacter GetSpriteCharacterFromSpriteAsset(uint unicode, TMP_SpriteAsset spriteAsset, bool includeFallbacks) - { - // Make sure we have a valid sprite asset to search - if (spriteAsset == null) - return null; - - TMP_SpriteCharacter spriteCharacter; - - // Search sprite asset for potential sprite character for the given unicode value - if (spriteAsset.spriteCharacterLookupTable.TryGetValue(unicode, out spriteCharacter)) - return spriteCharacter; - - if (includeFallbacks) - { - // Clear searched assets - if (k_SearchedAssets == null) - k_SearchedAssets = new HashSet(); - else - k_SearchedAssets.Clear(); - - // Add current sprite asset to already searched assets. - k_SearchedAssets.Add(spriteAsset.instanceID); + if (fontAssets[i] == null) continue; - List fallbackSpriteAsset = spriteAsset.fallbackSpriteAssets; + TMP_Character characterData = GetCharacterFromFontAsset_Internal(unicode, fontAssets[i], includeFallbacks, fontStyle, fontWeight, out isAlternativeTypeface, out fontAsset); - if (fallbackSpriteAsset != null && fallbackSpriteAsset.Count > 0) - { - int fallbackCount = fallbackSpriteAsset.Count; - - for (int i = 0; i < fallbackCount; i++) - { - TMP_SpriteAsset temp = fallbackSpriteAsset[i]; - - if (temp == null) - continue; - - int id = temp.instanceID; - - // Try adding asset to search list. If already present skip to the next one otherwise check if it contains the requested character. - if (k_SearchedAssets.Add(id) == false) - continue; - - spriteCharacter = GetSpriteCharacterFromSpriteAsset_Internal(unicode, temp, true); - - if (spriteCharacter != null) - return spriteCharacter; - } - } + if (characterData != null) + return characterData; } - return null; - } - - /// - /// - /// - /// - /// - /// - /// - static TMP_SpriteCharacter GetSpriteCharacterFromSpriteAsset_Internal(uint unicode, TMP_SpriteAsset spriteAsset, bool includeFallbacks) - { - TMP_SpriteCharacter spriteCharacter; - - // Search sprite asset for potential sprite character for the given unicode value - if (spriteAsset.spriteCharacterLookupTable.TryGetValue(unicode, out spriteCharacter)) - return spriteCharacter; - - if (includeFallbacks) - { - List fallbackSpriteAsset = spriteAsset.fallbackSpriteAssets; - - if (fallbackSpriteAsset != null && fallbackSpriteAsset.Count > 0) - { - int fallbackCount = fallbackSpriteAsset.Count; - - for (int i = 0; i < fallbackCount; i++) - { - TMP_SpriteAsset temp = fallbackSpriteAsset[i]; - - if (temp == null) - continue; - - int id = temp.instanceID; - - // Try adding asset to search list. If already present skip to the next one otherwise check if it contains the requested character. - if (k_SearchedAssets.Add(id) == false) - continue; - - spriteCharacter = GetSpriteCharacterFromSpriteAsset_Internal(unicode, temp, true); - - if (spriteCharacter != null) - return spriteCharacter; - } - } - } + fontAsset = null; return null; } @@ -365,7 +270,7 @@ static TMP_SpriteCharacter GetSpriteCharacterFromSpriteAsset_Internal(uint unico private static bool k_IsFontEngineInitialized; - /* + private static bool TryGetCharacterFromFontFile(uint unicode, TMP_FontAsset fontAsset, out TMP_Character character) { character = null; @@ -437,6 +342,6 @@ public static bool TryGetGlyphFromFontFile(uint glyphIndex, TMP_FontAsset fontAs return false; } - */ + } } diff --git a/Scripts/Runtime/TMP_FontFeatureTable.cs b/Scripts/Runtime/TMP_FontFeatureTable.cs index 633a84e..1e500d8 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. /// - public List glyphPairAdjustmentRecords + internal 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 26d5810..fb37a21 100644 --- a/Scripts/Runtime/TMP_InputField.cs +++ b/Scripts/Runtime/TMP_InputField.cs @@ -132,7 +132,7 @@ public class TouchScreenKeyboardEvent : UnityEvent { private float m_ScrollPosition; /// - /// + /// /// [SerializeField] protected float m_ScrollSensitivity = 1.0f; @@ -422,10 +422,6 @@ public bool shouldHideSoftKeyboard case RuntimePlatform.WSAPlayerX86: case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerARM: - #if UNITY_2019_3_OR_NEWER - case RuntimePlatform.Stadia: - #endif - case RuntimePlatform.Switch: return m_HideSoftKeyboard; default: return true; @@ -442,17 +438,13 @@ public bool shouldHideSoftKeyboard case RuntimePlatform.WSAPlayerX86: case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerARM: - #if UNITY_2019_3_OR_NEWER - case RuntimePlatform.Stadia: - #endif - case RuntimePlatform.Switch: SetPropertyUtility.SetStruct(ref m_HideSoftKeyboard, value); break; default: m_HideSoftKeyboard = true; break; } - + if (m_HideSoftKeyboard == true && m_SoftKeyboard != null && TouchScreenKeyboard.isSupported && m_SoftKeyboard.active) { m_SoftKeyboard.active = false; @@ -468,7 +460,6 @@ private bool isKeyboardUsingEvents() case RuntimePlatform.Android: case RuntimePlatform.IPhonePlayer: case RuntimePlatform.tvOS: - case RuntimePlatform.Switch: return false; default: return true; @@ -634,7 +625,7 @@ public Scrollbar verticalScrollbar if (m_VerticalScrollbar) { m_VerticalScrollbar.onValueChanged.AddListener(OnScrollbarValueChange); - + } } } @@ -687,14 +678,13 @@ public int characterLimit public float pointSize { get { return m_GlobalPointSize; } - set - { - if (SetPropertyUtility.SetStruct(ref m_GlobalPointSize, Math.Max(0, value))) - { - SetGlobalPointSize(m_GlobalPointSize); - UpdateLabel(); + set { + if (SetPropertyUtility.SetStruct(ref m_GlobalPointSize, Math.Max(0, value))) + { + SetGlobalPointSize(m_GlobalPointSize); + UpdateLabel(); + } } - } } /// @@ -740,7 +730,7 @@ public bool resetOnDeActivation private bool m_SelectionStillActive = false; private bool m_ReleaseSelection = false; - private GameObject m_PreviouslySelectedObject; + private GameObject m_SelectedObject; /// /// Controls whether the original text is restored when pressing "ESC". @@ -822,7 +812,7 @@ public TMP_InputValidator inputValidator set { if (SetPropertyUtility.SetClass(ref m_InputValidator, value)) SetToCustom(CharacterValidation.CustomValidator); } } [SerializeField] - protected TMP_InputValidator m_InputValidator = null; + protected TMP_InputValidator m_InputValidator = null; public bool readOnly { get { return m_ReadOnly; } set { m_ReadOnly = value; } } @@ -921,7 +911,7 @@ public int selectionFocusPosition /// - /// + /// /// public int stringPosition { @@ -1425,67 +1415,25 @@ 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_PreviouslySelectedObject) - return; - - m_PreviouslySelectedObject = selectedObject; - - // Special handling for Vertical Scrollbar - if (m_VerticalScrollbar && selectedObject == m_VerticalScrollbar.gameObject) + if (selectedObject != m_SelectedObject) { - // Do not release selection - return; - } + m_SelectedObject = selectedObject; - // Release selection for all objects when ResetOnDeActivation is true - if (m_ResetOnDeActivation) - { - ReleaseSelection(); - return; + // Release current selection of the newly selected object is another Input Field + if (selectedObject.GetComponent() != null) + { + // Release selection + m_SelectionStillActive = false; + MarkGeometryAsDirty(); + m_SelectedObject = null; + } } - // Release current selection of selected object is another Input Field - if (selectedObject.GetComponent() != null) - ReleaseSelection(); - return; } - #if ENABLE_INPUT_SYSTEM - if (m_ProcessingEvent != null && m_ProcessingEvent.rawType == EventType.MouseDown && m_ProcessingEvent.button == 0) - { - // Check for Double Click - bool isDoubleClick = false; - float timeStamp = Time.unscaledTime; - - if (m_KeyDownStartTime + m_DoubleClickDelay > timeStamp) - isDoubleClick = true; - - m_KeyDownStartTime = timeStamp; - - if (isDoubleClick) - { - //m_StringPosition = m_StringSelectPosition = 0; - //m_CaretPosition = m_CaretSelectPosition = 0; - //m_TextComponent.rectTransform.localPosition = m_DefaultTransformPosition; - - //if (caretRectTrans != null) - // caretRectTrans.localPosition = Vector3.zero; - - ReleaseSelection(); - - return; - } - } - #else if (Input.GetKeyDown(KeyCode.Mouse0)) { // Check for Double Click @@ -1506,12 +1454,13 @@ protected virtual void LateUpdate() //if (caretRectTrans != null) // caretRectTrans.localPosition = Vector3.zero; - ReleaseSelection(); + m_SelectionStillActive = false; + + MarkGeometryAsDirty(); return; } } - #endif } UpdateMaskRegions(); @@ -1759,12 +1708,7 @@ public override void OnPointerDown(PointerEventData eventData) } } - #if ENABLE_INPUT_SYSTEM - Event.PopEvent(m_ProcessingEvent); - bool shift = m_ProcessingEvent != null && (m_ProcessingEvent.modifiers & EventModifiers.Shift) != 0; - #else bool shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); - #endif // Check for Double Click bool isDoubleClick = false; @@ -1857,7 +1801,7 @@ public override void OnPointerDown(PointerEventData eventData) else { // Select current character - caretPositionInternal = insertionIndex; + caretPositionInternal = insertionIndex; caretSelectPositionInternal = caretPositionInternal + 1; stringPositionInternal = m_TextComponent.textInfo.characterInfo[insertionIndex].index; @@ -2063,7 +2007,7 @@ protected virtual bool IsValidChar(char c) // Null character if (c == 0) return false; - + // Delete key on mac if (c == 127) return false; @@ -2090,7 +2034,7 @@ public void ProcessEvent(Event e) /// - /// + /// /// /// public virtual void OnUpdateSelected(BaseEventData eventData) @@ -2169,17 +2113,12 @@ public virtual void OnUpdateSelected(BaseEventData eventData) /// - /// + /// /// /// public virtual void OnScroll(PointerEventData eventData) { - // Return if Single Line - if (m_LineType == LineType.SingleLine) - return; - - if (m_TextComponent.preferredHeight < m_TextViewport.rect.height) - return; + if (m_TextComponent.preferredHeight < m_TextViewport.rect.height) return; float scrollDirection = -eventData.scrollDelta.y; @@ -2189,6 +2128,9 @@ 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; @@ -2354,7 +2296,7 @@ private void MoveLeft(bool shift, bool ctrl) { stringSelectPositionInternal = stringPositionInternal = position; - // Only decrease caret position as we cross character boundary. + // Only decrease caret position as we cross character boundary. if (caretPositionInternal > 0 && stringPositionInternal <= m_TextComponent.textInfo.characterInfo[caretPositionInternal - 1].index) caretSelectPositionInternal = caretPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal); } @@ -3135,10 +3077,7 @@ protected void UpdateLabel() // Handle selections Delete(); - 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); + fullText = text.Substring(0, m_StringPosition) + "" + compositionString + "" + text.Substring(m_StringPosition); m_IsCompositionActive = true; @@ -3246,7 +3185,7 @@ void OnScrollbarValueChange(float value) void UpdateMaskRegions() { // TODO: Figure out a better way to handle adding an offset to the masking region - // This region is defined by the RectTransform of the GameObject that contains the RectMask2D component. + // This region is defined by the RectTransform of the GameObject that contains the RectMask2D component. /* // Update Masking Region if (m_TextViewportRectMask != null) @@ -3499,23 +3438,14 @@ private void GenerateCaret(VertexHelper vbo, Vector2 roundingOffset) if (caretPositionInternal == m_TextComponent.textInfo.lineInfo[currentLine].firstCharacterIndex) { currentCharacter = m_TextComponent.textInfo.characterInfo[caretPositionInternal]; + startPosition = new Vector2(currentCharacter.origin, currentCharacter.descender); height = currentCharacter.ascender - currentCharacter.descender; - - if (m_TextComponent.verticalAlignment == VerticalAlignmentOptions.Geometry) - startPosition = new Vector2(currentCharacter.origin, 0 - height / 2); - else - startPosition = new Vector2(currentCharacter.origin, currentCharacter.descender); } else { currentCharacter = m_TextComponent.textInfo.characterInfo[caretPositionInternal - 1]; + startPosition = new Vector2(currentCharacter.xAdvance, currentCharacter.descender); height = currentCharacter.ascender - currentCharacter.descender; - - if (m_TextComponent.verticalAlignment == VerticalAlignmentOptions.Geometry) - startPosition = new Vector2(currentCharacter.xAdvance, 0 - height / 2); - else - startPosition = new Vector2(currentCharacter.xAdvance, currentCharacter.descender); - } if (m_SoftKeyboard != null) @@ -3575,8 +3505,7 @@ private void GenerateCaret(VertexHelper vbo, Vector2 roundingOffset) Vector2 screenPosition = RectTransformUtility.WorldToScreenPoint(cameraRef, cursorPosition); screenPosition.y = Screen.height - screenPosition.y; - if (inputSystem != null) - inputSystem.compositionCursorPos = screenPosition; + inputSystem.compositionCursorPos = screenPosition; //Debug.Log("[" + Time.frameCount + "] Updating IME Window position(" + screenPosition + ") with Composition Length: " + compositionLength); } @@ -3711,7 +3640,7 @@ private void GenerateHightlight(VertexHelper vbo, Vector2 roundingOffset) /// - /// + /// /// /// /// @@ -3945,7 +3874,7 @@ private void ActivateInputFieldInternal() if (TouchScreenKeyboard.isSupported && shouldHideSoftKeyboard == false) { - if (inputSystem != null && inputSystem.touchSupported) + if (inputSystem.touchSupported) { TouchScreenKeyboard.hideInput = shouldHideMobileInput; } @@ -3958,7 +3887,7 @@ private void ActivateInputFieldInternal() OnFocus(); - // Opening the soft keyboard sets its selection to the end of the text. + // Opening the soft keyboard sets its selection to the end of the text. // As such, we set the selection to match the Input Field's internal selection. if (m_SoftKeyboard != null) { @@ -3976,7 +3905,7 @@ private void ActivateInputFieldInternal() } else { - if (!TouchScreenKeyboard.isSupported && m_ReadOnly == false && inputSystem != null) + if (!TouchScreenKeyboard.isSupported && m_ReadOnly == false) inputSystem.imeCompositionMode = IMECompositionMode.On; OnFocus(); @@ -4017,13 +3946,7 @@ public void OnControlClick() public void ReleaseSelection() { m_SelectionStillActive = false; - m_ReleaseSelection = false; - m_PreviouslySelectedObject = null; - MarkGeometryAsDirty(); - - SendOnEndEdit(); - SendOnEndTextSelection(); } public void DeactivateInputField(bool clearSelection = false) @@ -4059,12 +3982,18 @@ public void DeactivateInputField(bool clearSelection = false) //m_CaretPosition = m_CaretSelectPosition = 0; //m_TextComponent.rectTransform.localPosition = m_DefaultTransformPosition; - if (m_VerticalScrollbar == null) - ReleaseSelection(); + //if (caretRectTrans != null) + // caretRectTrans.localPosition = Vector3.zero; + + m_SelectionStillActive = false; + m_ReleaseSelection = false; + m_SelectedObject = null; } - if (inputSystem != null) - inputSystem.imeCompositionMode = IMECompositionMode.Auto; + SendOnEndEdit(); + SendOnEndTextSelection(); + + inputSystem.imeCompositionMode = IMECompositionMode.Auto; } MarkGeometryAsDirty(); @@ -4242,7 +4171,7 @@ void SetToCustom(CharacterValidation characterValidation) protected override void DoStateTransition(SelectionState state, bool instant) { if (m_HasDoneFocusTransition) - state = SelectionState.Selected; + state = SelectionState.Highlighted; else if (state == SelectionState.Pressed) m_HasDoneFocusTransition = true; @@ -4398,4 +4327,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 05d4b89..2e0d53e 100644 --- a/Scripts/Runtime/TMP_PackageResourceImporter.cs +++ b/Scripts/Runtime/TMP_PackageResourceImporter.cs @@ -4,7 +4,7 @@ using System.IO; using UnityEngine; using UnityEditor; - + namespace TMPro { @@ -62,9 +62,6 @@ public void OnGUI() // Set flag to get around importing scripts as per of this package which results in an assembly reload which in turn prevents / clears any callbacks. m_IsImportingExamples = true; - // Disable AssetDatabase refresh until examples have been imported. - //AssetDatabase.DisallowAutoRefresh(); - var packageFullPath = GetPackageFullPath(); AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Examples & Extras.unitypackage", false); } @@ -83,7 +80,7 @@ internal void RegisterResourceImportCallback() } /// - /// + /// /// /// void ImportCallback(string packageName) @@ -101,7 +98,6 @@ void ImportCallback(string packageName) { m_ExamplesAndExtrasResourcesImported = true; m_IsImportingExamples = false; - //AssetDatabase.AllowAutoRefresh(); } Debug.Log("[" + packageName + "] have been imported."); @@ -164,17 +160,11 @@ public class TMP_PackageResourceImporterWindow : EditorWindow [SerializeField] TMP_PackageResourceImporter m_ResourceImporter; - static TMP_PackageResourceImporterWindow m_ImporterWindow; - public static void ShowPackageImporterWindow() { - if (m_ImporterWindow == null) - { - m_ImporterWindow = GetWindow(); - m_ImporterWindow.titleContent = new GUIContent("TMP Importer"); - } - - m_ImporterWindow.Focus(); + var window = GetWindow(); + window.titleContent = new GUIContent("TMP Importer"); + window.Focus(); } void OnEnable() @@ -203,7 +193,7 @@ void OnInspectorUpdate() { Repaint(); } - + /// /// Limits the minimum size of the editor window. /// diff --git a/Scripts/Runtime/TMP_ResourcesManager.cs b/Scripts/Runtime/TMP_ResourcesManager.cs index 55f2f5d..817a58d 100644 --- a/Scripts/Runtime/TMP_ResourcesManager.cs +++ b/Scripts/Runtime/TMP_ResourcesManager.cs @@ -6,10 +6,13 @@ namespace TMPro { /// - /// + /// /// public class TMP_ResourceManager { + private static TMP_ResourceManager instance { get { return s_instance; } } + + private static Dictionary s_FontAssetReferenceLookup = new Dictionary(); private static readonly TMP_ResourceManager s_instance = new TMP_ResourceManager(); static TMP_ResourceManager() { } @@ -18,11 +21,8 @@ static TMP_ResourceManager() { } // FONT ASSET MANAGEMENT - Fields, Properties and Functions // ====================================================== - private static readonly List s_FontAssetReferences = new List(); - private static readonly Dictionary s_FontAssetReferenceLookup = new Dictionary(); - /// - /// + /// /// /// public static void AddFontAsset(TMP_FontAsset fontAsset) @@ -32,12 +32,11 @@ public static void AddFontAsset(TMP_FontAsset fontAsset) if (s_FontAssetReferenceLookup.ContainsKey(hashcode)) return; - s_FontAssetReferences.Add(fontAsset); s_FontAssetReferenceLookup.Add(hashcode, fontAsset); } /// - /// + /// /// /// /// @@ -46,20 +45,10 @@ public static bool TryGetFontAsset(int hashcode, out TMP_FontAsset fontAsset) { fontAsset = null; - return s_FontAssetReferenceLookup.TryGetValue(hashcode, out fontAsset); - } - - - internal static void RebuildFontAssetCache(int instanceID) - { - // Iterate over loaded font assets to update affected font assets - for (int i = 0; i < s_FontAssetReferences.Count; i++) - { - TMP_FontAsset fontAsset = s_FontAssetReferences[i]; + if (s_FontAssetReferenceLookup.TryGetValue(hashcode, out fontAsset)) + return true; - if (fontAsset.FallbackSearchQueryLookup.Contains(instanceID)) - fontAsset.ReadFontAssetDefinition(); - } + return false; } } } diff --git a/Scripts/Runtime/TMP_TextProcessingStack.cs b/Scripts/Runtime/TMP_RichTextTagStack.cs similarity index 76% rename from Scripts/Runtime/TMP_TextProcessingStack.cs rename to Scripts/Runtime/TMP_RichTextTagStack.cs index 2325795..1ce4f81 100644 --- a/Scripts/Runtime/TMP_TextProcessingStack.cs +++ b/Scripts/Runtime/TMP_RichTextTagStack.cs @@ -1,8 +1,4 @@ -using System; -using System.Diagnostics; -using UnityEngine; - -namespace TMPro +namespace TMPro { /// /// Structure used to track basic XML tags which are binary (on / off) @@ -124,73 +120,16 @@ public byte Remove(FontStyles style) /// Structure used to track XML tags of various types. /// /// - [DebuggerDisplay("Item count = {m_Count}")] - public struct TMP_TextProcessingStack + public struct TMP_RichTextTagStack { public T[] itemStack; public int index; - T m_DefaultItem; int m_Capacity; - int m_RolloverSize; - int m_Count; + T m_DefaultItem; const int k_DefaultCapacity = 4; - - /// - /// Constructor to create a new item stack. - /// - /// - public TMP_TextProcessingStack(T[] stack) - { - itemStack = stack; - m_Capacity = stack.Length; - index = 0; - m_RolloverSize = 0; - - m_DefaultItem = default; - m_Count = 0; - } - - - /// - /// Constructor for a new item stack with the given capacity. - /// - /// - public TMP_TextProcessingStack(int capacity) - { - itemStack = new T[capacity]; - m_Capacity = capacity; - index = 0; - m_RolloverSize = 0; - - m_DefaultItem = default; - m_Count = 0; - } - - - public TMP_TextProcessingStack(int capacity, int rolloverSize) - { - itemStack = new T[capacity]; - m_Capacity = capacity; - index = 0; - m_RolloverSize = rolloverSize; - - m_DefaultItem = default; - m_Count = 0; - } - - - /// - /// - /// - public int Count - { - get { return m_Count; } - } - - /// /// Returns the current item on the stack. /// @@ -205,20 +144,30 @@ public T current } } + /// + /// Constructor to create a new item stack. + /// + /// + public TMP_RichTextTagStack(T[] tagStack) + { + itemStack = tagStack; + m_Capacity = tagStack.Length; + index = 0; + + m_DefaultItem = default(T); + } /// - /// + /// Constructor for a new item stack with the given capacity. /// - public int rolloverSize + /// + public TMP_RichTextTagStack(int capacity) { - get { return m_RolloverSize; } - set - { - m_RolloverSize = value; + itemStack = new T[capacity]; + m_Capacity = capacity; + index = 0; - //if (m_Capacity < m_RolloverSize) - // Array.Resize(ref itemStack, m_RolloverSize); - } + m_DefaultItem = default(T); } @@ -228,7 +177,6 @@ public int rolloverSize public void Clear() { index = 0; - m_Count = 0; } @@ -242,7 +190,7 @@ public void SetDefault(T item) { m_Capacity = k_DefaultCapacity; itemStack = new T[m_Capacity]; - m_DefaultItem = default; + m_DefaultItem = default(T); } itemStack[0] = item; @@ -290,47 +238,27 @@ public void Push(T item) if (m_Capacity == 0) m_Capacity = k_DefaultCapacity; - Array.Resize(ref itemStack, m_Capacity); + System.Array.Resize(ref itemStack, m_Capacity); } itemStack[index] = item; - - if (m_RolloverSize == 0) - { - index += 1; - m_Count += 1; - } - else - { - index = (index + 1) % m_RolloverSize; - m_Count = m_Count < m_RolloverSize ? m_Count + 1 : m_RolloverSize; - } - + index += 1; } public T Pop() { - if (index == 0 && m_RolloverSize == 0) - return default; - - if (m_RolloverSize == 0) - index -= 1; - else - { - index = (index - 1) % m_RolloverSize; - index = index < 0 ? index + m_RolloverSize : index; - } + if (index == 0) + return default(T); + index -= 1; T item = itemStack[index]; itemStack[index] = m_DefaultItem; - m_Count = m_Count > 0 ? m_Count - 1 : 0; - return item; } /// - /// + /// /// /// public T Peek() diff --git a/Scripts/Runtime/TMP_TextProcessingStack.cs.meta b/Scripts/Runtime/TMP_RichTextTagStack.cs.meta similarity index 100% rename from Scripts/Runtime/TMP_TextProcessingStack.cs.meta rename to Scripts/Runtime/TMP_RichTextTagStack.cs.meta diff --git a/Scripts/Runtime/TMP_SelectionCaret.cs b/Scripts/Runtime/TMP_SelectionCaret.cs index 33b12ef..6242b8a 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_Settings.cs b/Scripts/Runtime/TMP_Settings.cs index c7ab798..9dbfaa4 100644 --- a/Scripts/Runtime/TMP_Settings.cs +++ b/Scripts/Runtime/TMP_Settings.cs @@ -251,17 +251,6 @@ public static bool enableEmojiSupport [SerializeField] private bool m_enableEmojiSupport; - /// - /// The unicode value of the sprite that will be used when the requested sprite is missing from the sprite asset and potential fallbacks. - /// - public static uint missingCharacterSpriteUnicode - { - get { return instance.m_MissingCharacterSpriteUnicode; } - set { instance.m_MissingCharacterSpriteUnicode = value; } - } - [SerializeField] - private uint m_MissingCharacterSpriteUnicode; - /// /// Determines if sprites will be scaled relative to the primary font asset assigned to the text object or relative to the current font asset. /// @@ -324,7 +313,7 @@ public static TextAsset followingCharacters private TextAsset m_followingCharacters; /// - /// + /// /// public static LineBreakingTable linebreakingRules { diff --git a/Scripts/Runtime/TMP_ShaderUtilities.cs b/Scripts/Runtime/TMP_ShaderUtilities.cs index edd789f..e2b224d 100644 --- a/Scripts/Runtime/TMP_ShaderUtilities.cs +++ b/Scripts/Runtime/TMP_ShaderUtilities.cs @@ -11,21 +11,21 @@ public static class ShaderUtilities public static int ID_MainTex; public static int ID_FaceTex; - public static int ID_FaceColor; + public static int ID_FaceColor; public static int ID_FaceDilate; public static int ID_Shininess; public static int ID_UnderlayColor; - public static int ID_UnderlayOffsetX; - public static int ID_UnderlayOffsetY; + public static int ID_UnderlayOffsetX; + public static int ID_UnderlayOffsetY; public static int ID_UnderlayDilate; public static int ID_UnderlaySoftness; - public static int ID_WeightNormal; + public static int ID_WeightNormal; public static int ID_WeightBold; public static int ID_OutlineTex; - public static int ID_OutlineWidth; + public static int ID_OutlineWidth; public static int ID_OutlineSoftness; public static int ID_OutlineColor; @@ -33,20 +33,20 @@ public static class ShaderUtilities public static int ID_Outline2Width; public static int ID_Padding; - public static int ID_GradientScale; - public static int ID_ScaleX; - public static int ID_ScaleY; + public static int ID_GradientScale; + public static int ID_ScaleX; + public static int ID_ScaleY; public static int ID_PerspectiveFilter; public static int ID_Sharpness; - public static int ID_TextureWidth; - public static int ID_TextureHeight; + public static int ID_TextureWidth; + public static int ID_TextureHeight; - public static int ID_BevelAmount; + public static int ID_BevelAmount; - public static int ID_GlowColor; + public static int ID_GlowColor; public static int ID_GlowOffset; - public static int ID_GlowPower; + public static int ID_GlowPower; public static int ID_GlowOuter; public static int ID_GlowInner; @@ -58,10 +58,10 @@ public static class ShaderUtilities //public static int ID_MaskID; public static int ID_MaskCoord; - public static int ID_ClipRect; - public static int ID_MaskSoftnessX; - public static int ID_MaskSoftnessY; - public static int ID_VertexOffsetX; + public static int ID_ClipRect; + public static int ID_MaskSoftnessX; + public static int ID_MaskSoftnessY; + public static int ID_VertexOffsetX; public static int ID_VertexOffsetY; public static int ID_UseClipRect; @@ -70,12 +70,12 @@ public static class ShaderUtilities public static int ID_StencilComp; public static int ID_StencilReadMask; public static int ID_StencilWriteMask; - - public static int ID_ShaderFlags; + + public static int ID_ShaderFlags; public static int ID_ScaleRatio_A; public static int ID_ScaleRatio_B; public static int ID_ScaleRatio_C; - + public static string Keyword_Bevel = "BEVEL_ON"; public static string Keyword_Glow = "GLOW_ON"; public static string Keyword_Underlay = "UNDERLAY_ON"; @@ -125,7 +125,7 @@ internal static Shader ShaderRef_MobileBitmap /// - /// + /// /// static ShaderUtilities() { @@ -133,7 +133,7 @@ static ShaderUtilities() } /// - /// + /// /// public static void GetShaderPropertyIDs() { @@ -148,7 +148,7 @@ public static void GetShaderPropertyIDs() ID_FaceColor = Shader.PropertyToID("_FaceColor"); ID_FaceDilate = Shader.PropertyToID("_FaceDilate"); ID_Shininess = Shader.PropertyToID("_FaceShininess"); - + ID_UnderlayColor = Shader.PropertyToID("_UnderlayColor"); ID_UnderlayOffsetX = Shader.PropertyToID("_UnderlayOffsetX"); ID_UnderlayOffsetY = Shader.PropertyToID("_UnderlayOffsetY"); @@ -222,7 +222,7 @@ public static void GetShaderPropertyIDs() - // Scale Ratios to ensure property ranges are optimum in Material Editor + // Scale Ratios to ensure property ranges are optimum in Material Editor public static void UpdateShaderRatios(Material mat) { //Debug.Log("UpdateShaderRatios() called."); @@ -233,9 +233,6 @@ public static void UpdateShaderRatios(Material mat) bool isRatioEnabled = !mat.shaderKeywords.Contains(Keyword_Ratios); - if (!mat.HasProperty(ID_GradientScale) || !mat.HasProperty(ID_FaceDilate)) - return; - // Compute Ratio A float scale = mat.GetFloat(ID_GradientScale); float faceDilate = mat.GetFloat(ID_FaceDilate); @@ -304,7 +301,7 @@ public static Vector4 GetFontExtent(Material material) /* if (material == null || !material.HasProperty(ShaderUtilities.ID_GradientScale)) return Vector4.zero; // We are using an non SDF Shader. - + float scaleRatioA = material.GetFloat(ID_ScaleRatio_A); float faceDilate = material.GetFloat(ID_FaceDilate) * scaleRatioA; float outlineThickness = material.GetFloat(ID_OutlineWidth) * scaleRatioA; @@ -349,7 +346,7 @@ public static float GetPadding(Material material, bool enableExtraPadding, bool if (material.HasProperty(ID_Padding)) extraPadding += (int)material.GetFloat(ID_Padding); - return extraPadding + 1.0f; + return extraPadding; } Vector4 padding = Vector4.zero; @@ -368,7 +365,7 @@ public static float GetPadding(Material material, bool enableExtraPadding, bool float uniformPadding = 0; // Iterate through each of the assigned materials to find the max values to set the padding. - + // Update Shader Ratios prior to computing padding UpdateShaderRatios(material); @@ -451,17 +448,19 @@ public static float GetPadding(Material material, bool enableExtraPadding, bool } + + // Function to determine how much extra padding is required as a result of material properties like dilate, outline thickness, softness, glow, etc... public static float GetPadding(Material[] materials, bool enableExtraPadding, bool isBold) { //Debug.Log("GetPadding() called."); - + if (isInitialized == false) GetShaderPropertyIDs(); // Return if Material is null if (materials == null) return 0; - + int extraPadding = enableExtraPadding ? 4 : 0; // Check if we are using a Bitmap Shader diff --git a/Scripts/Runtime/TMP_SpriteAsset.cs b/Scripts/Runtime/TMP_SpriteAsset.cs index 55b1b17..24a1e6d 100644 --- a/Scripts/Runtime/TMP_SpriteAsset.cs +++ b/Scripts/Runtime/TMP_SpriteAsset.cs @@ -9,6 +9,7 @@ namespace TMPro public class TMP_SpriteAsset : TMP_Asset { + internal Dictionary m_UnicodeLookup; internal Dictionary m_NameLookup; internal Dictionary m_GlyphIndexLookup; @@ -38,9 +39,6 @@ public FaceInfo faceInfo // The texture which contains the sprites. public Texture spriteSheet; - /// - /// - /// public List spriteCharacterTable { get @@ -56,22 +54,6 @@ public List spriteCharacterTable private List m_SpriteCharacterTable = new List(); - /// - /// Dictionary used to lookup sprite characters by their unicode value. - /// - public Dictionary spriteCharacterLookupTable - { - get - { - if (m_SpriteCharacterLookup == null) - UpdateLookupTables(); - - return m_SpriteCharacterLookup; - } - internal set { m_SpriteCharacterLookup = value; } - } - internal Dictionary m_SpriteCharacterLookup; - public List spriteGlyphTable { get { return m_SpriteGlyphTable; } @@ -80,11 +62,15 @@ public List spriteGlyphTable [SerializeField] private List m_SpriteGlyphTable = new List(); - internal Dictionary m_SpriteGlyphLookup; - // List which contains the SpriteInfo for the sprites contained in the sprite sheet. public List spriteInfoList; + /// + /// Dictionary used to lookup the index of a given sprite based on a Unicode value. + /// + //private Dictionary m_SpriteUnicodeLookup; + + /// /// List which contains the Fallback font assets for this font. /// @@ -93,7 +79,6 @@ public List spriteGlyphTable internal bool m_IsSpriteAssetLookupTablesDirty = false; - void Awake() { // Check version number of sprite asset to see if it needs to be upgraded. @@ -102,6 +87,21 @@ void Awake() } + #if UNITY_EDITOR + /// + /// + /// + void OnValidate() + { + //Debug.Log("Sprite Asset [" + name + "] has changed."); + + //UpdateLookupTables(); + + //TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, this); + } + #endif + + /// /// Create a material for the sprite asset. /// @@ -145,58 +145,26 @@ public void UpdateLookupTables() else m_GlyphIndexLookup.Clear(); - // - if (m_SpriteGlyphLookup == null) - m_SpriteGlyphLookup = new Dictionary(); - else - m_SpriteGlyphLookup.Clear(); - - // Initialize SpriteGlyphLookup for (int i = 0; i < m_SpriteGlyphTable.Count; i++) { - TMP_SpriteGlyph spriteGlyph = m_SpriteGlyphTable[i]; - uint glyphIndex = spriteGlyph.index; + uint glyphIndex = m_SpriteGlyphTable[i].index; if (m_GlyphIndexLookup.ContainsKey(glyphIndex) == false) m_GlyphIndexLookup.Add(glyphIndex, i); - - if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false) - m_SpriteGlyphLookup.Add(glyphIndex, spriteGlyph); } - // Initialize name lookup if (m_NameLookup == null) m_NameLookup = new Dictionary(); else m_NameLookup.Clear(); - - // Initialize character lookup - if (m_SpriteCharacterLookup == null) - m_SpriteCharacterLookup = new Dictionary(); + if (m_UnicodeLookup == null) + m_UnicodeLookup = new Dictionary(); else - m_SpriteCharacterLookup.Clear(); - + m_UnicodeLookup.Clear(); - // Populate Sprite Character lookup tables for (int i = 0; i < m_SpriteCharacterTable.Count; i++) { - TMP_SpriteCharacter spriteCharacter = m_SpriteCharacterTable[i]; - - // Make sure sprite character is valid - if (spriteCharacter == null) - continue; - - uint glyphIndex = spriteCharacter.glyphIndex; - - // Lookup the glyph for this character - if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false) - continue; - - // Assign glyph and text asset to this character - spriteCharacter.glyph = m_SpriteGlyphLookup[glyphIndex]; - spriteCharacter.textAsset = this; - int nameHashCode = m_SpriteCharacterTable[i].hashCode; if (m_NameLookup.ContainsKey(nameHashCode) == false) @@ -204,8 +172,15 @@ public void UpdateLookupTables() uint unicode = m_SpriteCharacterTable[i].unicode; - if (unicode != 0xFFFE && m_SpriteCharacterLookup.ContainsKey(unicode) == false) - m_SpriteCharacterLookup.Add(unicode, spriteCharacter); + if (m_UnicodeLookup.ContainsKey(unicode) == false) + m_UnicodeLookup.Add(unicode, i); + + // Update glyph reference which is not serialized + uint glyphIndex = m_SpriteCharacterTable[i].glyphIndex; + int index; + + if (m_GlyphIndexLookup.TryGetValue(glyphIndex, out index)) + m_SpriteCharacterTable[i].glyph = m_SpriteGlyphTable[index]; } m_IsSpriteAssetLookupTablesDirty = false; @@ -238,13 +213,13 @@ public int GetSpriteIndexFromHashcode(int hashCode) /// public int GetSpriteIndexFromUnicode (uint unicode) { - if (m_SpriteCharacterLookup == null) + if (m_UnicodeLookup == null) UpdateLookupTables(); - TMP_SpriteCharacter spriteCharacter; + int index; - if (m_SpriteCharacterLookup.TryGetValue(unicode, out spriteCharacter)) - return (int)spriteCharacter.glyphIndex; + if (m_UnicodeLookup.TryGetValue(unicode, out index)) + return index; return -1; } @@ -269,7 +244,7 @@ public int GetSpriteIndexFromName (string name) /// /// Used to keep track of which Sprite Assets have been searched. /// - private static HashSet k_searchedSpriteAssets; + private static List k_searchedSpriteAssets; /// /// Search through the given sprite asset and its fallbacks for the specified sprite matching the given unicode character. @@ -290,9 +265,9 @@ public static TMP_SpriteAsset SearchForSpriteByUnicode(TMP_SpriteAsset spriteAss // Initialize list to track instance of Sprite Assets that have already been searched. if (k_searchedSpriteAssets == null) - k_searchedSpriteAssets = new HashSet(); - else - k_searchedSpriteAssets.Clear(); + k_searchedSpriteAssets = new List(); + + k_searchedSpriteAssets.Clear(); // Get instance ID of sprite asset and add to list. int id = spriteAsset.GetInstanceID(); @@ -300,11 +275,11 @@ public static TMP_SpriteAsset SearchForSpriteByUnicode(TMP_SpriteAsset spriteAss // Search potential fallback sprite assets if includeFallbacks is true. if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) - return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex); + return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, includeFallbacks, out spriteIndex); // Search default sprite asset potentially assigned in the TMP Settings. if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) - return SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, unicode, true, out spriteIndex); + return SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, unicode, includeFallbacks, out spriteIndex); spriteIndex = -1; return null; @@ -328,9 +303,11 @@ private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(List 0) - return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex); + return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, includeFallbacks, out spriteIndex); spriteIndex = -1; return null; @@ -384,66 +360,22 @@ public static TMP_SpriteAsset SearchForSpriteByHashCode(TMP_SpriteAsset spriteAs if (spriteIndex != -1) return spriteAsset; - // Initialize or clear list to Sprite Assets that have already been searched. + // Initialize list to track instance of Sprite Assets that have already been searched. if (k_searchedSpriteAssets == null) - k_searchedSpriteAssets = new HashSet(); - else - k_searchedSpriteAssets.Clear(); + k_searchedSpriteAssets = new List(); - int id = spriteAsset.instanceID; + k_searchedSpriteAssets.Clear(); + int id = spriteAsset.GetInstanceID(); // Add to list of font assets already searched. k_searchedSpriteAssets.Add(id); - TMP_SpriteAsset tempSpriteAsset; - - // Search potential fallbacks assigned to local sprite asset. if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) - { - tempSpriteAsset = SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex); - - if (spriteIndex != -1) - return tempSpriteAsset; - } + return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, includeFallbacks, out spriteIndex); // Search default sprite asset potentially assigned in the TMP Settings. if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) - { - tempSpriteAsset = SearchForSpriteByHashCodeInternal(TMP_Settings.defaultSpriteAsset, hashCode, true, out spriteIndex); - - if (spriteIndex != -1) - return tempSpriteAsset; - } - - // Clear search list since we are now looking for the missing sprite character. - k_searchedSpriteAssets.Clear(); - - uint missingSpriteCharacterUnicode = TMP_Settings.missingCharacterSpriteUnicode; - - // Get sprite index for the given unicode - spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(missingSpriteCharacterUnicode); - if (spriteIndex != -1) - return spriteAsset; - - // Add current sprite asset to list of assets already searched. - k_searchedSpriteAssets.Add(id); - - // Search for the missing sprite character in the local sprite asset and potential fallbacks. - if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) - { - tempSpriteAsset = SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, missingSpriteCharacterUnicode, true, out spriteIndex); - - if (spriteIndex != -1) - return tempSpriteAsset; - } - - // Search for the missing sprite character in the default sprite asset and potential fallbacks. - if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) - { - tempSpriteAsset = SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, missingSpriteCharacterUnicode, true, out spriteIndex); - if (spriteIndex != -1) - return tempSpriteAsset; - } + return SearchForSpriteByHashCodeInternal(TMP_Settings.defaultSpriteAsset, hashCode, includeFallbacks, out spriteIndex); spriteIndex = -1; return null; @@ -466,11 +398,13 @@ private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(List 0) - return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex); + return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, searchFallbacks, out spriteIndex); spriteIndex = -1; return null; @@ -553,7 +487,7 @@ private void UpgradeSpriteAsset() TMP_Sprite oldSprite = spriteInfoList[i]; TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); - spriteGlyph.index = (uint)i; + spriteGlyph.index = (uint)i; spriteGlyph.sprite = oldSprite.sprite; spriteGlyph.metrics = new GlyphMetrics(oldSprite.width, oldSprite.height, oldSprite.xOffset, oldSprite.yOffset, oldSprite.xAdvance); spriteGlyph.glyphRect = new GlyphRect((int)oldSprite.x, (int)oldSprite.y, (int)oldSprite.width, (int)oldSprite.height); @@ -563,9 +497,7 @@ private void UpgradeSpriteAsset() m_SpriteGlyphTable.Add(spriteGlyph); - TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(); - spriteCharacter.glyph = spriteGlyph; - spriteCharacter.unicode = oldSprite.unicode == 0x0 ? 0xFFFE : (uint)oldSprite.unicode; + TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter((uint)oldSprite.unicode, spriteGlyph); spriteCharacter.name = oldSprite.name; spriteCharacter.scale = oldSprite.scale; diff --git a/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs b/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs index a5d6413..c543510 100644 --- a/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs +++ b/Scripts/Runtime/TMP_SpriteAssetImportFormats.cs @@ -1,4 +1,5 @@ using UnityEngine; +using System.Collections; using System.Collections.Generic; @@ -48,23 +49,10 @@ 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 d0a4d02..f7a3235 100644 --- a/Scripts/Runtime/TMP_SubMesh.cs +++ b/Scripts/Runtime/TMP_SubMesh.cs @@ -2,11 +2,12 @@ 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 { [RequireComponent(typeof(MeshRenderer))] + [RequireComponent(typeof(MeshFilter))] [ExecuteAlways] public class TMP_SubMesh : MonoBehaviour { @@ -148,22 +149,11 @@ public float padding /// public MeshFilter meshFilter { - get - { - if (m_meshFilter == null) - { - m_meshFilter = GetComponent(); - - if (m_meshFilter == null) - { - m_meshFilter = gameObject.AddComponent(); - m_meshFilter.hideFlags = HideFlags.HideInInspector | HideFlags.HideAndDontSave; - } - } - + get { if (m_meshFilter == null) m_meshFilter = GetComponent(); return m_meshFilter; } } + [SerializeField] private MeshFilter m_meshFilter; @@ -178,6 +168,7 @@ public Mesh mesh { m_mesh = new Mesh(); m_mesh.hideFlags = HideFlags.HideAndDontSave; + this.meshFilter.mesh = m_mesh; } return m_mesh; @@ -187,7 +178,7 @@ public Mesh mesh private Mesh m_mesh; /// - /// + /// /// //public BoxCollider boxCollider //{ @@ -320,14 +311,8 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) int fallbackSourceMaterialID = m_fallbackSourceMaterial == null ? 0 : m_fallbackSourceMaterial.GetInstanceID(); // Sync culling with parent text object - bool hasCullModeProperty = m_sharedMaterial.HasProperty(ShaderUtilities.ShaderTag_CullMode); - float cullMode = 0; - - if (hasCullModeProperty) - { - cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); - m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); - } + float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); + m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); // Filter events and return if the affected material is not this object's material. if (targetMaterialID != sharedMaterialID) @@ -338,8 +323,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) TMP_MaterialManager.CopyMaterialPresetProperties(mat, m_fallbackMaterial); // Re-sync culling with parent text object - if (hasCullModeProperty) - m_fallbackMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); + m_fallbackMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); } else return; @@ -423,7 +407,6 @@ 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(); @@ -433,6 +416,8 @@ public static TMP_SubMesh AddSubTextObject(TextMeshPro textComponent, MaterialRe go.transform.localScale = Vector3.one; go.layer = textComponent.gameObject.layer; + subMesh.m_meshFilter = go.GetComponent(); + subMesh.m_TextComponent = textComponent; subMesh.m_fontAsset = materialReference.fontAsset; subMesh.m_spriteAsset = materialReference.spriteAsset; @@ -465,7 +450,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(); @@ -514,7 +499,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(); @@ -550,7 +535,7 @@ public void UpdateMeshPadding(bool isExtraPadding, bool isUsingBold) /// - /// + /// /// public void SetVerticesDirty() { @@ -567,7 +552,7 @@ public void SetVerticesDirty() /// - /// + /// /// public void SetMaterialDirty() { @@ -582,22 +567,22 @@ public void SetMaterialDirty() /// - /// + /// /// protected void UpdateMaterial() { //Debug.Log("*** STO - UpdateMaterial() *** FRAME (" + Time.frameCount + ")"); - if (renderer == null || m_sharedMaterial == null) return; + if (m_renderer == null) m_renderer = this.renderer; m_renderer.sharedMaterial = m_sharedMaterial; + if (m_sharedMaterial == null) + return; + // Special handling to keep the Culling of the material in sync with parent text object - if (m_sharedMaterial.HasProperty(ShaderUtilities.ShaderTag_CullMode)) - { - float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); - m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); - } + float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); + m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); #if UNITY_EDITOR if (m_sharedMaterial != null && gameObject.name != "TMP SubMesh [" + m_sharedMaterial.name + "]") @@ -606,7 +591,7 @@ protected void UpdateMaterial() } /// - /// + /// /// //public void UpdateColliders(int vertexCount) //{ diff --git a/Scripts/Runtime/TMP_SubMeshUI.cs b/Scripts/Runtime/TMP_SubMeshUI.cs index d17a44e..c45c747 100644 --- a/Scripts/Runtime/TMP_SubMeshUI.cs +++ b/Scripts/Runtime/TMP_SubMeshUI.cs @@ -35,7 +35,7 @@ public TMP_SpriteAsset spriteAsset /// - /// + /// /// public override Texture mainTexture { @@ -44,6 +44,7 @@ public override Texture mainTexture if (this.sharedMaterial != null) return this.sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex); + return null; } } @@ -88,7 +89,7 @@ public Material sharedMaterial /// - /// + /// /// public Material fallbackMaterial { @@ -210,10 +211,8 @@ 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.transform.SetAsFirstSibling(); go.layer = textComponent.gameObject.layer; RectTransform rectTransform = go.GetComponent(); @@ -222,9 +221,6 @@ public static TMP_SubMeshUI AddSubTextObject(TextMeshProUGUI textComponent, Mate rectTransform.sizeDelta = Vector2.zero; rectTransform.pivot = textComponent.rectTransform.pivot; - LayoutElement layoutElement = go.AddComponent(); - layoutElement.ignoreLayout = true; - TMP_SubMeshUI subMesh = go.AddComponent(); //subMesh.canvasRenderer = subMesh.canvasRenderer; @@ -242,7 +238,7 @@ public static TMP_SubMeshUI AddSubTextObject(TextMeshProUGUI textComponent, Mate /// - /// + /// /// protected override void OnEnable() { @@ -276,7 +272,9 @@ protected override void OnEnable() protected override void OnDisable() { //Debug.Log("*** SubObject OnDisable() ***"); - base.OnDisable(); + + //m_canvasRenderer.Clear(); + TMP_UpdateRegistry.UnRegisterCanvasElementForRebuild(this); if (m_MaskMaterial != null) { @@ -289,6 +287,8 @@ protected override void OnDisable() TMP_MaterialManager.ReleaseFallbackMaterial(m_fallbackMaterial); m_fallbackMaterial = null; } + + base.OnDisable(); } @@ -344,14 +344,8 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) int fallbackSourceMaterialID = m_fallbackSourceMaterial == null ? 0 : m_fallbackSourceMaterial.GetInstanceID(); // Sync culling with parent text object - bool hasCullModeProperty = m_sharedMaterial.HasProperty(ShaderUtilities.ShaderTag_CullMode); - float cullMode = 0; - - if (hasCullModeProperty) - { - cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); - m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); - } + float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); + m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); // Filter events and return if the affected material is not this object's material. if (m_fallbackMaterial != null && fallbackSourceMaterialID == targetMaterialID && TMP_Settings.matchMaterialPreset) @@ -381,7 +375,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) } else if (targetMaterialID == maskingMaterialID) { - // Update the padding + // Update the padding GetPaddingForMaterial(mat); m_sharedMaterial.CopyPropertiesFromMaterial(mat); @@ -401,8 +395,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) } // Re-sync culling with parent text object - if (hasCullModeProperty) - m_MaskMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); + m_MaskMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); } m_padding = GetPaddingForMaterial(); @@ -480,7 +473,7 @@ void ON_TMP_SETTINGS_CHANGED() #endif /// - /// + /// /// protected override void OnTransformParentChanged() { @@ -516,8 +509,6 @@ public override Material GetModifiedMaterial(Material baseMaterial) m_MaskMaterial = mat; } - else if (m_MaskMaterial != null) - TMP_MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); return mat; } @@ -548,7 +539,7 @@ public float GetPaddingForMaterial(Material mat) /// - /// + /// /// /// /// @@ -559,7 +550,7 @@ public void UpdateMeshPadding(bool isExtraPadding, bool isUsingBold) /// - /// + /// /// public override void SetAllDirty() { @@ -570,7 +561,7 @@ public override void SetAllDirty() /// - /// + /// /// public override void SetVerticesDirty() { @@ -587,7 +578,7 @@ public override void SetVerticesDirty() /// - /// + /// /// public override void SetLayoutDirty() { @@ -596,7 +587,7 @@ public override void SetLayoutDirty() /// - /// + /// /// public override void SetMaterialDirty() { @@ -620,7 +611,7 @@ public override void SetMaterialDirty() /// - /// + /// /// public void SetPivotDirty() { @@ -630,14 +621,6 @@ public void SetPivotDirty() this.rectTransform.pivot = m_TextComponent.rectTransform.pivot; } - Transform GetRootCanvasTransform() - { - if (m_RootCanvasTransform == null) - m_RootCanvasTransform = m_TextComponent.canvas.rootCanvas.transform; - - return m_RootCanvasTransform; - } - private Transform m_RootCanvasTransform; /// /// Override to Cull function of MaskableGraphic to prevent Culling. @@ -646,21 +629,19 @@ Transform GetRootCanvasTransform() /// public override void Cull(Rect clipRect, bool validRect) { - // Get compound rect for the text object and sub text objects in local canvas space. - Rect rect = m_TextComponent.GetCanvasSpaceClippingRect(); - - var cull = !validRect || !clipRect.Overlaps(rect, true); - if (canvasRenderer.cull != cull) + if (validRect) { - canvasRenderer.cull = cull; - onCullStateChanged.Invoke(cull); - OnCullingChanged(); + canvasRenderer.cull = false; + CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); + return; } + + base.Cull(clipRect, validRect); } /// - /// + /// /// protected override void UpdateGeometry() { @@ -670,7 +651,7 @@ protected override void UpdateGeometry() /// - /// + /// /// /// public override void Rebuild(CanvasUpdate update) @@ -695,7 +676,7 @@ public void RefreshMaterial() /// - /// + /// /// protected override void UpdateMaterial() { @@ -707,11 +688,8 @@ protected override void UpdateMaterial() //if (canvasRenderer == null) m_canvasRenderer = this.canvasRenderer; // Special handling to keep the Culling of the material in sync with parent text object - if (m_sharedMaterial.HasProperty(ShaderUtilities.ShaderTag_CullMode)) - { - float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); - m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); - } + float cullMode = textComponent.fontSharedMaterial.GetFloat(ShaderUtilities.ShaderTag_CullMode); + m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, cullMode); canvasRenderer.materialCount = 1; canvasRenderer.SetMaterial(materialForRendering, 0); @@ -736,7 +714,7 @@ public override void RecalculateClipping() /// - /// + /// /// public override void RecalculateMasking() { @@ -784,7 +762,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(); diff --git a/Scripts/Runtime/TMP_Text.cs b/Scripts/Runtime/TMP_Text.cs index bc45dc0..349078f 100644 --- a/Scripts/Runtime/TMP_Text.cs +++ b/Scripts/Runtime/TMP_Text.cs @@ -100,7 +100,6 @@ public enum TextOverflowModes { Overflow = 0, Ellipsis = 1, Masking = 2, Truncat public enum MaskingOffsetMode { Percentage = 0, Pixel = 1 }; public enum TextureMappingOptions { Character = 0, Line = 1, Paragraph = 2, MatchAspect = 3 }; - [Flags] public enum FontStyles { Normal = 0x0, Bold = 0x1, Italic = 0x2, Underline = 0x4, LowerCase = 0x8, UpperCase = 0x10, SmallCaps = 0x20, Strikethrough = 0x40, Superscript = 0x80, Subscript = 0x100, Highlight = 0x200 }; public enum FontWeight { Thin = 100, ExtraLight = 200, Light = 300, Regular = 400, Medium = 500, SemiBold = 600, Bold = 700, Heavy = 800, Black = 900 }; @@ -123,6 +122,7 @@ public virtual string text m_text = value; m_inputSource = TextInputSources.String; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); @@ -132,24 +132,14 @@ public virtual string text [TextArea(5, 10)] protected string m_text; - /// - /// 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; /// - /// + /// /// public bool isRightToLeftText { get { return m_isRightToLeft; } - set { if (m_isRightToLeft == value) return; m_isRightToLeft = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_isRightToLeft == value) return; m_isRightToLeft = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected bool m_isRightToLeft = false; @@ -161,7 +151,7 @@ public bool isRightToLeftText public TMP_FontAsset font { get { return m_fontAsset; } - set { if (m_fontAsset == value) return; m_fontAsset = value; LoadFontAsset(); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_fontAsset == value) return; m_fontAsset = value; LoadFontAsset(); m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected TMP_FontAsset m_fontAsset; @@ -183,7 +173,7 @@ public virtual Material fontSharedMaterial protected MaterialReference[] m_materialReferences = new MaterialReference[32]; protected Dictionary m_materialReferenceIndexLookup = new Dictionary(); - protected TMP_TextProcessingStack m_materialReferenceStack = new TMP_TextProcessingStack(new MaterialReference[16]); + protected TMP_RichTextTagStack m_materialReferenceStack = new TMP_RichTextTagStack(new MaterialReference[16]); protected int m_currentMaterialIndex; @@ -282,7 +272,7 @@ public bool enableVertexGradient [SerializeField] protected ColorMode m_colorMode = ColorMode.FourCornersGradient; - + /// /// Sets the vertex colors for each of the 4 vertices of the character quads. /// @@ -314,7 +304,7 @@ public TMP_ColorGradient colorGradientPreset public TMP_SpriteAsset spriteAsset { get { return m_spriteAsset; } - set { m_spriteAsset = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { m_spriteAsset = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected TMP_SpriteAsset m_spriteAsset; @@ -339,13 +329,13 @@ public bool tintAllSprites public TMP_StyleSheet styleSheet { get { return m_StyleSheet; } - set { m_StyleSheet = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { m_StyleSheet = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected TMP_StyleSheet m_StyleSheet; /// - /// + /// /// public TMP_Style textStyle { @@ -362,7 +352,7 @@ public TMP_Style textStyle return m_TextStyle; } - set { m_TextStyle = value; m_TextStyleHashCode = m_TextStyle.hashCode; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { m_TextStyle = value; m_TextStyleHashCode = m_TextStyle.hashCode; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } internal TMP_Style m_TextStyle; [SerializeField] @@ -414,7 +404,7 @@ public Color32 outlineColor set { if (m_outlineColor.Compare(value)) return; SetOutlineColor(value); m_havePropertiesChanged = true; m_outlineColor = value; SetVerticesDirty(); } } - //[SerializeField] + [SerializeField] protected Color32 m_outlineColor = Color.black; @@ -441,14 +431,14 @@ public float outlineWidth public float fontSize { get { return m_fontSize; } - set { if (m_fontSize == value) return; m_havePropertiesChanged = true; m_fontSize = value; if (!m_enableAutoSizing) m_fontSizeBase = m_fontSize; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_fontSize == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_fontSize = value; if (!m_enableAutoSizing) m_fontSizeBase = m_fontSize; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_fontSize = 36; // Font Size protected float m_currentFontSize; // Temporary Font Size affected by tags - [SerializeField] // TODO: Review if this should be serialized + [SerializeField] protected float m_fontSizeBase = 36; - protected TMP_TextProcessingStack m_sizeStack = new TMP_TextProcessingStack(16); + protected TMP_RichTextTagStack m_sizeStack = new TMP_RichTextTagStack(16); /// @@ -466,15 +456,15 @@ public float fontScale public FontWeight fontWeight { get { return m_fontWeight; } - set { if (m_fontWeight == value) return; m_fontWeight = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_fontWeight == value) return; m_fontWeight = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected FontWeight m_fontWeight = FontWeight.Regular; protected FontWeight m_FontWeightInternal = FontWeight.Regular; - protected TMP_TextProcessingStack m_FontWeightStack = new TMP_TextProcessingStack(8); + protected TMP_RichTextTagStack m_FontWeightStack = new TMP_RichTextTagStack(8); /// - /// + /// /// public float pixelsPerUnit { @@ -542,7 +532,7 @@ public float fontSizeMax public FontStyles fontStyle { get { return m_fontStyle; } - set { if (m_fontStyle == value) return; m_fontStyle = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_fontStyle == value) return; m_fontStyle = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected FontStyles m_fontStyle = FontStyles.Normal; @@ -576,7 +566,7 @@ public HorizontalAlignmentOptions horizontalAlignment protected HorizontalAlignmentOptions m_HorizontalAlignment = HorizontalAlignmentOptions.Left; /// - /// Vertical alignment options + /// Vertical alignment options /// public VerticalAlignmentOptions verticalAlignment { @@ -617,12 +607,16 @@ public TextAlignmentOptions alignment } [SerializeField] [UnityEngine.Serialization.FormerlySerializedAs("m_lineJustification")] - protected TextAlignmentOptions m_textAlignment = TextAlignmentOptions.Converted; + protected TextAlignmentOptions m_textAlignment = TextAlignmentOptions.TopLeft; + //protected TextAlignmentOptions m_lineJustification; protected HorizontalAlignmentOptions m_lineJustification; - protected TMP_TextProcessingStack m_lineJustificationStack = new TMP_TextProcessingStack(new HorizontalAlignmentOptions[16]); + protected TMP_RichTextTagStack m_lineJustificationStack = new TMP_RichTextTagStack(new HorizontalAlignmentOptions[16]); protected Vector3[] m_textContainerLocalCorners = new Vector3[4]; + [SerializeField] + protected bool m_isAlignmentEnumConverted; + /// /// Use the extents of the text geometry for alignment instead of font metrics. /// @@ -641,7 +635,7 @@ public TextAlignmentOptions alignment public float characterSpacing { get { return m_characterSpacing; } - set { if (m_characterSpacing == value) return; m_havePropertiesChanged = true; m_characterSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_characterSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_characterSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_characterSpacing = 0; @@ -654,7 +648,7 @@ public float characterSpacing public float wordSpacing { get { return m_wordSpacing; } - set { if (m_wordSpacing == value) return; m_havePropertiesChanged = true; m_wordSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_wordSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_wordSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_wordSpacing = 0; @@ -665,13 +659,12 @@ public float wordSpacing public float lineSpacing { get { return m_lineSpacing; } - set { if (m_lineSpacing == value) return; m_havePropertiesChanged = true; m_lineSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_lineSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_lineSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_lineSpacing = 0; protected float m_lineSpacingDelta = 0; // Used with Text Auto Sizing feature protected float m_lineHeight = TMP_Math.FLOAT_UNSET; // Used with the tag. - protected bool m_IsDrivenLineSpacing; /// @@ -680,7 +673,7 @@ public float lineSpacing public float lineSpacingAdjustment { get { return m_lineSpacingMax; } - set { if (m_lineSpacingMax == value) return; m_havePropertiesChanged = true; m_lineSpacingMax = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_lineSpacingMax == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_lineSpacingMax = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_lineSpacingMax = 0; // Text Auto Sizing Max Line spacing reduction. @@ -692,7 +685,7 @@ public float lineSpacingAdjustment public float paragraphSpacing { get { return m_paragraphSpacing; } - set { if (m_paragraphSpacing == value) return; m_havePropertiesChanged = true; m_paragraphSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_paragraphSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_paragraphSpacing = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_paragraphSpacing = 0; @@ -704,7 +697,7 @@ public float paragraphSpacing public float characterWidthAdjustment { get { return m_charWidthMaxAdj; } - set { if (m_charWidthMaxAdj == value) return; m_havePropertiesChanged = true; m_charWidthMaxAdj = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_charWidthMaxAdj == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_charWidthMaxAdj = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_charWidthMaxAdj = 0f; // Text Auto Sizing Max Character Width reduction. @@ -717,7 +710,7 @@ public float characterWidthAdjustment public bool enableWordWrapping { get { return m_enableWordWrapping; } - set { if (m_enableWordWrapping == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_enableWordWrapping = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_enableWordWrapping == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; m_enableWordWrapping = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected bool m_enableWordWrapping = false; @@ -731,14 +724,14 @@ public bool enableWordWrapping public float wordWrappingRatios { get { return m_wordWrappingRatios; } - set { if (m_wordWrappingRatios == value) return; m_wordWrappingRatios = value; m_havePropertiesChanged = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_wordWrappingRatios == value) return; m_wordWrappingRatios = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected float m_wordWrappingRatios = 0.4f; // Controls word wrapping ratios between word or characters. /// - /// + /// /// //public bool enableAdaptiveJustification //{ @@ -756,7 +749,7 @@ public float wordWrappingRatios public TextOverflowModes overflowMode { get { return m_overflowMode; } - set { if (m_overflowMode == value) return; m_overflowMode = value; m_havePropertiesChanged = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_overflowMode == value) return; m_overflowMode = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected TextOverflowModes m_overflowMode = TextOverflowModes.Overflow; @@ -778,7 +771,7 @@ public int firstOverflowCharacterIndex { get { return m_firstOverflowCharacterIndex; } } - //[SerializeField] + [SerializeField] protected int m_firstOverflowCharacterIndex = -1; @@ -813,6 +806,7 @@ public TMP_Text linkedTextComponent } m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } @@ -827,7 +821,7 @@ public TMP_Text linkedTextComponent /// Property indicating whether the text is Truncated or using Ellipsis. /// public bool isTextTruncated { get { return m_isTextTruncated; } } - //[SerializeField] + [SerializeField] protected bool m_isTextTruncated; @@ -837,7 +831,7 @@ public TMP_Text linkedTextComponent public bool enableKerning { get { return m_enableKerning; } - set { if (m_enableKerning == value) return; m_havePropertiesChanged = true; m_enableKerning = value; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_enableKerning == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_enableKerning = value; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected bool m_enableKerning; @@ -849,7 +843,7 @@ public bool enableKerning public bool extraPadding { get { return m_enableExtraPadding; } - set { if (m_enableExtraPadding == value) return; m_havePropertiesChanged = true; m_enableExtraPadding = value; UpdateMeshPadding(); SetVerticesDirty(); /* SetLayoutDirty();*/ } + set { if (m_enableExtraPadding == value) return; m_havePropertiesChanged = true; m_enableExtraPadding = value; UpdateMeshPadding(); /* m_isCalculateSizeRequired = true;*/ SetVerticesDirty(); /* SetLayoutDirty();*/ } } [SerializeField] protected bool m_enableExtraPadding = false; @@ -863,7 +857,7 @@ public bool extraPadding public bool richText { get { return m_isRichText; } - set { if (m_isRichText == value) return; m_isRichText = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_isRichText == value) return; m_isRichText = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected bool m_isRichText = true; // Used to enable or disable Rich Text. @@ -875,7 +869,7 @@ public bool richText public bool parseCtrlCharacters { get { return m_parseCtrlCharacters; } - set { if (m_parseCtrlCharacters == value) return; m_parseCtrlCharacters = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } + set { if (m_parseCtrlCharacters == value) return; m_parseCtrlCharacters = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); } } [SerializeField] protected bool m_parseCtrlCharacters = true; @@ -915,7 +909,7 @@ public bool enableCulling [SerializeField] protected bool m_isCullingEnabled = false; - // + // protected bool m_isMaskingEnabled; protected bool isMaskUpdateRequired; @@ -927,7 +921,7 @@ public bool ignoreVisibility get { return m_ignoreCulling; } set { if (m_ignoreCulling == value) return; m_havePropertiesChanged = true; m_ignoreCulling = value; } } - //[SerializeField] + [SerializeField] protected bool m_ignoreCulling = true; // Not implemented yet. @@ -1025,7 +1019,7 @@ public bool isTextObjectScaleStatic /// /// Determines if the data structures allocated to contain the geometry of the text object will be reduced in size if the number of characters required to display the text is reduced by more than 256 characters. - /// This reduction has the benefit of reducing the amount of vertex data being submitted to the graphic device but results in GC when it occurs. + /// This reduction has the benefit of reducing the amount of vertex data being submitted to the graphic device but results in GC when it occurs. /// public bool vertexBufferAutoSizeReduction { @@ -1043,7 +1037,7 @@ public int firstVisibleCharacter get { return m_firstVisibleCharacter; } set { if (m_firstVisibleCharacter == value) return; m_havePropertiesChanged = true; m_firstVisibleCharacter = value; SetVerticesDirty(); } } - //[SerializeField] + [SerializeField] protected int m_firstVisibleCharacter; /// @@ -1085,7 +1079,7 @@ public int maxVisibleLines public bool useMaxVisibleDescender { get { return m_useMaxVisibleDescender; } - set { if (m_useMaxVisibleDescender == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_useMaxVisibleDescender = value; SetVerticesDirty(); } + set { if (m_useMaxVisibleDescender == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); } } [SerializeField] protected bool m_useMaxVisibleDescender = true; @@ -1127,8 +1121,8 @@ public TMP_TextInfo textInfo { get { return m_textInfo; } } - //[SerializeField] - protected TMP_TextInfo m_textInfo; // Class which holds information about the Text object such as characters, lines, mesh data as well as metrics. + [SerializeField] + protected TMP_TextInfo m_textInfo; // Class which holds information about the Text object such as characters, lines, mesh data as well as metrics. /// /// Property tracking if any of the text properties have changed. Flag is set before the text is regenerated. @@ -1184,17 +1178,6 @@ public bool isUsingLegacyAnimationComponent protected RectTransform m_rectTransform; - /// - /// Used to track potential changes in RectTransform size to allow us to ignore OnRectTransformDimensionsChange getting called due to rounding errors when using Stretch Anchors. - /// - protected Vector2 m_PreviousRectTransformSize; - - /// - /// Used to track potential changes in pivot position to allow us to ignore OnRectTransformDimensionsChange getting called due to rounding errors when using Stretch Anchors. - /// - protected Vector2 m_PreviousPivotPosition; - - /// /// Enables control over setting the size of the text container to match the text object. /// @@ -1321,12 +1304,12 @@ protected TMP_SpriteAnimator spriteAnimator } } - //[SerializeField] + [SerializeField] protected TMP_SpriteAnimator m_spriteAnimator; /// - /// + /// /// //public TMP_TextShaper textShaper //{ @@ -1343,43 +1326,43 @@ protected TMP_SpriteAnimator spriteAnimator // *** PROPERTIES RELATED TO UNITY LAYOUT SYSTEM *** /// - /// + /// /// public float flexibleHeight { get { return m_flexibleHeight; } } protected float m_flexibleHeight = -1f; /// - /// + /// /// public float flexibleWidth { get { return m_flexibleWidth; } } protected float m_flexibleWidth = -1f; /// - /// + /// /// public float minWidth { get { return m_minWidth; } } protected float m_minWidth; /// - /// + /// /// public float minHeight { get { return m_minHeight; } } protected float m_minHeight; /// - /// + /// /// public float maxWidth { get { return m_maxWidth; } } protected float m_maxWidth; /// - /// + /// /// public float maxHeight { get { return m_maxHeight; } } protected float m_maxHeight; /// - /// + /// /// protected LayoutElement layoutElement { @@ -1398,7 +1381,7 @@ protected LayoutElement layoutElement /// /// Computed preferred width of the text object. /// - public virtual float preferredWidth { get { m_preferredWidth = GetPreferredWidth(); return m_preferredWidth; } } + public virtual float preferredWidth { get { if (!m_isPreferredWidthDirty) return m_preferredWidth; m_preferredWidth = GetPreferredWidth(); return m_preferredWidth; } } protected float m_preferredWidth; protected float m_renderedWidth; protected bool m_isPreferredWidthDirty; @@ -1406,7 +1389,7 @@ protected LayoutElement layoutElement /// /// Computed preferred height of the text object. /// - public virtual float preferredHeight { get { m_preferredHeight = GetPreferredHeight(); return m_preferredHeight; } } + public virtual float preferredHeight { get { if (!m_isPreferredHeightDirty) return m_preferredHeight; m_preferredHeight = GetPreferredHeight(); return m_preferredHeight; } } protected float m_preferredHeight; protected float m_renderedHeight; protected bool m_isPreferredHeightDirty; @@ -1427,13 +1410,17 @@ protected LayoutElement layoutElement /// - /// + /// /// public int layoutPriority { get { return m_layoutPriority; } } protected int m_layoutPriority = 0; + protected bool m_isCalculateSizeRequired = false; protected bool m_isLayoutDirty; + protected bool m_verticesAlreadyDirty; + protected bool m_layoutAlreadyDirty; + protected bool m_isAwake; internal bool m_isWaitingOnResourceLoad; @@ -1463,7 +1450,7 @@ internal enum TextInputSources { Text = 0, SetText = 1, SetCharArray = 2, String //[SerializeField] internal TextInputSources m_inputSource; - protected float m_fontScale; // Scaling of the font based on Atlas true Font Size and Rendered Font Size. + protected float m_fontScale; // Scaling of the font based on Atlas true Font Size and Rendered Font Size. protected float m_fontScaleMultiplier; // Used for handling of superscript and subscript. protected char[] m_htmlTag = new char[128]; // Maximum length of rich text tag. This is preallocated to avoid GC. @@ -1473,7 +1460,7 @@ internal enum TextInputSources { Text = 0, SetText = 1, SetCharArray = 2, String protected float tag_LineIndent = 0; protected float tag_Indent = 0; - protected TMP_TextProcessingStack m_indentStack = new TMP_TextProcessingStack(new float[16]); + protected TMP_RichTextTagStack m_indentStack = new TMP_RichTextTagStack(new float[16]); protected bool tag_NoParsing; //protected TMP_LinkInfo tag_LinkInfo = new TMP_LinkInfo(); @@ -1481,15 +1468,8 @@ 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]; - /// - /// The number of Unicode characters that have been parsed and contained in the m_InternalParsingBuffer - /// - protected int m_InternalParsingBufferSize; + protected UnicodeChar[] m_TextParsingBuffer; // This array holds the characters to be processed by GenerateMesh(); protected struct UnicodeChar { @@ -1498,22 +1478,6 @@ protected struct UnicodeChar public int length; } - protected struct SpecialCharacter - { - public TMP_Character character; - public TMP_FontAsset fontAsset; - public Material material; - public int materialIndex; - - public SpecialCharacter(TMP_Character character, int materialIndex) - { - this.character = character; - this.fontAsset = character.textAsset as TMP_FontAsset; - this.material = this.fontAsset != null ? this.fontAsset.material : null; - this.materialIndex = materialIndex; - } - } - private TMP_CharacterInfo[] m_internalCharacterInfo; // Used by functions to calculate preferred values. protected char[] m_input_CharArray = new char[256]; // This array hold the characters from the SetText(); private int m_charArray_Length = 0; @@ -1524,10 +1488,7 @@ public SpecialCharacter(TMP_Character character, int materialIndex) protected WordWrapState m_SavedLineState = new WordWrapState(); protected WordWrapState m_SavedEllipsisState = new WordWrapState(); protected WordWrapState m_SavedLastValidState = new WordWrapState(); - protected WordWrapState m_SavedSoftLineBreakState = new WordWrapState(); - - //internal Stack m_LineBreakCandiateStack = new Stack(); - internal TMP_TextProcessingStack m_EllipsisInsertionCandidateStack = new TMP_TextProcessingStack(8, 8); + //protected WordWrapState m_SavedInvalidLineBreakingState = new WordWrapState(); // Fields whose state is saved in conjunction with text parsing and word wrapping. protected int m_characterCount; @@ -1540,15 +1501,12 @@ public SpecialCharacter(TMP_Character character, int materialIndex) protected int m_lineNumber; protected int m_lineVisibleCharacterCount; protected int m_pageNumber; - protected float m_PageAscender; - protected float m_maxTextAscender; + protected float m_maxAscender; protected float m_maxCapHeight; - protected float m_ElementAscender; - protected float m_ElementDescender; + protected float m_maxDescender; protected float m_maxLineAscender; protected float m_maxLineDescender; protected float m_startOfLineAscender; - protected float m_startOfLineDescender; //protected float m_maxFontScale; protected float m_lineOffset; protected Extents m_meshExtents; @@ -1556,37 +1514,36 @@ public SpecialCharacter(TMP_Character character, int materialIndex) // Fields used for vertex colors protected Color32 m_htmlColor = new Color(255, 255, 255, 128); - protected TMP_TextProcessingStack m_colorStack = new TMP_TextProcessingStack(new Color32[16]); - protected TMP_TextProcessingStack m_underlineColorStack = new TMP_TextProcessingStack(new Color32[16]); - protected TMP_TextProcessingStack m_strikethroughColorStack = new TMP_TextProcessingStack(new Color32[16]); - protected TMP_TextProcessingStack m_HighlightStateStack = new TMP_TextProcessingStack(new HighlightState[16]); + protected TMP_RichTextTagStack m_colorStack = new TMP_RichTextTagStack(new Color32[16]); + protected TMP_RichTextTagStack m_underlineColorStack = new TMP_RichTextTagStack(new Color32[16]); + protected TMP_RichTextTagStack m_strikethroughColorStack = new TMP_RichTextTagStack(new Color32[16]); + protected TMP_RichTextTagStack m_HighlightStateStack = new TMP_RichTextTagStack(new HighlightState[16]); protected TMP_ColorGradient m_colorGradientPreset; - protected TMP_TextProcessingStack m_colorGradientStack = new TMP_TextProcessingStack(new TMP_ColorGradient[16]); + protected TMP_RichTextTagStack m_colorGradientStack = new TMP_RichTextTagStack(new TMP_ColorGradient[16]); protected bool m_colorGradientPresetIsTinted; protected float m_tabSpacing = 0; protected float m_spacing = 0; // STYLE TAGS - protected TMP_TextProcessingStack[] m_TextStyleStacks = new TMP_TextProcessingStack[8]; + protected TMP_RichTextTagStack[] m_TextStyleStacks = new TMP_RichTextTagStack[8]; protected int m_TextStyleStackDepth = 0; - protected TMP_TextProcessingStack m_ItalicAngleStack = new TMP_TextProcessingStack(new int[16]); + protected TMP_RichTextTagStack m_ItalicAngleStack = new TMP_RichTextTagStack(new int[16]); protected int m_ItalicAngle; - protected TMP_TextProcessingStack m_actionStack = new TMP_TextProcessingStack(new int[16]); + protected TMP_RichTextTagStack m_actionStack = new TMP_RichTextTagStack(new int[16]); protected float m_padding = 0; protected float m_baselineOffset; // Used for superscript and subscript. - protected TMP_TextProcessingStack m_baselineOffsetStack = new TMP_TextProcessingStack(new float[16]); + protected TMP_RichTextTagStack m_baselineOffsetStack = new TMP_RichTextTagStack(new float[16]); protected float m_xAdvance; // Tracks x advancement from character to character. protected TMP_TextElementType m_textElementType; protected TMP_TextElement m_cached_TextElement; // Glyph / Character information is cached into this variable which is faster than having to fetch from the Dictionary multiple times. - - protected SpecialCharacter m_Ellipsis; - protected SpecialCharacter m_Underline; + protected TMP_Character m_cached_Underline_Character; // Same as above but for the underline character which is used for Underline. + protected TMP_Character m_cached_Ellipsis_Character; protected TMP_SpriteAsset m_defaultSpriteAsset; protected TMP_SpriteAsset m_currentSpriteAsset; @@ -1624,7 +1581,7 @@ protected virtual void SetFontBaseMaterial(Material mat) { } protected virtual Material[] GetSharedMaterials() { return null; } /// - /// + /// /// protected virtual void SetSharedMaterials(Material[] materials) { } @@ -1671,7 +1628,7 @@ protected void SetVertexColorGradient(TMP_ColorGradient gradient) /// protected void SetTextSortingOrder(VertexSortingOrder order) { - + } /// @@ -1771,7 +1728,7 @@ public virtual void ForceMeshUpdate(bool ignoreActiveState = false, bool forceTe /// - /// Internal function used by the Text Input Field to populate TMP_TextInfo data. + /// Internal function used by the Text Input Field to populate TMP_TextInfo data. /// internal void SetTextInternal(string text) { @@ -1823,7 +1780,7 @@ public virtual void UpdateMeshPadding() { } /// - /// + /// /// //public virtual new void UpdateGeometry() { } @@ -1856,7 +1813,7 @@ public override void CrossFadeAlpha(float alpha, float duration, bool ignoreTime /// - /// + /// /// /// /// @@ -1867,7 +1824,7 @@ protected virtual void InternalCrossFadeColor(Color targetColor, float duration, /// - /// + /// /// /// /// @@ -1889,25 +1846,22 @@ protected void ParseInputText() { case TextInputSources.String: case TextInputSources.Text: - if (m_TextPreprocessor != null) - m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_TextPreprocessor.PreprocessText(m_text), ref m_InternalParsingBuffer); - else - m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_text, ref m_InternalParsingBuffer); + StringToCharArray(m_text, ref m_TextParsingBuffer); break; case TextInputSources.SetText: - m_InternalParsingBufferSize = CharArrayToInternalParsingBuffer(m_input_CharArray, ref m_InternalParsingBuffer); + SetTextArrayToCharArray(m_input_CharArray, ref m_TextParsingBuffer); break; case TextInputSources.SetCharArray: break; } - SetArraySizes(m_InternalParsingBuffer); + SetArraySizes(m_TextParsingBuffer); ////Profiler.EndSample(); } /// - /// + /// /// /// public void SetText(string text, bool syncTextInputBox = true) @@ -1918,259 +1872,91 @@ public void SetText(string text, bool syncTextInputBox = true) /// /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." + /// ex. TextMeshPro.SetText ("Number is {0:1}.", 5.56f); /// - /// String containing the pattern. - /// First float value. + /// + /// String containing the pattern." + /// Value is a float. public void SetText(string text, float arg0) { - SetText(text, arg0, 0, 0, 0, 0, 0, 0, 0); + SetText(text, arg0, 255, 255); } /// /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." + /// ex. TextMeshPro.SetText ("First number is {0} and second is {1:2}.", 10, 5.756f); /// - /// String containing the pattern. - /// First float value. - /// Second float value. + /// + /// String containing the pattern." + /// Value is a float. + /// Value is a float. public void SetText(string text, float arg0, float arg1) { - SetText(text, arg0, arg1, 0, 0, 0, 0, 0, 0); + SetText(text, arg0, arg1, 255); } /// /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." + /// ex. TextMeshPro.SetText ("A = {0}, B = {1} and C = {2}.", 2, 5, 7); /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. + /// + /// String containing the pattern." + /// Value is a float. + /// Value is a float. + /// Value is a float. public void SetText(string text, float arg0, float arg1, float arg2) { - SetText(text, arg0, arg1, arg2, 0, 0, 0, 0, 0); - } - - /// - /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." - /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. - /// Forth float value. - public void SetText(string text, float arg0, float arg1, float arg2, float arg3) - { - SetText(text, arg0, arg1, arg2, arg3, 0, 0, 0, 0); - } - - /// - /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." - /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. - /// Forth float value. - /// Fifth float value. - public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4) - { - SetText(text, arg0, arg1, arg2, arg3, arg4, 0, 0, 0); - } - - /// - /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." - /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. - /// Forth float value. - /// Fifth float value. - /// Sixth float value. - public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5) - { - SetText(text, arg0, arg1, arg2, arg3, arg4, arg5, 0, 0); - } - - /// - /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." - /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. - /// Forth float value. - /// Fifth float value. - /// Sixth float value. - /// Seventh float value. - public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5, float arg6) - { - SetText(text, arg0, arg1, arg2, arg3, arg4, arg5, arg6, 0); - } - - /// - /// Formatted string containing a pattern and a value representing the text to be rendered. - /// Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f); - /// Results "A = 10.75, B = 11, C = 010.8." - /// - /// String containing the pattern. - /// First float value. - /// Second float value. - /// Third float value. - /// Forth float value. - /// Fifth float value. - /// Sixth float value. - /// Seventh float value. - /// Eighth float value. - public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5, float arg6, float arg7) - { - int argIndex = 0; - int padding = 0; int decimalPrecision = 0; + int index = 0; - int readFlag = 0; - - int readIndex = 0; - int writeIndex = 0; - - for (; readIndex < text.Length; readIndex++) + for (int i = 0; i < text.Length; i++) { - char c = text[readIndex]; + char c = text[i]; - if (c == '{') + if (c == 123) // '{' { - readFlag = 1; - continue; - } + // Check if user is requesting some decimal precision. Format is {0:2} + if (text[i + 2] == 58) // ':' + { + decimalPrecision = text[i + 3] - 48; + } - if (c == '}') - { - // Add arg(index) to array - switch (argIndex) + switch (text[i + 1] - 48) { - case 0: - AddFloatToCharArray(arg0, padding, decimalPrecision, ref writeIndex); - break; - case 1: - AddFloatToCharArray(arg1, padding, decimalPrecision, ref writeIndex); + case 0: // 1st Arg + AddFloatToCharArray(arg0, ref index, decimalPrecision); break; - case 2: - AddFloatToCharArray(arg2, padding, decimalPrecision, ref writeIndex); + case 1: // 2nd Arg + AddFloatToCharArray(arg1, ref index, decimalPrecision); break; - case 3: - AddFloatToCharArray(arg3, padding, decimalPrecision, ref writeIndex); + case 2: // 3rd Arg + AddFloatToCharArray(arg2, ref index, decimalPrecision); break; - case 4: - AddFloatToCharArray(arg4, padding, decimalPrecision, ref writeIndex); - break; - case 5: - AddFloatToCharArray(arg5, padding, decimalPrecision, ref writeIndex); - break; - case 6: - AddFloatToCharArray(arg6, padding, decimalPrecision, ref writeIndex); - break; - case 7: - AddFloatToCharArray(arg7, padding, decimalPrecision, ref writeIndex); - break; - } - - argIndex = 0; - readFlag = 0; - padding = 0; - decimalPrecision = 0; - continue; - } - - // Read Argument index - if (readFlag == 1) - { - if (c >= '0' && c <= '8') - { - argIndex = c - 48; - readFlag = 2; - continue; - } - } - - // Read formatting for integral part of the value - if (readFlag == 2) - { - // Skip ':' separator - if (c == ':') - continue; - - // Done reading integral formatting and value - if (c == '.') - { - readFlag = 3; - continue; - } - - if (c == '#') - { - // do something - continue; - } - - if (c == '0') - { - padding += 1; - continue; - } - - if (c == ',') - { - // Use commas in the integral value - continue; } - // Legacy mode - if (c >= '1' && c <= '9') - { - decimalPrecision = c - 48; - continue; - } - } + if (text[i + 2] == 58) + i += 4; + else + i += 2; - // Read Decimal Precision value - if (readFlag == 3) - { - if (c == '0') - { - decimalPrecision += 1; - continue; - } + continue; } - - // Write value - m_input_CharArray[writeIndex] = c; - writeIndex += 1; + m_input_CharArray[index] = c; + index += 1; } - m_input_CharArray[writeIndex] = (char)0; - m_charArray_Length = writeIndex; // Set the length to where this '0' termination is. + m_input_CharArray[index] = (char)0; + m_charArray_Length = index; // Set the length to where this '0' termination is. #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - m_text = new string(m_input_CharArray, 0, writeIndex - 1); + m_text = new string(m_input_CharArray, 0, index); #endif m_inputSource = TextInputSources.SetText; m_isInputParsingRequired = true; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); @@ -2193,66 +1979,34 @@ public void SetText(StringBuilder text) m_text = text.ToString(); #endif - m_InternalParsingBufferSize = StringBuilderToInternalParsingBuffer(text, ref m_InternalParsingBuffer); + StringBuilderToIntArray(text, ref m_TextParsingBuffer); m_isInputParsingRequired = true; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); } - /// - /// 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) { - int characterCount = sourceText == null ? 0 : sourceText.Length; + // Initialize internal character buffer if necessary + if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - if (characterCount == 0) + if (sourceText == null || sourceText.Length == 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); @@ -2262,7 +2016,7 @@ public void SetCharArray(char[] sourceText) // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); for (int i = 0; sourceText != null && i < sourceText.Length; i++) { @@ -2271,30 +2025,30 @@ public void SetCharArray(char[] sourceText) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r LineFeed - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 13; + m_TextParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 9; + m_TextParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 11; + m_TextParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2306,9 +2060,9 @@ public void SetCharArray(char[] sourceText) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2316,19 +2070,9 @@ public void SetCharArray(char[] sourceText) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - - m_InternalParsingBuffer[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0x200B; + m_TextParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2339,7 +2083,7 @@ public void SetCharArray(char[] sourceText) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2349,7 +2093,7 @@ public void SetCharArray(char[] sourceText) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2357,9 +2101,9 @@ public void SetCharArray(char[] sourceText) } } - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; + m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2367,16 +2111,16 @@ public void SetCharArray(char[] sourceText) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0; - m_InternalParsingBufferSize = writeIndex; + m_TextParsingBuffer[writeIndex].unicode = 0; m_inputSource = TextInputSources.SetCharArray; m_isInputParsingRequired = true; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); @@ -2389,36 +2133,23 @@ public void SetCharArray(char[] sourceText) /// public void SetCharArray(char[] sourceText, int start, int length) { - 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; - } + // Initialize internal character buffer if necessary + if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. - if (characterCount == 0) + if (sourceText == null || sourceText.Length == 0 || length == 0) + { m_text = string.Empty; + start = 0; + length = 0; + } else - 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; + // TODO: Add potential range check on start + length relative to array size. + m_text = new string(sourceText, start, length); } - - // Make sure parsing buffer is large enough to handle the required text. - if (m_InternalParsingBuffer.Length < characterCount) - ResizeInternalArray(ref m_InternalParsingBuffer, characterCount); + #endif // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) @@ -2429,7 +2160,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_InternalParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); int i = start; int end = start + length; @@ -2440,30 +2171,30 @@ public void SetCharArray(char[] sourceText, int start, int length) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r Carriage Return - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 13; + m_TextParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 9; + m_TextParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 11; + m_TextParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2475,9 +2206,9 @@ public void SetCharArray(char[] sourceText, int start, int length) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2485,19 +2216,9 @@ public void SetCharArray(char[] sourceText, int start, int length) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - - m_InternalParsingBuffer[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0x200B; + m_TextParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2508,7 +2229,7 @@ public void SetCharArray(char[] sourceText, int start, int length) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2518,7 +2239,7 @@ public void SetCharArray(char[] sourceText, int start, int length) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2526,9 +2247,9 @@ public void SetCharArray(char[] sourceText, int start, int length) } } - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; + m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2536,15 +2257,16 @@ public void SetCharArray(char[] sourceText, int start, int length) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0; + m_TextParsingBuffer[writeIndex].unicode = 0; m_inputSource = TextInputSources.SetCharArray; m_havePropertiesChanged = true; m_isInputParsingRequired = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); @@ -2558,7 +2280,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_InternalParsingBuffer == null) m_InternalParsingBuffer = new UnicodeChar[8]; + if (m_TextParsingBuffer == null) m_TextParsingBuffer = new UnicodeChar[8]; #if UNITY_EDITOR // Create new string to be displayed in the Input Text Box of the Editor Panel. @@ -2583,7 +2305,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_InternalParsingBuffer, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, ref writeIndex); int end = start + length; for (int i = start; i < end && i < sourceText.Length; i++) @@ -2593,30 +2315,30 @@ public void SetCharArray(int[] sourceText, int start, int length) switch ((int)sourceText[i + 1]) { case 110: // \n LineFeed - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r LineFeed - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 13; + m_TextParsingBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 9; + m_TextParsingBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 118: // \v Vertical tab used as soft line break - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 11; + m_TextParsingBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -2628,9 +2350,9 @@ public void SetCharArray(int[] sourceText, int start, int length) { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 10; + m_TextParsingBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2638,19 +2360,9 @@ public void SetCharArray(int[] sourceText, int start, int length) } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); - - m_InternalParsingBuffer[writeIndex].unicode = 0x200B; + m_TextParsingBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2661,7 +2373,7 @@ public void SetCharArray(int[] sourceText, int start, int length) m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_TextParsingBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2671,7 +2383,7 @@ public void SetCharArray(int[] sourceText, int start, int length) { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref m_TextParsingBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2679,9 +2391,9 @@ public void SetCharArray(int[] sourceText, int start, int length) } } - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = sourceText[i]; + m_TextParsingBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2689,15 +2401,16 @@ public void SetCharArray(int[] sourceText, int start, int length) // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex); + InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == m_TextParsingBuffer.Length) ResizeInternalArray(ref m_TextParsingBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0; + m_TextParsingBuffer[writeIndex].unicode = 0; m_inputSource = TextInputSources.SetCharArray; m_havePropertiesChanged = true; m_isInputParsingRequired = true; + m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); @@ -2708,34 +2421,14 @@ public void SetCharArray(int[] sourceText, int start, int length) /// Copies Content of formatted SetText() to charBuffer. ///
/// - /// - protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeChar[] internalParsingArray) + /// + protected void SetTextArrayToCharArray(char[] sourceText, ref UnicodeChar[] charBuffer) { - 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 - - // Early exit if string is null or empty - if (characterCount == 0) - { - if (internalParsingArray != null) - internalParsingArray[0].unicode = 0; - - return 0; - } + //Debug.Log("SetText Array to Char called."); + if (sourceText == null || m_charArray_Length == 0) + return; - // 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); + if (charBuffer == null) charBuffer = new UnicodeChar[8]; // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) @@ -2746,16 +2439,16 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref m_TextParsingBuffer, 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 == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); i += 1; writeIndex += 1; continue; @@ -2766,9 +2459,9 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 10; + charBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -2776,19 +2469,9 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - - internalParsingArray[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - m_InternalParsingBuffer[writeIndex].unicode = 0x200B; + charBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -2799,7 +2482,7 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -2809,7 +2492,7 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -2817,9 +2500,9 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha } } - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = sourceText[i]; + charBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -2827,13 +2510,11 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); + InsertClosingStyleTag(ref m_TextParsingBuffer, ref writeIndex); - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 0; - - return writeIndex; + charBuffer[writeIndex].unicode = 0; } @@ -2841,25 +2522,16 @@ protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeCha /// Method to store the content of a string into an integer array. ///
/// - /// - protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] internalParsingArray) + /// + protected void StringToCharArray(string sourceText, ref UnicodeChar[] charBuffer) { - int characterCount = sourceText == null ? 0 : sourceText.Length; - - // Early exit if string is null or empty - if (characterCount == 0) + if (sourceText == null) { - if (internalParsingArray != null) - internalParsingArray[0].unicode = 0; - - return 0; + charBuffer[0].unicode = 0; + return; } - // 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); + if (charBuffer == null) charBuffer = new UnicodeChar[8]; // Clear Style stacks. for (int j = 0; j < m_TextStyleStacks.Length; j++) @@ -2870,7 +2542,7 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref charBuffer, ref writeIndex); for (int i = 0; i < sourceText.Length; i++) { @@ -2881,11 +2553,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] case 85: // \U00000000 for UTF-32 Unicode if (sourceText.Length > i + 9) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2); - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 10; + charBuffer[writeIndex].unicode = GetUTF32(sourceText, i + 2); + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 10; i += 9; writeIndex += 1; @@ -2897,21 +2569,21 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] if (sourceText.Length <= i + 2) break; - if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = sourceText[i + 1]; - internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2]; + charBuffer[writeIndex].unicode = sourceText[i + 1]; + charBuffer[writeIndex + 1].unicode = sourceText[i + 2]; i += 2; writeIndex += 2; continue; case 110: // \n LineFeed if (!m_parseCtrlCharacters) break; - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 10; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 10; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2919,11 +2591,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] case 114: // \r if (!m_parseCtrlCharacters) break; - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 13; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 13; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2931,11 +2603,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] case 116: // \t Tab if (!m_parseCtrlCharacters) break; - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 9; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 9; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2943,11 +2615,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] case 117: // \u0000 for UTF-16 Unicode if (sourceText.Length > i + 5) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2); - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 6; + charBuffer[writeIndex].unicode = GetUTF16(sourceText, i + 2); + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 6; i += 5; writeIndex += 1; @@ -2957,11 +2629,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] case 118: // \v Vertical tab used as soft line break if (!m_parseCtrlCharacters) break; - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 11; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 11; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; i += 1; writeIndex += 1; @@ -2972,11 +2644,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] // 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 == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 2; + charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 2; i += 1; writeIndex += 1; @@ -2988,11 +2660,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 10; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 10; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; writeIndex += 1; i += 3; @@ -3001,24 +2673,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - - internalParsingArray[writeIndex].unicode = 160; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; - - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 0x200B; - internalParsingArray[writeIndex].stringIndex = i; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = 160; + charBuffer[writeIndex].stringIndex = i; + charBuffer[writeIndex].length = 1; writeIndex += 1; i += 5; @@ -3030,7 +2689,7 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -3040,18 +2699,18 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); i += 7; continue; } } - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = sourceText[i]; - internalParsingArray[writeIndex].stringIndex = writeIndex; - internalParsingArray[writeIndex].length = 1; + charBuffer[writeIndex].unicode = sourceText[i]; + charBuffer[writeIndex].stringIndex = writeIndex; + charBuffer[writeIndex].length = 1; writeIndex += 1; } @@ -3060,12 +2719,11 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); + InsertClosingStyleTag(ref charBuffer, ref writeIndex); - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 0; - return writeIndex; + charBuffer[writeIndex].unicode = 0; } @@ -3073,35 +2731,22 @@ protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] /// Copy contents of StringBuilder into int array. ///
/// Text to copy. - /// Array to store contents. - protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref UnicodeChar[] internalParsingArray) + /// Array to store contents. + protected void StringBuilderToIntArray(StringBuilder sourceText, ref UnicodeChar[] charBuffer) { - int characterCount = sourceText == null ? 0 : sourceText.Length; + if (sourceText == null) + { + charBuffer[0].unicode = 0; + return; + } + + if (charBuffer == null) charBuffer = new UnicodeChar[8]; #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 = sourceText.ToString(); + 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); @@ -3111,7 +2756,7 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref // Insert Opening Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex); + InsertOpeningStyleTag(m_TextStyle, 0, ref charBuffer, ref writeIndex); for (int i = 0; i < sourceText.Length; i++) { @@ -3122,9 +2767,9 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref case 85: // \U00000000 for UTF-32 Unicode if (sourceText.Length > i + 9) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2); + charBuffer[writeIndex].unicode = GetUTF32(sourceText, i + 2); i += 9; writeIndex += 1; continue; @@ -3133,49 +2778,49 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref case 92: // \ escape if (sourceText.Length <= i + 2) break; - if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = sourceText[i + 1]; - internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2]; + charBuffer[writeIndex].unicode = sourceText[i + 1]; + charBuffer[writeIndex + 1].unicode = sourceText[i + 2]; i += 2; writeIndex += 2; continue; case 110: // \n LineFeed - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 10; + charBuffer[writeIndex].unicode = 10; i += 1; writeIndex += 1; continue; case 114: // \r - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 13; + charBuffer[writeIndex].unicode = 13; i += 1; writeIndex += 1; continue; case 116: // \t Tab - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 9; + charBuffer[writeIndex].unicode = 9; i += 1; writeIndex += 1; continue; case 117: // \u0000 for UTF-16 Unicode if (sourceText.Length > i + 5) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2); + charBuffer[writeIndex].unicode = GetUTF16(sourceText, i + 2); i += 5; writeIndex += 1; continue; } break; case 118: // \v Vertical tab used as soft line break - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 11; + charBuffer[writeIndex].unicode = 11; i += 1; writeIndex += 1; continue; @@ -3185,9 +2830,9 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref // Handle UTF-32 in the input text (string). if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1])) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); + charBuffer[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]); i += 1; writeIndex += 1; continue; @@ -3198,9 +2843,9 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref { if (IsTagName(ref sourceText, "
", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 10; + charBuffer[writeIndex].unicode = 10; writeIndex += 1; i += 3; @@ -3208,19 +2853,9 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref } else if (IsTagName(ref sourceText, "", i)) { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); - - internalParsingArray[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref sourceText, "", i)) - { - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 0x200B; + charBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -3231,7 +2866,7 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref m_TextStyleStackDepth += 1; int srcOffset; - if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex)) + if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex)) { i = srcOffset; continue; @@ -3241,7 +2876,7 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref { m_TextStyleStackDepth += 1; - ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex); + ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex); // Strip even if style is invalid. i += 7; @@ -3249,9 +2884,9 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref } } - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = sourceText[i]; + charBuffer[writeIndex].unicode = sourceText[i]; writeIndex += 1; } @@ -3259,12 +2894,11 @@ protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref // Insert Closing Style if (textStyle.hashCode != (int)TagHashCode.NORMAL) - InsertClosingStyleTag(ref internalParsingArray, ref writeIndex); + InsertClosingStyleTag(ref charBuffer, ref writeIndex); - if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray); + if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - internalParsingArray[writeIndex].unicode = 0; - return writeIndex; + charBuffer[writeIndex].unicode = 0; } @@ -3357,16 +2991,6 @@ bool ReplaceOpeningStyleTag(ref string sourceText, int srcIndex, out int srcOffs continue; } - else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, " even if style is invalid. i += 7; continue; @@ -3490,16 +3114,6 @@ bool ReplaceOpeningStyleTag(ref int[] sourceText, int srcIndex, out int srcOffse continue; } - else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, " even if style is invalid. i += 7; continue; @@ -3624,16 +3238,6 @@ bool ReplaceOpeningStyleTag(ref char[] sourceText, int srcIndex, out int srcOffs continue; } - else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 160; - writeIndex += 1; - i += 5; - - continue; - } - else if (IsTagName(ref tagDefinition, "", i)) + else if (IsTagName(ref tagDefinition, "", i)) { if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - charBuffer[writeIndex].unicode = 0x200B; + charBuffer[writeIndex].unicode = 160; writeIndex += 1; i += 5; @@ -4142,16 +3716,6 @@ bool ReplaceClosingStyleTag(ref char[] sourceText, int srcIndex, ref UnicodeChar continue; } - else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, " - /// + /// ///
/// /// @@ -4410,16 +3964,6 @@ bool InsertOpeningStyleTag(TMP_Style style, int srcIndex, ref UnicodeChar[] char continue; } - else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, "", i)) - { - if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer); - - charBuffer[writeIndex].unicode = 0x200B; - writeIndex += 1; - i += 5; - - continue; - } else if (IsTagName(ref tagDefinition, " - /// + /// ///
void ResizeInternalArray (ref T[] array) { @@ -4761,104 +4295,89 @@ 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 decimal[] k_Power = { 5e-1m, 5e-2m, 5e-3m, 5e-4m, 5e-5m, 5e-6m, 5e-7m, 5e-8m, 5e-9m, 5e-10m }; // Used by FormatText to enable rounding and avoid using Mathf.Pow. + 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. - - void AddFloatToCharArray(float value, int padding, int precision, ref int writeIndex) + /// + /// Function used in conjunction with SetText() + /// + /// + /// + /// + protected void AddFloatToCharArray(double number, ref int index, int precision) { - if (value < 0) + if (number < 0) { - m_input_CharArray[writeIndex] = '-'; - writeIndex += 1; - value = -value; + m_input_CharArray[index++] = '-'; + number = -number; } - // Using decimal type due to floating point precision impacting formatting - decimal valueD = (decimal)value; - - // Round up value to the specified prevision otherwise set precision to max. - if (padding == 0 && precision == 0) - precision = 9; - else - valueD += k_Power[Mathf.Min(9, precision)]; + number += k_Power[Mathf.Min(9, precision)]; - long integer = (long)valueD; + double integer = Math.Truncate(number); - AddIntegerToCharArray(integer, padding, ref writeIndex); + AddIntToCharArray(integer, ref index, precision); if (precision > 0) { - valueD -= integer; + // Add the decimal point + m_input_CharArray[index++] = '.'; - // Add decimal point and values only if remainder is not zero. - if (valueD != 0) + number -= integer; + for (int p = 0; p < precision; p++) { - // Add decimal point - m_input_CharArray[writeIndex++] = '.'; + number *= 10; + long d = (long)(number); - for (int p = 0; p < precision; p++) - { - valueD *= 10; - long d = (long)valueD; - - m_input_CharArray[writeIndex++] = (char)(d + 48); - valueD -= d; - - if (valueD == 0) - p = precision; - } + m_input_CharArray[index++] = (char)(d + 48); + number -= d; } } } /// - /// + /// // Function used in conjunction with SetText() /// /// - /// - /// - void AddIntegerToCharArray(double number, int padding, ref int writeIndex) + /// + /// + protected void AddIntToCharArray(double number, ref int index, int precision) { - int integralCount = 0; - int i = writeIndex; + if (number < 0) + { + m_input_CharArray[index++] = '-'; + number = -number; + } + int i = index; do { m_input_CharArray[i++] = (char)(number % 10 + 48); number /= 10; - integralCount += 1; - } while (number > 0.999d || integralCount < padding); + } while (number > 0.999d); int lastIndex = i; - //// Reverse string - while (writeIndex + 1 < i) + // Reverse string + while (index + 1 < i) { i -= 1; - char t = m_input_CharArray[writeIndex]; - m_input_CharArray[writeIndex] = m_input_CharArray[i]; + char t = m_input_CharArray[index]; + m_input_CharArray[index] = m_input_CharArray[i]; m_input_CharArray[i] = t; - writeIndex += 1; + index += 1; } - writeIndex = lastIndex; + index = lastIndex; } /// /// Method used to determine the number of visible characters and required buffer allocations. /// - /// + /// /// - protected virtual int SetArraySizes(UnicodeChar[] unicodeChars) { return 0; } + protected virtual int SetArraySizes(UnicodeChar[] chars) { return 0; } /// @@ -4922,8 +4441,8 @@ public Vector2 GetPreferredValues(string text) { m_isCalculatingPreferredValues = true; - StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); - SetArraySizes(m_InternalParsingBuffer); + StringToCharArray(text, ref m_TextParsingBuffer); + SetArraySizes(m_TextParsingBuffer); Vector2 margin = k_LargePositiveVector2; @@ -4946,8 +4465,8 @@ public Vector2 GetPreferredValues(string text, float width, float height) { m_isCalculatingPreferredValues = true; - StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); - SetArraySizes(m_InternalParsingBuffer); + StringToCharArray(text, ref m_TextParsingBuffer); + SetArraySizes(m_TextParsingBuffer); Vector2 margin = new Vector2(width, height); @@ -4969,10 +4488,6 @@ protected float GetPreferredWidth() { if (TMP_Settings.instance == null) return 0; - // Return cached preferred height if already computed - if (!m_isPreferredWidthDirty) - return m_preferredWidth; - float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize; // Reset auto sizing point size bounds @@ -4990,11 +4505,11 @@ protected float GetPreferredWidth() } m_AutoSizeIterationCount = 0; - float preferredWidth = CalculatePreferredValues(ref fontSize, margin, false, false).x; + float preferredWidth = CalculatePreferredValues(fontSize, margin, true).x; m_isPreferredWidthDirty = false; - //Debug.Log("GetPreferredWidth() called on Object ID: " + GetInstanceID() + " on frame: " + Time.frameCount + ". Returning width of " + preferredWidth); + //Debug.Log("GetPreferredWidth() Called at frame " + Time.frameCount + ". Returning width of " + preferredWidth); return preferredWidth; } @@ -5005,7 +4520,7 @@ protected float GetPreferredWidth() /// /// /// - float GetPreferredWidth(Vector2 margin) + protected float GetPreferredWidth(Vector2 margin) { float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize; @@ -5015,7 +4530,7 @@ float GetPreferredWidth(Vector2 margin) m_charWidthAdjDelta = 0; m_AutoSizeIterationCount = 0; - float preferredWidth = CalculatePreferredValues(ref fontSize, margin, false, false).x; + float preferredWidth = CalculatePreferredValues(fontSize, margin, true).x; //Debug.Log("GetPreferredWidth() Called. Returning width of " + preferredWidth); @@ -5031,10 +4546,6 @@ protected float GetPreferredHeight() { if (TMP_Settings.instance == null) return 0; - // Return cached preferred height if already computed - if (!m_isPreferredHeightDirty) - return m_preferredHeight; - float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize; // Reset auto sizing point size bounds @@ -5050,23 +4561,12 @@ protected float GetPreferredHeight() ParseInputText(); } - // Reset Text Auto Size iteration tracking. - m_IsAutoSizePointSizeSet = false; m_AutoSizeIterationCount = 0; - - // The CalculatePreferredValues function is potentially called repeatedly when text auto size is enabled. - // This is a revised implementation to remove the use of recursion which could potentially result in stack overflow issues. - float preferredHeight = 0; - - while (m_IsAutoSizePointSizeSet == false) - { - preferredHeight = CalculatePreferredValues(ref fontSize, margin, m_enableAutoSizing, m_enableWordWrapping).y; - m_AutoSizeIterationCount += 1; - } + float preferredHeight = CalculatePreferredValues(fontSize, margin, !m_enableAutoSizing).y; m_isPreferredHeightDirty = false; - //Debug.Log("GetPreferredHeight() called on Object ID: " + GetInstanceID() + " on frame: " + Time.frameCount +". Returning height of " + preferredHeight); + //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight); return preferredHeight; } @@ -5077,7 +4577,7 @@ protected float GetPreferredHeight() ///
/// /// - float GetPreferredHeight(Vector2 margin) + protected float GetPreferredHeight(Vector2 margin) { float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize; @@ -5086,19 +4586,8 @@ float GetPreferredHeight(Vector2 margin) m_maxFontSize = m_fontSizeMax; m_charWidthAdjDelta = 0; - // Reset Text Auto Size iteration tracking. - m_IsAutoSizePointSizeSet = false; m_AutoSizeIterationCount = 0; - - // The CalculatePreferredValues function is potentially called repeatedly when text auto size is enabled. - // This is a revised implementation to remove the use of recursion which could potentially result in stack overflow issues. - float preferredHeight = 0; - - while (m_IsAutoSizePointSizeSet == false) - { - preferredHeight = CalculatePreferredValues(ref fontSize, margin, m_enableAutoSizing, m_enableWordWrapping).y; - m_AutoSizeIterationCount += 1; - } + float preferredHeight = CalculatePreferredValues(fontSize, margin, true).y; //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight); @@ -5116,7 +4605,7 @@ public Vector2 GetRenderedValues() } /// - /// + /// /// /// Should returned value only factor in visible characters and exclude those greater than maxVisibleCharacters for instance. /// @@ -5130,7 +4619,7 @@ public Vector2 GetRenderedValues(bool onlyVisibleCharacters) /// Method returning the rendered width of the text object. /// /// - float GetRenderedWidth() + protected float GetRenderedWidth() { return GetRenderedValues().x; } @@ -5148,7 +4637,7 @@ protected float GetRenderedWidth(bool onlyVisibleCharacters) /// Method returning the rendered height of the text object. /// /// - float GetRenderedHeight() + protected float GetRenderedHeight() { return GetRenderedValues().y; } @@ -5167,7 +4656,7 @@ protected float GetRenderedHeight(bool onlyVisibleCharacters) /// Method to calculate the preferred width and height of the text object. /// /// - protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 marginSize, bool isTextAutoSizingEnabled, bool isWordWrappingEnabled) + protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector2 marginSize, bool ignoreTextAutoSizing) { //Debug.Log("*** CalculatePreferredValues() ***"); // ***** Frame: " + Time.frameCount); @@ -5178,14 +4667,12 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m { Debug.LogWarning("Can't Generate Mesh! No Font Asset has been assigned to Object ID: " + this.GetInstanceID()); - m_IsAutoSizePointSizeSet = true; return Vector2.zero; } // Early exit if we don't have any Text to generate. - if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == (char)0) + if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) { - m_IsAutoSizePointSizeSet = true; return Vector2.zero; } @@ -5202,20 +4689,23 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Calculate the scale of the font based on selected font size and sampling point size. // baseScale is calculated using the font asset assigned to the text object. - float baseScale = m_fontScale = (fontSize / m_fontAsset.faceInfo.pointSize * m_fontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); + float baseScale = m_fontScale = (defaultFontSize / m_fontAsset.faceInfo.pointSize * m_fontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); float currentElementScale = baseScale; - float currentEmScale = fontSize * 0.01f * (m_isOrthographic ? 1 : 0.1f); + float currentEmScale = m_fontSize * 0.01f * (m_isOrthographic ? 1 : 0.1f); m_fontScaleMultiplier = 1; - m_currentFontSize = fontSize; + m_currentFontSize = defaultFontSize; m_sizeStack.SetDefault(m_currentFontSize); - float fontSizeDelta = 0; + + int charCode = 0; // Holds the character code of the currently being processed character. m_FontStyleInternal = m_fontStyle; // Set the default style. m_lineJustification = m_HorizontalAlignment; // m_textAlignment; // Sets the line justification mode to match editor alignment. m_lineJustificationStack.SetDefault(m_lineJustification); + float boldSpacingAdjustment = 0; + m_baselineOffset = 0; // Used by subscript characters. m_baselineOffsetStack.Clear(); @@ -5244,7 +4734,8 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m m_maxLineDescender = k_LargePositiveFloat; m_lineNumber = 0; m_startOfLineAscender = 0; - m_IsDrivenLineSpacing = false; + bool isDrivenLineSpacing = false; + float marginWidth = marginSize.x; float marginHeight = marginSize.y; @@ -5265,32 +4756,30 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Tracking of the highest Ascender m_maxCapHeight = 0; - m_maxTextAscender = 0; - m_ElementDescender = 0; + m_maxAscender = 0; + m_maxDescender = 0; float maxVisibleDescender = 0; bool isMaxVisibleDescenderSet = false; + // Initialize struct to track states of word wrapping bool isFirstWordOfLine = true; - m_isNonBreakingSpace = false; - //bool isLastBreakingChar = false; - bool isLastCharacterCJK = false; - //int lastSoftLineBreak = 0; + bool isLastBreakingChar = false; CharacterSubstitution characterToSubstitute = new CharacterSubstitution(-1, 0); bool isSoftHyphenIgnored = false; + bool isInjectingCharacter = false; WordWrapState internalWordWrapState = new WordWrapState(); WordWrapState internalLineState = new WordWrapState(); - WordWrapState internalSoftLineBreak = new WordWrapState(); // Counter to prevent recursive lockup when computing preferred values. m_AutoSizeIterationCount += 1; // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) { - int charCode = m_InternalParsingBuffer[i].unicode; + charCode = m_TextParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -5301,7 +4790,7 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m int endTagIndex; // Check if Tag is valid. If valid, skip to the end of the validated tag. - if (ValidateHtmlTag(m_InternalParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -5325,7 +4814,7 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Handle potential character substitutions #region Character Substitutions - bool isInjectingCharacter = false; + isInjectingCharacter = false; if (characterToSubstitute.index == m_characterCount) { @@ -5336,18 +4825,17 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m switch (charCode) { case 0x03: - m_internalCharacterInfo[m_characterCount].textElement = m_currentFontAsset.characterLookupTable[0x03]; - m_isTextTruncated = true; + // break; case 0x2D: - // + // break; case 0x2026: - m_internalCharacterInfo[m_characterCount].textElement = m_Ellipsis.character; ; + m_internalCharacterInfo[m_characterCount].textElement = m_cached_Ellipsis_Character; m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character; - m_internalCharacterInfo[m_characterCount].fontAsset = m_Ellipsis.fontAsset; - m_internalCharacterInfo[m_characterCount].material = m_Ellipsis.material; - m_internalCharacterInfo[m_characterCount].materialReferenceIndex = m_Ellipsis.materialIndex; + m_internalCharacterInfo[m_characterCount].fontAsset = m_materialReferences[0].fontAsset; + m_internalCharacterInfo[m_characterCount].material = m_materialReferences[0].material; + m_internalCharacterInfo[m_characterCount].materialReferenceIndex = 0; // Indicates the source parsing data has been modified. m_isTextTruncated = true; @@ -5408,10 +4896,10 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Look up Character Data from Dictionary and cache it. #region Look up Character Data - //float baselineOffset = 0; + float baselineOffset = 0; float spriteScale = 1; - float elementAscentLine = 0; - float elementDescentLine = 0; + float spriteAscentLine = 0; + float spriteDescentLine = 0; if (m_textElementType == TMP_TextElementType.Sprite) { // If a sprite is used as a fallback then get a reference to it and set the color to white. @@ -5425,22 +4913,24 @@ 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) { spriteScale = (m_currentFontSize / m_currentSpriteAsset.faceInfo.pointSize * m_currentSpriteAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); currentElementScale = sprite.scale * sprite.glyph.scale * spriteScale; - elementAscentLine = m_currentSpriteAsset.faceInfo.ascentLine; - //baselineOffset = m_currentSpriteAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentSpriteAsset.faceInfo.scale; - elementDescentLine = m_currentSpriteAsset.faceInfo.descentLine; + spriteAscentLine = m_currentSpriteAsset.faceInfo.ascentLine; + baselineOffset = m_currentSpriteAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentSpriteAsset.faceInfo.scale; + spriteDescentLine = m_currentSpriteAsset.faceInfo.descentLine; } else { spriteScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); currentElementScale = m_currentFontAsset.faceInfo.ascentLine / sprite.glyph.metrics.height * sprite.scale * sprite.glyph.scale * spriteScale; - elementAscentLine = m_currentFontAsset.faceInfo.ascentLine; - //baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale; - elementDescentLine = m_currentFontAsset.faceInfo.descentLine; + spriteAscentLine = m_currentFontAsset.faceInfo.ascentLine; + baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale; + spriteDescentLine = m_currentFontAsset.faceInfo.descentLine; } m_cached_TextElement = sprite; @@ -5457,17 +4947,11 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; - float adjustedScale; - if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) - adjustedScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - else - adjustedScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - - elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; - elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; + // Re-calculate font scale as the font asset may have changed. + m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - currentElementScale = adjustedScale * m_fontScaleMultiplier * m_cached_TextElement.scale; - //baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale; + currentElementScale = m_fontScale * m_fontScaleMultiplier * m_cached_TextElement.scale; + baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale; m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character; } @@ -5476,7 +4960,7 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Handle Soft Hyphen #region Handle Soft Hyphen - float currentElementUnmodifiedScale = currentElementScale; + float unModifiedScale = currentElementScale; if (charCode == 0xAD || charCode == 0x03) currentElementScale = 0; #endregion @@ -5554,84 +5038,73 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Set Padding based on selected font style #region Handle Style Padding - float boldSpacingAdjustment = 0; if (m_textElementType == TMP_TextElementType.Character && !isUsingAltTypeface && ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold)) // Checks for any combination of Bold Style. + { boldSpacingAdjustment = m_currentFontAsset.boldSpacing; + } + else + { + boldSpacingAdjustment = 0; + } #endregion Handle Style Padding m_internalCharacterInfo[m_characterCount].baseLine = 0 - m_lineOffset + m_baselineOffset; - // Compute text metrics + // Compute and save text element Ascender and maximum line Ascender. #region Compute Ascender & Descender values - // Element Ascender in line space float elementAscender = m_textElementType == TMP_TextElementType.Character - ? elementAscentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementAscentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.faceInfo.ascentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteAscentLine * spriteScale + m_baselineOffset; + + m_internalCharacterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; - // Element Descender in line space + // Compute and save text element Descender and maximum line Descender. float elementDescender = m_textElementType == TMP_TextElementType.Character - ? elementDescentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementDescentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.faceInfo.descentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteDescentLine * spriteScale + m_baselineOffset; - float adjustedAscender = elementAscender; - float adjustedDescender = elementDescender; + float elementDescenderII = m_internalCharacterInfo[m_characterCount].descender = elementDescender - m_lineOffset; - bool isFirstCharacterOfLine = m_characterCount == m_firstCharacterOfLine; - // Max line ascender and descender in line space - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode != 0x0A || m_characterCount == m_firstCharacterOfLine) { - // Special handling for Superscript and Subscript where we use the unadjusted line ascender and descender - if (m_baselineOffset != 0) - { - adjustedAscender = Mathf.Max((elementAscender - m_baselineOffset) / m_fontScaleMultiplier, adjustedAscender); - adjustedDescender = Mathf.Min((elementDescender - m_baselineOffset) / m_fontScaleMultiplier, adjustedDescender); - } - - m_maxLineAscender = Mathf.Max(adjustedAscender, m_maxLineAscender); - m_maxLineDescender = Mathf.Min(adjustedDescender, m_maxLineDescender); + m_maxLineAscender = elementAscender > m_maxLineAscender ? elementAscender : m_maxLineAscender; + m_maxLineDescender = elementDescender < m_maxLineDescender ? elementDescender : m_maxLineDescender; } - // Element Ascender and Descender in object space - if (isFirstCharacterOfLine || isWhiteSpace == false) - { - m_internalCharacterInfo[m_characterCount].adjustedAscender = adjustedAscender; - m_internalCharacterInfo[m_characterCount].adjustedDescender = adjustedDescender; - - m_ElementAscender = m_internalCharacterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; - m_ElementDescender = m_internalCharacterInfo[m_characterCount].descender = elementDescender - m_lineOffset; - } - else + // Adjust maxLineAscender and maxLineDescender if style is superscript or subscript + if ((m_FontStyleInternal & FontStyles.Subscript) == FontStyles.Subscript || (m_FontStyleInternal & FontStyles.Superscript) == FontStyles.Superscript) { - m_internalCharacterInfo[m_characterCount].adjustedAscender = m_maxLineAscender; - m_internalCharacterInfo[m_characterCount].adjustedDescender = m_maxLineDescender; + float baseAscender = (elementAscender - m_baselineOffset) / m_currentFontAsset.faceInfo.subscriptSize; + elementAscender = m_maxLineAscender; + m_maxLineAscender = baseAscender > m_maxLineAscender ? baseAscender : m_maxLineAscender; - m_ElementAscender = m_internalCharacterInfo[m_characterCount].ascender = m_maxLineAscender - m_lineOffset; - m_ElementDescender = m_internalCharacterInfo[m_characterCount].descender = m_maxLineDescender - m_lineOffset; + float baseDescender = (elementDescender - m_baselineOffset) / m_currentFontAsset.faceInfo.subscriptSize; + elementDescender = m_maxLineDescender; + m_maxLineDescender = baseDescender < m_maxLineDescender ? baseDescender : m_maxLineDescender; } - // Max text object ascender and cap height if (m_lineNumber == 0 || m_isNewPage) { - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode == 0x0A && m_characterCount != m_firstCharacterOfLine) + { + // Skip Line Feed that are not at the start of a line. + } + else { - m_maxTextAscender = m_maxLineAscender; + m_maxAscender = m_maxAscender > elementAscender ? m_maxAscender : elementAscender; m_maxCapHeight = Mathf.Max(m_maxCapHeight, m_currentFontAsset.m_FaceInfo.capLine * currentElementScale / smallCapsMultiplier); } } - // Page ascender - if (m_lineOffset == 0) - { - if (!isWhiteSpace || m_characterCount == m_firstCharacterOfLine) - m_PageAscender = m_PageAscender > elementAscender ? m_PageAscender : elementAscender; - } + //if (m_lineOffset == 0) + // pageAscender = pageAscender > elementAscender ? pageAscender : elementAscender; #endregion bool isJustifiedOrFlush = (m_lineJustification & HorizontalAlignmentOptions.Flush) == HorizontalAlignmentOptions.Flush || (m_lineJustification & HorizontalAlignmentOptions.Justified) == HorizontalAlignmentOptions.Justified; // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN. #region Handle Visible Characters - if (charCode == 9 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) + if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007 || (char.IsWhiteSpace((char)charCode) == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) { //float marginLeft = m_marginLeft; //float marginRight = m_marginRight; @@ -5639,14 +5112,14 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Injected characters do not override margins //if (isInjectingCharacter) //{ - // marginLeft = m_textInfo.lineInfo[m_lineNumber].marginLeft; - // marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; + //marginLeft = m_textInfo.lineInfo[m_lineNumber].marginLeft; + //marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; //} widthOfTextArea = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - m_marginLeft - m_marginRight, m_width) : marginWidth + 0.0001f - m_marginLeft - m_marginRight; // Calculate the line breaking width of the text. - textWidth = Mathf.Abs(m_xAdvance) + currentGlyphMetrics.horizontalAdvance * (1 - m_charWidthAdjDelta) * (charCode == 0xAD ? currentElementUnmodifiedScale : currentElementScale); + textWidth = Mathf.Abs(m_xAdvance) + currentGlyphMetrics.horizontalAdvance * (1 - m_charWidthAdjDelta) * (charCode != 0xAD ? currentElementScale : unModifiedScale); int testedCharacterCount = m_characterCount; @@ -5655,14 +5128,14 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m if (textWidth > widthOfTextArea * (isJustifiedOrFlush ? 1.05f : 1.0f)) { // Handle Line Breaking (if still possible) - if (isWordWrappingEnabled && m_characterCount != m_firstCharacterOfLine) // && isFirstWord == false) + if (m_enableWordWrapping && m_characterCount != m_firstCharacterOfLine) // && isFirstWord == false) { // Restore state to previous safe line breaking i = RestoreWordWrappingState(ref internalWordWrapState); // Replace Soft Hyphen by Hyphen Minus 0x2D #region Handle Soft Hyphenation - if (m_internalCharacterInfo[m_characterCount - 1].character == 0xAD && isSoftHyphenIgnored == false && m_overflowMode == TextOverflowModes.Overflow) + if (m_internalCharacterInfo[m_characterCount - 1].character == 0xAD && isSoftHyphenIgnored == false) { characterToSubstitute.index = m_characterCount - 1; characterToSubstitute.unicode = 0x2D; @@ -5682,76 +5155,27 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m } #endregion - // Adjust character spacing before breaking up word if auto size is enabled - #region Handle Text Auto Size (if word wrapping is no longer possible) - if (isTextAutoSizingEnabled && isFirstWordOfLine) - { - // Handle Character Width Adjustments - #region Character Width Adjustments - if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) - { - float adjustedTextWidth = textWidth; - - // Determine full width of the text - if (m_charWidthAdjDelta > 0) - adjustedTextWidth /= 1f - m_charWidthAdjDelta; - - float adjustmentDelta = textWidth - (widthOfTextArea - 0.0001f) * (isJustifiedOrFlush ? 1.05f : 1.0f); - m_charWidthAdjDelta += adjustmentDelta / adjustedTextWidth; - m_charWidthAdjDelta = Mathf.Min(m_charWidthAdjDelta, m_charWidthMaxAdj / 100); - - //Debug.Log("[" + m_AutoSizeIterationCount + "] Reducing Character Width by " + (m_charWidthAdjDelta * 100) + "%"); - return Vector2.zero; - } - #endregion - - // Handle Text Auto-sizing resulting from text exceeding vertical bounds. - #region Text Auto-Sizing (Text greater than vertical bounds) - if (fontSize > m_fontSizeMin && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) - { - m_maxFontSize = fontSize; - - float sizeDelta = Mathf.Max((fontSize - m_minFontSize) / 2, 0.05f); - fontSize -= sizeDelta; - fontSize = Mathf.Max((int)(fontSize * 20 + 0.5f) / 20f, m_fontSizeMin); - - //Debug.Log("[" + m_AutoSizeIterationCount + "] Reducing Point Size from [" + m_maxFontSize.ToString("f3") + "] to [" + m_fontSize.ToString("f3") + "] with delta of [" + sizeDelta.ToString("f3") + "]."); - return Vector2.zero; - } - #endregion Text Auto-Sizing - } - #endregion - - // Adjust line spacing if necessary - float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender; - if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage) - { - //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta); - m_ElementDescender -= baselineAdjustmentDelta; - m_lineOffset += baselineAdjustmentDelta; - } - - // Calculate line ascender and make sure if last character is superscript or subscript that we check that as well. + // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well. float lineAscender = m_maxLineAscender - m_lineOffset; float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender - m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender; + m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; if (!isMaxVisibleDescenderSet) - maxVisibleDescender = m_ElementDescender; + maxVisibleDescender = m_maxDescender; if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)) isMaxVisibleDescenderSet = true; - + // Store first character of the next line. - m_firstCharacterOfLine = m_characterCount; + m_firstCharacterOfLine = m_characterCount; m_lineVisibleCharacterCount = 0; // Compute Preferred Width & Height renderedWidth += m_xAdvance; - if (isWordWrappingEnabled) - renderedHeight = m_maxTextAscender - m_ElementDescender; + if (m_enableWordWrapping) + renderedHeight = m_maxAscender - m_maxDescender; else renderedHeight = Mathf.Max(renderedHeight, lineAscender - lineDescender); @@ -5760,26 +5184,24 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m m_lineNumber += 1; - float ascender = m_internalCharacterInfo[m_characterCount].adjustedAscender; - // Compute potential new line offset in the event a line break is needed. if (m_lineHeight == TMP_Math.FLOAT_UNSET) { + float ascender = m_internalCharacterInfo[m_characterCount].ascender - m_internalCharacterInfo[m_characterCount].baseLine; m_lineOffset += 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; - m_IsDrivenLineSpacing = false; + isDrivenLineSpacing = false; } else { m_lineOffset += m_lineHeight + m_lineSpacing * currentEmScale; - m_IsDrivenLineSpacing = true; + isDrivenLineSpacing = true; } m_maxLineAscender = k_LargeNegativeFloat; m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = ascender; + m_startOfLineAscender = elementAscender; m_xAdvance = 0 + tag_Indent; - //isStartOfNewLine = true; isFirstWordOfLine = true; continue; } @@ -5795,17 +5217,17 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Check if Line Spacing of previous line needs to be adjusted. #region Adjust Line Spacing - /*if (m_lineOffset > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_IsDrivenLineSpacing == false && !m_isNewPage) + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && isDrivenLineSpacing == false && !m_isNewPage && isInjectingCharacter == false) { float offsetDelta = m_maxLineAscender - m_startOfLineAscender; //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); - m_ElementDescender -= offsetDelta; + elementDescenderII -= offsetDelta; m_lineOffset += offsetDelta; m_startOfLineAscender += offsetDelta; internalWordWrapState.lineOffset = m_lineOffset; - internalWordWrapState.startOfLineAscender = m_startOfLineAscender; - }*/ + internalWordWrapState.previousLineAscender = m_startOfLineAscender; + } #endregion @@ -5821,14 +5243,14 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m { m_xAdvance += (m_monoSpacing - monoAdvance + ((m_currentFontAsset.normalSpacingOffset + characterSpacingAdjustment) * currentEmScale) + m_cSpacing) * (1 - m_charWidthAdjDelta); - if (isWhiteSpace || charCode == 0x200B) + if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B) m_xAdvance += m_wordSpacing * currentEmScale; } else { m_xAdvance += ((currentGlyphMetrics.horizontalAdvance + glyphAdjustments.xAdvance) * currentElementScale + (m_currentFontAsset.normalSpacingOffset + characterSpacingAdjustment + boldSpacingAdjustment) * currentEmScale + m_cSpacing) * (1 - m_charWidthAdjDelta); - if (isWhiteSpace || charCode == 0x200B) + if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B) m_xAdvance += m_wordSpacing * currentEmScale; } #endregion Tabulation & Stops @@ -5847,23 +5269,22 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Handle Line Spacing Adjustments + Word Wrapping & special case for last line. #region Check for Line Feed and Last Character - if (charCode == 10 || charCode == 11 || charCode == 0x03 || charCode == 0x2028 || charCode == 0x2029 || m_characterCount == totalCharacterCount - 1) + if (charCode == 10 || charCode == 11 || charCode == 0x03 || m_characterCount == totalCharacterCount - 1) { // Check if Line Spacing of previous line needs to be adjusted. - float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender; - if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage) + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && isDrivenLineSpacing == false && !m_isNewPage && isInjectingCharacter == false) { - m_ElementDescender -= baselineAdjustmentDelta; - m_lineOffset += baselineAdjustmentDelta; + float offsetDelta = m_maxLineAscender - m_startOfLineAscender; + elementDescenderII -= offsetDelta; + m_lineOffset += offsetDelta; } - m_isNewPage = false; // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well. //float lineAscender = m_maxLineAscender - m_lineOffset; float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender - m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender; + m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; // Store PreferredWidth paying attention to linefeed and last character of text. if (m_characterCount == totalCharacterCount - 1) @@ -5874,10 +5295,10 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m renderedWidth = 0; } - renderedHeight = m_maxTextAscender - m_ElementDescender; + renderedHeight = m_maxAscender - m_maxDescender; // Add new line if not last lines or character. - if (charCode == 10 || charCode == 11 || charCode == 0x2D || charCode == 0x2028 || charCode == 0x2029) + if (charCode == 10 || charCode == 11 || charCode == 0x2D) { // Store the state of the line before starting on the new line. SaveWordWrappingState(ref internalLineState, i, m_characterCount); @@ -5887,24 +5308,22 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m m_lineNumber += 1; m_firstCharacterOfLine = m_characterCount + 1; - float ascender = m_internalCharacterInfo[m_characterCount].adjustedAscender; - // Apply Line Spacing with special handling for VT char(11) if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; + float lineOffsetDelta = 0 - m_maxLineDescender + elementAscender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; m_lineOffset += lineOffsetDelta; - m_IsDrivenLineSpacing = false; + isDrivenLineSpacing = false; } else { - m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; - m_IsDrivenLineSpacing = true; + m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; + isDrivenLineSpacing = true; } m_maxLineAscender = k_LargeNegativeFloat; m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = ascender; + m_startOfLineAscender = elementAscender; m_xAdvance = 0 + tag_LineIndent + tag_Indent; @@ -5914,79 +5333,42 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // If End of Text if (charCode == 0x03) - i = m_InternalParsingBuffer.Length; + i = m_TextParsingBuffer.Length; } #endregion Check for Linefeed or Last Character // Save State of Mesh Creation for handling of Word Wrapping #region Save Word Wrapping State - if (isWordWrappingEnabled || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis) + if (m_enableWordWrapping || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis) { - if ((isWhiteSpace || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && !m_isNonBreakingSpace && charCode != 0xA0 && charCode != 0x2007 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060) + if ((char.IsWhiteSpace((char)charCode) || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && !m_isNonBreakingSpace && charCode != 0xA0 && charCode != 0x2007 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060) { - // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored + // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored // for Word Wrapping. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount); isFirstWordOfLine = false; - isLastCharacterCJK = false; - - // Reset soft line breaking point since we now have a valid hard break point. - internalSoftLineBreak.previous_WordBreak = -1; } // Handling for East Asian languages - else if (m_isNonBreakingSpace == false && - ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ - charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */ - charCode > 0xAC00 && charCode < 0xD7FF)&& /* Hangul Syllables */ - TMP_Settings.useModernHangulLineBreakingRules == false || - - (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ - charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ - charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ - charCode > 0xFF00 && charCode < 0xFFEF))) /* CJK Halfwidth */ - { - bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); - bool isFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_internalCharacterInfo[m_characterCount + 1].character); - - if (isFirstWordOfLine || isLeadingCharacter == false) + else if ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ + charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ + charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jame Extended-A */ + charCode > 0xAC00 && charCode < 0xD7FF || /* Hangul Syllables */ + charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ + charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ + charCode > 0xFF00 && charCode < 0xFFEF) /* CJK Halfwidth */ + && !m_isNonBreakingSpace && !TMP_Settings.useModernHangulLineBreakingRules) + { + if (isFirstWordOfLine || isLastBreakingChar || TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode) == false && + (m_characterCount < totalCharacterCount - 1 && + TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_internalCharacterInfo[m_characterCount + 1].character) == false)) { - if (isFollowingCharacter == false) - { - SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount); - isFirstWordOfLine = false; - } - - if (isFirstWordOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace) - SaveWordWrappingState(ref internalSoftLineBreak, i, m_characterCount); - - SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount); - } - } - - isLastCharacterCJK = true; - } - else if (isLastCharacterCJK) - { - bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); - - if (isLeadingCharacter == false) SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount); - - isLastCharacterCJK = false; + isFirstWordOfLine = false; + } } - else if (isFirstWordOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace || (charCode == 0xAD && isSoftHyphenIgnored == false)) - SaveWordWrappingState(ref internalSoftLineBreak, i, m_characterCount); - + else if ((isFirstWordOfLine || isLastBreakingChar)) SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount); - isLastCharacterCJK = false; - } } #endregion Save Word Wrapping State @@ -5995,26 +5377,17 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m // Check Auto Sizing and increase font size to fill text container. #region Check Auto-Sizing (Upper Font Size Bounds) - fontSizeDelta = m_maxFontSize - m_minFontSize; - if (isTextAutoSizingEnabled && fontSizeDelta > 0.051f && fontSize < m_fontSizeMax && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) - { - // Reset character width adjustment delta - if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100) - m_charWidthAdjDelta = 0; - - m_minFontSize = fontSize; - - float sizeDelta = Mathf.Max((m_maxFontSize - fontSize) / 2, 0.05f); - fontSize += sizeDelta; - fontSize = Mathf.Min((int)(fontSize * 20 + 0.5f) / 20f, m_fontSizeMax); - - //Debug.Log("[" + m_AutoSizeIterationCount + "] Increasing Point Size from [" + m_minFontSize.ToString("f3") + "] to [" + m_fontSize.ToString("f3") + "] with delta of [" + sizeDelta.ToString("f3") + "]."); - return Vector2.zero; - } + //fontSizeDelta = m_maxFontSize - m_minFontSize; + //if (!m_isCharacterWrappingEnabled && ignoreTextAutoSizing == false && fontSizeDelta > 0.051f && defaultFontSize < m_fontSizeMax && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) + //{ + // m_minFontSize = defaultFontSize; + // defaultFontSize += Mathf.Max((m_maxFontSize - defaultFontSize) / 2, 0.05f); + // defaultFontSize = (int)(Mathf.Min(defaultFontSize, m_fontSizeMax) * 20 + 0.5f) / 20f; + + // return CalculatePreferredValues(defaultFontSize, marginSize, false); + //} #endregion End Auto-sizing Check - m_IsAutoSizePointSizeSet = true; - m_isCalculatingPreferredValues = false; // Adjust Preferred Width and Height to account for Margins. @@ -6041,7 +5414,6 @@ protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 m /// protected virtual Bounds GetCompoundBounds() { return new Bounds(); } - internal virtual Rect GetCanvasSpaceClippingRect() { return Rect.zero; } /// /// Method which returns the bounds of the text object; @@ -6240,23 +5612,14 @@ public virtual void ComputeMarginSize() { } protected void InsertNewLine(int i, float baseScale, float currentEmScale, float characterSpacingAdjustment, float width, float lineGap, ref bool isMaxVisibleDescenderSet, ref float maxVisibleDescender) { - // Adjust line spacing if necessary - float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender; - if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage) - { - AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta); - m_ElementDescender -= baselineAdjustmentDelta; - m_lineOffset += baselineAdjustmentDelta; - } - // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well. float lineAscender = m_maxLineAscender - m_lineOffset; float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender - m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender; + m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; if (!isMaxVisibleDescenderSet) - maxVisibleDescender = m_ElementDescender; + maxVisibleDescender = m_maxDescender; if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)) isMaxVisibleDescenderSet = true; @@ -6296,15 +5659,17 @@ protected void InsertNewLine(int i, float baseScale, float currentEmScale, float // Apply Line Spacing based on scale of the last character of the line. if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float ascender = m_textInfo.characterInfo[m_characterCount].adjustedAscender; + float ascender = m_textInfo.characterInfo[m_characterCount].ascender - m_textInfo.characterInfo[m_characterCount].baseLine; float lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; m_lineOffset += lineOffsetDelta; m_startOfLineAscender = ascender; + //isDrivenLineSpacing = false; } else { m_lineOffset += m_lineHeight + m_lineSpacing * currentEmScale; + //isDrivenLineSpacing = true; } m_maxLineAscender = k_LargeNegativeFloat; @@ -6348,13 +5713,11 @@ protected void SaveWordWrappingState(ref WordWrapState state, int index, int cou state.xAdvance = m_xAdvance; state.maxCapHeight = m_maxCapHeight; - state.maxAscender = m_maxTextAscender; - state.maxDescender = m_ElementDescender; - state.startOfLineAscender = m_startOfLineAscender; + state.maxAscender = m_maxAscender; + state.maxDescender = m_maxDescender; state.maxLineAscender = m_maxLineAscender; state.maxLineDescender = m_maxLineDescender; - state.pageAscender = m_PageAscender; - + state.previousLineAscender = m_startOfLineAscender; state.preferredWidth = m_preferredWidth; state.preferredHeight = m_preferredHeight; state.meshExtents = m_meshExtents; @@ -6362,7 +5725,6 @@ protected void SaveWordWrappingState(ref WordWrapState state, int index, int cou state.lineNumber = m_lineNumber; state.lineOffset = m_lineOffset; state.baselineOffset = m_baselineOffset; - state.isDrivenLineSpacing = m_IsDrivenLineSpacing; state.cSpace = m_cSpacing; state.mSpace = m_monoSpacing; @@ -6439,13 +5801,11 @@ protected int RestoreWordWrappingState(ref WordWrapState state) m_xAdvance = state.xAdvance; m_maxCapHeight = state.maxCapHeight; - m_maxTextAscender = state.maxAscender; - m_ElementDescender = state.maxDescender; - m_startOfLineAscender = state.startOfLineAscender; + m_maxAscender = state.maxAscender; + m_maxDescender = state.maxDescender; m_maxLineAscender = state.maxLineAscender; m_maxLineDescender = state.maxLineDescender; - m_PageAscender = state.pageAscender; - + m_startOfLineAscender = state.previousLineAscender; m_preferredWidth = state.preferredWidth; m_preferredHeight = state.preferredHeight; m_meshExtents = state.meshExtents; @@ -6453,7 +5813,6 @@ protected int RestoreWordWrappingState(ref WordWrapState state) m_lineNumber = state.lineNumber; m_lineOffset = state.lineOffset; m_baselineOffset = state.baselineOffset; - m_IsDrivenLineSpacing = state.isDrivenLineSpacing; m_cSpacing = state.cSpace; m_monoSpacing = state.mSpace; @@ -6729,9 +6088,9 @@ protected virtual void FillCharacterVertexBuffers(int i, int index_X4) int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex; index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount; - // Check to make sure our current mesh buffer allocations can hold these new Quads. - if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length) - m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4)); + // Make sure buffers allocation are sufficient to hold the vertex data + //if (m_textInfo.meshInfo[materialIndex].vertices.Length < index_X4 + 4) + // m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo(index_X4 + 4)); TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo; @@ -6780,10 +6139,6 @@ protected virtual void FillCharacterVertexBuffers(int i, int index_X4, bool isVo int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex; index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount; - // Check to make sure our current mesh buffer allocations can hold these new Quads. - if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length) - m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + (isVolumetric ? 8 : 4)) / 4)); - TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo; m_textInfo.characterInfo[i].vertexIndex = index_X4; @@ -6868,10 +6223,6 @@ protected virtual void FillSpriteVertexBuffers(int i, int index_X4) int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex; index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount; - // Check to make sure our current mesh buffer allocations can hold these new Quads. - if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length) - m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4)); - TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo; m_textInfo.characterInfo[i].vertexIndex = index_X4; @@ -6924,37 +6275,29 @@ protected virtual void FillSpriteVertexBuffers(int i, int index_X4) /// protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int index, float startScale, float endScale, float maxScale, float sdfScale, Color32 underlineColor) { - // Get Underline special character from the primary font asset. - GetUnderlineSpecialCharacter(m_fontAsset); - - if (m_Underline.character == null) + if (m_cached_Underline_Character == null) { if (!TMP_Settings.warningsDisabled) - Debug.LogWarning("Unable to add underline since the primary Font Asset doesn't contain the underline character.", this); + Debug.LogWarning("Unable to add underline since the Font Asset doesn't contain the underline character.", this); return; } - int underlineMaterialIndex = m_Underline.materialIndex; - int verticesCount = index + 12; // Check to make sure our current mesh buffer allocations can hold these new Quads. - if (verticesCount > m_textInfo.meshInfo[underlineMaterialIndex].vertices.Length) + if (verticesCount > m_textInfo.meshInfo[0].vertices.Length) { // Resize Mesh Buffers - m_textInfo.meshInfo[underlineMaterialIndex].ResizeMeshInfo(verticesCount / 4); + m_textInfo.meshInfo[0].ResizeMeshInfo(verticesCount / 4); } // Adjust the position of the underline based on the lowest character. This matters for subscript character. start.y = Mathf.Min(start.y, end.y); end.y = Mathf.Min(start.y, end.y); - GlyphMetrics underlineGlyphMetrics = m_Underline.character.glyph.metrics; - GlyphRect underlineGlyphRect = m_Underline.character.glyph.glyphRect; - - float segmentWidth = underlineGlyphMetrics.width / 2 * maxScale; + float segmentWidth = m_cached_Underline_Character.glyph.metrics.width / 2 * maxScale; - if (end.x - start.x < underlineGlyphMetrics.width * maxScale) + if (end.x - start.x < m_cached_Underline_Character.glyph.metrics.width * maxScale) { segmentWidth = (end.x - start.x) / 2f; } @@ -6962,11 +6305,11 @@ protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int ind float startPadding = m_padding * startScale / maxScale; float endPadding = m_padding * endScale / maxScale; - float underlineThickness = m_Underline.fontAsset.faceInfo.underlineThickness; + float underlineThickness = m_fontAsset.faceInfo.underlineThickness; // UNDERLINE VERTICES FOR (3) LINE SEGMENTS #region UNDERLINE VERTICES - Vector3[] vertices = m_textInfo.meshInfo[underlineMaterialIndex].vertices; + Vector3[] vertices = m_textInfo.meshInfo[0].vertices; // Front Part of the Underline vertices[index + 0] = start + new Vector3(0, 0 - (underlineThickness + m_padding) * maxScale, 0); // BL @@ -6989,19 +6332,16 @@ protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int ind // UNDERLINE UV0 #region HANDLE UV0 - Vector2[] uvs0 = m_textInfo.meshInfo[underlineMaterialIndex].uvs0; - - int atlasWidth = m_Underline.fontAsset.atlasWidth; - int atlasHeight = m_Underline.fontAsset.atlasHeight; + Vector2[] uvs0 = m_textInfo.meshInfo[0].uvs0; // Calculate UV required to setup the 3 Quads for the Underline. - Vector2 uv0 = new Vector2((underlineGlyphRect.x - startPadding) / atlasWidth, (underlineGlyphRect.y - m_padding) / atlasHeight); // bottom left - Vector2 uv1 = new Vector2(uv0.x, (underlineGlyphRect.y + underlineGlyphRect.height + m_padding) / atlasHeight); // top left - Vector2 uv2 = new Vector2((underlineGlyphRect.x - startPadding + (float)underlineGlyphRect.width / 2) / atlasWidth, uv1.y); // Mid Top Left + Vector2 uv0 = new Vector2((m_cached_Underline_Character.glyph.glyphRect.x - startPadding) / m_fontAsset.atlasWidth, (m_cached_Underline_Character.glyph.glyphRect.y - m_padding) / m_fontAsset.atlasHeight); // bottom left + Vector2 uv1 = new Vector2(uv0.x, (m_cached_Underline_Character.glyph.glyphRect.y + m_cached_Underline_Character.glyph.glyphRect.height + m_padding) / m_fontAsset.atlasHeight); // top left + Vector2 uv2 = new Vector2((m_cached_Underline_Character.glyph.glyphRect.x - startPadding + (float)m_cached_Underline_Character.glyph.glyphRect.width / 2) / m_fontAsset.atlasWidth, uv1.y); // Mid Top Left Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Mid Bottom Left - Vector2 uv4 = new Vector2((underlineGlyphRect.x + endPadding + (float)underlineGlyphRect.width / 2) / atlasWidth, uv1.y); // Mid Top Right + Vector2 uv4 = new Vector2((m_cached_Underline_Character.glyph.glyphRect.x + endPadding + (float)m_cached_Underline_Character.glyph.glyphRect.width / 2) / m_fontAsset.atlasWidth, uv1.y); // Mid Top Right Vector2 uv5 = new Vector2(uv4.x, uv0.y); // Mid Bottom right - Vector2 uv6 = new Vector2((underlineGlyphRect.x + endPadding + underlineGlyphRect.width) / atlasWidth, uv1.y); // End Part - Bottom Right + Vector2 uv6 = new Vector2((m_cached_Underline_Character.glyph.glyphRect.x + endPadding + m_cached_Underline_Character.glyph.glyphRect.width) / m_fontAsset.atlasWidth, uv1.y); // End Part - Bottom Right Vector2 uv7 = new Vector2(uv6.x, uv0.y); // End Part - Top Right // Left Part of the Underline @@ -7032,7 +6372,7 @@ protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int ind //Calculate the xScale or how much the UV's are getting stretched on the X axis for the middle section of the underline. float xScale = Mathf.Abs(sdfScale); - Vector2[] uvs2 = m_textInfo.meshInfo[underlineMaterialIndex].uvs2; + Vector2[] uvs2 = m_textInfo.meshInfo[0].uvs2; uvs2[0 + index] = PackUV(0, 0, xScale); uvs2[1 + index] = PackUV(0, 1, xScale); @@ -7057,11 +6397,11 @@ protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int ind #endregion // UNDERLINE VERTEX COLORS - #region UNDERLINE VERTEX COLORS + #region // Alpha is the lower of the vertex color or tag color alpha used. underlineColor.a = m_fontColor32.a < underlineColor.a ? (byte)(m_fontColor32.a) : (byte)(underlineColor.a); - Color32[] colors32 = m_textInfo.meshInfo[underlineMaterialIndex].colors32; + Color32[] colors32 = m_textInfo.meshInfo[0].colors32; colors32[0 + index] = underlineColor; colors32[1 + index] = underlineColor; colors32[2 + index] = underlineColor; @@ -7084,32 +6424,23 @@ protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int ind protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int index, Color32 highlightColor) { - if (m_Underline.character == null) + if (m_cached_Underline_Character == null) { - GetUnderlineSpecialCharacter(m_fontAsset); - - if (m_Underline.character == null) - { - if (!TMP_Settings.warningsDisabled) - Debug.LogWarning("Unable to add highlight since the primary Font Asset doesn't contain the underline character.", this); - - return; - } + if (!TMP_Settings.warningsDisabled) Debug.LogWarning("Unable to add highlight since the Font Asset doesn't contain the underline character.", this); + return; } - int underlineMaterialIndex = m_Underline.materialIndex; - int verticesCount = index + 4; // Check to make sure our current mesh buffer allocations can hold these new Quads. - if (verticesCount > m_textInfo.meshInfo[underlineMaterialIndex].vertices.Length) + if (verticesCount > m_textInfo.meshInfo[0].vertices.Length) { // Resize Mesh Buffers - m_textInfo.meshInfo[underlineMaterialIndex].ResizeMeshInfo(verticesCount / 4); + m_textInfo.meshInfo[0].ResizeMeshInfo(verticesCount / 4); } // UNDERLINE VERTICES FOR (3) LINE SEGMENTS #region HIGHLIGHT VERTICES - Vector3[] vertices = m_textInfo.meshInfo[underlineMaterialIndex].vertices; + Vector3[] vertices = m_textInfo.meshInfo[0].vertices; // Front Part of the Underline vertices[index + 0] = start; // BL @@ -7120,26 +6451,22 @@ protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int ind // UNDERLINE UV0 #region HANDLE UV0 - Vector2[] uvs0 = m_textInfo.meshInfo[underlineMaterialIndex].uvs0; + Vector2[] uvs0 = m_textInfo.meshInfo[0].uvs0; - int atlasWidth = m_fontAsset.atlasWidth; - int atlasHeight = m_fontAsset.atlasHeight; - GlyphRect glyphRect = m_Underline.character.glyph.glyphRect; - - // Calculate UV - Vector2 uv0 = new Vector2(((float)glyphRect.x + glyphRect.width / 2) / atlasWidth, (glyphRect.y + (float)glyphRect.height / 2) / atlasHeight); // bottom left + // Calculate UV required to setup the 3 Quads for the Underline. + Vector2 uv0 = new Vector2(((float)m_cached_Underline_Character.glyph.glyphRect.x + m_cached_Underline_Character.glyph.glyphRect.width / 2) / m_fontAsset.atlasWidth, (m_cached_Underline_Character.glyph.glyphRect.y + (float)m_cached_Underline_Character.glyph.glyphRect.height / 2) / m_fontAsset.atlasHeight); // bottom left //Vector2 uv1 = new Vector2(uv0.x, uv0.y); // top left //Vector2 uv2 = new Vector2(uv0.x, uv0.y); // Top Right //Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Bottom Right - // UVs for the Quad + // Left Part of the Underline uvs0[0 + index] = uv0; // BL uvs0[1 + index] = uv0; // TL uvs0[2 + index] = uv0; // TR uvs0[3 + index] = uv0; // BR #endregion - // HIGHLIGHT UV2 + // UNDERLINE UV2 #region HANDLE UV2 - SDF SCALE // UV1 contains Face / Border UV layout. //float min_UvX = 0; @@ -7148,12 +6475,12 @@ protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int ind ////Calculate the xScale or how much the UV's are getting stretched on the X axis for the middle section of the underline. //float xScale = 0; // Mathf.Abs(sdfScale); - Vector2[] uvs2 = m_textInfo.meshInfo[underlineMaterialIndex].uvs2; + Vector2[] uvs2 = m_textInfo.meshInfo[0].uvs2; Vector2 customUV = new Vector2(0, 1); - uvs2[0 + index] = customUV; - uvs2[1 + index] = customUV; - uvs2[2 + index] = customUV; - uvs2[3 + index] = customUV; + uvs2[0 + index] = customUV; // PackUV(-0.2f, -0.2f, xScale); + uvs2[1 + index] = customUV; // PackUV(-0.2f, -0.1f, xScale); + uvs2[2 + index] = customUV; // PackUV(-0.1f, -0.1f, xScale); + uvs2[3 + index] = customUV; // PackUV(-0.1f, -0.2f, xScale); #endregion // HIGHLIGHT VERTEX COLORS @@ -7161,7 +6488,7 @@ protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int ind // Alpha is the lower of the vertex color or tag color alpha used. highlightColor.a = m_fontColor32.a < highlightColor.a ? m_fontColor32.a : highlightColor.a; - Color32[] colors32 = m_textInfo.meshInfo[underlineMaterialIndex].colors32; + Color32[] colors32 = m_textInfo.meshInfo[0].colors32; colors32[0 + index] = highlightColor; colors32[1 + index] = highlightColor; colors32[2 + index] = highlightColor; @@ -7177,14 +6504,12 @@ protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int ind /// protected void LoadDefaultSettings() { - if (m_fontAsset == null || m_isWaitingOnResourceLoad) + if (m_text == null || m_isWaitingOnResourceLoad) { m_rectTransform = this.rectTransform; if (TMP_Settings.autoSizeTextContainer) - { autoSizeTextContainer = true; - } else { if (GetType() == typeof(TextMeshPro)) @@ -7208,6 +6533,7 @@ protected void LoadDefaultSettings() m_fontSize = m_fontSizeBase = TMP_Settings.defaultFontSize; m_fontSizeMin = m_fontSize * TMP_Settings.defaultTextAutoSizingMinRatio; m_fontSizeMax = m_fontSize * TMP_Settings.defaultTextAutoSizingMaxRatio; + m_isAlignmentEnumConverted = true; m_isWaitingOnResourceLoad = false; raycastTarget = TMP_Settings.enableRaycastTarget; } @@ -7232,84 +6558,32 @@ protected void LoadDefaultSettings() /// /// protected void GetSpecialCharacters(TMP_FontAsset fontAsset) - { - GetEllipsisSpecialCharacter(fontAsset); - - GetUnderlineSpecialCharacter(fontAsset); - } - - - protected void GetEllipsisSpecialCharacter(TMP_FontAsset fontAsset) - { - bool isUsingAlternativeTypeface; - - // Search base font asset - TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x2026, fontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); - - if (character == null) - { - // Search primary fallback list - if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x2026, fontAsset, fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); - } - - // Search TMP Settings general fallback list - if (character == null) - { - if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x2026, fontAsset, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); - } - - // Search TMP Settings' default font asset - if (character == null) - { - if (TMP_Settings.defaultFontAsset != null) - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x2026, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); - } - - if (character != null) - m_Ellipsis = new SpecialCharacter(character, 0); - } - - - protected void GetUnderlineSpecialCharacter(TMP_FontAsset fontAsset) { bool isUsingAlternativeTypeface; + TMP_FontAsset tempFontAsset; - // Search base font asset - TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x5F, fontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); - - /* - if (m_Underline.character == null) + // Check & Assign Underline Character for use with the Underline tag. + if (!fontAsset.characterLookupTable.TryGetValue(95, out m_cached_Underline_Character)) { - // Search primary fallback list - if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0) - m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x5F, fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - } + m_cached_Underline_Character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(95,fontAsset, false, m_FontStyleInternal, (FontWeight)m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - // Search TMP Settings general fallback list - if (m_Underline.character == null) + if (m_cached_Underline_Character == null) { - if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x5F, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + if (!TMP_Settings.warningsDisabled) + Debug.LogWarning("The character used for Underline and Strikethrough is not available in font asset [" + fontAsset.name + "].", this); + } } - // Search TMP Settings' default font asset - if (m_Underline.character == null) + // Check & Assign Ellipsis Character + if (!fontAsset.characterLookupTable.TryGetValue(8230, out m_cached_Ellipsis_Character)) //95 { - if (TMP_Settings.defaultFontAsset != null) - m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x5F, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - } - */ + m_cached_Ellipsis_Character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(8230, fontAsset, false, m_FontStyleInternal, (FontWeight)m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - if (character != null) - { - m_Underline = new SpecialCharacter(character, 0); - } - else + if (m_cached_Ellipsis_Character == null) { - if (!TMP_Settings.warningsDisabled) - Debug.LogWarning("The character used for Underline is not available in font asset [" + fontAsset.name + "].", this); + if (!TMP_Settings.warningsDisabled) + Debug.LogWarning("The character used for Ellipsis is not available in font asset [" + fontAsset.name + "].", this); + } } } @@ -7333,7 +6607,7 @@ protected void ReplaceTagWithCharacter(int[] chars, int insertionIndex, int tagL /// - /// + /// /// /// //protected int GetMaterialReferenceForFontWeight() @@ -7347,7 +6621,7 @@ protected void ReplaceTagWithCharacter(int[] chars, int insertionIndex, int tagL /// - /// + /// /// /// protected TMP_FontAsset GetFontAssetForWeight(int fontWeight) @@ -7366,101 +6640,6 @@ protected TMP_FontAsset GetFontAssetForWeight(int fontWeight) return fontAsset; } - internal TMP_TextElement GetTextElement(uint unicode, TMP_FontAsset fontAsset, FontStyles fontStyle, FontWeight fontWeight, out bool isUsingAlternativeTypeface) - { - TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, fontAsset, false, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - if (character != null) - return character; - - // Search potential list of fallback font assets assigned to the font asset. - if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, fontAsset.m_FallbackFontAssetTable, true, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - if (character != null) - { - // Add character to font asset lookup cache - //fontAsset.AddCharacterToLookupCache(unicode, character); - - return character; - } - - // Search for the character in the primary font asset if not the current font asset - if (fontAsset.instanceID != m_fontAsset.instanceID) - { - // Search primary font asset - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, m_fontAsset, false, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - // Use material and index of primary font asset. - if (character != null) - { - m_currentMaterialIndex = 0; - m_currentMaterial = m_materialReferences[0].material; - - // Add character to font asset lookup cache - //fontAsset.AddCharacterToLookupCache(unicode, character); - - return character; - } - - // Search list of potential fallback font assets assigned to the primary font asset. - if (m_fontAsset.m_FallbackFontAssetTable != null && m_fontAsset.m_FallbackFontAssetTable.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, m_fontAsset.m_FallbackFontAssetTable, true, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - if (character != null) - { - // Add character to font asset lookup cache - //fontAsset.AddCharacterToLookupCache(unicode, character); - - return character; - } - } - - // Search for the character in potential local Sprite Asset assigned to the text object. - if (m_spriteAsset != null) - { - TMP_SpriteCharacter spriteCharacter = TMP_FontAssetUtilities.GetSpriteCharacterFromSpriteAsset(unicode, m_spriteAsset, true); - - if (spriteCharacter != null) - return spriteCharacter; - } - - // Search for the character in the list of fallback assigned in the TMP Settings (General Fallbacks). - if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, TMP_Settings.fallbackFontAssets, true, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - if (character != null) - { - // Add character to font asset lookup cache - //fontAsset.AddCharacterToLookupCache(unicode, character); - - return character; - } - - // Search for the character in the Default Font Asset assigned in the TMP Settings file. - if (TMP_Settings.defaultFontAsset != null) - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, TMP_Settings.defaultFontAsset, true, fontStyle, fontWeight, out isUsingAlternativeTypeface); - - if (character != null) - { - // Add character to font asset lookup cache - //fontAsset.AddCharacterToLookupCache(unicode, character); - - return character; - } - - // Search for the character in the Default Sprite Asset assigned in the TMP Settings file. - if (TMP_Settings.defaultSpriteAsset != null) - { - TMP_SpriteCharacter spriteCharacter = TMP_FontAssetUtilities.GetSpriteCharacterFromSpriteAsset(unicode, TMP_Settings.defaultSpriteAsset, true); - - if (spriteCharacter != null) - return spriteCharacter; - } - - return null; - } - /// /// Method to Enable or Disable child SubMesh objects. @@ -7472,7 +6651,7 @@ protected virtual void SetActiveSubMeshes(bool state) { } /// /// Destroy Sub Mesh Objects. /// - protected virtual void DestroySubMeshObjects() { } + protected virtual void ClearSubMeshObjects() { } /// @@ -7586,7 +6765,7 @@ protected Vector2 PackUV(float x, float y, float scale) /// - /// + /// /// /// /// @@ -7625,7 +6804,7 @@ internal virtual void InternalUpdate() { } /// - /// + /// /// /// /// @@ -7924,7 +7103,7 @@ protected float ConvertToFloat(char[] chars, int startIndex, int length) /// - /// Extracts a float value from char[] given a start index and length. + /// Extracts a float value from char[] given a start index and length. /// /// The Char[] containing the numerical sequence. /// The index of the start of the numerical sequence. @@ -8235,14 +7414,14 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI return true; } // Color <#FF00FF> - else if (m_htmlTag[0] == 35 && tagCharCount == 7) // if Tag begins with # and contains 7 characters. + else if (m_htmlTag[0] == 35 && tagCharCount == 7) // if Tag begins with # and contains 7 characters. { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); return true; } // Color <#FF00FF00> with alpha - else if (m_htmlTag[0] == 35 && tagCharCount == 9) // if Tag begins with # and contains 9 characters. + else if (m_htmlTag[0] == 35 && tagCharCount == 9) // if Tag begins with # and contains 9 characters. { m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount); m_colorStack.Add(m_htmlColor); @@ -8323,8 +7502,6 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI if (m_fontStyleStack.Remove(FontStyles.Strikethrough) == 0) m_FontStyleInternal &= ~FontStyles.Strikethrough; } - - m_strikethroughColor = m_strikethroughColorStack.Remove(); return true; case 117: // case 85: // @@ -8351,8 +7528,6 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI if (m_fontStyleStack.Remove(FontStyles.Underline) == 0) m_FontStyleInternal &= ~FontStyles.Underline; } - - m_underlineColor = m_underlineColorStack.Remove(); return true; case 43045: // case 30245: // @@ -8510,7 +7685,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI case 6380: // case 4556: // value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); - + // Reject tag if value is invalid. if (value == Int16.MinValue) return false; @@ -8537,7 +7712,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI case 16034505: // case 11642281: // value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); - + // Reject tag if value is invalid. if (value == Int16.MinValue) return false; @@ -8761,7 +7936,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI } - // Check if material + // Check if material if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial)) { // Check if material font atlas texture matches that of the current font asset. @@ -8810,7 +7985,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI case 320078: // case 230446: // value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); - + // Reject tag if value is invalid. if (value == Int16.MinValue) return false; @@ -8999,18 +8174,10 @@ 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); @@ -9094,7 +8261,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI case 1983971: // case 1356515: // value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); - + // Reject tag if value is invalid. if (value == Int16.MinValue) return false; @@ -9249,7 +8416,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI // Load Sprite Asset if (tempSpriteAsset == null) { - // + // if (onSpriteAssetRequest != null) tempSpriteAsset = onSpriteAssetRequest(spriteAssetHashCode, new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength)); @@ -9302,7 +8469,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI case 295562: // case 205930: // index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength); - + // Reject tag if value is invalid. if (index == Int16.MinValue) return false; @@ -9538,7 +8705,7 @@ protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endI switch (tagUnitType) { case TagUnitType.Pixels: - m_lineHeight = value * (m_isOrthographic ? 1 : 0.1f); + m_lineHeight = value * (m_isOrthographic ? 1 : 0.1f); break; case TagUnitType.FontUnits: m_lineHeight = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize; diff --git a/Scripts/Runtime/TMP_TextElement.cs b/Scripts/Runtime/TMP_TextElement.cs index 9bb8cf1..fa34fd6 100644 --- a/Scripts/Runtime/TMP_TextElement.cs +++ b/Scripts/Runtime/TMP_TextElement.cs @@ -26,11 +26,6 @@ public class TMP_TextElement /// public uint unicode { get { return m_Unicode; } set { m_Unicode = value; } } - /// - /// The Text Asset to which this Text Element belongs. - /// - public TMP_Asset textAsset { get { return m_TextAsset; } set { m_TextAsset = value; } } - /// /// The glyph used by this text element. /// @@ -56,8 +51,6 @@ public class TMP_TextElement [SerializeField] internal uint m_Unicode; - internal TMP_Asset m_TextAsset; - internal Glyph m_Glyph; [SerializeField] diff --git a/Scripts/Runtime/TMP_TextInfo.cs b/Scripts/Runtime/TMP_TextInfo.cs index 9681305..67c5e5d 100644 --- a/Scripts/Runtime/TMP_TextInfo.cs +++ b/Scripts/Runtime/TMP_TextInfo.cs @@ -48,16 +48,6 @@ 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) { @@ -162,9 +152,6 @@ public void ClearLineInfo() this.lineInfo[i].ascender = k_InfinityVectorNegative.x; this.lineInfo[i].descender = k_InfinityVectorPositive.x; - this.lineInfo[i].marginLeft = 0; - this.lineInfo[i].marginRight = 0; - this.lineInfo[i].lineExtents.min = k_InfinityVectorPositive; this.lineInfo[i].lineExtents.max = k_InfinityVectorNegative; @@ -274,12 +261,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/TMP_UpdateManager.cs b/Scripts/Runtime/TMP_UpdateManager.cs index 8d51686..2b77411 100644 --- a/Scripts/Runtime/TMP_UpdateManager.cs +++ b/Scripts/Runtime/TMP_UpdateManager.cs @@ -2,6 +2,12 @@ using UnityEngine.UI; using System.Collections.Generic; +#if UNITY_2019_1_OR_NEWER +using UnityEngine.Rendering; +#elif UNITY_2018_1_OR_NEWER +using UnityEngine.Experimental.Rendering; +#endif + namespace TMPro { @@ -11,44 +17,53 @@ public class TMP_UpdateManager private static TMP_UpdateManager s_Instance; private readonly List m_LayoutRebuildQueue = new List(); - private readonly HashSet m_LayoutQueueLookup = new HashSet(); + private HashSet m_LayoutQueueLookup = new HashSet(); private readonly List m_GraphicRebuildQueue = new List(); - private readonly HashSet m_GraphicQueueLookup = new HashSet(); + private HashSet m_GraphicQueueLookup = new HashSet(); private readonly List m_InternalUpdateQueue = new List(); - private readonly HashSet m_InternalUpdateLookup = new HashSet(); + private HashSet m_InternalUpdateLookup = new HashSet(); + //private bool m_PerformingGraphicRebuild; + //private bool m_PerformingLayoutRebuild; /// /// Get a singleton instance of the registry /// - static TMP_UpdateManager instance + public static TMP_UpdateManager instance { get { - if (s_Instance == null) - s_Instance = new TMP_UpdateManager(); - - return s_Instance; + if (TMP_UpdateManager.s_Instance == null) + TMP_UpdateManager.s_Instance = new TMP_UpdateManager(); + return TMP_UpdateManager.s_Instance; } } + /// /// Register to receive rendering callbacks. /// - TMP_UpdateManager() + protected TMP_UpdateManager() { - Canvas.willRenderCanvases += DoRebuilds; + Camera.onPreCull += OnCameraPreCull; + + #if UNITY_2019_1_OR_NEWER + RenderPipelineManager.beginFrameRendering += OnBeginFrameRendering; + #elif UNITY_2018_1_OR_NEWER + RenderPipeline.beginFrameRendering += OnBeginFrameRendering; + #endif } + /// /// Function used as a replacement for LateUpdate() to handle SDF Scale updates and Legacy Animation updates. /// /// internal static void RegisterTextObjectForUpdate(TMP_Text textObject) { - instance.InternalRegisterTextObjectForUpdate(textObject); + TMP_UpdateManager.instance.InternalRegisterTextObjectForUpdate(textObject); } private void InternalRegisterTextObjectForUpdate(TMP_Text textObject) @@ -60,56 +75,89 @@ private void InternalRegisterTextObjectForUpdate(TMP_Text textObject) m_InternalUpdateLookup.Add(id); m_InternalUpdateQueue.Add(textObject); + + return; } + /// /// Function to register elements which require a layout rebuild. /// /// public static void RegisterTextElementForLayoutRebuild(TMP_Text element) { - instance.InternalRegisterTextElementForLayoutRebuild(element); + TMP_UpdateManager.instance.InternalRegisterTextElementForLayoutRebuild(element); } - private void InternalRegisterTextElementForLayoutRebuild(TMP_Text element) + private bool InternalRegisterTextElementForLayoutRebuild(TMP_Text element) { int id = element.GetInstanceID(); if (m_LayoutQueueLookup.Contains(id)) - return; + return false; m_LayoutQueueLookup.Add(id); m_LayoutRebuildQueue.Add(element); + + return true; } + /// /// Function to register elements which require a layout rebuild. /// /// public static void RegisterTextElementForGraphicRebuild(TMP_Text element) { - instance.InternalRegisterTextElementForGraphicRebuild(element); + TMP_UpdateManager.instance.InternalRegisterTextElementForGraphicRebuild(element); } - private void InternalRegisterTextElementForGraphicRebuild(TMP_Text element) + private bool InternalRegisterTextElementForGraphicRebuild(TMP_Text element) { int id = element.GetInstanceID(); if (m_GraphicQueueLookup.Contains(id)) - return; + return false; m_GraphicQueueLookup.Add(id); m_GraphicRebuildQueue.Add(element); + + return true; } + /// - /// Callback which occurs just before the cam is rendered. + /// Callback which occurs just before the Scriptable Render Pipeline (SRP) begins rendering. /// - void OnCameraPreCull() + /// + #if UNITY_2019_1_OR_NEWER + void OnBeginFrameRendering(ScriptableRenderContext renderContext, Camera[] cameras) + #elif UNITY_2018_1_OR_NEWER + void OnBeginFrameRendering(Camera[] cameras) + #endif { + // Exclude the PreRenderCamera + #if UNITY_EDITOR + if (cameras.Length == 1 && cameras[0].cameraType == CameraType.Preview) + return; + #endif DoRebuilds(); } + /// + /// Callback which occurs just before the cam is rendered. + /// + /// + void OnCameraPreCull(Camera cam) + { + // Exclude the PreRenderCamera + #if UNITY_EDITOR + if (cam.cameraType == CameraType.Preview) + return; + #endif + DoRebuilds(); + } + /// /// Process the rebuild requests in the rebuild queues. /// @@ -149,7 +197,7 @@ void DoRebuilds() internal static void UnRegisterTextObjectForUpdate(TMP_Text textObject) { - instance.InternalUnRegisterTextObjectForUpdate(textObject); + TMP_UpdateManager.instance.InternalUnRegisterTextObjectForUpdate(textObject); } /// @@ -158,16 +206,16 @@ internal static void UnRegisterTextObjectForUpdate(TMP_Text textObject) /// public static void UnRegisterTextElementForRebuild(TMP_Text element) { - instance.InternalUnRegisterTextElementForGraphicRebuild(element); - instance.InternalUnRegisterTextElementForLayoutRebuild(element); - instance.InternalUnRegisterTextObjectForUpdate(element); + TMP_UpdateManager.instance.InternalUnRegisterTextElementForGraphicRebuild(element); + TMP_UpdateManager.instance.InternalUnRegisterTextElementForLayoutRebuild(element); + TMP_UpdateManager.instance.InternalUnRegisterTextObjectForUpdate(element); } private void InternalUnRegisterTextElementForGraphicRebuild(TMP_Text element) { int id = element.GetInstanceID(); - instance.m_GraphicRebuildQueue.Remove(element); + TMP_UpdateManager.instance.m_GraphicRebuildQueue.Remove(element); m_GraphicQueueLookup.Remove(id); } @@ -175,7 +223,7 @@ private void InternalUnRegisterTextElementForLayoutRebuild(TMP_Text element) { int id = element.GetInstanceID(); - instance.m_LayoutRebuildQueue.Remove(element); + TMP_UpdateManager.instance.m_LayoutRebuildQueue.Remove(element); m_LayoutQueueLookup.Remove(id); } @@ -183,8 +231,8 @@ private void InternalUnRegisterTextObjectForUpdate(TMP_Text textObject) { int id = textObject.GetInstanceID(); - instance.m_InternalUpdateQueue.Remove(textObject); + TMP_UpdateManager.instance.m_InternalUpdateQueue.Remove(textObject); m_InternalUpdateLookup.Remove(id); } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/TMP_UpdateRegistery.cs b/Scripts/Runtime/TMP_UpdateRegistery.cs index 7b66891..dc1686b 100644 --- a/Scripts/Runtime/TMP_UpdateRegistery.cs +++ b/Scripts/Runtime/TMP_UpdateRegistery.cs @@ -141,6 +141,7 @@ private void PerformUpdateForCanvasRendererObjects() private void PerformUpdateForMeshRendererObjects() { Debug.Log("Perform update of MeshRenderer objects."); + } diff --git a/Scripts/Runtime/TMPro_ExtensionMethods.cs b/Scripts/Runtime/TMPro_ExtensionMethods.cs index 5c8ddbd..30c2140 100644 --- a/Scripts/Runtime/TMPro_ExtensionMethods.cs +++ b/Scripts/Runtime/TMPro_ExtensionMethods.cs @@ -67,7 +67,7 @@ public static string IntToString(this int[] unicodes, int start, int length) public static int FindInstanceID (this List list, T target) where T : Object { int targetID = target.GetInstanceID(); - + for (int i = 0; i < list.Count; i++) { if (list[i].GetInstanceID() == targetID) @@ -239,11 +239,5 @@ public static bool Approximately(float a, float b) { return (b - 0.0001f) < a && a < (b + 0.0001f); } - - public static int Mod(int a, int b) - { - int r = a % b; - return r < 0 ? r + b : r; - } } } diff --git a/Scripts/Runtime/TMPro_MeshUtilities.cs b/Scripts/Runtime/TMPro_MeshUtilities.cs index 88a8efd..b331ad9 100644 --- a/Scripts/Runtime/TMPro_MeshUtilities.cs +++ b/Scripts/Runtime/TMPro_MeshUtilities.cs @@ -60,7 +60,7 @@ public enum TMP_VertexDataUpdateFlags //public struct TMP_VertexInfo - //{ + //{ // public TMP_Vertex topLeft; // public TMP_Vertex bottomLeft; // public TMP_Vertex topRight; @@ -193,7 +193,7 @@ public string GetWord() { string word = string.Empty; TMP_CharacterInfo[] charInfo = textComponent.textInfo.characterInfo; - + for (int i = firstCharacterIndex; i < lastCharacterIndex + 1; i++) { word += charInfo[i].character; @@ -214,7 +214,7 @@ public struct TMP_SpriteInfo //public struct SpriteInfo //{ - // + // //} @@ -234,7 +234,7 @@ public Extents(Vector2 min, Vector2 max) public override string ToString() { - string s = "Min (" + min.x.ToString("f2") + ", " + min.y.ToString("f2") + ") Max (" + max.x.ToString("f2") + ", " + max.y.ToString("f2") + ")"; + string s = "Min (" + min.x.ToString("f2") + ", " + min.y.ToString("f2") + ") Max (" + max.x.ToString("f2") + ", " + max.y.ToString("f2") + ")"; return s; } } @@ -245,8 +245,8 @@ public struct Mesh_Extents { public Vector2 min; public Vector2 max; - - + + public Mesh_Extents(Vector2 min, Vector2 max) { this.min = min; @@ -261,88 +261,8 @@ public override string ToString() } } - // internal struct TMP_TextProcessingState - // { - // // Multi Font & Material support related - // public TMP_FontAsset CurrentFontAsset; - // public TMP_SpriteAsset CurrentSpriteAsset; - // public Material CurrentMaterial; - // public int CurrentMaterialIndex; - // - // public float CurrentFontSize; - // public float FontScale; - // public float FontScaleMultiplier; - // public FontStyles FontStyle; - // public int ItalicAngle; - // - // public float CharacterSpacing; - // public float CharacterMonoSpacing; - // public bool TagNoParsing; - // - // public float HorizontalAdvance; - // public float MaxCapHeight; - // public float MaxTextAscender; - // public float MaxTextDescender; - // public float MaxElementAscender; - // public float MaxElementDescender; - // public float StartOfLineAscender; - // public float MaxLineAscender; - // public float MaxLineDescender; - // public float PageAscender; - // - // public int PreviousWordBreak; - // public int TotalCharacterCount; - // //public int VisibleCharacterCount; - // //public int VisibleSpriteCount; - // public int VisibleLinkCount; - // public int FirstCharacterIndex; - // public int FirstVisibleCharacterIndex; - // public int LastCharacterIndex; - // public int LastVisibleCharIndex; - // - // public int LineNumber; - // public float baselineOffset; - // public float lineOffset; - // public bool isDrivenLineSpacing; - // public bool IsNonBreakingSpace; - // - // public HorizontalAlignmentOptions HorizontalAlignment; - // public float MarginLeft; - // public float MarginRight; - // - // public float PreferredWidth; - // public float PreferredHeight; - // - // public Color32 VertexColor; - // public Color32 UnderlineColor; - // public Color32 StrikethroughColor; - // //public Color32 HighlightColor; - // - // public Extents MeshExtents; - // public TMP_LineInfo lineInfo; - // - // public int spriteAnimationID; - // - // public TMP_FontStyleStack BasicStyleStack; - // public TMP_RichTextTagStack ItalicAngleStack; - // public TMP_RichTextTagStack ColorStack; - // public TMP_RichTextTagStack UnderlineColorStack; - // public TMP_RichTextTagStack StrikethroughColorStack; - // public TMP_RichTextTagStack HighlightColorStack; - // public TMP_RichTextTagStack HighlightStateStack; - // public TMP_RichTextTagStack ColorGradientStack; - // public TMP_RichTextTagStack SizeStack; - // public TMP_RichTextTagStack IndentStack; - // public TMP_RichTextTagStack FontWeightStack; - // - // public TMP_RichTextTagStack BaselineStack; - // //public TMP_RichTextTagStack ActionStack; - // public TMP_RichTextTagStack MaterialReferenceStack; - // public TMP_RichTextTagStack LineJustificationStack; - // } - - - // Structure used for Word Wrapping which tracks the state of execution when the last space or carriage return character was encountered. + + // Structure used for Word Wrapping which tracks the state of execution when the last space or carriage return character was encountered. public struct WordWrapState { public int previous_WordBreak; @@ -359,11 +279,10 @@ public struct WordWrapState public float maxCapHeight; public float maxAscender; public float maxDescender; - public float startOfLineAscender; public float maxLineAscender; public float maxLineDescender; - public float pageAscender; - + public float previousLineAscender; + public HorizontalAlignmentOptions horizontalAlignment; public float marginLeft; public float marginRight; @@ -373,44 +292,45 @@ public struct WordWrapState public float preferredHeight; //public float maxFontScale; public float previousLineScale; - + public int wordCount; public FontStyles fontStyle; public int italicAngle; public float fontScale; public float fontScaleMultiplier; - + public float currentFontSize; public float baselineOffset; public float lineOffset; - public bool isDrivenLineSpacing; public float cSpace; public float mSpace; public TMP_TextInfo textInfo; + //public TMPro_CharacterInfo[] characterInfo; public TMP_LineInfo lineInfo; - + public Color32 vertexColor; public Color32 underlineColor; public Color32 strikethroughColor; public Color32 highlightColor; public TMP_FontStyleStack basicStyleStack; - public TMP_TextProcessingStack italicAngleStack; - public TMP_TextProcessingStack colorStack; - public TMP_TextProcessingStack underlineColorStack; - public TMP_TextProcessingStack strikethroughColorStack; - public TMP_TextProcessingStack highlightColorStack; - public TMP_TextProcessingStack highlightStateStack; - public TMP_TextProcessingStack colorGradientStack; - public TMP_TextProcessingStack sizeStack; - public TMP_TextProcessingStack indentStack; - public TMP_TextProcessingStack fontWeightStack; - public TMP_TextProcessingStack styleStack; - public TMP_TextProcessingStack baselineStack; - public TMP_TextProcessingStack actionStack; - public TMP_TextProcessingStack materialReferenceStack; - public TMP_TextProcessingStack lineJustificationStack; + public TMP_RichTextTagStack italicAngleStack; + public TMP_RichTextTagStack colorStack; + public TMP_RichTextTagStack underlineColorStack; + public TMP_RichTextTagStack strikethroughColorStack; + public TMP_RichTextTagStack highlightColorStack; + public TMP_RichTextTagStack highlightStateStack; + public TMP_RichTextTagStack colorGradientStack; + public TMP_RichTextTagStack sizeStack; + public TMP_RichTextTagStack indentStack; + public TMP_RichTextTagStack fontWeightStack; + public TMP_RichTextTagStack styleStack; + public TMP_RichTextTagStack baselineStack; + public TMP_RichTextTagStack actionStack; + public TMP_RichTextTagStack materialReferenceStack; + public TMP_RichTextTagStack lineJustificationStack; + //public TMP_XmlTagStack spriteAnimationStack; public int spriteAnimationID; public TMP_FontAsset currentFontAsset; @@ -422,6 +342,7 @@ public struct WordWrapState public bool tagNoParsing; public bool isNonBreakingSpace; + //public Mesh_Extents lineExtents; } diff --git a/Scripts/Runtime/TMPro_Private.cs b/Scripts/Runtime/TMPro_Private.cs index 1394abb..512c530 100644 --- a/Scripts/Runtime/TMPro_Private.cs +++ b/Scripts/Runtime/TMPro_Private.cs @@ -26,11 +26,10 @@ public partial class TextMeshPro [SerializeField] private Renderer m_renderer; private MeshFilter m_meshFilter; - private CanvasRenderer m_CanvasRenderer; private bool m_isFirstAllocation; // Flag to determine if this is the first allocation of the buffers. private int m_max_characters = 8; // Determines the initial allocation and size of the character array / buffer. - private int m_max_numberOfLines = 4; // Determines the initial allocation and maximum number of lines of text. + private int m_max_numberOfLines = 4; // Determines the initial allocation and maximum number of lines of text. protected TMP_SubMesh[] m_subTextObjects = new TMP_SubMesh[8]; @@ -82,10 +81,13 @@ protected override void Awake() if (m_renderer == null) m_renderer = gameObject.AddComponent(); - // Get reference to CanvasRenderer (if one exists) - m_CanvasRenderer = GetComponent(); - if (m_CanvasRenderer != null) - m_CanvasRenderer.hideFlags = HideFlags.HideInInspector; + // Remove CanvasRenderer from text object if one exists + CanvasRenderer canvasRenderer = GetComponent(); + if (canvasRenderer != null) + { + Debug.Log("Removing unnecessary CanvasRenderer component from text object.", this); + DestroyImmediate(canvasRenderer); + } // Cache Reference to RectTransform m_rectTransform = this.rectTransform; @@ -106,7 +108,7 @@ protected override void Awake() #if DEVELOPMENT_BUILD || UNITY_EDITOR m_mesh.name = "TextMeshPro Mesh"; #endif - m_meshFilter.sharedMesh = m_mesh; + m_meshFilter.mesh = m_mesh; // Create new TextInfo for the text object. m_textInfo = new TMP_TextInfo(this); @@ -120,8 +122,8 @@ protected override void Awake() LoadFontAsset(); // Allocate our initial buffers. - if (m_InternalParsingBuffer == null) - m_InternalParsingBuffer = new UnicodeChar[m_max_characters]; + if (m_TextParsingBuffer == null) + m_TextParsingBuffer = new UnicodeChar[m_max_characters]; m_cached_TextElement = new TMP_Character(); m_isFirstAllocation = true; @@ -137,6 +139,7 @@ protected override void Awake() // Set flags to ensure our text is parsed and redrawn. m_isInputParsingRequired = true; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; m_isAwake = true; } @@ -177,6 +180,8 @@ protected override void OnEnable() // Schedule potential text object update (if any of the properties have changed. ComputeMarginSize(); + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; m_isInputParsingRequired = true; SetAllDirty(); @@ -195,7 +200,7 @@ protected override void OnDisable() TMP_UpdateManager.UnRegisterTextElementForRebuild(this); TMP_UpdateManager.UnRegisterTextObjectForUpdate(this); - meshFilter.sharedMesh = null; + m_meshFilter.sharedMesh = null; SetActiveSubMeshes(false); } @@ -206,7 +211,9 @@ protected override void OnDestroy() // Destroy the mesh if we have one. if (m_mesh != null) + { DestroyImmediate(m_mesh); + } // Unregister the event this object was listening to #if UNITY_EDITOR @@ -254,15 +261,13 @@ protected override void OnValidate() if (meshFilter != null && m_meshFilter.hideFlags != (HideFlags.HideInInspector | HideFlags.HideAndDontSave)) m_meshFilter.hideFlags = HideFlags.HideInInspector | HideFlags.HideAndDontSave; - if (m_CanvasRenderer != null) - m_CanvasRenderer.hideFlags = HideFlags.HideInInspector; - // Additional Properties could be added to sync up Serialized Properties & Properties. // Handle Font Asset changes in the inspector if (m_fontAsset == null || m_hasFontAssetChanged) { LoadFontAsset(); + m_isCalculateSizeRequired = true; m_hasFontAssetChanged = false; } @@ -272,6 +277,7 @@ protected override void OnValidate() m_isInputParsingRequired = true; m_inputSource = TextInputSources.Text; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; m_isPreferredWidthDirty = true; m_isPreferredHeightDirty = true; @@ -285,13 +291,6 @@ 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(); @@ -320,7 +319,7 @@ void ON_RESOURCES_LOADED() // Event received when custom material editor properties are changed. void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) { - //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED event received. Targeted Material is: " + mat.name + " m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial); + //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED event received. Targeted Material is: " + mat.name + " m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial); if (m_renderer.sharedMaterial == null) { @@ -342,7 +341,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) if (m_renderer.sharedMaterial != m_sharedMaterial) // || m_renderer.sharedMaterials.Contains(mat)) { - //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED Called on Target ID: " + GetInstanceID() + ". Previous Material:" + m_sharedMaterial + " New Material:" + m_renderer.sharedMaterial); // on Object ID:" + GetInstanceID() + ". m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial.name); + //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED Called on Target ID: " + GetInstanceID() + ". Previous Material:" + m_sharedMaterial + " New Material:" + m_renderer.sharedMaterial); // on Object ID:" + GetInstanceID() + ". m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial.name); m_sharedMaterial = m_renderer.sharedMaterial; } @@ -352,7 +351,6 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) UpdateMask(); UpdateEnvMapMatrix(); m_havePropertiesChanged = true; - SetVerticesDirty(); } @@ -360,8 +358,6 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) // Event received when font asset properties are changed in Font Inspector void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) { - //Debug.Log("ON_FONT_PROPERTY_CHANGED event received. Target is [" + font.name + "]"); - if (MaterialReference.Contains(m_materialReferences, font)) { //Debug.Log("ON_FONT_PROPERTY_CHANGED event received."); @@ -375,7 +371,7 @@ void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) } } - + // Event received when UNDO / REDO Event alters the properties of the object. void ON_TEXTMESHPRO_PROPERTY_CHANGED(bool isChanged, TextMeshPro obj) { @@ -387,7 +383,6 @@ void ON_TEXTMESHPRO_PROPERTY_CHANGED(bool isChanged, TextMeshPro obj) m_padding = GetPaddingForMaterial(); ComputeMarginSize(); // Verify this change - SetVerticesDirty(); } } @@ -412,7 +407,6 @@ void ON_DRAG_AND_DROP_MATERIAL(GameObject obj, Material currentMaterial, Materia m_padding = GetPaddingForMaterial(); m_havePropertiesChanged = true; - SetVerticesDirty(); SetMaterialDirty(); } @@ -424,7 +418,6 @@ void ON_TEXT_STYLE_CHANGED(bool isChanged) { m_havePropertiesChanged = true; m_isInputParsingRequired = true; - SetVerticesDirty(); } @@ -436,7 +429,6 @@ void ON_TEXT_STYLE_CHANGED(bool isChanged) void ON_COLOR_GRADIENT_CHANGED(TMP_ColorGradient gradient) { m_havePropertiesChanged = true; - SetVerticesDirty(); } @@ -449,7 +441,6 @@ void ON_TMP_SETTINGS_CHANGED() m_defaultSpriteAsset = null; m_havePropertiesChanged = true; m_isInputParsingRequired = true; - SetAllDirty(); } #endif @@ -480,27 +471,36 @@ protected override void LoadFontAsset() Debug.Log("Dictionary is Null!"); } + m_renderer.sharedMaterial = m_fontAsset.material; m_sharedMaterial = m_fontAsset.material; m_sharedMaterial.SetFloat("_CullMode", 0); m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_ZTestMode, 4); - m_renderer.receiveShadows = false; - m_renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + m_renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; // true; + // Get a Reference to the Shader } else { if (m_fontAsset.characterLookupTable == null) + { + //Debug.Log("Reading Font Definition and Creating Character Dictionary."); m_fontAsset.ReadFontAssetDefinition(); + } + + //Debug.Log("Font Asset name:" + font.material.name); // If font atlas texture doesn't match the assigned material font atlas, switch back to default material specified in the Font Asset. - if (m_sharedMaterial == null || m_sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex) == null || m_fontAsset.atlasTexture.GetInstanceID() != m_sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) + if (m_renderer.sharedMaterial == null || m_renderer.sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex) == null || m_fontAsset.atlasTexture.GetInstanceID() != m_renderer.sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) { - if (m_fontAsset.material == null) - Debug.LogWarning("The Font Atlas Texture of the Font Asset " + m_fontAsset.name + " assigned to " + gameObject.name + " is missing.", this); - else - m_sharedMaterial = m_fontAsset.material; + m_renderer.sharedMaterial = m_fontAsset.material; + m_sharedMaterial = m_fontAsset.material; + } + else + { + m_sharedMaterial = m_renderer.sharedMaterial; } + //m_sharedMaterial.SetFloat("_CullMode", 0); m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_ZTestMode, 4); // Check if we are using the SDF Surface Shader @@ -513,12 +513,18 @@ protected override void LoadFontAsset() } m_padding = GetPaddingForMaterial(); + //m_alignmentPadding = ShaderUtilities.GetFontExtent(m_sharedMaterial); m_isMaskingEnabled = ShaderUtilities.IsMaskingEnabled(m_sharedMaterial); + // Find and cache Underline & Ellipsis characters. GetSpecialCharacters(m_fontAsset); - SetMaterialDirty(); + + //m_sharedMaterials.Add(m_sharedMaterial); + //m_sharedMaterialHashCode = TMP_TextUtilities.GetSimpleHashCode(m_sharedMaterial.name); + // Hide Material Editor Component + //m_renderer.sharedMaterial.hideFlags = HideFlags.None; } @@ -613,7 +619,7 @@ void DisableMasking() void UpdateMask() { //Debug.Log("UpdateMask() called."); - + if (!m_isMaskingEnabled) { // Release Masking Material @@ -622,13 +628,13 @@ void UpdateMask() return; } - + if (m_isMaskingEnabled && m_fontMaterial == null) { CreateMaterialInstance(); } - + /* if (!m_isMaskingEnabled) { @@ -643,18 +649,18 @@ void UpdateMask() //else // Debug.Log("Updating Masking..."); */ - + // Compute Masking Coordinates & Softness //float softnessX = Mathf.Min(Mathf.Min(m_textContainer.margins.x, m_textContainer.margins.z), m_sharedMaterial.GetFloat(ShaderUtilities.ID_MaskSoftnessX)); //float softnessY = Mathf.Min(Mathf.Min(m_textContainer.margins.y, m_textContainer.margins.w), m_sharedMaterial.GetFloat(ShaderUtilities.ID_MaskSoftnessY)); //softnessX = softnessX > 0 ? softnessX : 0; //softnessY = softnessY > 0 ? softnessY : 0; - + //float width = (m_textContainer.width - Mathf.Max(m_textContainer.margins.x, 0) - Mathf.Max(m_textContainer.margins.z, 0)) / 2 + softnessX; //float height = (m_textContainer.height - Mathf.Max(m_textContainer.margins.y, 0) - Mathf.Max(m_textContainer.margins.w, 0)) / 2 + softnessY; - - //Vector2 center = new Vector2((0.5f - m_textContainer.pivot.x) * m_textContainer.width + (Mathf.Max(m_textContainer.margins.x, 0) - Mathf.Max(m_textContainer.margins.z, 0)) / 2, (0.5f - m_textContainer.pivot.y) * m_textContainer.height + (- Mathf.Max(m_textContainer.margins.y, 0) + Mathf.Max(m_textContainer.margins.w, 0)) / 2); + + //Vector2 center = new Vector2((0.5f - m_textContainer.pivot.x) * m_textContainer.width + (Mathf.Max(m_textContainer.margins.x, 0) - Mathf.Max(m_textContainer.margins.z, 0)) / 2, (0.5f - m_textContainer.pivot.y) * m_textContainer.height + (- Mathf.Max(m_textContainer.margins.y, 0) + Mathf.Max(m_textContainer.margins.w, 0)) / 2); //Vector4 mask = new Vector4(center.x, center.y, width, height); @@ -662,11 +668,11 @@ void UpdateMask() //m_fontMaterial.SetFloat(ShaderUtilities.ID_MaskSoftnessX, softnessX); //m_fontMaterial.SetFloat(ShaderUtilities.ID_MaskSoftnessY, softnessY); - /* + /* if(m_maskingPropertyBlock == null) - { + { m_maskingPropertyBlock = new MaterialPropertyBlock(); - + //m_maskingPropertyBlock.AddFloat(ShaderUtilities.ID_VertexOffsetX, m_sharedMaterial.GetFloat(ShaderUtilities.ID_VertexOffsetX)); //m_maskingPropertyBlock.AddFloat(ShaderUtilities.ID_VertexOffsetY, m_sharedMaterial.GetFloat(ShaderUtilities.ID_VertexOffsetY)); //Debug.Log("Creating new MaterialPropertyBlock."); @@ -678,7 +684,7 @@ void UpdateMask() m_maskingPropertyBlock.AddVector(ShaderUtilities.ID_MaskCoord, mask); m_maskingPropertyBlock.AddFloat(ShaderUtilities.ID_MaskSoftnessX, softnessX); m_maskingPropertyBlock.AddFloat(ShaderUtilities.ID_MaskSoftnessY, softnessY); - + m_renderer.SetPropertyBlock(m_maskingPropertyBlock); */ } @@ -870,7 +876,7 @@ void CreateMaterialInstance() } - // Sets the Render Queue and Ztest mode + // Sets the Render Queue and Ztest mode protected override void SetShaderDepth() { if (m_isOverlay) @@ -888,7 +894,7 @@ protected override void SetShaderDepth() // Should this use an instanced material? m_sharedMaterial.SetFloat(ShaderUtilities.ShaderTag_ZTestMode, 4); m_renderer.material.renderQueue = -1; - + m_sharedMaterial = m_renderer.material; //Debug.Log("Text set to Normal mode."); } @@ -940,7 +946,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[] unicodeChars) + protected override int SetArraySizes(UnicodeChar[] chars) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP SetArraySizes()"); @@ -968,77 +974,21 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_materialReferenceIndexLookup.Clear(); MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup); - // 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); - + if (m_textInfo == null) m_textInfo = new TMP_TextInfo(); m_textElementType = TMP_TextElementType.Character; - // Handling for Underline special character - #region Setup Underline Special Character - /* - GetUnderlineSpecialCharacter(m_currentFontAsset); - if (m_Underline.character != null) - { - if (m_Underline.fontAsset.GetInstanceID() != m_currentFontAsset.GetInstanceID()) - { - if (TMP_Settings.matchMaterialPreset && m_currentMaterial.GetInstanceID() != m_Underline.fontAsset.material.GetInstanceID()) - m_Underline.material = TMP_MaterialManager.GetFallbackMaterial(m_currentMaterial, m_Underline.fontAsset.material); - else - m_Underline.material = m_Underline.fontAsset.material; - - m_Underline.materialIndex = MaterialReference.AddMaterialReference(m_Underline.material, m_Underline.fontAsset, m_materialReferences, m_materialReferenceIndexLookup); - m_materialReferences[m_Underline.materialIndex].referenceCount = 0; - } - } - */ - #endregion - - - // Handling for Ellipsis special character - #region Setup Ellipsis Special Character - if (m_overflowMode == TextOverflowModes.Ellipsis) - { - GetEllipsisSpecialCharacter(m_currentFontAsset); - - if (m_Ellipsis.character != null) - { - if (m_Ellipsis.fontAsset.GetInstanceID() != m_currentFontAsset.GetInstanceID()) - { - if (TMP_Settings.matchMaterialPreset && m_currentMaterial.GetInstanceID() != m_Ellipsis.fontAsset.material.GetInstanceID()) - m_Ellipsis.material = TMP_MaterialManager.GetFallbackMaterial(m_currentMaterial, m_Ellipsis.fontAsset.material); - else - m_Ellipsis.material = m_Ellipsis.fontAsset.material; - - m_Ellipsis.materialIndex = MaterialReference.AddMaterialReference(m_Ellipsis.material, m_Ellipsis.fontAsset, m_materialReferences, m_materialReferenceIndexLookup); - 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 - - // Clear Linked Text object if we have one. if (m_linkedTextComponent != null && !m_isCalculatingPreferredValues) m_linkedTextComponent.text = string.Empty; // Parsing XML tags in the text - for (int i = 0; i < unicodeChars.Length && unicodeChars[i].unicode != 0; i++) + for (int i = 0; i < chars.Length && chars[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 = unicodeChars[i].unicode; + int unicode = chars[i].unicode; // PARSE XML TAGS #region PARSE XML TAGS @@ -1048,9 +998,9 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) int endTagIndex; // Check if Tag is Valid - if (ValidateHtmlTag(unicodeChars, i + 1, out endTagIndex)) + if (ValidateHtmlTag(chars, i + 1, out endTagIndex)) { - int tagStartIndex = unicodeChars[i].stringIndex; + int tagStartIndex = chars[i].stringIndex; i = endTagIndex; if ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold) @@ -1068,7 +1018,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) 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 = unicodeChars[i].stringIndex - tagStartIndex + 1; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].stringIndex - tagStartIndex + 1; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1086,10 +1036,13 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) bool isUsingAlternativeTypeface = false; bool isUsingFallbackOrAlternativeTypeface = false; + TMP_Character character; + TMP_FontAsset tempFontAsset; TMP_FontAsset prev_fontAsset = m_currentFontAsset; Material prev_material = m_currentMaterial; int prev_materialIndex = m_currentMaterialIndex; + // Handle Font Styles like LowerCase, UpperCase and SmallCaps. #region Handling of LowerCase, UpperCase and SmallCaps Font Styles if (m_textElementType == TMP_TextElementType.Character) @@ -1116,27 +1069,132 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) } #endregion + // Lookup the Glyph data for each character and cache it. #region LOOKUP GLYPH - TMP_TextElement character = GetTextElement((uint)unicode, m_currentFontAsset, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + 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. + 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); + } - // Check if Lowercase or Uppercase variant of the character is available. - /* Not sure this is necessary anyone as it is very unlikely with recursive search through fallback fonts. - if (glyph == null) + // Search for the glyph in the Sprite Asset assigned to the text object. + if (character == null) { - if (char.IsLower((char)c)) + TMP_SpriteAsset spriteAsset = this.spriteAsset; + + if (spriteAsset != null) { - if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToUpper((char)c), out glyph)) - c = chars[i] = char.ToUpper((char)c); + int spriteIndex = -1; + + // Check Default Sprite Asset and its Fallbacks + spriteAsset = TMP_SpriteAsset.SearchForSpriteByUnicode(spriteAsset, (uint)unicode, true, out spriteIndex); + + if (spriteIndex != -1) + { + m_textElementType = TMP_TextElementType.Sprite; + m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; + + m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAsset.material, spriteAsset, m_materialReferences, m_materialReferenceIndexLookup); + m_materialReferences[m_currentMaterialIndex].referenceCount += 1; + + m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; + m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = spriteIndex; + m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; + 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; + + // Restore element type and material index to previous values. + m_textElementType = TMP_TextElementType.Character; + m_currentMaterialIndex = prev_materialIndex; + + spriteCount += 1; + m_totalCharacterCount += 1; + + continue; + } } - else if (char.IsUpper((char)c)) + } + + // Search for the glyph in the list of fallback assigned in the TMP Settings (General Fallbacks). + if (character == null) + { + if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + + // Search for the glyph in the Default Font Asset assigned in the TMP Settings file. + if (character == null) + { + if (TMP_Settings.defaultFontAsset != null) + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + + // TODO: Add support for using Sprite Assets like a special Emoji only Sprite Asset when UTF16 or UTF32 glyphs are requested. + // This would kind of mirror native Emoji support. + if (character == null) + { + TMP_SpriteAsset spriteAsset = TMP_Settings.defaultSpriteAsset; + + if (spriteAsset != null) { - if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToLower((char)c), out glyph)) - c = chars[i] = char.ToLower((char)c); + int spriteIndex = -1; + + // Check Default Sprite Asset and its Fallbacks + spriteAsset = TMP_SpriteAsset.SearchForSpriteByUnicode(spriteAsset, (uint)unicode, true, out spriteIndex); + + if (spriteIndex != -1) + { + m_textElementType = TMP_TextElementType.Sprite; + m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; + + m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAsset.material, spriteAsset, m_materialReferences, m_materialReferenceIndexLookup); + m_materialReferences[m_currentMaterialIndex].referenceCount += 1; + + m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; + m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = spriteIndex; + m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; + 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; + + // Restore element type and material index to previous values. + m_textElementType = TMP_TextElementType.Character; + m_currentMaterialIndex = prev_materialIndex; + + spriteCount += 1; + m_totalCharacterCount += 1; + + continue; + } + } - }*/ + } + + //Check if Lowercase or Uppercase variant of the character is available. + // Not sure this is necessary anyone as it is very unlikely with recursive search through fallback fonts. + //if (glyph == null) + //{ + // if (char.IsLower((char)c)) + // { + // if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToUpper((char)c), out glyph)) + // c = chars[i] = char.ToUpper((char)c); + // } + // else if (char.IsUpper((char)c)) + // { + // if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToLower((char)c), out glyph)) + // c = chars[i] = char.ToLower((char)c); + // } + //} - // Special handling for missing character. // Replace missing glyph by the Square (9633) glyph or possibly the Space (32) glyph. if (character == null) { @@ -1144,84 +1202,55 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) int srcGlyph = unicode; // Try replacing the missing glyph character by TMP Settings Missing Glyph or Square (9633) character. - unicode = unicodeChars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; + unicode = chars[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); + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (character == null) { // Search for the missing glyph character in the TMP Settings Fallback list. if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_currentFontAsset, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } if (character == null) { // Search for the missing glyph in the TMP Settings Default Font Asset. if (TMP_Settings.defaultFontAsset != null) - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } if (character == null) { // Use Space (32) Glyph from the currently assigned font asset. - unicode = unicodeChars[i].unicode = 32; - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + unicode = chars[i].unicode = 32; + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) - { - 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.LogWarning(formattedWarning, this); - } + Debug.LogWarning("Character with ASCII value of " + srcGlyph + " was not found in the Font Asset Glyph Table. It was replaced by a space.", this); } } - if (character.elementType == TextElementType.Character) + // Determine if the font asset is still the current font asset or a fallback. + if (tempFontAsset != null) { - if (character.textAsset.instanceID != m_currentFontAsset.instanceID) + if (tempFontAsset.instanceID != m_currentFontAsset.instanceID) { isUsingFallbackOrAlternativeTypeface = true; - m_currentFontAsset = character.textAsset as TMP_FontAsset; - + m_currentFontAsset = tempFontAsset; } } #endregion - // Save text element data m_textInfo.characterInfo[m_totalCharacterCount].elementType = TMP_TextElementType.Character; m_textInfo.characterInfo[m_totalCharacterCount].textElement = character; m_textInfo.characterInfo[m_totalCharacterCount].isUsingAlternateTypeface = isUsingAlternativeTypeface; m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; - m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; 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; - // Special handling if the character is a sprite. - if (character.elementType == TextElementType.Sprite) - { - TMP_SpriteAsset spriteAssetRef = character.textAsset as TMP_SpriteAsset; - m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAssetRef.material, spriteAssetRef, m_materialReferences, m_materialReferenceIndexLookup); - m_materialReferences[m_currentMaterialIndex].referenceCount += 1; - - m_textInfo.characterInfo[m_totalCharacterCount].elementType = TMP_TextElementType.Sprite; - m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAssetRef; - m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = (int)character.glyphIndex; - - // Restore element type and material index to previous values. - m_textElementType = TMP_TextElementType.Character; - m_currentMaterialIndex = prev_materialIndex; - - spriteCount += 1; - m_totalCharacterCount += 1; - - continue; - } - - if (isUsingFallbackOrAlternativeTypeface && m_currentFontAsset.instanceID != m_fontAsset.instanceID) + if (isUsingFallbackOrAlternativeTypeface) { // Create Fallback material instance matching current material preset if necessary if (TMP_Settings.matchMaterialPreset) @@ -1235,7 +1264,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) // Handle Multi Atlas Texture support if (character != null && character.glyph.atlasIndex > 0) { - m_currentMaterial = TMP_MaterialManager.GetFallbackMaterial(m_currentFontAsset, m_currentMaterial, character.glyph.atlasIndex); + m_currentMaterial = TMP_MaterialManager.GetFallbackMaterial( m_currentFontAsset, m_currentMaterial, character.glyph.atlasIndex); m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup); @@ -1314,9 +1343,17 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) // Check if the material has changed. if (m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetInstanceID() != m_materialReferences[i].material.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; + 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; + } } // Check if we need to use a Fallback Material @@ -1421,18 +1458,6 @@ protected override void OnTransformParentChanged() protected override void OnRectTransformDimensionsChange() { //Debug.Log("*** OnRectTransformDimensionsChange() ***"); - - // Ignore changes to RectTransform SizeDelta that are very small and typically the result of rounding errors when using RectTransform in Anchor Stretch mode. - if (rectTransform != null && - Mathf.Abs(m_rectTransform.rect.width - m_PreviousRectTransformSize.x) < 0.0001f && Mathf.Abs(m_rectTransform.rect.height - m_PreviousRectTransformSize.y) < 0.0001f && - Mathf.Abs(m_rectTransform.pivot.x - m_PreviousPivotPosition.x) < 0.0001f && Mathf.Abs(m_rectTransform.pivot.y - m_PreviousPivotPosition.y) < 0.0001f) - { - return; - } - - m_PreviousRectTransformSize = m_rectTransform.rect.size; - m_PreviousPivotPosition = m_rectTransform.pivot; - ComputeMarginSize(); SetVerticesDirty(); @@ -1449,10 +1474,7 @@ internal override void InternalUpdate() if (m_havePropertiesChanged == false) { float lossyScaleY = m_rectTransform.lossyScale.y; - - // Ignore very small lossy scale changes as their effect on SDF Scale would not be visually noticeable. - // Do not update SDF Scale if the text is null or empty - if (Mathf.Abs(lossyScaleY - m_previousLossyScaleY) > 0.0001f && m_InternalParsingBuffer[0].unicode != 0) + if (lossyScaleY != m_previousLossyScaleY && m_text != string.Empty && m_text != null) { float scaleDelta = lossyScaleY / m_previousLossyScaleY; @@ -1477,7 +1499,7 @@ internal override void InternalUpdate() /// void OnPreRenderObject() { - //Debug.Log("*** OnPreRenderObject() called on object [" + this.name + "] ***"); + //Debug.Log("*** OnPreRenderObject() ***"); if (!m_isAwake || (this.IsActive() == false && m_ignoreActiveState == false)) return; @@ -1517,7 +1539,7 @@ void OnPreRenderObject() ParseInputText(); - TMP_FontAsset.UpdateFontFeaturesForFontAssetsInQueue(); + TMP_FontAsset.UpdateFontAssets(); #if TMP_PROFILE_ON Profiler.EndSample(); @@ -1577,7 +1599,7 @@ protected override void GenerateTextMesh() m_textInfo.Clear(); // Early exit if we don't have any Text to generate. - if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == 0) + if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) { // Clear mesh and upload changes to the mesh. ClearMesh(true); @@ -1699,10 +1721,9 @@ protected override void GenerateTextMesh() m_maxLineDescender = k_LargePositiveFloat; m_lineNumber = 0; m_startOfLineAscender = 0; - m_startOfLineDescender = 0; m_lineVisibleCharacterCount = 0; bool isStartOfNewLine = true; - m_IsDrivenLineSpacing = false; + bool isDrivenLineSpacing = false; m_firstOverflowCharacterIndex = -1; m_pageNumber = 0; @@ -1726,9 +1747,9 @@ protected override void GenerateTextMesh() // Tracking of the highest Ascender m_maxCapHeight = 0; - m_maxTextAscender = 0; - m_ElementDescender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + m_maxDescender = 0; + float pageAscender = 0; float maxVisibleDescender = 0; bool isMaxVisibleDescenderSet = false; m_isNewPage = false; @@ -1737,8 +1758,7 @@ protected override void GenerateTextMesh() bool isFirstWordOfLine = true; m_isNonBreakingSpace = false; bool ignoreNonBreakingSpace = false; - //bool isLastCharacterCJK = false; - int lastSoftLineBreak = 0; + bool isLastCharacterCJK = false; CharacterSubstitution characterToSubstitute = new CharacterSubstitution(-1, 0); bool isSoftHyphenIgnored = false; @@ -1749,28 +1769,15 @@ protected override void GenerateTextMesh() SaveWordWrappingState(ref m_SavedLineState, -1, -1); SaveWordWrappingState(ref m_SavedEllipsisState, -1, -1); SaveWordWrappingState(ref m_SavedLastValidState, -1, -1); - SaveWordWrappingState(ref m_SavedSoftLineBreakState, -1, -1); - - m_EllipsisInsertionCandidateStack.Clear(); - - // Safety Tracker - int restoreCount = 0; #if TMP_PROFILE_ON Profiler.BeginSample("TMP GenerateText() - Phase I"); #endif // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) { - charCode = m_InternalParsingBuffer[i].unicode; - - if (restoreCount > 5) - { - Debug.LogError("Line breaking recursion max threshold hit... Character [" + charCode + "] index: " + i); - characterToSubstitute.index = m_characterCount; - characterToSubstitute.unicode = 0x03; - } + charCode = m_TextParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -1785,7 +1792,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_InternalParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -1812,7 +1819,7 @@ protected override void GenerateTextMesh() } #endregion End Parse Rich Text Tag - int previousMaterialIndex = m_currentMaterialIndex; + int prev_MaterialIndex = m_currentMaterialIndex; bool isUsingAltTypeface = m_textInfo.characterInfo[m_characterCount].isUsingAlternateTypeface; m_isParsingText = false; @@ -1830,18 +1837,17 @@ protected override void GenerateTextMesh() switch (charCode) { case 0x03: - m_textInfo.characterInfo[m_characterCount].textElement = m_currentFontAsset.characterLookupTable[0x03]; - m_isTextTruncated = true; + // break; case 0x2D: - // + // break; case 0x2026: - m_textInfo.characterInfo[m_characterCount].textElement = m_Ellipsis.character; + m_textInfo.characterInfo[m_characterCount].textElement = m_cached_Ellipsis_Character; m_textInfo.characterInfo[m_characterCount].elementType = TMP_TextElementType.Character; - m_textInfo.characterInfo[m_characterCount].fontAsset = m_Ellipsis.fontAsset; - m_textInfo.characterInfo[m_characterCount].material = m_Ellipsis.material; - m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = m_Ellipsis.materialIndex; + m_textInfo.characterInfo[m_characterCount].fontAsset = m_materialReferences[0].fontAsset; + m_textInfo.characterInfo[m_characterCount].material = m_materialReferences[0].material; + m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = 0; // Indicates the source parsing data has been modified. m_isTextTruncated = true; @@ -1907,8 +1913,8 @@ protected override void GenerateTextMesh() #endif float baselineOffset = 0; float spriteScale = 1; - float elementAscentLine = 0; - float elementDescentLine = 0; + float spriteAscentLine = 0; + float spriteDescentLine = 0; if (m_textElementType == TMP_TextElementType.Sprite) { // If a sprite is used as a fallback then get a reference to it and set the color to white. @@ -1927,19 +1933,19 @@ protected override void GenerateTextMesh() // The sprite scale calculations are based on the font asset assigned to the text object. if (m_currentSpriteAsset.m_FaceInfo.pointSize > 0) { - spriteScale = m_currentFontSize / m_currentSpriteAsset.m_FaceInfo.pointSize * m_currentSpriteAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + spriteScale = (m_currentFontSize / m_currentSpriteAsset.m_FaceInfo.pointSize * m_currentSpriteAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); currentElementScale = sprite.m_Scale * sprite.m_Glyph.scale * spriteScale; - elementAscentLine = m_currentSpriteAsset.m_FaceInfo.ascentLine; + spriteAscentLine = m_currentSpriteAsset.m_FaceInfo.ascentLine; baselineOffset = m_currentSpriteAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentSpriteAsset.m_FaceInfo.scale; - elementDescentLine = m_currentSpriteAsset.m_FaceInfo.descentLine; + spriteDescentLine = m_currentSpriteAsset.m_FaceInfo.descentLine; } else { - spriteScale = m_currentFontSize / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + spriteScale = (m_currentFontSize / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); currentElementScale = m_currentFontAsset.m_FaceInfo.ascentLine / sprite.m_Glyph.metrics.height * sprite.m_Scale * sprite.m_Glyph.scale * spriteScale; - elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; + spriteAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; - elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; + spriteDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; } m_cached_TextElement = sprite; @@ -1950,31 +1956,31 @@ protected override void GenerateTextMesh() m_textInfo.characterInfo[m_characterCount].fontAsset = m_currentFontAsset; m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = m_currentMaterialIndex; - m_currentMaterialIndex = previousMaterialIndex; + m_currentMaterialIndex = prev_MaterialIndex; padding = 0; } else if (m_textElementType == TMP_TextElementType.Character) { - m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement; + if (isInjectingCharacter) + m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].fontAsset.characterLookupTable[(uint)charCode]; + else + m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement; + if (m_cached_TextElement == null) continue; m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset; m_currentMaterial = m_textInfo.characterInfo[m_characterCount].material; m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; - // Special handling if replaced character was a line feed where in this case we have to use the scale of the previous character. - float adjustedScale; - if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) - adjustedScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + // Re-calculate font scale as the font asset may have changed. + if (isInjectingCharacter && m_TextParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) + m_fontScale = m_textInfo.characterInfo[m_characterCount - 1].scale; else - adjustedScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - - elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; - elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; + m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - currentElementScale = adjustedScale * m_fontScaleMultiplier * m_cached_TextElement.m_Scale * m_cached_TextElement.m_Glyph.scale; - baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * adjustedScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; + currentElementScale = m_fontScale * m_fontScaleMultiplier * m_cached_TextElement.m_Scale * m_cached_TextElement.m_Glyph.scale; + baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; m_textInfo.characterInfo[m_characterCount].elementType = TMP_TextElementType.Character; m_textInfo.characterInfo[m_characterCount].scale = currentElementScale; @@ -1989,7 +1995,7 @@ protected override void GenerateTextMesh() // Handle Soft Hyphen #region Handle Soft Hyphen - float currentElementUnmodifiedScale = currentElementScale; + float unModifiedScale = currentElementScale; if (charCode == 0xAD || charCode == 0x03) currentElementScale = 0; #endregion @@ -2009,7 +2015,6 @@ protected override void GenerateTextMesh() // Optimization to avoid calling this more than once per character. bool isWhiteSpace = char.IsWhiteSpace((char)charCode); - //bool isVisibleCharacter = !isWhiteSpace; // Handle Kerning if Enabled. #region Handle Kerning @@ -2199,73 +2204,59 @@ protected override void GenerateTextMesh() m_textInfo.characterInfo[m_characterCount].aspectRatio = (top_right.x - bottom_left.x) / (top_left.y - bottom_left.y); - // Compute text metrics + // Compute and save text element Ascender and maximum line Ascender. #region Compute Ascender & Descender values #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Compute Text Metrics"); #endif - // Element Ascender in line space + float elementAscender = m_textElementType == TMP_TextElementType.Character - ? elementAscentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementAscentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.m_FaceInfo.ascentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteAscentLine * spriteScale + m_baselineOffset; + + m_textInfo.characterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; - // Element Descender in line space + // Compute and save text element Descender and maximum line Descender. float elementDescender = m_textElementType == TMP_TextElementType.Character - ? elementDescentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementDescentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.m_FaceInfo.descentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteDescentLine * spriteScale + m_baselineOffset; - float adjustedAscender = elementAscender; - float adjustedDescender = elementDescender; + float elementDescenderII = m_textInfo.characterInfo[m_characterCount].descender = elementDescender - m_lineOffset; - bool isFirstCharacterOfLine = m_characterCount == m_firstCharacterOfLine; - // Max line ascender and descender in line space - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode != 0x0A || m_characterCount == m_firstCharacterOfLine) { - // Special handling for Superscript and Subscript where we use the unadjusted line ascender and descender - if (m_baselineOffset != 0) - { - adjustedAscender = Mathf.Max((elementAscender - m_baselineOffset) / m_fontScaleMultiplier, adjustedAscender); - adjustedDescender = Mathf.Min((elementDescender - m_baselineOffset) / m_fontScaleMultiplier, adjustedDescender); - } - - m_maxLineAscender = Mathf.Max(adjustedAscender, m_maxLineAscender); - m_maxLineDescender = Mathf.Min(adjustedDescender, m_maxLineDescender); + m_maxLineAscender = elementAscender > m_maxLineAscender ? elementAscender : m_maxLineAscender; + m_maxLineDescender = elementDescender < m_maxLineDescender ? elementDescender : m_maxLineDescender; } - // Element Ascender and Descender in object space - if (isFirstCharacterOfLine || isWhiteSpace == false) + // Adjust maxLineAscender and maxLineDescender if style is superscript or subscript + if ((m_FontStyleInternal & FontStyles.Subscript) == FontStyles.Subscript || (m_FontStyleInternal & FontStyles.Superscript) == FontStyles.Superscript) { - m_textInfo.characterInfo[m_characterCount].adjustedAscender = adjustedAscender; - m_textInfo.characterInfo[m_characterCount].adjustedDescender = adjustedDescender; + float baseAscender = (elementAscender - m_baselineOffset) / m_currentFontAsset.m_FaceInfo.subscriptSize; + elementAscender = m_maxLineAscender; + m_maxLineAscender = baseAscender > m_maxLineAscender ? baseAscender : m_maxLineAscender; - m_ElementAscender = m_textInfo.characterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; - m_ElementDescender = m_textInfo.characterInfo[m_characterCount].descender = elementDescender - m_lineOffset; + float baseDescender = (elementDescender - m_baselineOffset) / m_currentFontAsset.m_FaceInfo.subscriptSize; + elementDescender = m_maxLineDescender; + m_maxLineDescender = baseDescender < m_maxLineDescender ? baseDescender : m_maxLineDescender; } - else - { - m_textInfo.characterInfo[m_characterCount].adjustedAscender = m_maxLineAscender; - m_textInfo.characterInfo[m_characterCount].adjustedDescender = m_maxLineDescender; - m_ElementAscender = m_textInfo.characterInfo[m_characterCount].ascender = m_maxLineAscender - m_lineOffset; - m_ElementDescender = m_textInfo.characterInfo[m_characterCount].descender = m_maxLineDescender - m_lineOffset; - } - - // Max text object ascender and cap height if (m_lineNumber == 0 || m_isNewPage) { - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode == 0x0A && m_characterCount != m_firstCharacterOfLine) + { + // Skip Line Feed that are not at the start of a line. + } + else { - m_maxTextAscender = m_maxLineAscender; + m_maxAscender = m_maxAscender > elementAscender ? m_maxAscender : elementAscender; m_maxCapHeight = Mathf.Max(m_maxCapHeight, m_currentFontAsset.m_FaceInfo.capLine * currentElementScale / smallCapsMultiplier); } } - // Page ascender if (m_lineOffset == 0) - { - if (isFirstCharacterOfLine || isWhiteSpace == false) - m_PageAscender = m_PageAscender > elementAscender ? m_PageAscender : elementAscender; - } + pageAscender = pageAscender > elementAscender ? pageAscender : elementAscender; + #if TMP_PROFILE_ON Profiler.EndSample(); #endif @@ -2279,7 +2270,7 @@ protected override void GenerateTextMesh() // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN. #region Handle Visible Characters - if (charCode == 9 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) + if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Handle Visible Character"); @@ -2335,8 +2326,8 @@ protected override void GenerateTextMesh() widthOfTextArea = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - marginLeft - marginRight, m_width) : marginWidth + 0.0001f - marginLeft - marginRight; // Calculate the line breaking width of the text. - float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? currentGlyphMetrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * (charCode == 0xAD ? currentElementUnmodifiedScale : currentElementScale); - float textHeight = m_maxTextAscender - (m_maxLineDescender - m_lineOffset) + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); + float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? currentGlyphMetrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * (charCode != 0xAD ? currentElementScale : unModifiedScale); + float textHeight = (m_maxAscender - elementDescenderII) + ((m_lineNumber > 0 && isDrivenLineSpacing == false) ? m_maxLineAscender - m_startOfLineAscender : 0); int testedCharacterCount = m_characterCount; @@ -2353,7 +2344,7 @@ protected override void GenerateTextMesh() { // Handle Line spacing adjustments #region Line Spacing Adjustments - if (m_lineSpacingDelta > m_lineSpacingMax && m_lineOffset > 0 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) + if (m_lineSpacingDelta > m_lineSpacingMax && m_lineNumber > 0 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) { float adjustmentDelta = (marginHeight - textHeight) / m_lineNumber; @@ -2398,25 +2389,21 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0 || testedCharacterCount == 0) { i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -2446,30 +2433,15 @@ protected override void GenerateTextMesh() characterToSubstitute.unicode = 0x03; continue; } - else if (m_maxLineAscender - m_maxLineDescender > marginHeight + 0.0001f) - { - // Current line exceeds the height of the text container - // as such we stop on the previous line. - i = RestoreWordWrappingState(ref m_SavedLineState); - characterToSubstitute.index = testedCharacterCount; - characterToSubstitute.unicode = 0x03; - continue; - } - - // Go back to previous line and re-layout + // Go back to previous line and re-layout i = RestoreWordWrappingState(ref m_SavedLineState); m_isNewPage = true; - m_firstCharacterOfLine = m_characterCount; - m_maxLineAscender = k_LargeNegativeFloat; - m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = 0; - m_xAdvance = 0 + tag_Indent; m_lineOffset = 0; - m_maxTextAscender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + pageAscender = 0; m_lineNumber += 1; m_pageNumber += 1; @@ -2498,17 +2470,17 @@ protected override void GenerateTextMesh() float lineOffsetDelta = 0; if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float ascender = m_textInfo.characterInfo[m_characterCount].adjustedAscender; - lineOffsetDelta = (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0) - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; + float ascender = m_textInfo.characterInfo[m_characterCount].ascender - m_textInfo.characterInfo[m_characterCount].baseLine; + lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; } else { lineOffsetDelta = m_lineHeight + m_lineSpacing * currentEmScale; - m_IsDrivenLineSpacing = true; + isDrivenLineSpacing = true; } // Calculate new text height - float newTextHeight = m_maxTextAscender + lineOffsetDelta + m_lineOffset - m_textInfo.characterInfo[m_characterCount].adjustedDescender; + float newTextHeight = m_maxAscender - m_textInfo.characterInfo[m_characterCount].descender + lineOffsetDelta; // Replace Soft Hyphen by Hyphen Minus 0x2D #region Handle Soft Hyphenation @@ -2574,29 +2546,6 @@ protected override void GenerateTextMesh() #endregion Text Auto-Sizing } - - // Special handling if first word of line and non breaking space - int savedSoftLineBreakingSpace = m_SavedSoftLineBreakState.previous_WordBreak; - if (isFirstWordOfLine && savedSoftLineBreakingSpace != -1) - { - if (savedSoftLineBreakingSpace != lastSoftLineBreak) - { - i = RestoreWordWrappingState(ref m_SavedSoftLineBreakState); - lastSoftLineBreak = savedSoftLineBreakingSpace; - - // check if soft hyphen - if (m_textInfo.characterInfo[m_characterCount - 1].character == 0xAD) - { - characterToSubstitute.index = m_characterCount - 1; - characterToSubstitute.unicode = 0x2D; - - i -= 1; - m_characterCount -= 1; - continue; - } - } - } - // Determine if new line of text would exceed the vertical bounds of text container if (newTextHeight > marginHeight + 0.0001f) { @@ -2690,25 +2639,20 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0) { - i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -2732,10 +2676,9 @@ protected override void GenerateTextMesh() InsertNewLine(i, baseScale, currentEmScale, characterSpacingAdjustment, widthOfTextArea, lineGap, ref isMaxVisibleDescenderSet, ref maxVisibleDescender); - m_startOfLineAscender = 0; m_lineOffset = 0; - m_maxTextAscender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + pageAscender = 0; m_pageNumber += 1; isStartOfNewLine = true; @@ -2852,25 +2795,20 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0) { - i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -2902,12 +2840,15 @@ protected override void GenerateTextMesh() // Special handling of characters that are not ignored at the end of a line. - if (charCode == 9) + if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007) { m_textInfo.characterInfo[m_characterCount].isVisible = false; m_lastVisibleCharacterOfLine = m_characterCount; m_textInfo.lineInfo[m_lineNumber].spaceCount += 1; m_textInfo.spaceCount += 1; + + if (charCode == 0xA0) + m_textInfo.lineInfo[m_lineNumber].controlCharacterCount += 1; } else if (charCode == 0xAD) { @@ -2962,15 +2903,12 @@ protected override void GenerateTextMesh() // This is white spacing / non visible characters. // Track # of spaces per line which is used for line justification. - if ((charCode == 10 || charCode == 11 || charCode == 0xA0 || charCode == 0x2007 || charCode == 0x2028 || charCode == 0x2029 || char.IsSeparator((char)charCode)) && charCode != 0xAD && charCode != 0x200B && charCode != 0x2060) + if ((charCode == 10 || charCode == 11 || char.IsSeparator((char)charCode)) && charCode != 0xAD && charCode != 0x200B && charCode != 0x2060) { m_textInfo.lineInfo[m_lineNumber].spaceCount += 1; m_textInfo.spaceCount += 1; } - if (charCode == 0xA0) - m_textInfo.lineInfo[m_lineNumber].controlCharacterCount += 1; - #if TMP_PROFILE_ON Profiler.EndSample(); #endif @@ -2978,33 +2916,55 @@ protected override void GenerateTextMesh() #endregion Handle Visible Characters + // Check if Line Spacing of previous line needs to be adjusted. + #region Adjust Line Spacing + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && /* m_lineHeight == TMP_Math.FLOAT_UNSET && */ isDrivenLineSpacing == false && !m_isNewPage && isInjectingCharacter == false) + { + #if TMP_PROFILE_ON + Profiler.BeginSample("TMP - Handle Line Spacing Adjustments"); + #endif + + float offsetDelta = m_maxLineAscender - m_startOfLineAscender; + AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); + elementDescenderII -= offsetDelta; + m_lineOffset += offsetDelta; + + m_startOfLineAscender += offsetDelta; + m_SavedWordWrapState.lineOffset = m_lineOffset; + m_SavedWordWrapState.previousLineAscender = m_startOfLineAscender; + + #if TMP_PROFILE_ON + Profiler.EndSample(); + #endif + } + #endregion + + // Tracking of potential insertion positions for Ellipsis character #region Track Potential Insertion Location for Ellipsis - if (m_overflowMode == TextOverflowModes.Ellipsis && (isInjectingCharacter == false || charCode == 0x2D)) + if (m_overflowMode == TextOverflowModes.Ellipsis && isInjectingCharacter == false) { - float fontScale = m_currentFontSize / m_Ellipsis.fontAsset.m_FaceInfo.pointSize * m_Ellipsis.fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - float scale = fontScale * m_fontScaleMultiplier * m_Ellipsis.character.m_Scale * m_Ellipsis.character.m_Glyph.scale; + float fontScale = m_currentFontSize * smallCapsMultiplier / m_fontAsset.m_FaceInfo.pointSize * m_fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + float scale = fontScale * m_fontScaleMultiplier * m_cached_Ellipsis_Character.m_Scale * m_cached_Ellipsis_Character.m_Glyph.scale; float marginLeft = m_marginLeft; float marginRight = m_marginRight; // Use the scale and margins of the previous character if Line Feed (LF) is not the first character of a line. if (charCode == 0x0A && m_characterCount != m_firstCharacterOfLine) { - fontScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize / m_Ellipsis.fontAsset.m_FaceInfo.pointSize * m_Ellipsis.fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - scale = fontScale * m_fontScaleMultiplier * m_Ellipsis.character.m_Scale * m_Ellipsis.character.m_Glyph.scale; + scale = m_textInfo.characterInfo[m_characterCount - 1].scale; marginLeft = m_textInfo.lineInfo[m_lineNumber].marginLeft; marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; } - float textHeight = m_maxTextAscender - (m_maxLineDescender - m_lineOffset) + (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 descender = m_fontAsset.m_FaceInfo.descentLine * scale / smallCapsMultiplier + m_baselineOffset; + float textHeight = m_maxAscender - (descender - m_lineOffset); + + float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? m_cached_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; if (textWidth < widthOfTextAreaForEllipsis * (isJustifiedOrFlush ? 1.05f : 1.0f) && textHeight < marginHeight + 0.0001f) - { SaveWordWrappingState(ref m_SavedEllipsisState, i, m_characterCount); - m_EllipsisInsertionCandidateStack.Push(m_SavedEllipsisState); - } } #endregion @@ -3079,29 +3039,20 @@ protected override void GenerateTextMesh() // Handle Line Spacing Adjustments + Word Wrapping & special case for last line. #region Check for Line Feed and Last Character - if (charCode == 10 || charCode == 11 || charCode == 0x03 || charCode == 0x2028 || charCode == 0x2029 || (charCode == 0x2D && isInjectingCharacter) || m_characterCount == totalCharacterCount - 1) + if (charCode == 10 || charCode == 11 || charCode == 0x03 || (charCode == 0x2D && isInjectingCharacter) || m_characterCount == totalCharacterCount - 1) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Handle Line & Text Termination"); #endif - // Adjust current line spacing (if necessary) before inserting new line - float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender; - if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage) + // Check if Line Spacing of previous line needs to be adjusted. + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && isDrivenLineSpacing == false /* && m_lineHeight == TMP_Math.FLOAT_UNSET */ && !m_isNewPage && isInjectingCharacter == false) { //Debug.Log("Line Feed - Adjusting Line Spacing on line #" + m_lineNumber); - AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta); - m_ElementDescender -= baselineAdjustmentDelta; - m_lineOffset += baselineAdjustmentDelta; - - // Adjust saved ellipsis state only if we are adjusting the same line number - if (m_SavedEllipsisState.lineNumber == m_lineNumber) - { - m_SavedEllipsisState = m_EllipsisInsertionCandidateStack.Pop(); - m_SavedEllipsisState.startOfLineAscender += baselineAdjustmentDelta; - m_SavedEllipsisState.lineOffset += baselineAdjustmentDelta; - m_EllipsisInsertionCandidateStack.Push(m_SavedEllipsisState); - } + float offsetDelta = m_maxLineAscender - m_startOfLineAscender; + AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); + elementDescenderII -= offsetDelta; + m_lineOffset += offsetDelta; } m_isNewPage = false; @@ -3110,9 +3061,9 @@ protected override void GenerateTextMesh() float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender - m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender; + m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; if (!isMaxVisibleDescenderSet) - maxVisibleDescender = m_ElementDescender; + maxVisibleDescender = m_maxDescender; if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)) isMaxVisibleDescenderSet = true; @@ -3144,7 +3095,7 @@ protected override void GenerateTextMesh() m_textInfo.lineInfo[m_lineNumber].lineHeight = lineAscender - lineDescender + lineGap * baseScale; // Add new line if not last line or character. - if (charCode == 10 || charCode == 11 || charCode == 0x2D || charCode == 0x2028 || charCode == 0x2029) + if (charCode == 10 || charCode == 11 || charCode == 0x2D) { // Store the state of the line before starting on the new line. SaveWordWrappingState(ref m_SavedLineState, i, m_characterCount); @@ -3161,27 +3112,29 @@ protected override void GenerateTextMesh() if (m_lineNumber >= m_textInfo.lineInfo.Length) ResizeLineExtents(m_lineNumber); - float lastVisibleAscender = m_textInfo.characterInfo[m_characterCount].adjustedAscender; + float lastVisibleAscender = m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].ascender + m_lineOffset; // Apply Line Spacing with special handling for VT char(11) if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float lineOffsetDelta = 0 - m_maxLineDescender + lastVisibleAscender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; + float lineOffsetDelta = 0 - m_maxLineDescender + lastVisibleAscender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; m_lineOffset += lineOffsetDelta; - m_IsDrivenLineSpacing = false; + isDrivenLineSpacing = false; } else { - m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; - m_IsDrivenLineSpacing = true; + m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; + isDrivenLineSpacing = true; } m_maxLineAscender = k_LargeNegativeFloat; m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = lastVisibleAscender; + m_startOfLineAscender = lastVisibleAscender; // elementAscender; m_xAdvance = 0 + tag_LineIndent + tag_Indent; + //ellipsisIndex = m_characterCount - 1; + SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); SaveWordWrappingState(ref m_SavedLastValidState, i, m_characterCount); @@ -3196,7 +3149,7 @@ protected override void GenerateTextMesh() // If End of Text if (charCode == 0x03) - i = m_InternalParsingBuffer.Length; + i = m_TextParsingBuffer.Length; #if TMP_PROFILE_ON Profiler.EndSample(); @@ -3225,15 +3178,15 @@ protected override void GenerateTextMesh() // Save pageInfo Data - if (m_overflowMode == TextOverflowModes.Page && charCode != 10 && charCode != 11 && charCode != 13 && charCode != 0x2028 && charCode != 0x2029) // && m_pageNumber < 16) + if (m_overflowMode == TextOverflowModes.Page && charCode != 10 && charCode != 11 && charCode != 13) // && m_pageNumber < 16) { // Check if we need to increase allocations for the pageInfo array. if (m_pageNumber + 1 > m_textInfo.pageInfo.Length) TMP_TextInfo.Resize(ref m_textInfo.pageInfo, m_pageNumber + 1, true); - m_textInfo.pageInfo[m_pageNumber].ascender = m_PageAscender; - m_textInfo.pageInfo[m_pageNumber].descender = m_ElementDescender < m_textInfo.pageInfo[m_pageNumber].descender - ? m_ElementDescender + m_textInfo.pageInfo[m_pageNumber].ascender = pageAscender; + m_textInfo.pageInfo[m_pageNumber].descender = elementDescenderII < m_textInfo.pageInfo[m_pageNumber].descender + ? elementDescenderII : m_textInfo.pageInfo[m_pageNumber].descender; if (m_pageNumber == 0 && m_characterCount == 0) @@ -3262,69 +3215,53 @@ protected override void GenerateTextMesh() if ((isWhiteSpace || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && (!m_isNonBreakingSpace || ignoreNonBreakingSpace) && charCode != 0xA0 && charCode != 0x2007 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060) { - // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored + // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored // for Word Wrapping. SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); isFirstWordOfLine = false; - //isLastCharacterCJK = false; - - // Reset soft line breaking point since we now have a valid hard break point. - m_SavedSoftLineBreakState.previous_WordBreak = -1; + isLastCharacterCJK = false; } // Handling for East Asian characters - else if (m_isNonBreakingSpace == false && - ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ - charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */ - charCode > 0xAC00 && charCode < 0xD7FF)&& /* Hangul Syllables */ - TMP_Settings.useModernHangulLineBreakingRules == false || - - (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ - charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ - charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ - charCode > 0xFF00 && charCode < 0xFFEF))) /* CJK Halfwidth */ + else if (!m_isNonBreakingSpace && + (charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ + charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */ + charCode > 0xAC00 && charCode < 0xD7FF) /* Hangul Syllables */ && + !TMP_Settings.useModernHangulLineBreakingRules || + (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ + charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ + charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ + charCode > 0xFF00 && charCode < 0xFFEF)) /* CJK Halfwidth */ { - bool isCurrentLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); - bool isNextFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_textInfo.characterInfo[m_characterCount + 1].character); + bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); + bool isFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_textInfo.characterInfo[m_characterCount + 1].character); - if (isCurrentLeadingCharacter == false) + if (isFirstWordOfLine || isLeadingCharacter == false) { - if (isNextFollowingCharacter == false) + if (isFollowingCharacter == false) { SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); isFirstWordOfLine = false; } if (isFirstWordOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - } } - else - { - if (isFirstWordOfLine && isFirstCharacterOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - } - } + isLastCharacterCJK = true; + } + else if (isLastCharacterCJK) + { + bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); - //isLastCharacterCJK = true; + if (isLeadingCharacter == false) + SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); + + isLastCharacterCJK = false; } else if (isFirstWordOfLine) { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace || (charCode == 0xAD && isSoftHyphenIgnored == false)) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - //isLastCharacterCJK = false; + isLastCharacterCJK = false; } #if TMP_PROFILE_ON @@ -3359,12 +3296,13 @@ protected override void GenerateTextMesh() #endregion End Auto-sizing Check m_IsAutoSizePointSizeSet = true; + //m_isCharacterWrappingEnabled = false; if (m_AutoSizeIterationCount >= m_AutoSizeMaxIterationCount) Debug.Log("Auto Size Iteration Count: " + m_AutoSizeIterationCount + ". Final Point Size: " + m_fontSize); - // If there are no visible characters or only character is End of Text (0x03)... no need to continue - if (m_characterCount == 0 || (m_characterCount == 1 && charCode == 0x03)) + // If there are no visible characters... no need to continue + if (m_characterCount == 0) // && m_visibleSpriteCount == 0) { ClearMesh(true); @@ -3381,7 +3319,7 @@ protected override void GenerateTextMesh() #endif // *** PHASE II of Text Generation *** - int last_vert_index = m_materialReferences[m_Underline.materialIndex].referenceCount * (!m_isVolumetricText ? 4 : 8); + int last_vert_index = m_materialReferences[0].referenceCount * (!m_isVolumetricText ? 4 : 8); // Partial clear of the vertices array to mark unused vertices as degenerate. m_textInfo.meshInfo[0].Clear(false); @@ -3397,7 +3335,7 @@ protected override void GenerateTextMesh() // Top Vertically case VerticalAlignmentOptions.Top: if (m_overflowMode != TextOverflowModes.Page) - anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_maxTextAscender - margins.y, 0); + anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_maxAscender - margins.y, 0); else anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_textInfo.pageInfo[pageToDisplay].ascender - margins.y, 0); break; @@ -3405,7 +3343,7 @@ protected override void GenerateTextMesh() // Middle Vertically case VerticalAlignmentOptions.Middle: if (m_overflowMode != TextOverflowModes.Page) - anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxTextAscender + margins.y + maxVisibleDescender - margins.w) / 2, 0); + anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxAscender + margins.y + maxVisibleDescender - margins.w) / 2, 0); else anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_textInfo.pageInfo[pageToDisplay].ascender + margins.y + m_textInfo.pageInfo[pageToDisplay].descender - margins.w) / 2, 0); break; @@ -3423,12 +3361,12 @@ protected override void GenerateTextMesh() anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0, 0); break; - // Midline Vertically + // Midline Vertically case VerticalAlignmentOptions.Geometry: anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_meshExtents.max.y + margins.y + m_meshExtents.min.y - margins.w) / 2, 0); break; - // Capline Vertically + // Capline Vertically case VerticalAlignmentOptions.Capline: anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxCapHeight - margins.y - margins.w) / 2, 0); break; @@ -3734,7 +3672,7 @@ protected override void GenerateTextMesh() characterInfos[i].vertex_BR.uv2.x = PackUV(x1, y0); characterInfos[i].vertex_BR.uv2.y = xScale; #endregion break; - + // SPRITES case TMP_TextElementType.Sprite: // Nothing right now @@ -4204,8 +4142,6 @@ protected override void GenerateTextMesh() } #endregion - // Set vertex count for Underline geometry - //m_textInfo.meshInfo[m_Underline.materialIndex].vertexCount = last_vert_index; // METRICS ABOUT THE TEXT OBJECT m_textInfo.characterCount = m_characterCount; @@ -4340,10 +4276,13 @@ protected override void SetActiveSubMeshes(bool state) /// /// Destroy Sub Mesh Objects /// - protected override void DestroySubMeshObjects() + protected override void ClearSubMeshObjects() { for (int i = 1; i < m_subTextObjects.Length && m_subTextObjects[i] != null; i++) + { + Debug.Log("Destroying Sub Text object[" + i + "]."); DestroyImmediate(m_subTextObjects[i]); + } } @@ -4445,4 +4384,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 f89fd1e..7bc1c63 100644 --- a/Scripts/Runtime/TMPro_UGUI_Private.cs +++ b/Scripts/Runtime/TMPro_UGUI_Private.cs @@ -29,7 +29,7 @@ public partial class TextMeshProUGUI private bool m_isFirstAllocation; // Flag to determine if this is the first allocation of the buffers. private int m_max_characters = 8; // Determines the initial allocation and size of the character array / buffer. - //private int m_max_numberOfLines = 4; // Determines the initial allocation and maximum number of lines of text. + //private int m_max_numberOfLines = 4; // Determines the initial allocation and maximum number of lines of text. // MASKING RELATED PROPERTIES // This property is now obsolete and used for compatibility with previous releases (prior to release 0.1.54). @@ -39,7 +39,7 @@ public partial class TextMeshProUGUI private bool m_isScrollRegionSet; //private Mask m_mask; private int m_stencilID = 0; - + [SerializeField] private Vector4 m_maskOffset; @@ -86,12 +86,12 @@ protected override void Awake() // Cache Reference to RectTransform. m_rectTransform = gameObject.GetComponent(); - if (m_rectTransform == null) + if (m_rectTransform == null) m_rectTransform = gameObject.AddComponent(); // Cache a reference to the CanvasRenderer. m_canvasRenderer = GetComponent(); - if (m_canvasRenderer == null) + if (m_canvasRenderer == null) m_canvasRenderer = gameObject.AddComponent (); if (m_mesh == null) @@ -112,8 +112,8 @@ protected override void Awake() LoadFontAsset(); // Allocate our initial buffers. - if (m_InternalParsingBuffer == null) - m_InternalParsingBuffer = new UnicodeChar[m_max_characters]; + if (m_TextParsingBuffer == null) + m_TextParsingBuffer = new UnicodeChar[m_max_characters]; m_cached_TextElement = new TMP_Character(); m_isFirstAllocation = true; @@ -129,6 +129,7 @@ protected override void Awake() // Set flags to ensure our text is parsed and redrawn. m_isInputParsingRequired = true; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; m_isAwake = true; } @@ -145,7 +146,7 @@ protected override void OnEnable() if (!m_isRegisteredForEvents) { //Debug.Log("Registering for Events."); - + #if UNITY_EDITOR // Register Callbacks for various events. TMPro_EventManager.MATERIAL_PROPERTY_EVENT.Add(ON_MATERIAL_PROPERTY_CHANGED); @@ -175,6 +176,8 @@ protected override void OnEnable() ComputeMarginSize(); + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; m_ShouldRecalculateStencil = true; m_isInputParsingRequired = true; SetAllDirty(); @@ -192,7 +195,7 @@ protected override void OnDisable() return; if (m_MaskMaterial != null) - { + { TMP_MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); m_MaskMaterial = null; } @@ -278,12 +281,14 @@ protected override void OnValidate() if (m_fontAsset == null || m_hasFontAssetChanged) { LoadFontAsset(); + m_isCalculateSizeRequired = true; m_hasFontAssetChanged = false; } if (m_canvasRenderer == null || m_canvasRenderer.GetMaterial() == null || m_canvasRenderer.GetMaterial().GetTexture(ShaderUtilities.ID_MainTex) == null || m_fontAsset == null || m_fontAsset.atlasTexture.GetInstanceID() != m_canvasRenderer.GetMaterial().GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) { LoadFontAsset(); + m_isCalculateSizeRequired = true; m_hasFontAssetChanged = false; } @@ -293,6 +298,7 @@ protected override void OnValidate() m_isInputParsingRequired = true; m_inputSource = TextInputSources.Text; m_havePropertiesChanged = true; + m_isCalculateSizeRequired = true; m_isPreferredWidthDirty = true; m_isPreferredHeightDirty = true; @@ -306,13 +312,6 @@ 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(); @@ -365,7 +364,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) if (m_canvasRenderer.GetMaterial() != m_sharedMaterial && m_fontAsset == null) // || m_renderer.sharedMaterials.Contains(mat)) { - //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED Called on Target ID: " + GetInstanceID() + ". Previous Material:" + m_sharedMaterial + " New Material:" + m_uiRenderer.GetMaterial()); // on Object ID:" + GetInstanceID() + ". m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial.name); + //Debug.Log("ON_MATERIAL_PROPERTY_CHANGED Called on Target ID: " + GetInstanceID() + ". Previous Material:" + m_sharedMaterial + " New Material:" + m_uiRenderer.GetMaterial()); // on Object ID:" + GetInstanceID() + ". m_sharedMaterial: " + m_sharedMaterial.name + " m_renderer.sharedMaterial: " + m_renderer.sharedMaterial.name); m_sharedMaterial = m_canvasRenderer.GetMaterial(); } @@ -396,7 +395,7 @@ void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat) } else if (materialID == maskingMaterialID) { - // Update the padding + // Update the padding GetPaddingForMaterial(mat); m_sharedMaterial.CopyPropertiesFromMaterial(mat); @@ -438,7 +437,7 @@ void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font) void ON_TEXTMESHPRO_UGUI_PROPERTY_CHANGED(bool isChanged, TextMeshProUGUI obj) { //Debug.Log("Event Received by " + obj); - + if (obj == this) { //Debug.Log("Undo / Redo Event Received by Object ID:" + GetInstanceID()); @@ -514,7 +513,7 @@ void ON_TMP_SETTINGS_CHANGED() protected override void LoadFontAsset() { //Debug.Log("***** LoadFontAsset() *****"); //TextMeshPro LoadFontAsset() has been called."); // Current Font Asset is " + (font != null ? font.name: "Null") ); - + ShaderUtilities.GetShaderPropertyIDs(); // Initialize & Get shader property IDs. if (m_fontAsset == null) @@ -664,14 +663,14 @@ void DisableMasking() m_sharedMaterial = m_MaskMaterial; else m_sharedMaterial = m_baseMaterial; - + m_canvasRenderer.SetMaterial(m_sharedMaterial, m_sharedMaterial.GetTexture(ShaderUtilities.ID_MainTex)); DestroyImmediate(m_fontMaterial); } - + m_isMaskingEnabled = false; - + /* if (m_maskingMaterial != null && m_stencilID == 0) { @@ -685,8 +684,8 @@ void DisableMasking() m_sharedMaterial.DisableKeyword("MASK_SOFT"); } */ - - + + /* Material mat = m_uiRenderer.GetMaterial(); if (mat.HasProperty(ShaderUtilities.ID_MaskCoord)) @@ -715,7 +714,7 @@ void UpdateMask() if (!ShaderUtilities.isInitialized) ShaderUtilities.GetShaderPropertyIDs(); - + //Debug.Log("Setting Mask for the first time."); m_isScrollRegionSet = true; @@ -729,9 +728,9 @@ void UpdateMask() float width = (m_rectTransform.rect.width - Mathf.Max(m_margin.x, 0) - Mathf.Max(m_margin.z, 0)) / 2 + softnessX; float height = (m_rectTransform.rect.height - Mathf.Max(m_margin.y, 0) - Mathf.Max(m_margin.w, 0)) / 2 + softnessY; - + Vector2 center = m_rectTransform.localPosition + new Vector3((0.5f - m_rectTransform.pivot.x) * m_rectTransform.rect.width + (Mathf.Max(m_margin.x, 0) - Mathf.Max(m_margin.z, 0)) / 2, (0.5f - m_rectTransform.pivot.y) * m_rectTransform.rect.height + (-Mathf.Max(m_margin.y, 0) + Mathf.Max(m_margin.w, 0)) / 2); - + //Vector2 center = m_rectTransform.localPosition + new Vector3((0.5f - m_rectTransform.pivot.x) * m_rectTransform.rect.width + (margin.x - margin.z) / 2, (0.5f - m_rectTransform.pivot.y) * m_rectTransform.rect.height + (-margin.y + margin.w) / 2); Vector4 mask = new Vector4(center.x, center.y, width, height); //Debug.Log(mask); @@ -750,7 +749,7 @@ protected override Material GetMaterial(Material mat) { // Get Shader PropertyIDs if they haven't been cached already. ShaderUtilities.GetShaderPropertyIDs(); - + // Check in case Object is disabled. If so, we don't have a valid reference to the Renderer. // This can occur when the Duplicate Material Context menu is used on an inactive object. //if (m_canvasRenderer == null) @@ -801,10 +800,10 @@ protected override Material[] GetMaterials(Material[] mats) // Function called internally when a new shared material is assigned via the fontSharedMaterial property. - protected override void SetSharedMaterial(Material mat) + protected override void SetSharedMaterial(Material mat) { // Check in case Object is disabled. If so, we don't have a valid reference to the Renderer. - // This can occur when the Duplicate Material Context menu is used on an inactive object. + // This can occur when the Duplicate Material Context menu is used on an inactive object. //if (m_canvasRenderer == null) // m_canvasRenderer = GetComponent(); @@ -930,7 +929,7 @@ protected override void SetOutlineColor(Color32 color) } - // Sets the Render Queue and Ztest mode + // Sets the Render Queue and Ztest mode protected override void SetShaderDepth() { if (m_canvas == null || m_sharedMaterial == null) @@ -1008,7 +1007,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[] unicodeChars) + protected override int SetArraySizes(UnicodeChar[] chars) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP SetArraySizes()"); @@ -1036,65 +1035,9 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_materialReferenceIndexLookup.Clear(); MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup); - // 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); - + if (m_textInfo == null) m_textInfo = new TMP_TextInfo(); m_textElementType = TMP_TextElementType.Character; - // Handling for Underline special character - #region Setup Underline Special Character - /* - GetUnderlineSpecialCharacter(m_currentFontAsset); - if (m_Underline.character != null) - { - if (m_Underline.fontAsset.GetInstanceID() != m_currentFontAsset.GetInstanceID()) - { - if (TMP_Settings.matchMaterialPreset && m_currentMaterial.GetInstanceID() != m_Underline.fontAsset.material.GetInstanceID()) - m_Underline.material = TMP_MaterialManager.GetFallbackMaterial(m_currentMaterial, m_Underline.fontAsset.material); - else - m_Underline.material = m_Underline.fontAsset.material; - - m_Underline.materialIndex = MaterialReference.AddMaterialReference(m_Underline.material, m_Underline.fontAsset, m_materialReferences, m_materialReferenceIndexLookup); - m_materialReferences[m_Underline.materialIndex].referenceCount = 0; - } - } - */ - #endregion - - - // Handling for Ellipsis special character - #region Setup Ellipsis Special Character - if (m_overflowMode == TextOverflowModes.Ellipsis) - { - GetEllipsisSpecialCharacter(m_currentFontAsset); - - if (m_Ellipsis.character != null) - { - if (m_Ellipsis.fontAsset.GetInstanceID() != m_currentFontAsset.GetInstanceID()) - { - if (TMP_Settings.matchMaterialPreset && m_currentMaterial.GetInstanceID() != m_Ellipsis.fontAsset.material.GetInstanceID()) - m_Ellipsis.material = TMP_MaterialManager.GetFallbackMaterial(m_currentMaterial, m_Ellipsis.fontAsset.material); - else - m_Ellipsis.material = m_Ellipsis.fontAsset.material; - - m_Ellipsis.materialIndex = MaterialReference.AddMaterialReference(m_Ellipsis.material, m_Ellipsis.fontAsset, m_materialReferences, m_materialReferenceIndexLookup); - 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 - - // Clear Linked Text object if we have one. if (m_linkedTextComponent != null && !m_isCalculatingPreferredValues) { @@ -1102,14 +1045,15 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_linkedTextComponent.ClearMesh(); } + // Parsing XML tags in the text - for (int i = 0; i < unicodeChars.Length && unicodeChars[i].unicode != 0; i++) + for (int i = 0; i < chars.Length && chars[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 = unicodeChars[i].unicode; + int unicode = chars[i].unicode; // PARSE XML TAGS #region PARSE XML TAGS @@ -1119,13 +1063,12 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) int endTagIndex; // Check if Tag is Valid - if (ValidateHtmlTag(unicodeChars, i + 1, out endTagIndex)) + if (ValidateHtmlTag(chars, i + 1, out endTagIndex)) { - int tagStartIndex = unicodeChars[i].stringIndex; + int tagStartIndex = chars[i].stringIndex; i = endTagIndex; - if ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold) - m_isUsingBold = true; + if ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold) m_isUsingBold = true; if (m_textElementType == TMP_TextElementType.Sprite) { @@ -1139,7 +1082,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) 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 = unicodeChars[i].stringIndex - tagStartIndex + 1; + m_textInfo.characterInfo[m_totalCharacterCount].stringLength = chars[i].stringIndex - tagStartIndex + 1; // Restore element type and material index to previous values. m_textElementType = TMP_TextElementType.Character; @@ -1157,10 +1100,13 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) bool isUsingAlternativeTypeface = false; bool isUsingFallbackOrAlternativeTypeface = false; + TMP_Character character; + TMP_FontAsset tempFontAsset; TMP_FontAsset prev_fontAsset = m_currentFontAsset; Material prev_material = m_currentMaterial; int prev_materialIndex = m_currentMaterialIndex; + // Handle Font Styles like LowerCase, UpperCase and SmallCaps. #region Handling of LowerCase, UpperCase and SmallCaps Font Styles if (m_textElementType == TMP_TextElementType.Character) @@ -1187,27 +1133,132 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) } #endregion + // Lookup the Glyph data for each character and cache it. #region LOOKUP GLYPH - TMP_TextElement character = GetTextElement((uint)unicode, m_currentFontAsset, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); - // Check if Lowercase or Uppercase variant of the character is available. - /* Not sure this is necessary anyone as it is very unlikely with recursive search through fallback fonts. - if (glyph == null) + // Search for the glyph in the list of fallback assigned to the primary font asset. + if (character == null) { - if (char.IsLower((char)c)) + 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 Sprite Asset assigned to the text object. + if (character == null) + { + TMP_SpriteAsset spriteAsset = this.spriteAsset; + + if (spriteAsset != null) { - if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToUpper((char)c), out glyph)) - c = chars[i] = char.ToUpper((char)c); + int spriteIndex = -1; + + // Check Default Sprite Asset and its Fallbacks + spriteAsset = TMP_SpriteAsset.SearchForSpriteByUnicode(spriteAsset, (uint)unicode, true, out spriteIndex); + + if (spriteIndex != -1) + { + m_textElementType = TMP_TextElementType.Sprite; + m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; + + m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAsset.material, spriteAsset, m_materialReferences, m_materialReferenceIndexLookup); + m_materialReferences[m_currentMaterialIndex].referenceCount += 1; + + m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; + m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = spriteIndex; + m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; + 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; + + // Restore element type and material index to previous values. + m_textElementType = TMP_TextElementType.Character; + m_currentMaterialIndex = prev_materialIndex; + + spriteCount += 1; + m_totalCharacterCount += 1; + + continue; + } } - else if (char.IsUpper((char)c)) + } + + // Search for the glyph in the list of fallback assigned in the TMP Settings (General Fallbacks). + if (character == null) + { + if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + + // Search for the glyph in the Default Font Asset assigned in the TMP Settings file. + if (character == null) + { + if (TMP_Settings.defaultFontAsset != null) + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); + } + + // TODO: Add support for using Sprite Assets like a special Emoji only Sprite Asset when UTF16 or UTF32 glyphs are requested. + // This would kind of mirror native Emoji support. + if (character == null) + { + TMP_SpriteAsset spriteAsset = TMP_Settings.defaultSpriteAsset; + + if (spriteAsset != null) { - if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToLower((char)c), out glyph)) - c = chars[i] = char.ToLower((char)c); + int spriteIndex = -1; + + // Check Default Sprite Asset and its Fallbacks + spriteAsset = TMP_SpriteAsset.SearchForSpriteByUnicode(spriteAsset, (uint)unicode, true, out spriteIndex); + + if (spriteIndex != -1) + { + m_textElementType = TMP_TextElementType.Sprite; + m_textInfo.characterInfo[m_totalCharacterCount].elementType = m_textElementType; + + m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAsset.material, spriteAsset, m_materialReferences, m_materialReferenceIndexLookup); + m_materialReferences[m_currentMaterialIndex].referenceCount += 1; + + m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; + m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = spriteIndex; + m_textInfo.characterInfo[m_totalCharacterCount].fontAsset = m_currentFontAsset; + 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; + + // Restore element type and material index to previous values. + m_textElementType = TMP_TextElementType.Character; + m_currentMaterialIndex = prev_materialIndex; + + spriteCount += 1; + m_totalCharacterCount += 1; + + continue; + } + } - }*/ + } + + //Check if Lowercase or Uppercase variant of the character is available. + // Not sure this is necessary anyone as it is very unlikely with recursive search through fallback fonts. + //if (glyph == null) + //{ + // if (char.IsLower((char)c)) + // { + // if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToUpper((char)c), out glyph)) + // c = chars[i] = char.ToUpper((char)c); + // } + // else if (char.IsUpper((char)c)) + // { + // if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToLower((char)c), out glyph)) + // c = chars[i] = char.ToLower((char)c); + // } + //} - // Special handling for missing character. // Replace missing glyph by the Square (9633) glyph or possibly the Space (32) glyph. if (character == null) { @@ -1215,84 +1266,55 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) int srcGlyph = unicode; // Try replacing the missing glyph character by TMP Settings Missing Glyph or Square (9633) character. - unicode = unicodeChars[i].unicode = TMP_Settings.missingGlyphCharacter == 0 ? 9633 : TMP_Settings.missingGlyphCharacter; + unicode = chars[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); + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (character == null) { // Search for the missing glyph character in the TMP Settings Fallback list. if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) - character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, m_currentFontAsset, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + character = TMP_FontAssetUtilities.GetCharacterFromFontAssets((uint)unicode, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } if (character == null) { // Search for the missing glyph in the TMP Settings Default Font Asset. if (TMP_Settings.defaultFontAsset != null) - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); } if (character == null) { // Use Space (32) Glyph from the currently assigned font asset. - unicode = unicodeChars[i].unicode = 32; - character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface); + unicode = chars[i].unicode = 32; + character = TMP_FontAssetUtilities.GetCharacterFromFontAsset((uint)unicode, m_currentFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset); if (!TMP_Settings.warningsDisabled) - { - 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.LogWarning(formattedWarning, this); - } + Debug.LogWarning("Character with ASCII value of " + srcGlyph + " was not found in the Font Asset Glyph Table. It was replaced by a space.", this); } } - if (character.elementType == TextElementType.Character) + // Determine if the font asset is still the current font asset or a fallback. + if (tempFontAsset != null) { - if (character.textAsset.instanceID != m_currentFontAsset.instanceID) + if (tempFontAsset.instanceID != m_currentFontAsset.instanceID) { isUsingFallbackOrAlternativeTypeface = true; - m_currentFontAsset = character.textAsset as TMP_FontAsset; - + m_currentFontAsset = tempFontAsset; } } #endregion - // Save text element data m_textInfo.characterInfo[m_totalCharacterCount].elementType = TMP_TextElementType.Character; m_textInfo.characterInfo[m_totalCharacterCount].textElement = character; m_textInfo.characterInfo[m_totalCharacterCount].isUsingAlternateTypeface = isUsingAlternativeTypeface; m_textInfo.characterInfo[m_totalCharacterCount].character = (char)unicode; - m_textInfo.characterInfo[m_totalCharacterCount].index = unicodeChars[i].stringIndex; - m_textInfo.characterInfo[m_totalCharacterCount].stringLength = unicodeChars[i].length; 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; - // Special handling if the character is a sprite. - if (character.elementType == TextElementType.Sprite) - { - TMP_SpriteAsset spriteAssetRef = character.textAsset as TMP_SpriteAsset; - m_currentMaterialIndex = MaterialReference.AddMaterialReference(spriteAssetRef.material, spriteAssetRef, m_materialReferences, m_materialReferenceIndexLookup); - m_materialReferences[m_currentMaterialIndex].referenceCount += 1; - - m_textInfo.characterInfo[m_totalCharacterCount].elementType = TMP_TextElementType.Sprite; - m_textInfo.characterInfo[m_totalCharacterCount].materialReferenceIndex = m_currentMaterialIndex; - m_textInfo.characterInfo[m_totalCharacterCount].spriteAsset = spriteAssetRef; - m_textInfo.characterInfo[m_totalCharacterCount].spriteIndex = (int)character.glyphIndex; - - // Restore element type and material index to previous values. - m_textElementType = TMP_TextElementType.Character; - m_currentMaterialIndex = prev_materialIndex; - - spriteCount += 1; - m_totalCharacterCount += 1; - - continue; - } - - if (isUsingFallbackOrAlternativeTypeface && m_currentFontAsset.instanceID != m_fontAsset.instanceID) + if (isUsingFallbackOrAlternativeTypeface) { // Create Fallback material instance matching current material preset if necessary if (TMP_Settings.matchMaterialPreset) @@ -1389,9 +1411,17 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) // Check if the material has changed. if (m_subTextObjects[i].sharedMaterial == null || m_subTextObjects[i].sharedMaterial.GetInstanceID() != m_materialReferences[i].material.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; + 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; + } } // Check if we need to use a Fallback Material @@ -1401,7 +1431,7 @@ protected override int SetArraySizes(UnicodeChar[] unicodeChars) m_subTextObjects[i].fallbackSourceMaterial = m_materialReferences[i].fallbackMaterial; } } - + int referenceCount = m_materialReferences[i].referenceCount; // Check to make sure our buffers allocations can accommodate the required text elements. @@ -1477,7 +1507,7 @@ public override void ComputeMarginSize() /// - /// + /// /// protected override void OnDidApplyAnimationProperties() { @@ -1500,7 +1530,7 @@ protected override void OnCanvasHierarchyChanged() // Special handling to stop InternalUpdate calls when parent Canvas is disabled. if (m_canvas == null || m_canvas.enabled == false) TMP_UpdateManager.UnRegisterTextObjectForUpdate(this); - else if (m_IsTextObjectScaleStatic == false) + else TMP_UpdateManager.RegisterTextObjectForUpdate(this); } @@ -1520,23 +1550,12 @@ protected override void OnTransformParentChanged() protected override void OnRectTransformDimensionsChange() { - //Debug.Log("*** OnRectTransformDimensionsChange() *** ActiveInHierarchy: " + this.gameObject.activeInHierarchy + " Frame: " + Time.frameCount); + //Debug.Log("*** OnRectTransformDimensionsChange() *** ActiveInHierarchy: " + this.gameObject.activeInHierarchy + " Frame: " + Time.frameCount); // Make sure object is active in Hierarchy if (!this.gameObject.activeInHierarchy) return; - // Ignore changes to RectTransform SizeDelta that are very small and typically the result of rounding errors when using RectTransform in Anchor Stretch mode. - if (rectTransform != null && - Mathf.Abs(m_rectTransform.rect.width - m_PreviousRectTransformSize.x) < 0.0001f && Mathf.Abs(m_rectTransform.rect.height - m_PreviousRectTransformSize.y) < 0.0001f && - Mathf.Abs(m_rectTransform.pivot.x - m_PreviousPivotPosition.x) < 0.0001f && Mathf.Abs(m_rectTransform.pivot.y - m_PreviousPivotPosition.y) < 0.0001f) - { - return; - } - - m_PreviousRectTransformSize = m_rectTransform.rect.size; - m_PreviousPivotPosition = m_rectTransform.pivot; - ComputeMarginSize(); UpdateSubObjectPivot(); @@ -1555,10 +1574,7 @@ internal override void InternalUpdate() if (m_havePropertiesChanged == false) { float lossyScaleY = m_rectTransform.lossyScale.y; - - // Ignore very small lossy scale changes as their effect on SDF Scale would not be visually noticeable. - // Do not update SDF Scale if the text is null or empty - if (Mathf.Abs(lossyScaleY - m_previousLossyScaleY) > 0.0001f && m_InternalParsingBuffer[0].unicode != 0) + if (lossyScaleY != m_previousLossyScaleY && m_text != string.Empty && m_text != null) { float scaleDelta = lossyScaleY / m_previousLossyScaleY; @@ -1582,7 +1598,7 @@ internal override void InternalUpdate() // Called just before the Canvas is rendered. void OnPreRenderCanvas() { - //Debug.Log("*** OnPreRenderCanvas() *** Frame: " + Time.frameCount); + //Debug.Log("*** OnPreRenderCanvas() *** Frame: " + Time.frameCount); // Make sure object is active and that we have a valid Canvas. if (!m_isAwake || (this.IsActive() == false && m_ignoreActiveState == false)) @@ -1630,7 +1646,7 @@ void OnPreRenderCanvas() ParseInputText(); - TMP_FontAsset.UpdateFontFeaturesForFontAssetsInQueue(); + TMP_FontAsset.UpdateFontAssets(); #if TMP_PROFILE_ON Profiler.EndSample(); @@ -1690,7 +1706,7 @@ protected override void GenerateTextMesh() m_textInfo.Clear(); // Early exit if we don't have any Text to generate. - if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == 0) + if (m_TextParsingBuffer == null || m_TextParsingBuffer.Length == 0 || m_TextParsingBuffer[0].unicode == (char)0) { // Clear mesh and upload changes to the mesh. ClearMesh(); @@ -1720,9 +1736,9 @@ protected override void GenerateTextMesh() // Calculate the scale of the font based on selected font size and sampling point size. // baseScale is calculated using the font asset assigned to the text object. - float baseScale = m_fontScale = (m_fontSize / m_fontAsset.m_FaceInfo.pointSize * m_fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f)); + float baseScale = m_fontScale = (m_fontSize / m_fontAsset.m_FaceInfo.pointSize * m_fontAsset.m_FaceInfo.scale); float currentElementScale = baseScale; - float currentEmScale = m_fontSize * 0.01f * (m_isOrthographic ? 1 : 0.1f); + float currentEmScale = m_fontSize * 0.01f; m_fontScaleMultiplier = 1; m_currentFontSize = m_fontSize; @@ -1812,10 +1828,9 @@ protected override void GenerateTextMesh() m_maxLineDescender = k_LargePositiveFloat; m_lineNumber = 0; m_startOfLineAscender = 0; - m_startOfLineDescender = 0; m_lineVisibleCharacterCount = 0; bool isStartOfNewLine = true; - m_IsDrivenLineSpacing = false; + bool isDrivenLineSpacing = false; m_firstOverflowCharacterIndex = -1; m_pageNumber = 0; @@ -1839,9 +1854,9 @@ protected override void GenerateTextMesh() // Tracking of the highest Ascender m_maxCapHeight = 0; - m_maxTextAscender = 0; - m_ElementDescender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + m_maxDescender = 0; + float pageAscender = 0; float maxVisibleDescender = 0; bool isMaxVisibleDescenderSet = false; m_isNewPage = false; @@ -1850,8 +1865,7 @@ protected override void GenerateTextMesh() bool isFirstWordOfLine = true; m_isNonBreakingSpace = false; bool ignoreNonBreakingSpace = false; - //bool isLastCharacterCJK = false; - int lastSoftLineBreak = 0; + bool isLastCharacterCJK = false; CharacterSubstitution characterToSubstitute = new CharacterSubstitution(-1, 0); bool isSoftHyphenIgnored = false; @@ -1862,28 +1876,15 @@ protected override void GenerateTextMesh() SaveWordWrappingState(ref m_SavedLineState, -1, -1); SaveWordWrappingState(ref m_SavedEllipsisState, -1, -1); SaveWordWrappingState(ref m_SavedLastValidState, -1, -1); - SaveWordWrappingState(ref m_SavedSoftLineBreakState, -1, -1); - - m_EllipsisInsertionCandidateStack.Clear(); - - // Safety Tracker - int restoreCount = 0; #if TMP_PROFILE_ON Profiler.BeginSample("TMP GenerateText() - Phase I"); #endif // Parse through Character buffer to read HTML tags and begin creating mesh. - for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++) + for (int i = 0; i < m_TextParsingBuffer.Length && m_TextParsingBuffer[i].unicode != 0; i++) { - charCode = m_InternalParsingBuffer[i].unicode; - - if (restoreCount > 5) - { - Debug.LogError("Line breaking recursion max threshold hit... Character [" + charCode + "] index: " + i); - characterToSubstitute.index = m_characterCount; - characterToSubstitute.unicode = 0x03; - } + charCode = m_TextParsingBuffer[i].unicode; // Parse Rich Text Tag #region Parse Rich Text Tag @@ -1898,7 +1899,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_InternalParsingBuffer, i + 1, out endTagIndex)) + if (ValidateHtmlTag(m_TextParsingBuffer, i + 1, out endTagIndex)) { i = endTagIndex; @@ -1925,7 +1926,7 @@ protected override void GenerateTextMesh() } #endregion End Parse Rich Text Tag - int previousMaterialIndex = m_currentMaterialIndex; + int prev_MaterialIndex = m_currentMaterialIndex; bool isUsingAltTypeface = m_textInfo.characterInfo[m_characterCount].isUsingAlternateTypeface; m_isParsingText = false; @@ -1943,18 +1944,17 @@ protected override void GenerateTextMesh() switch (charCode) { case 0x03: - m_textInfo.characterInfo[m_characterCount].textElement = m_currentFontAsset.characterLookupTable[0x03]; - m_isTextTruncated = true; + // break; case 0x2D: - // + // break; case 0x2026: - m_textInfo.characterInfo[m_characterCount].textElement = m_Ellipsis.character; + m_textInfo.characterInfo[m_characterCount].textElement = m_cached_Ellipsis_Character; m_textInfo.characterInfo[m_characterCount].elementType = TMP_TextElementType.Character; - m_textInfo.characterInfo[m_characterCount].fontAsset = m_Ellipsis.fontAsset; - m_textInfo.characterInfo[m_characterCount].material = m_Ellipsis.material; - m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = m_Ellipsis.materialIndex; + m_textInfo.characterInfo[m_characterCount].fontAsset = m_materialReferences[0].fontAsset; + m_textInfo.characterInfo[m_characterCount].material = m_materialReferences[0].material; + m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = 0; // Indicates the source parsing data has been modified. m_isTextTruncated = true; @@ -2020,8 +2020,8 @@ protected override void GenerateTextMesh() #endif float baselineOffset = 0; float spriteScale = 1; - float elementAscentLine = 0; - float elementDescentLine = 0; + float spriteAscentLine = 0; + float spriteDescentLine = 0; if (m_textElementType == TMP_TextElementType.Sprite) { // If a sprite is used as a fallback then get a reference to it and set the color to white. @@ -2040,19 +2040,19 @@ protected override void GenerateTextMesh() // The sprite scale calculations are based on the font asset assigned to the text object. if (m_currentSpriteAsset.m_FaceInfo.pointSize > 0) { - spriteScale = m_currentFontSize / m_currentSpriteAsset.m_FaceInfo.pointSize * m_currentSpriteAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + spriteScale = (m_currentFontSize / m_currentSpriteAsset.m_FaceInfo.pointSize * m_currentSpriteAsset.m_FaceInfo.scale); currentElementScale = sprite.m_Scale * sprite.m_Glyph.scale * spriteScale; - elementAscentLine = m_currentSpriteAsset.m_FaceInfo.ascentLine; + spriteAscentLine = m_currentSpriteAsset.m_FaceInfo.ascentLine; baselineOffset = m_currentSpriteAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentSpriteAsset.m_FaceInfo.scale; - elementDescentLine = m_currentSpriteAsset.m_FaceInfo.descentLine; + spriteDescentLine = m_currentSpriteAsset.m_FaceInfo.descentLine; } else { - spriteScale = m_currentFontSize / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + spriteScale = (m_currentFontSize / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale); currentElementScale = m_currentFontAsset.m_FaceInfo.ascentLine / sprite.m_Glyph.metrics.height * sprite.m_Scale * sprite.m_Glyph.scale * spriteScale; - elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; + spriteAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; - elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; + spriteDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; } m_cached_TextElement = sprite; @@ -2063,31 +2063,31 @@ protected override void GenerateTextMesh() m_textInfo.characterInfo[m_characterCount].fontAsset = m_currentFontAsset; m_textInfo.characterInfo[m_characterCount].materialReferenceIndex = m_currentMaterialIndex; - m_currentMaterialIndex = previousMaterialIndex; + m_currentMaterialIndex = prev_MaterialIndex; padding = 0; } else if (m_textElementType == TMP_TextElementType.Character) { - m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement; + if (isInjectingCharacter) + m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].fontAsset.characterLookupTable[(uint)charCode]; + else + m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement; + if (m_cached_TextElement == null) continue; m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset; m_currentMaterial = m_textInfo.characterInfo[m_characterCount].material; m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex; - // Special handling if replaced character was a line feed where in this case we have to use the scale of the previous character. - float adjustedScale; - if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) - adjustedScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + // Re-calculate font scale as the font asset may have changed. + if (isInjectingCharacter && m_TextParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine) + m_fontScale = m_textInfo.characterInfo[m_characterCount - 1].scale; else - adjustedScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine; - elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine; - - currentElementScale = adjustedScale * m_fontScaleMultiplier * m_cached_TextElement.m_Scale * m_cached_TextElement.m_Glyph.scale; - baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * adjustedScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; + currentElementScale = m_fontScale * m_fontScaleMultiplier * m_cached_TextElement.m_Scale * m_cached_TextElement.m_Glyph.scale; + baselineOffset = m_currentFontAsset.m_FaceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.m_FaceInfo.scale; m_textInfo.characterInfo[m_characterCount].elementType = TMP_TextElementType.Character; m_textInfo.characterInfo[m_characterCount].scale = currentElementScale; @@ -2102,7 +2102,7 @@ protected override void GenerateTextMesh() // Handle Soft Hyphen #region Handle Soft Hyphen - float currentElementUnmodifiedScale = currentElementScale; + float unModifiedScale = currentElementScale; if (charCode == 0xAD || charCode == 0x03) currentElementScale = 0; #endregion @@ -2122,7 +2122,6 @@ protected override void GenerateTextMesh() // Optimization to avoid calling this more than once per character. bool isWhiteSpace = char.IsWhiteSpace((char)charCode); - //bool isVisibleCharacter = !isWhiteSpace; // Handle Kerning if Enabled. #region Handle Kerning @@ -2312,73 +2311,59 @@ protected override void GenerateTextMesh() m_textInfo.characterInfo[m_characterCount].aspectRatio = (top_right.x - bottom_left.x) / (top_left.y - bottom_left.y); - // Compute text metrics + // Compute and save text element Ascender and maximum line Ascender. #region Compute Ascender & Descender values #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Compute Text Metrics"); #endif - // Element Ascender in line space + float elementAscender = m_textElementType == TMP_TextElementType.Character - ? elementAscentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementAscentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.m_FaceInfo.ascentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteAscentLine * spriteScale + m_baselineOffset; - // Element Descender in line space + m_textInfo.characterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; + + // Compute and save text element Descender and maximum line Descender. float elementDescender = m_textElementType == TMP_TextElementType.Character - ? elementDescentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset - : elementDescentLine * spriteScale + m_baselineOffset; + ? m_currentFontAsset.m_FaceInfo.descentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset + : spriteDescentLine * spriteScale + m_baselineOffset; - float adjustedAscender = elementAscender; - float adjustedDescender = elementDescender; + float elementDescenderII = m_textInfo.characterInfo[m_characterCount].descender = elementDescender - m_lineOffset; - bool isFirstCharacterOfLine = m_characterCount == m_firstCharacterOfLine; - // Max line ascender and descender in line space - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode != 0x0A || m_characterCount == m_firstCharacterOfLine) { - // Special handling for Superscript and Subscript where we use the unadjusted line ascender and descender - if (m_baselineOffset != 0) - { - adjustedAscender = Mathf.Max((elementAscender - m_baselineOffset) / m_fontScaleMultiplier, adjustedAscender); - adjustedDescender = Mathf.Min((elementDescender - m_baselineOffset) / m_fontScaleMultiplier, adjustedDescender); - } - - m_maxLineAscender = Mathf.Max(adjustedAscender, m_maxLineAscender); - m_maxLineDescender = Mathf.Min(adjustedDescender, m_maxLineDescender); + m_maxLineAscender = elementAscender > m_maxLineAscender ? elementAscender : m_maxLineAscender; + m_maxLineDescender = elementDescender < m_maxLineDescender ? elementDescender : m_maxLineDescender; } - // Element Ascender and Descender in object space - if (isFirstCharacterOfLine || isWhiteSpace == false) + // Adjust maxLineAscender and maxLineDescender if style is superscript or subscript + if ((m_FontStyleInternal & FontStyles.Subscript) == FontStyles.Subscript || (m_FontStyleInternal & FontStyles.Superscript) == FontStyles.Superscript) { - m_textInfo.characterInfo[m_characterCount].adjustedAscender = adjustedAscender; - m_textInfo.characterInfo[m_characterCount].adjustedDescender = adjustedDescender; + float baseAscender = (elementAscender - m_baselineOffset) / m_currentFontAsset.m_FaceInfo.subscriptSize; + elementAscender = m_maxLineAscender; + m_maxLineAscender = baseAscender > m_maxLineAscender ? baseAscender : m_maxLineAscender; - m_ElementAscender = m_textInfo.characterInfo[m_characterCount].ascender = elementAscender - m_lineOffset; - m_ElementDescender = m_textInfo.characterInfo[m_characterCount].descender = elementDescender - m_lineOffset; - } - else - { - m_textInfo.characterInfo[m_characterCount].adjustedAscender = m_maxLineAscender; - m_textInfo.characterInfo[m_characterCount].adjustedDescender = m_maxLineDescender; - - m_ElementAscender = m_textInfo.characterInfo[m_characterCount].ascender = m_maxLineAscender - m_lineOffset; - m_ElementDescender = m_textInfo.characterInfo[m_characterCount].descender = m_maxLineDescender - m_lineOffset; + float baseDescender = (elementDescender - m_baselineOffset) / m_currentFontAsset.m_FaceInfo.subscriptSize; + elementDescender = m_maxLineDescender; + m_maxLineDescender = baseDescender < m_maxLineDescender ? baseDescender : m_maxLineDescender; } - // Max text object ascender and cap height if (m_lineNumber == 0 || m_isNewPage) { - if (isFirstCharacterOfLine || isWhiteSpace == false) + if (charCode == 0x0A && m_characterCount != m_firstCharacterOfLine) { - m_maxTextAscender = m_maxLineAscender; + // Skip Line Feed that are not at the start of a line. + } + else + { + m_maxAscender = m_maxAscender > elementAscender ? m_maxAscender : elementAscender; m_maxCapHeight = Mathf.Max(m_maxCapHeight, m_currentFontAsset.m_FaceInfo.capLine * currentElementScale / smallCapsMultiplier); } } - // Page ascender if (m_lineOffset == 0) - { - if (isFirstCharacterOfLine || isWhiteSpace == false) - m_PageAscender = m_PageAscender > elementAscender ? m_PageAscender : elementAscender; - } + pageAscender = pageAscender > elementAscender ? pageAscender : elementAscender; + #if TMP_PROFILE_ON Profiler.EndSample(); #endif @@ -2392,7 +2377,7 @@ protected override void GenerateTextMesh() // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN. #region Handle Visible Characters - if (charCode == 9 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) + if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Handle Visible Character"); @@ -2448,8 +2433,8 @@ protected override void GenerateTextMesh() widthOfTextArea = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - marginLeft - marginRight, m_width) : marginWidth + 0.0001f - marginLeft - marginRight; // Calculate the line breaking width of the text. - float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? currentGlyphMetrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * (charCode == 0xAD ? currentElementUnmodifiedScale : currentElementScale); - float textHeight = m_maxTextAscender - (m_maxLineDescender - m_lineOffset) + (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0); + float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? currentGlyphMetrics.horizontalAdvance : 0) * (1 - m_charWidthAdjDelta) * (charCode != 0xAD ? currentElementScale : unModifiedScale); + float textHeight = (m_maxAscender - elementDescenderII) + ((m_lineNumber > 0 && isDrivenLineSpacing == false) ? m_maxLineAscender - m_startOfLineAscender : 0); int testedCharacterCount = m_characterCount; @@ -2466,7 +2451,7 @@ protected override void GenerateTextMesh() { // Handle Line spacing adjustments #region Line Spacing Adjustments - if (m_lineSpacingDelta > m_lineSpacingMax && m_lineOffset > 0 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) + if (m_lineSpacingDelta > m_lineSpacingMax && m_lineNumber > 0 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount) { float adjustmentDelta = (marginHeight - textHeight) / m_lineNumber; @@ -2511,25 +2496,21 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0 || testedCharacterCount == 0) { i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -2559,30 +2540,15 @@ protected override void GenerateTextMesh() characterToSubstitute.unicode = 0x03; continue; } - else if (m_maxLineAscender - m_maxLineDescender > marginHeight + 0.0001f) - { - // Current line exceeds the height of the text container - // as such we stop on the previous line. - i = RestoreWordWrappingState(ref m_SavedLineState); - - characterToSubstitute.index = testedCharacterCount; - characterToSubstitute.unicode = 0x03; - continue; - } - // Go back to previous line and re-layout + // Go back to previous line and re-layout i = RestoreWordWrappingState(ref m_SavedLineState); m_isNewPage = true; - m_firstCharacterOfLine = m_characterCount; - m_maxLineAscender = k_LargeNegativeFloat; - m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = 0; - m_xAdvance = 0 + tag_Indent; m_lineOffset = 0; - m_maxTextAscender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + pageAscender = 0; m_lineNumber += 1; m_pageNumber += 1; @@ -2611,17 +2577,17 @@ protected override void GenerateTextMesh() float lineOffsetDelta = 0; if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float ascender = m_textInfo.characterInfo[m_characterCount].adjustedAscender; - lineOffsetDelta = (m_lineOffset > 0 && m_IsDrivenLineSpacing == false ? m_maxLineAscender - m_startOfLineAscender : 0) - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; + float ascender = m_textInfo.characterInfo[m_characterCount].ascender - m_textInfo.characterInfo[m_characterCount].baseLine; + lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale; } else { lineOffsetDelta = m_lineHeight + m_lineSpacing * currentEmScale; - m_IsDrivenLineSpacing = true; + isDrivenLineSpacing = true; } // Calculate new text height - float newTextHeight = m_maxTextAscender + lineOffsetDelta + m_lineOffset - m_textInfo.characterInfo[m_characterCount].adjustedDescender; + float newTextHeight = m_maxAscender - m_textInfo.characterInfo[m_characterCount].descender + lineOffsetDelta; // Replace Soft Hyphen by Hyphen Minus 0x2D #region Handle Soft Hyphenation @@ -2687,29 +2653,6 @@ protected override void GenerateTextMesh() #endregion Text Auto-Sizing } - - // Special handling if first word of line and non breaking space - int savedSoftLineBreakingSpace = m_SavedSoftLineBreakState.previous_WordBreak; - if (isFirstWordOfLine && savedSoftLineBreakingSpace != -1) - { - if (savedSoftLineBreakingSpace != lastSoftLineBreak) - { - i = RestoreWordWrappingState(ref m_SavedSoftLineBreakState); - lastSoftLineBreak = savedSoftLineBreakingSpace; - - // check if soft hyphen - if (m_textInfo.characterInfo[m_characterCount - 1].character == 0xAD) - { - characterToSubstitute.index = m_characterCount - 1; - characterToSubstitute.unicode = 0x2D; - - i -= 1; - m_characterCount -= 1; - continue; - } - } - } - // Determine if new line of text would exceed the vertical bounds of text container if (newTextHeight > marginHeight + 0.0001f) { @@ -2803,25 +2746,20 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0) { - i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -2845,10 +2783,9 @@ protected override void GenerateTextMesh() InsertNewLine(i, baseScale, currentEmScale, characterSpacingAdjustment, widthOfTextArea, lineGap, ref isMaxVisibleDescenderSet, ref maxVisibleDescender); - m_startOfLineAscender = 0; m_lineOffset = 0; - m_maxTextAscender = 0; - m_PageAscender = 0; + m_maxAscender = 0; + pageAscender = 0; m_pageNumber += 1; isStartOfNewLine = true; @@ -2965,25 +2902,20 @@ protected override void GenerateTextMesh() continue; case TextOverflowModes.Ellipsis: - if (m_EllipsisInsertionCandidateStack.Count == 0) + i = RestoreWordWrappingState(ref m_SavedEllipsisState); + + if (i < 0) { - i = -1; m_characterCount = 0; characterToSubstitute.index = 0; characterToSubstitute.unicode = 0x03; - m_firstCharacterOfLine = 0; continue; } - var ellipsisState = m_EllipsisInsertionCandidateStack.Pop(); - i = RestoreWordWrappingState(ref ellipsisState); - i -= 1; m_characterCount -= 1; characterToSubstitute.index = m_characterCount; characterToSubstitute.unicode = 0x2026; - - restoreCount += 1; continue; case TextOverflowModes.Linked: @@ -3015,12 +2947,15 @@ protected override void GenerateTextMesh() // Special handling of characters that are not ignored at the end of a line. - if (charCode == 9) + if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007) { m_textInfo.characterInfo[m_characterCount].isVisible = false; m_lastVisibleCharacterOfLine = m_characterCount; m_textInfo.lineInfo[m_lineNumber].spaceCount += 1; m_textInfo.spaceCount += 1; + + if (charCode == 0xA0) + m_textInfo.lineInfo[m_lineNumber].controlCharacterCount += 1; } else if (charCode == 0xAD) { @@ -3075,15 +3010,12 @@ protected override void GenerateTextMesh() // This is white spacing / non visible characters. // Track # of spaces per line which is used for line justification. - if ((charCode == 10 || charCode == 11 || charCode == 0xA0 || charCode == 0x2007 || charCode == 0x2028 || charCode == 0x2029 || char.IsSeparator((char)charCode)) && charCode != 0xAD && charCode != 0x200B && charCode != 0x2060) + if ((charCode == 10 || charCode == 11 || char.IsSeparator((char)charCode)) && charCode != 0xAD && charCode != 0x200B && charCode != 0x2060) { m_textInfo.lineInfo[m_lineNumber].spaceCount += 1; m_textInfo.spaceCount += 1; } - if (charCode == 0xA0) - m_textInfo.lineInfo[m_lineNumber].controlCharacterCount += 1; - #if TMP_PROFILE_ON Profiler.EndSample(); #endif @@ -3091,33 +3023,55 @@ protected override void GenerateTextMesh() #endregion Handle Visible Characters + // Check if Line Spacing of previous line needs to be adjusted. + #region Adjust Line Spacing + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && /* m_lineHeight == TMP_Math.FLOAT_UNSET && */ isDrivenLineSpacing == false && !m_isNewPage && isInjectingCharacter == false) + { + #if TMP_PROFILE_ON + Profiler.BeginSample("TMP - Handle Line Spacing Adjustments"); + #endif + + float offsetDelta = m_maxLineAscender - m_startOfLineAscender; + AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); + elementDescenderII -= offsetDelta; + m_lineOffset += offsetDelta; + + m_startOfLineAscender += offsetDelta; + m_SavedWordWrapState.lineOffset = m_lineOffset; + m_SavedWordWrapState.previousLineAscender = m_startOfLineAscender; + + #if TMP_PROFILE_ON + Profiler.EndSample(); + #endif + } + #endregion + + // Tracking of potential insertion positions for Ellipsis character #region Track Potential Insertion Location for Ellipsis - if (m_overflowMode == TextOverflowModes.Ellipsis && (isInjectingCharacter == false || charCode == 0x2D)) + if (m_overflowMode == TextOverflowModes.Ellipsis && isInjectingCharacter == false) { - float fontScale = m_currentFontSize / m_Ellipsis.fontAsset.m_FaceInfo.pointSize * m_Ellipsis.fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - float scale = fontScale * m_fontScaleMultiplier * m_Ellipsis.character.m_Scale * m_Ellipsis.character.m_Glyph.scale; + float fontScale = m_currentFontSize * smallCapsMultiplier / m_fontAsset.m_FaceInfo.pointSize * m_fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); + float scale = fontScale * m_fontScaleMultiplier * m_cached_Ellipsis_Character.m_Scale * m_cached_Ellipsis_Character.m_Glyph.scale; float marginLeft = m_marginLeft; float marginRight = m_marginRight; // Use the scale and margins of the previous character if Line Feed (LF) is not the first character of a line. if (charCode == 0x0A && m_characterCount != m_firstCharacterOfLine) { - fontScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize / m_Ellipsis.fontAsset.m_FaceInfo.pointSize * m_Ellipsis.fontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f); - scale = fontScale * m_fontScaleMultiplier * m_Ellipsis.character.m_Scale * m_Ellipsis.character.m_Glyph.scale; + scale = m_textInfo.characterInfo[m_characterCount - 1].scale; marginLeft = m_textInfo.lineInfo[m_lineNumber].marginLeft; marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight; } - float textHeight = m_maxTextAscender - (m_maxLineDescender - m_lineOffset) + (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 descender = m_fontAsset.m_FaceInfo.descentLine * scale / smallCapsMultiplier + m_baselineOffset; + float textHeight = m_maxAscender - (descender - m_lineOffset); + + float textWidth = Mathf.Abs(m_xAdvance) + (!m_isRightToLeft ? m_cached_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; if (textWidth < widthOfTextAreaForEllipsis * (isJustifiedOrFlush ? 1.05f : 1.0f) && textHeight < marginHeight + 0.0001f) - { SaveWordWrappingState(ref m_SavedEllipsisState, i, m_characterCount); - m_EllipsisInsertionCandidateStack.Push(m_SavedEllipsisState); - } } #endregion @@ -3192,29 +3146,20 @@ protected override void GenerateTextMesh() // Handle Line Spacing Adjustments + Word Wrapping & special case for last line. #region Check for Line Feed and Last Character - if (charCode == 10 || charCode == 11 || charCode == 0x03 || charCode == 0x2028 || charCode == 0x2029 || (charCode == 0x2D && isInjectingCharacter) || m_characterCount == totalCharacterCount - 1) + if (charCode == 10 || charCode == 11 || charCode == 0x03 || (charCode == 0x2D && isInjectingCharacter) || m_characterCount == totalCharacterCount - 1) { #if TMP_PROFILE_ON Profiler.BeginSample("TMP - Handle Line & Text Termination"); #endif - // Adjust current line spacing (if necessary) before inserting new line - float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender; - if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage) + // Check if Line Spacing of previous line needs to be adjusted. + if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && isDrivenLineSpacing == false /* && m_lineHeight == TMP_Math.FLOAT_UNSET */ && !m_isNewPage && isInjectingCharacter == false) { //Debug.Log("Line Feed - Adjusting Line Spacing on line #" + m_lineNumber); - AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta); - m_ElementDescender -= baselineAdjustmentDelta; - m_lineOffset += baselineAdjustmentDelta; - - // Adjust saved ellipsis state only if we are adjusting the same line number - if (m_SavedEllipsisState.lineNumber == m_lineNumber) - { - m_SavedEllipsisState = m_EllipsisInsertionCandidateStack.Pop(); - m_SavedEllipsisState.startOfLineAscender += baselineAdjustmentDelta; - m_SavedEllipsisState.lineOffset += baselineAdjustmentDelta; - m_EllipsisInsertionCandidateStack.Push(m_SavedEllipsisState); - } + float offsetDelta = m_maxLineAscender - m_startOfLineAscender; + AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta); + elementDescenderII -= offsetDelta; + m_lineOffset += offsetDelta; } m_isNewPage = false; @@ -3223,9 +3168,9 @@ protected override void GenerateTextMesh() float lineDescender = m_maxLineDescender - m_lineOffset; // Update maxDescender and maxVisibleDescender - m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender; + m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender; if (!isMaxVisibleDescenderSet) - maxVisibleDescender = m_ElementDescender; + maxVisibleDescender = m_maxDescender; if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)) isMaxVisibleDescenderSet = true; @@ -3257,7 +3202,7 @@ protected override void GenerateTextMesh() m_textInfo.lineInfo[m_lineNumber].lineHeight = lineAscender - lineDescender + lineGap * baseScale; // Add new line if not last line or character. - if (charCode == 10 || charCode == 11 || charCode == 0x2D || charCode == 0x2028 || charCode == 0x2029) + if (charCode == 10 || charCode == 11 || charCode == 0x2D) { // Store the state of the line before starting on the new line. SaveWordWrappingState(ref m_SavedLineState, i, m_characterCount); @@ -3274,27 +3219,29 @@ protected override void GenerateTextMesh() if (m_lineNumber >= m_textInfo.lineInfo.Length) ResizeLineExtents(m_lineNumber); - float lastVisibleAscender = m_textInfo.characterInfo[m_characterCount].adjustedAscender; + float lastVisibleAscender = m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].ascender + m_lineOffset; // Apply Line Spacing with special handling for VT char(11) if (m_lineHeight == TMP_Math.FLOAT_UNSET) { - float lineOffsetDelta = 0 - m_maxLineDescender + lastVisibleAscender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; + float lineOffsetDelta = 0 - m_maxLineDescender + lastVisibleAscender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; m_lineOffset += lineOffsetDelta; - m_IsDrivenLineSpacing = false; + isDrivenLineSpacing = false; } else { - m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale; - m_IsDrivenLineSpacing = true; + m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 ? m_paragraphSpacing : 0)) * currentEmScale; + isDrivenLineSpacing = true; } m_maxLineAscender = k_LargeNegativeFloat; m_maxLineDescender = k_LargePositiveFloat; - m_startOfLineAscender = lastVisibleAscender; + m_startOfLineAscender = lastVisibleAscender; // elementAscender; m_xAdvance = 0 + tag_LineIndent + tag_Indent; + //ellipsisIndex = m_characterCount - 1; + SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); SaveWordWrappingState(ref m_SavedLastValidState, i, m_characterCount); @@ -3309,7 +3256,7 @@ protected override void GenerateTextMesh() // If End of Text if (charCode == 0x03) - i = m_InternalParsingBuffer.Length; + i = m_TextParsingBuffer.Length; #if TMP_PROFILE_ON Profiler.EndSample(); @@ -3338,15 +3285,15 @@ protected override void GenerateTextMesh() // Save pageInfo Data - if (m_overflowMode == TextOverflowModes.Page && charCode != 10 && charCode != 11 && charCode != 13 && charCode != 0x2028 && charCode != 0x2029) // && m_pageNumber < 16) + if (m_overflowMode == TextOverflowModes.Page && charCode != 10 && charCode != 11 && charCode != 13) // && m_pageNumber < 16) { // Check if we need to increase allocations for the pageInfo array. if (m_pageNumber + 1 > m_textInfo.pageInfo.Length) TMP_TextInfo.Resize(ref m_textInfo.pageInfo, m_pageNumber + 1, true); - m_textInfo.pageInfo[m_pageNumber].ascender = m_PageAscender; - m_textInfo.pageInfo[m_pageNumber].descender = m_ElementDescender < m_textInfo.pageInfo[m_pageNumber].descender - ? m_ElementDescender + m_textInfo.pageInfo[m_pageNumber].ascender = pageAscender; + m_textInfo.pageInfo[m_pageNumber].descender = elementDescenderII < m_textInfo.pageInfo[m_pageNumber].descender + ? elementDescenderII : m_textInfo.pageInfo[m_pageNumber].descender; if (m_pageNumber == 0 && m_characterCount == 0) @@ -3375,69 +3322,53 @@ protected override void GenerateTextMesh() if ((isWhiteSpace || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && (!m_isNonBreakingSpace || ignoreNonBreakingSpace) && charCode != 0xA0 && charCode != 0x2007 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060) { - // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored + // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored // for Word Wrapping. SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); isFirstWordOfLine = false; - //isLastCharacterCJK = false; - - // Reset soft line breaking point since we now have a valid hard break point. - m_SavedSoftLineBreakState.previous_WordBreak = -1; + isLastCharacterCJK = false; } // Handling for East Asian characters - else if (m_isNonBreakingSpace == false && - ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ - charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */ - charCode > 0xAC00 && charCode < 0xD7FF)&& /* Hangul Syllables */ - TMP_Settings.useModernHangulLineBreakingRules == false || - - (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ - charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ - charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ - charCode > 0xFF00 && charCode < 0xFFEF))) /* CJK Halfwidth */ + else if (!m_isNonBreakingSpace && + (charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */ + charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */ + charCode > 0xAC00 && charCode < 0xD7FF) /* Hangul Syllables */ && + !TMP_Settings.useModernHangulLineBreakingRules || + (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */ + charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */ + charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */ + charCode > 0xFF00 && charCode < 0xFFEF)) /* CJK Halfwidth */ { - bool isCurrentLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); - bool isNextFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_textInfo.characterInfo[m_characterCount + 1].character); + bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); + bool isFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_textInfo.characterInfo[m_characterCount + 1].character); - if (isCurrentLeadingCharacter == false) + if (isFirstWordOfLine || isLeadingCharacter == false) { - if (isNextFollowingCharacter == false) + if (isFollowingCharacter == false) { SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); isFirstWordOfLine = false; } if (isFirstWordOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - } } - else - { - if (isFirstWordOfLine && isFirstCharacterOfLine) - { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - } - } + isLastCharacterCJK = true; + } + else if (isLastCharacterCJK) + { + bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode); + + if (isLeadingCharacter == false) + SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - //isLastCharacterCJK = true; + isLastCharacterCJK = false; } else if (isFirstWordOfLine) { - // Special handling for non-breaking space and soft line breaks - if (isWhiteSpace || (charCode == 0xAD && isSoftHyphenIgnored == false)) - SaveWordWrappingState(ref m_SavedSoftLineBreakState, i, m_characterCount); - SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount); - //isLastCharacterCJK = false; + isLastCharacterCJK = false; } #if TMP_PROFILE_ON @@ -3472,12 +3403,13 @@ protected override void GenerateTextMesh() #endregion End Auto-sizing Check m_IsAutoSizePointSizeSet = true; + //m_isCharacterWrappingEnabled = false; if (m_AutoSizeIterationCount >= m_AutoSizeMaxIterationCount) Debug.Log("Auto Size Iteration Count: " + m_AutoSizeIterationCount + ". Final Point Size: " + m_fontSize); - // If there are no visible characters or only character is End of Text (0x03)... no need to continue - if (m_characterCount == 0 || (m_characterCount == 1 && charCode == 0x03)) + // If there are no visible characters... no need to continue + if (m_characterCount == 0) // && m_visibleSpriteCount == 0) { ClearMesh(); @@ -3494,7 +3426,7 @@ protected override void GenerateTextMesh() #endif // *** PHASE II of Text Generation *** - int last_vert_index = m_materialReferences[m_Underline.materialIndex].referenceCount * 4; + int last_vert_index = m_materialReferences[0].referenceCount * 4; // Partial clear of the vertices array to mark unused vertices as degenerate. m_textInfo.meshInfo[0].Clear(false); @@ -3510,7 +3442,7 @@ protected override void GenerateTextMesh() // Top Vertically case VerticalAlignmentOptions.Top: if (m_overflowMode != TextOverflowModes.Page) - anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_maxTextAscender - margins.y, 0); + anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_maxAscender - margins.y, 0); else anchorOffset = corners[1] + new Vector3(0 + margins.x, 0 - m_textInfo.pageInfo[pageToDisplay].ascender - margins.y, 0); break; @@ -3518,7 +3450,7 @@ protected override void GenerateTextMesh() // Middle Vertically case VerticalAlignmentOptions.Middle: if (m_overflowMode != TextOverflowModes.Page) - anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxTextAscender + margins.y + maxVisibleDescender - margins.w) / 2, 0); + anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxAscender + margins.y + maxVisibleDescender - margins.w) / 2, 0); else anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_textInfo.pageInfo[pageToDisplay].ascender + margins.y + m_textInfo.pageInfo[pageToDisplay].descender - margins.w) / 2, 0); break; @@ -3536,12 +3468,12 @@ protected override void GenerateTextMesh() anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0, 0); break; - // Midline Vertically + // Midline Vertically case VerticalAlignmentOptions.Geometry: anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_meshExtents.max.y + margins.y + m_meshExtents.min.y - margins.w) / 2, 0); break; - // Capline Vertically + // Capline Vertically case VerticalAlignmentOptions.Capline: anchorOffset = (corners[0] + corners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxCapHeight - margins.y - margins.w) / 2, 0); break; @@ -3864,7 +3796,7 @@ protected override void GenerateTextMesh() characterInfos[i].vertex_BR.uv2.x = PackUV(x1, y0); characterInfos[i].vertex_BR.uv2.y = xScale; #endregion break; - + // SPRITES case TMP_TextElementType.Sprite: // Nothing right now @@ -4342,9 +4274,6 @@ protected override void GenerateTextMesh() m_textInfo.wordCount = wordCount != 0 && m_characterCount > 0 ? wordCount : 1; m_textInfo.pageCount = m_pageNumber + 1; - // Set vertex count for Underline geometry - //m_textInfo.meshInfo[m_Underline.materialIndex].vertexCount = last_vert_index; - #if TMP_PROFILE_ON // End Sampling of Phase II Profiler.EndSample(); @@ -4375,7 +4304,7 @@ protected override void GenerateTextMesh() //m_mesh.uv4 = m_textInfo.meshInfo[0].uvs4; m_mesh.colors32 = m_textInfo.meshInfo[0].colors32; - // Compute Bounds for the mesh. Manual computation is more efficient then using Mesh.RecalcualteBounds. + // Compute Bounds for the mesh. Manual computation is more efficient then using Mesh.recalcualteBounds. m_mesh.RecalculateBounds(); //m_mesh.bounds = new Bounds(new Vector3((m_meshExtents.max.x + m_meshExtents.min.x) / 2, (m_meshExtents.max.y + m_meshExtents.min.y) / 2, 0) + offset, new Vector3(m_meshExtents.max.x - m_meshExtents.min.x, m_meshExtents.max.y - m_meshExtents.min.y, 0)); @@ -4459,16 +4388,6 @@ protected override void SetActiveSubMeshes(bool state) } - /// - /// Destroy Sub Mesh Objects - /// - protected override void DestroySubMeshObjects() - { - for (int i = 1; i < m_subTextObjects.Length && m_subTextObjects[i] != null; i++) - DestroyImmediate(m_subTextObjects[i]); - } - - /// /// Method returning the compound bounds of the text object and child sub objects. /// @@ -4494,16 +4413,6 @@ protected override Bounds GetCompoundBounds() return new Bounds(center, size); } - internal override Rect GetCanvasSpaceClippingRect() - { - Transform rootCanvasTransform = m_canvas.rootCanvas.transform; - Bounds compoundBounds = GetCompoundBounds(); - - Vector3 position = rootCanvasTransform.InverseTransformPoint(m_rectTransform.position); - - return new Rect(position + compoundBounds.min, compoundBounds.size); - } - //public override void UpdateGeometry() //{ @@ -4614,4 +4523,4 @@ void UpdateSDFScale(float scaleDelta) } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/TextMeshPro.cs b/Scripts/Runtime/TextMeshPro.cs index 47dc537..5a7eaf9 100644 --- a/Scripts/Runtime/TextMeshPro.cs +++ b/Scripts/Runtime/TextMeshPro.cs @@ -9,9 +9,9 @@ namespace TMPro [DisallowMultipleComponent] [RequireComponent(typeof(MeshRenderer))] + [RequireComponent(typeof(MeshFilter))] [AddComponentMenu("Mesh/TextMeshPro - Text")] [ExecuteAlways] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.textmeshpro@2.1")] public partial class TextMeshPro : TMP_Text, ILayoutElement { // Public Properties and Serializable Properties @@ -21,48 +21,18 @@ public partial class TextMeshPro : TMP_Text, ILayoutElement /// public int sortingLayerID { - get - { - if (renderer == null) - return 0; - - return m_renderer.sortingLayerID; - } - set - { - if (renderer == null) - return; - - m_renderer.sortingLayerID = value; - _SortingLayerID = value; - } + get { return m_renderer.sortingLayerID; } + set { m_renderer.sortingLayerID = value; } } - [SerializeField] - internal int _SortingLayerID; /// /// Sets the Renderer's sorting order within the assigned layer. /// public int sortingOrder { - get - { - if (renderer == null) - return 0; - - return m_renderer.sortingOrder; - } - set - { - if (renderer == null) - return; - - m_renderer.sortingOrder = value; - _SortingOrder = value; - } + get { return m_renderer.sortingOrder; } + set { m_renderer.sortingOrder = value; } } - [SerializeField] - internal int _SortingOrder; /// /// Determines if the size of the text container will be adjusted to fit the text object when it is first created. @@ -97,7 +67,7 @@ public TextContainer textContainer { if (m_transform == null) m_transform = GetComponent(); - + return m_transform; } } @@ -130,6 +100,7 @@ public override Mesh mesh { m_mesh = new Mesh(); m_mesh.hideFlags = HideFlags.HideAndDontSave; + this.meshFilter.mesh = m_mesh; } return m_mesh; @@ -144,23 +115,15 @@ public MeshFilter meshFilter get { if (m_meshFilter == null) - { m_meshFilter = GetComponent(); - if (m_meshFilter == null) - { - m_meshFilter = gameObject.AddComponent(); - m_meshFilter.hideFlags = HideFlags.HideInInspector | HideFlags.HideAndDontSave; - } - } - return m_meshFilter; } } // MASKING RELATED PROPERTIES /// - /// Sets the mask type + /// Sets the mask type /// public MaskingTypes maskType { @@ -201,28 +164,28 @@ public void SetMask(MaskingTypes type, Vector4 maskCoords, float softnessX, floa /// public override void SetVerticesDirty() { - //Debug.Log("***** SetVerticesDirty() called on object [" + this.name + "] at frame [" + Time.frameCount + "] *****"); - - if (this == null || !this.IsActive()) + if (m_verticesAlreadyDirty || this == null || !this.IsActive()) return; + //Debug.Log("***** SetVerticesDirty() called on object ID " + GetInstanceID() + ". ***** Dirty = " + m_verticesAlreadyDirty); + TMP_UpdateManager.RegisterTextElementForGraphicRebuild(this); + m_verticesAlreadyDirty = true; } /// - /// + /// /// public override void SetLayoutDirty() { m_isPreferredWidthDirty = true; m_isPreferredHeightDirty = true; - if (this == null || !this.IsActive()) + if (m_layoutAlreadyDirty || this == null || !this.IsActive()) return; - LayoutRebuilder.MarkLayoutForRebuild(this.rectTransform); - + m_layoutAlreadyDirty = true; m_isLayoutDirty = true; } @@ -244,7 +207,7 @@ public override void SetMaterialDirty() /// - /// + /// /// public override void SetAllDirty() { @@ -257,7 +220,7 @@ public override void SetAllDirty() /// - /// + /// /// /// public override void Rebuild(CanvasUpdate update) @@ -274,6 +237,8 @@ public override void Rebuild(CanvasUpdate update) else if (update == CanvasUpdate.PreRender) { this.OnPreRenderObject(); + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; if (!m_isMaterialDirty) return; @@ -284,7 +249,7 @@ public override void Rebuild(CanvasUpdate update) /// - /// + /// /// protected override void UpdateMaterial() { @@ -293,11 +258,13 @@ protected override void UpdateMaterial() //if (!this.IsActive()) // return; - if (renderer == null || m_sharedMaterial == null) + if (m_sharedMaterial == null) return; + if (m_renderer == null) m_renderer = this.renderer; + // Only update the material if it has changed. - if (m_renderer.sharedMaterial == null || m_renderer.sharedMaterial.GetInstanceID() != m_sharedMaterial.GetInstanceID()) + if (m_renderer.sharedMaterial.GetInstanceID() != m_sharedMaterial.GetInstanceID()) m_renderer.sharedMaterial = m_sharedMaterial; } @@ -332,6 +299,9 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT m_ignoreActiveState = ignoreActiveState; m_isInputParsingRequired = m_isInputParsingRequired ? true : forceTextReparsing; OnPreRenderObject(); + + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; } @@ -342,8 +312,8 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT /// public override TMP_TextInfo GetTextInfo(string text) { - StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); - SetArraySizes(m_InternalParsingBuffer); + StringToCharArray(text, ref m_TextParsingBuffer); + SetArraySizes(m_TextParsingBuffer); m_renderMode = TextRenderFlags.DontRender; @@ -472,8 +442,102 @@ public void UpdateFontAsset() private bool m_currentAutoSizeMode; - public void CalculateLayoutInputHorizontal() { } + public void CalculateLayoutInputHorizontal() + { + //Debug.Log("*** CalculateLayoutInputHorizontal() ***"); + + if (!this.gameObject.activeInHierarchy) + return; + + //IsRectTransformDriven = true; + + m_currentAutoSizeMode = m_enableAutoSizing; + + if (m_isCalculateSizeRequired || m_rectTransform.hasChanged) + { + //Debug.Log("Calculating Layout Horizontal"); + + //m_LayoutPhase = AutoLayoutPhase.Horizontal; + //m_isRebuildingLayout = true; + + m_minWidth = 0; + m_flexibleWidth = 0; + + //m_renderMode = TextRenderFlags.GetPreferredSizes; // Set Text to not Render and exit early once we have new width values. + + if (m_enableAutoSizing) + { + m_fontSize = m_fontSizeMax; + } + + // Set Margins to Infinity + m_marginWidth = k_LargePositiveFloat; + m_marginHeight = k_LargePositiveFloat; + + if (m_isInputParsingRequired || m_isTextTruncated) + ParseInputText(); + + GenerateTextMesh(); + + m_renderMode = TextRenderFlags.Render; + + //m_preferredWidth = (int)m_preferredWidth + 1f; + + ComputeMarginSize(); + + //Debug.Log("Preferred Width: " + m_preferredWidth + " Margin Width: " + m_marginWidth + " Preferred Height: " + m_preferredHeight + " Margin Height: " + m_marginHeight + " Rendered Width: " + m_renderedWidth + " Height: " + m_renderedHeight + " RectTransform Width: " + m_rectTransform.rect); + + m_isLayoutDirty = true; + } + } + + + public void CalculateLayoutInputVertical() + { + //Debug.Log("*** CalculateLayoutInputVertical() ***"); - public void CalculateLayoutInputVertical() { } + // Check if object is active + if (!this.gameObject.activeInHierarchy) // || IsRectTransformDriven == false) + return; + + //IsRectTransformDriven = true; + + if (m_isCalculateSizeRequired || m_rectTransform.hasChanged) + { + //Debug.Log("Calculating Layout InputVertical"); + + //m_LayoutPhase = AutoLayoutPhase.Vertical; + //m_isRebuildingLayout = true; + + m_minHeight = 0; + m_flexibleHeight = 0; + + //m_renderMode = TextRenderFlags.GetPreferredSizes; + + if (m_enableAutoSizing) + { + m_currentAutoSizeMode = true; + m_enableAutoSizing = false; + } + + m_marginHeight = k_LargePositiveFloat; + + GenerateTextMesh(); + + m_enableAutoSizing = m_currentAutoSizeMode; + + m_renderMode = TextRenderFlags.Render; + + //m_preferredHeight = (int)m_preferredHeight + 1f; + + ComputeMarginSize(); + + //Debug.Log("Preferred Height: " + m_preferredHeight + " Margin Height: " + m_marginHeight + " Preferred Width: " + m_preferredWidth + " Margin Width: " + m_marginWidth + " Rendered Width: " + m_renderedWidth + " Height: " + m_renderedHeight + " RectTransform Width: " + m_rectTransform.rect); + + m_isLayoutDirty = true; + } + + m_isCalculateSizeRequired = false; + } } -} +} \ No newline at end of file diff --git a/Scripts/Runtime/TextMeshProUGUI.cs b/Scripts/Runtime/TextMeshProUGUI.cs index b06c9f3..1499e98 100644 --- a/Scripts/Runtime/TextMeshProUGUI.cs +++ b/Scripts/Runtime/TextMeshProUGUI.cs @@ -1,18 +1,23 @@ using UnityEngine; +using System; using System.Collections; +using System.Collections.Generic; + using UnityEngine.UI; +using UnityEngine.EventSystems; +using UnityEngine.UI.CoroutineTween; -#pragma warning disable 0414 // Disabled a few warnings related to serialized variables not used in this script but used in the editor. +#pragma warning disable 0414 // Disabled a few warnings related to serialized variables not used in this script but used in the editor. namespace TMPro { + [DisallowMultipleComponent] [RequireComponent(typeof(RectTransform))] [RequireComponent(typeof(CanvasRenderer))] [AddComponentMenu("UI/TextMeshPro - Text (UI)", 11)] [ExecuteAlways] - [HelpURL("https://docs.unity3d.com/Packages/com.unity.textmeshpro@2.1")] public partial class TextMeshProUGUI : TMP_Text, ILayoutElement { /// @@ -23,7 +28,6 @@ public override Material materialForRendering get { return TMP_MaterialManager.GetMaterialForRendering(this, m_sharedMaterial); } } - /// /// Determines if the size of the text container will be adjusted to fit the text object when it is first created. /// @@ -35,6 +39,7 @@ public override bool autoSizeTextContainer } + /// /// Reference to the Mesh used by the text object. /// @@ -69,15 +74,28 @@ public override Mesh mesh private bool m_isRebuildingLayout = false; - private Coroutine m_DelayedGraphicRebuild; - private Coroutine m_DelayedMaterialRebuild; + //private bool m_isLayoutDirty = false; + /// /// Function called by Unity when the horizontal layout needs to be recalculated. /// public void CalculateLayoutInputHorizontal() { - //Debug.Log("*** CalculateLayoutHorizontal() on Object ID: " + GetInstanceID() + " at frame: " + Time.frameCount + "***"); + //Debug.Log("*** CalculateLayoutHorizontal() ***"); // at Frame: " + Time.frameCount); // called on Object ID " + GetInstanceID()); + + //// Check if object is active + if (!this.gameObject.activeInHierarchy) + return; + + if (m_isCalculateSizeRequired || m_rectTransform.hasChanged) + { + m_preferredWidth = GetPreferredWidth(); + + ComputeMarginSize(); + + m_isLayoutDirty = true; + } } @@ -86,23 +104,31 @@ public void CalculateLayoutInputHorizontal() /// public void CalculateLayoutInputVertical() { - //Debug.Log("*** CalculateLayoutInputVertical() on Object ID: " + GetInstanceID() + " at frame: " + Time.frameCount + "***"); + //Debug.Log("*** CalculateLayoutInputVertical() ***"); // at Frame: " + Time.frameCount); // called on Object ID " + GetInstanceID()); + + //// Check if object is active + if (!this.gameObject.activeInHierarchy) // || IsRectTransformDriven == false) + return; + + if (m_isCalculateSizeRequired || m_rectTransform.hasChanged) + { + m_preferredHeight = GetPreferredHeight(); + + ComputeMarginSize(); + + m_isLayoutDirty = true; + } + + m_isCalculateSizeRequired = false; } public override void SetVerticesDirty() { - if (this == null || !this.IsActive()) + if (m_verticesAlreadyDirty || this == null || !this.IsActive() || CanvasUpdateRegistry.IsRebuildingGraphics()) return; - if (CanvasUpdateRegistry.IsRebuildingGraphics()) - { - if (m_DelayedGraphicRebuild == null) - m_DelayedGraphicRebuild = StartCoroutine(DelayedGraphicRebuild()); - - return; - } - + m_verticesAlreadyDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild((ICanvasElement)this); if (m_OnDirtyVertsCallback != null) @@ -111,16 +137,17 @@ public override void SetVerticesDirty() /// - /// + /// /// public override void SetLayoutDirty() { m_isPreferredWidthDirty = true; m_isPreferredHeightDirty = true; - if (this == null || !this.IsActive()) + if ( m_layoutAlreadyDirty || this == null || !this.IsActive()) return; + m_layoutAlreadyDirty = true; LayoutRebuilder.MarkLayoutForRebuild(this.rectTransform); m_isLayoutDirty = true; @@ -131,20 +158,14 @@ public override void SetLayoutDirty() /// - /// + /// /// public override void SetMaterialDirty() { - if (this == null || !this.IsActive()) - return; - - if (CanvasUpdateRegistry.IsRebuildingGraphics()) - { - if (m_DelayedMaterialRebuild == null) - m_DelayedMaterialRebuild = StartCoroutine(DelayedMaterialRebuild()); + //Debug.Log("SetMaterialDirty()"); + if (this == null || !this.IsActive() || CanvasUpdateRegistry.IsRebuildingGraphics()) return; - } m_isMaterialDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild((ICanvasElement)this); @@ -155,7 +176,7 @@ public override void SetMaterialDirty() /// - /// + /// /// public override void SetAllDirty() { @@ -167,39 +188,9 @@ public override void SetAllDirty() } - /// - /// Delay registration of text object for graphic rebuild by one frame. - /// - /// - IEnumerator DelayedGraphicRebuild() - { - yield return null; - - CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); - - if (m_OnDirtyVertsCallback != null) - m_OnDirtyVertsCallback(); - } - - - /// - /// Delay registration of text object for graphic rebuild by one frame. - /// - /// - IEnumerator DelayedMaterialRebuild() - { - yield return null; - - m_isMaterialDirty = true; - CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); - - if (m_OnDirtyMaterialCallback != null) - m_OnDirtyMaterialCallback(); - } - /// - /// + /// /// /// public override void Rebuild(CanvasUpdate update) @@ -217,6 +208,9 @@ public override void Rebuild(CanvasUpdate update) { OnPreRenderCanvas(); + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; + if (!m_isMaterialDirty) return; UpdateMaterial(); @@ -241,7 +235,7 @@ private void UpdateSubObjectPivot() /// - /// + /// /// /// /// @@ -255,6 +249,10 @@ 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); @@ -263,15 +261,13 @@ public override Material GetModifiedMaterial(Material baseMaterial) m_MaskMaterial = mat; } - else if (m_MaskMaterial != null) - TMP_MaterialManager.ReleaseStencilMaterial(m_MaskMaterial); return mat; } /// - /// + /// /// protected override void UpdateMaterial() { @@ -280,7 +276,9 @@ protected override void UpdateMaterial() //if (!this.IsActive()) // return; - if (m_sharedMaterial == null || canvasRenderer == null) return; + if (m_sharedMaterial == null) return; + + if (m_canvasRenderer == null) m_canvasRenderer = this.canvasRenderer; m_canvasRenderer.materialCount = 1; m_canvasRenderer.SetMaterial(materialForRendering, 0); @@ -315,7 +313,7 @@ public Vector4 maskOffset } - //public override Material defaultMaterial + //public override Material defaultMaterial //{ // get { Debug.Log("Default Material called."); return m_sharedMaterial; } //} @@ -339,7 +337,6 @@ public override void RecalculateClipping() base.RecalculateClipping(); } - // IMaskable Implementation /// /// Method called when Stencil Mask needs to be updated on this element and parents. @@ -352,7 +349,6 @@ public override void RecalculateMasking() SetMaterialDirty(); } - //public override void SetClipRect(Rect clipRect, bool validRect) //{ // //Debug.Log("***** SetClipRect (" + clipRect + ", " + validRect + ") *****"); @@ -360,7 +356,6 @@ public override void RecalculateMasking() // base.SetClipRect(clipRect, validRect); //} - /// /// Override of the Cull function to provide for the ability to override the culling of the text object. /// @@ -370,16 +365,14 @@ public override void Cull(Rect clipRect, bool validRect) { //Debug.Log("***** Cull (" + clipRect + ", " + validRect + ") Cull: " + m_canvasRenderer.cull + " *****"); - // Get compound rect for the text object and sub text objects in local canvas space. - Rect rect = GetCanvasSpaceClippingRect(); - - var cull = !validRect || !clipRect.Overlaps(rect, true); - if (m_canvasRenderer.cull != cull) + if (validRect) { - m_canvasRenderer.cull = cull; - onCullStateChanged.Invoke(cull); - OnCullingChanged(); + m_canvasRenderer.cull = false; + CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); + return; } + + base.Cull(clipRect, validRect); } @@ -399,7 +392,7 @@ public override void Cull(Rect clipRect, bool validRect) /* /// - /// Sets the mask type + /// Sets the mask type /// public MaskingTypes mask { @@ -407,7 +400,6 @@ public MaskingTypes mask set { m_mask = value; havePropertiesChanged = true; isMaskUpdateRequired = true; } } - /// /// Set the masking offset mode (as percentage or pixels) /// @@ -419,6 +411,7 @@ public MaskingOffsetMode maskOffsetMode */ + /* /// /// Sets the softness of the mask @@ -429,7 +422,6 @@ public Vector2 maskSoftness set { m_maskSoftness = value; havePropertiesChanged = true; isMaskUpdateRequired = true; } } - /// /// Allows to move / offset the mesh vertices by a set amount /// @@ -505,12 +497,10 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT m_havePropertiesChanged = true; m_ignoreActiveState = ignoreActiveState; m_isInputParsingRequired = m_isInputParsingRequired ? true : forceTextReparsing; - - // Special handling in the event the Canvas is only disabled - if (m_canvas == null) - m_canvas = GetComponentInParent(); - OnPreRenderCanvas(); + + m_verticesAlreadyDirty = false; + m_layoutAlreadyDirty = false; } @@ -521,8 +511,8 @@ public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceT /// public override TMP_TextInfo GetTextInfo(string text) { - StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer); - SetArraySizes(m_InternalParsingBuffer); + StringToCharArray(text, ref m_TextParsingBuffer); + SetArraySizes(m_TextParsingBuffer); m_renderMode = TextRenderFlags.DontRender; @@ -538,7 +528,6 @@ public override TMP_TextInfo GetTextInfo(string text) return this.textInfo; } - /// /// Function to clear the geometry of the Primary and Sub Text objects. /// @@ -667,9 +656,9 @@ public override void UpdateVertexData() public void UpdateFontAsset() - { + { LoadFontAsset(); } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 6f632d3..02fc588 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "name": "com.unity.textmeshpro", "displayName": "TextMeshPro", - "version": "2.1.0-preview.11", - "unity": "2019.1", + "version": "3.0.0-preview.1", + "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.", "keywords": [ "TextMeshPro", @@ -12,15 +13,10 @@ "SDF" ], "category": "Text Rendering", - "dependencies": { - "com.unity.ugui": "1.0.0" - }, + "dependencies": { "com.unity.ugui": "1.0.0" }, "repository": { "type": "git", "url": "https://github.cds.internal.unity3d.com/unity/com.unity.textmeshpro.git", - "revision": "f9d8197de7dfb9de06e6f691d4fcfc5b385f9216" - }, - "upmCi": { - "footprint": "25f50928394cbda7a650de307c055c04a3f2f95a" + "revision": "81642628efbfa43cc3570b0c7239553b8cc8004b" } }