4 using System.Collections;
5 using System.Collections.Generic;
7 using System.Text.RegularExpressions;
20 [AddComponentMenu(
"UI/TextMeshPro - Input Field", 11)]
22 IUpdateSelectedHandler,
33 public enum ContentType
54 public enum CharacterValidation
74 public delegate
char OnValidateInput(
string text,
int charIndex,
char addedChar);
88 protected TouchScreenKeyboard m_Keyboard;
89 static private readonly
char[] kSeparators = {
' ',
'.',
',',
'\t',
'\r',
'\n' };
91 #region Exposed properties 104 protected RectTransform m_TextComponentRectTransform;
107 protected Graphic m_Placeholder;
110 protected Scrollbar m_VerticalScrollbar;
131 private ContentType m_ContentType = ContentType.Standard;
149 private TouchScreenKeyboardType
m_KeyboardType = TouchScreenKeyboardType.Default;
152 private LineType m_LineType = LineType.SingleLine;
233 private Color m_CaretColor =
new Color(50f / 255f, 50f / 255f, 50f / 255f, 1f);
236 private bool m_CustomCaretColor =
false;
239 private Color m_SelectionColor =
new Color(168f / 255f, 206f / 255f, 255f / 255f, 192f / 255f);
251 private float m_CaretBlinkRate = 0.85f;
255 private int m_CaretWidth = 1;
258 private bool m_ReadOnly =
false;
261 private bool m_RichText =
true;
265 protected int m_StringPosition = 0;
266 protected int m_StringSelectPosition = 0;
267 protected int m_CaretPosition = 0;
268 protected int m_CaretSelectPosition = 0;
270 private RectTransform caretRectTrans =
null;
271 protected UIVertex[] m_CursorVerts =
null;
272 private CanvasRenderer m_CachedInputRenderer;
273 private Vector2 m_DefaultTransformPosition;
274 private Vector2 m_LastPosition;
277 protected Mesh m_Mesh;
278 private bool m_AllowInput =
false;
280 private bool m_ShouldActivateNextUpdate =
false;
281 private bool m_UpdateDrag =
false;
282 private bool m_DragPositionOutOfBounds =
false;
283 private const float kHScrollSpeed = 0.05f;
284 private const float kVScrollSpeed = 0.10f;
285 protected bool m_CaretVisible;
286 private Coroutine m_BlinkCoroutine =
null;
287 private float m_BlinkStartTime = 0.0f;
288 private Coroutine m_DragCoroutine =
null;
289 private string m_OriginalText =
"";
290 private bool m_WasCanceled =
false;
291 private bool m_HasDoneFocusTransition =
false;
293 private bool m_IsScrollbarUpdateRequired =
false;
294 private bool m_IsUpdatingScrollbarValues =
false;
296 private bool m_isLastKeyBackspace =
false;
297 private float m_ClickStartTime;
298 private float m_DoubleClickDelay = 0.5f;
301 const string kEmailSpecialCharacters =
"!#$%&'*+-/=?^_`{|}~";
328 switch (Application.platform)
330 case RuntimePlatform.Android:
331 case RuntimePlatform.IPhonePlayer:
332 case RuntimePlatform.tvOS:
353 if (this.text == value)
356 if (value ==
null) value =
string.Empty;
383 if (!Application.isPlaying)
385 SendOnValueChangedAndUpdateLabel();
390 if (m_Keyboard !=
null)
393 if (m_StringPosition >
m_Text.Length)
394 m_StringPosition = m_StringSelectPosition =
m_Text.Length;
399 m_forceRectTransformAdjustment =
true;
401 SendOnValueChangedAndUpdateLabel();
405 public bool isFocused
407 get {
return m_AllowInput; }
410 public float caretBlinkRate
412 get {
return m_CaretBlinkRate; }
415 if (SetPropertyUtility.SetStruct(ref m_CaretBlinkRate, value))
423 public int caretWidth {
get {
return m_CaretWidth; }
set {
if (SetPropertyUtility.SetStruct(ref m_CaretWidth, value)) MarkGeometryAsDirty(); } }
427 public TMP_Text textComponent {
get {
return m_TextComponent; }
set { SetPropertyUtility.SetClass(ref m_TextComponent, value); } }
431 public Graphic placeholder {
get {
return m_Placeholder; }
set { SetPropertyUtility.SetClass(ref m_Placeholder, value); } }
433 public Scrollbar verticalScrollbar
435 get {
return m_VerticalScrollbar; }
438 if (m_VerticalScrollbar !=
null)
441 SetPropertyUtility.SetClass(ref m_VerticalScrollbar, value);
443 if (m_VerticalScrollbar)
453 public Color caretColor {
get {
return customCaretColor ? m_CaretColor : textComponent.
color; }
set {
if (SetPropertyUtility.SetColor(ref m_CaretColor, value)) MarkGeometryAsDirty(); } }
455 public bool customCaretColor {
get {
return m_CustomCaretColor; }
set {
if (m_CustomCaretColor != value) { m_CustomCaretColor = value; MarkGeometryAsDirty(); } } }
457 public Color selectionColor {
get {
return m_SelectionColor; }
set {
if (SetPropertyUtility.SetColor(ref m_SelectionColor, value)) MarkGeometryAsDirty(); } }
459 public SubmitEvent onEndEdit {
get {
return m_OnEndEdit; }
set { SetPropertyUtility.SetClass(ref
m_OnEndEdit, value); } }
461 public SubmitEvent onSubmit {
get {
return m_OnSubmit; }
set { SetPropertyUtility.SetClass(ref
m_OnSubmit, value); } }
463 public SelectionEvent onSelect {
get {
return m_OnSelect; }
set { SetPropertyUtility.SetClass(ref
m_OnSelect, value); } }
465 public SelectionEvent onDeselect {
get {
return m_OnDeselect; }
set { SetPropertyUtility.SetClass(ref
m_OnDeselect, value); } }
499 get {
return m_GlobalFontAsset; }
502 if (SetPropertyUtility.SetClass(ref m_GlobalFontAsset, value))
517 get {
return m_OnFocusSelectAll; }
518 set { m_OnFocusSelectAll = value; }
521 protected bool m_OnFocusSelectAll =
true;
522 protected bool m_isSelectAll;
529 get {
return m_ResetOnDeActivation; }
530 set { m_ResetOnDeActivation = value; }
533 protected bool m_ResetOnDeActivation =
true;
540 get {
return m_RestoreOriginalTextOnEscape; }
541 set { m_RestoreOriginalTextOnEscape = value; }
544 private bool m_RestoreOriginalTextOnEscape =
true;
551 get {
return m_isRichTextEditingAllowed; }
552 set { m_isRichTextEditingAllowed = value; }
555 protected bool m_isRichTextEditingAllowed =
true;
560 public ContentType contentType {
get {
return m_ContentType; }
set {
if (SetPropertyUtility.SetStruct(ref m_ContentType, value)) EnforceContentType(); } }
562 public LineType lineType {
get {
return m_LineType; }
set {
if (SetPropertyUtility.SetStruct(ref m_LineType, value)) SetTextComponentWrapMode(); SetToCustomIfContentTypeIsNot(ContentType.Standard, ContentType.Autocorrected); } }
564 public InputType inputType {
get {
return m_InputType; }
set {
if (SetPropertyUtility.SetStruct(ref
m_InputType, value)) SetToCustom(); } }
566 public TouchScreenKeyboardType keyboardType {
get {
return m_KeyboardType; }
set {
if (SetPropertyUtility.SetStruct(ref
m_KeyboardType, value)) SetToCustom(); } }
575 get {
return m_InputValidator; }
576 set {
if (SetPropertyUtility.SetClass(ref m_InputValidator, value)) SetToCustom(CharacterValidation.CustomValidator); }
581 public bool readOnly {
get {
return m_ReadOnly; }
set { m_ReadOnly = value; } }
583 public bool richText {
get {
return m_RichText; }
set { m_RichText = value; SetTextComponentRichTextMode(); } }
586 public bool multiLine {
get {
return m_LineType == LineType.MultiLineNewline || lineType == LineType.MultiLineSubmit; } }
589 public bool wasCanceled {
get {
return m_WasCanceled; } }
592 protected void ClampStringPos(ref
int pos)
596 else if (pos >
text.Length)
600 protected void ClampCaretPos(ref
int pos)
604 else if (pos > m_TextComponent.
textInfo.characterCount - 1)
605 pos = m_TextComponent.
textInfo.characterCount - 1;
613 protected int caretPositionInternal {
get {
return m_CaretPosition + Input.compositionString.Length; }
set { m_CaretPosition = value; ClampCaretPos(ref m_CaretPosition); } }
614 protected int stringPositionInternal {
get {
return m_StringPosition + Input.compositionString.Length; }
set { m_StringPosition = value; ClampStringPos(ref m_StringPosition); } }
616 protected int caretSelectPositionInternal {
get {
return m_CaretSelectPosition + Input.compositionString.Length; }
set { m_CaretSelectPosition = value; ClampCaretPos(ref m_CaretSelectPosition); } }
617 protected int stringSelectPositionInternal {
get {
return m_StringSelectPosition + Input.compositionString.Length; }
set { m_StringSelectPosition = value; ClampStringPos(ref m_StringSelectPosition); } }
619 private bool hasSelection {
get {
return stringPositionInternal != stringSelectPositionInternal; } }
620 private bool m_isSelected;
621 private bool isStringPositionDirty;
622 private bool m_forceRectTransformAdjustment;
630 get {
return caretSelectPositionInternal; }
647 if (Input.compositionString.Length != 0)
651 isStringPositionDirty =
true;
663 return caretSelectPositionInternal;
667 if (Input.compositionString.Length != 0)
670 caretSelectPositionInternal = value;
671 isStringPositionDirty =
true;
681 get {
return stringSelectPositionInternal; }
693 return stringPositionInternal;
698 if (Input.compositionString.Length != 0)
701 stringPositionInternal = value;
714 return stringSelectPositionInternal;
718 if (Input.compositionString.Length != 0)
721 stringSelectPositionInternal = value;
730 protected override void OnValidate()
733 EnforceContentType();
741 SetTextComponentRichTextMode();
748 #endif // if UNITY_EDITOR 750 protected override void OnEnable()
759 if (Application.isPlaying)
761 if (m_CachedInputRenderer ==
null && m_TextComponent !=
null)
763 GameObject go =
new GameObject(transform.name +
" Input Caret", typeof(RectTransform));
766 TMP_SelectionCaret caret = go.AddComponent<TMP_SelectionCaret>();
767 caret.raycastTarget =
false;
768 caret.color = Color.clear;
770 go.hideFlags = HideFlags.DontSave;
771 go.transform.SetParent(m_TextComponent.
transform.parent);
772 go.transform.SetAsFirstSibling();
773 go.layer = gameObject.layer;
775 caretRectTrans = go.GetComponent<RectTransform>();
776 m_CachedInputRenderer = go.GetComponent<CanvasRenderer>();
777 m_CachedInputRenderer.SetMaterial(Graphic.defaultGraphicMaterial, Texture2D.whiteTexture);
780 go.AddComponent<LayoutElement>().ignoreLayout =
true;
787 if (m_CachedInputRenderer !=
null)
788 m_CachedInputRenderer.SetMaterial(Graphic.defaultGraphicMaterial, Texture2D.whiteTexture);
790 if (m_TextComponent !=
null)
792 m_TextComponent.RegisterDirtyVerticesCallback(MarkGeometryAsDirty);
793 m_TextComponent.RegisterDirtyVerticesCallback(
UpdateLabel);
796 m_DefaultTransformPosition = m_TextComponent.
rectTransform.localPosition;
799 if (m_VerticalScrollbar !=
null)
812 protected override void OnDisable()
815 m_BlinkCoroutine =
null;
817 DeactivateInputField();
818 if (m_TextComponent !=
null)
820 m_TextComponent.UnregisterDirtyVerticesCallback(MarkGeometryAsDirty);
821 m_TextComponent.UnregisterDirtyVerticesCallback(
UpdateLabel);
823 if (m_VerticalScrollbar !=
null)
827 CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(
this);
830 if (m_CachedInputRenderer !=
null)
831 m_CachedInputRenderer.Clear();
834 DestroyImmediate(m_Mesh);
850 if (obj == m_TextComponent && Application.isPlaying)
853 caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
860 IEnumerator CaretBlink()
863 m_CaretVisible =
true;
866 while ( m_CaretBlinkRate > 0)
869 float blinkPeriod = 1f / m_CaretBlinkRate;
872 bool blinkState = (Time.unscaledTime - m_BlinkStartTime) % blinkPeriod < blinkPeriod / 2;
873 if (m_CaretVisible != blinkState)
875 m_CaretVisible = blinkState;
877 MarkGeometryAsDirty();
883 m_BlinkCoroutine =
null;
886 void SetCaretVisible()
891 m_CaretVisible =
true;
892 m_BlinkStartTime = Time.unscaledTime;
898 void SetCaretActive()
903 if (m_CaretBlinkRate > 0.0f)
905 if (m_BlinkCoroutine ==
null)
906 m_BlinkCoroutine = StartCoroutine(CaretBlink());
910 m_CaretVisible =
true;
914 protected void OnFocus()
916 if (m_OnFocusSelectAll)
920 protected void SelectAll()
922 m_isSelectAll =
true;
923 stringPositionInternal =
text.Length;
924 stringSelectPositionInternal = 0;
933 if (m_isRichTextEditingAllowed)
935 int position =
text.Length;
939 stringSelectPositionInternal = position;
943 stringPositionInternal = position;
944 stringSelectPositionInternal = stringPositionInternal;
949 int position = m_TextComponent.
textInfo.characterCount - 1;
953 caretSelectPositionInternal = position;
954 stringSelectPositionInternal = GetStringIndexFromCaretPosition(position);
959 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(position);
972 if (m_isRichTextEditingAllowed)
978 stringSelectPositionInternal = position;
982 stringPositionInternal = position;
983 stringSelectPositionInternal = stringPositionInternal;
992 caretSelectPositionInternal = position;
993 stringSelectPositionInternal = GetStringIndexFromCaretPosition(position);
998 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(position);
1016 int position = ctrl ==
true ? m_TextComponent.
textInfo.characterCount - 1 : m_TextComponent.
textInfo.lineInfo[currentLine].lastCharacterIndex;
1018 position = GetStringIndexFromCaretPosition(position);
1022 stringSelectPositionInternal = position;
1026 stringPositionInternal = position;
1027 stringSelectPositionInternal = stringPositionInternal;
1043 int position = ctrl ==
true ? 0 : m_TextComponent.
textInfo.lineInfo[currentLine].firstCharacterIndex;
1045 position = GetStringIndexFromCaretPosition(position);
1049 stringSelectPositionInternal = position;
1053 stringPositionInternal = position;
1054 stringSelectPositionInternal = stringPositionInternal;
1061 static string clipboard
1065 return GUIUtility.systemCopyBuffer;
1069 GUIUtility.systemCopyBuffer = value;
1073 private bool InPlaceEditing()
1075 return !TouchScreenKeyboard.isSupported;
1085 if (m_ShouldActivateNextUpdate)
1089 ActivateInputFieldInternal();
1090 m_ShouldActivateNextUpdate =
false;
1095 m_ShouldActivateNextUpdate =
false;
1099 if (m_IsScrollbarUpdateRequired)
1102 m_IsScrollbarUpdateRequired =
false;
1124 if (InPlaceEditing() || !isFocused)
1131 if (m_Keyboard ==
null || !m_Keyboard.active)
1133 if (m_Keyboard !=
null)
1136 text = m_Keyboard.text;
1138 if (m_Keyboard.status == TouchScreenKeyboard.Status.Canceled)
1139 m_WasCanceled =
true;
1141 if (m_Keyboard.status == TouchScreenKeyboard.Status.Done)
1149 string val = m_Keyboard.text;
1155 m_Keyboard.text =
m_Text;
1161 for (
int i = 0; i < val.Length; ++i)
1165 if (c ==
'\r' || (
int)c == 3)
1168 if (onValidateInput !=
null)
1170 else if (characterValidation != CharacterValidation.None)
1173 if (lineType == LineType.MultiLineSubmit && c ==
'\n')
1175 m_Keyboard.text =
m_Text;
1186 if (characterLimit > 0 &&
m_Text.Length > characterLimit)
1188 stringPositionInternal = stringSelectPositionInternal =
m_Text.Length;
1193 m_Keyboard.text =
m_Text;
1195 SendOnValueChangedAndUpdateLabel();
1200 if (m_Keyboard.status == TouchScreenKeyboard.Status.Done)
1202 if (m_Keyboard.status == TouchScreenKeyboard.Status.Canceled)
1203 m_WasCanceled =
true;
1210 private bool MayDrag(PointerEventData eventData)
1212 return IsActive() &&
1214 eventData.button == PointerEventData.InputButton.Left &&
1215 m_TextComponent !=
null &&
1219 public virtual void OnBeginDrag(PointerEventData eventData)
1221 if (!MayDrag(eventData))
1224 m_UpdateDrag =
true;
1227 public virtual void OnDrag(PointerEventData eventData)
1229 if (!MayDrag(eventData))
1232 CaretPosition insertionSide;
1233 int insertionIndex = TMP_TextUtilities.GetCursorIndexFromPosition(m_TextComponent, eventData.position, eventData.pressEventCamera, out insertionSide);
1235 if (insertionSide == CaretPosition.Left)
1236 stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex);
1237 else if (insertionSide == CaretPosition.Right)
1238 stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex) + 1;
1240 caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1242 MarkGeometryAsDirty();
1244 m_DragPositionOutOfBounds = !RectTransformUtility.RectangleContainsScreenPoint(textViewport, eventData.position, eventData.pressEventCamera);
1245 if (m_DragPositionOutOfBounds && m_DragCoroutine ==
null)
1246 m_DragCoroutine = StartCoroutine(MouseDragOutsideRect(eventData));
1251 IEnumerator MouseDragOutsideRect(PointerEventData eventData)
1253 while (m_UpdateDrag && m_DragPositionOutOfBounds)
1255 Vector2 localMousePos;
1256 RectTransformUtility.ScreenPointToLocalPointInRectangle(textViewport, eventData.position, eventData.pressEventCamera, out localMousePos);
1258 Rect rect = textViewport.rect;
1262 if (localMousePos.y > rect.yMax)
1264 else if (localMousePos.y < rect.yMin)
1265 MoveDown(
true,
true);
1269 if (localMousePos.x < rect.xMin)
1270 MoveLeft(
true,
false);
1271 else if (localMousePos.x > rect.xMax)
1272 MoveRight(
true,
false);
1277 float delay = multiLine ? kVScrollSpeed : kHScrollSpeed;
1278 yield
return new WaitForSeconds(delay);
1281 m_DragCoroutine =
null;
1284 public virtual void OnEndDrag(PointerEventData eventData)
1286 if (!MayDrag(eventData))
1289 m_UpdateDrag =
false;
1292 public override void OnPointerDown(PointerEventData eventData)
1294 if (!MayDrag(eventData))
1297 EventSystem.current.SetSelectedGameObject(gameObject, eventData);
1299 bool hadFocusBefore = m_AllowInput;
1300 base.OnPointerDown(eventData);
1302 if (!InPlaceEditing())
1304 if (m_Keyboard ==
null || !m_Keyboard.active)
1306 OnSelect(eventData);
1311 bool shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
1314 bool isDoubleClick =
false;
1315 float timeStamp = Time.unscaledTime;
1317 if (m_ClickStartTime + m_DoubleClickDelay > timeStamp)
1318 isDoubleClick =
true;
1320 m_ClickStartTime = timeStamp;
1324 if (hadFocusBefore || !m_OnFocusSelectAll)
1326 CaretPosition insertionSide;
1327 int insertionIndex = TMP_TextUtilities.GetCursorIndexFromPosition(m_TextComponent, eventData.position, eventData.pressEventCamera, out insertionSide);
1331 if (insertionSide == CaretPosition.Left)
1332 stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex);
1333 else if (insertionSide == CaretPosition.Right)
1334 stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex) + 1;
1338 if (insertionSide == CaretPosition.Left)
1339 stringPositionInternal = stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex);
1340 else if (insertionSide == CaretPosition.Right)
1341 stringPositionInternal = stringSelectPositionInternal = GetStringIndexFromCaretPosition(insertionIndex) + 1;
1347 int wordIndex = TMP_TextUtilities.FindIntersectingWord(m_TextComponent, eventData.position, eventData.pressEventCamera);
1349 if (wordIndex != -1)
1353 caretSelectPositionInternal = m_TextComponent.
textInfo.wordInfo[wordIndex].lastCharacterIndex + 1;
1356 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
1363 stringSelectPositionInternal += 1;
1365 caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1370 caretPositionInternal = caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringPositionInternal);
1378 protected enum EditState
1384 protected EditState KeyPressed(Event evt)
1386 var currentEventModifiers = evt.modifiers;
1387 RuntimePlatform rp = Application.platform;
1388 bool isMac = (rp == RuntimePlatform.OSXEditor || rp == RuntimePlatform.OSXPlayer);
1389 bool ctrl = isMac ? (currentEventModifiers & EventModifiers.Command) != 0 : (currentEventModifiers & EventModifiers.Control) != 0;
1390 bool shift = (currentEventModifiers & EventModifiers.Shift) != 0;
1391 bool alt = (currentEventModifiers & EventModifiers.Alt) != 0;
1392 bool ctrlOnly = ctrl && !alt && !shift;
1394 switch (evt.keyCode)
1396 case KeyCode.Backspace:
1399 return EditState.Continue;
1402 case KeyCode.Delete:
1405 return EditState.Continue;
1411 return EditState.Continue;
1417 return EditState.Continue;
1426 return EditState.Continue;
1436 if (inputType != InputType.Password)
1437 clipboard = GetSelectedString();
1440 return EditState.Continue;
1451 return EditState.Continue;
1461 if (inputType != InputType.Password)
1462 clipboard = GetSelectedString();
1466 SendOnValueChangedAndUpdateLabel();
1467 return EditState.Continue;
1472 case KeyCode.LeftArrow:
1474 MoveLeft(shift, ctrl);
1475 return EditState.Continue;
1478 case KeyCode.RightArrow:
1480 MoveRight(shift, ctrl);
1481 return EditState.Continue;
1484 case KeyCode.UpArrow:
1487 return EditState.Continue;
1490 case KeyCode.DownArrow:
1493 return EditState.Continue;
1496 case KeyCode.PageUp:
1499 return EditState.Continue;
1502 case KeyCode.PageDown:
1504 MovePageDown(shift);
1505 return EditState.Continue;
1509 case KeyCode.Return:
1510 case KeyCode.KeypadEnter:
1512 if (lineType != LineType.MultiLineNewline)
1514 return EditState.Finish;
1519 case KeyCode.Escape:
1521 m_WasCanceled =
true;
1522 return EditState.Finish;
1526 char c = evt.character;
1529 if (!multiLine && (c ==
'\t' || c ==
'\r' || c == 10))
1530 return EditState.Continue;
1533 if (c ==
'\r' || (
int)c == 3)
1543 if (Input.compositionString.Length > 0)
1548 return EditState.Continue;
1551 private bool IsValidChar(
char c)
1557 if (c ==
'\t' || c ==
'\n')
1568 public void ProcessEvent(Event e)
1583 bool consumedEvent =
false;
1588 consumedEvent =
true;
1590 if (shouldContinue == EditState.Finish)
1593 DeactivateInputField();
1600 case EventType.ValidateCommand:
1601 case EventType.ExecuteCommand:
1606 consumedEvent =
true;
1624 public virtual void OnScroll(PointerEventData eventData)
1628 float scrollDirection = -eventData.scrollDelta.y;
1637 m_AllowInput =
false;
1639 if (m_VerticalScrollbar)
1641 m_IsUpdatingScrollbarValues =
true;
1650 private string GetSelectedString()
1655 int startPos = stringPositionInternal;
1656 int endPos = stringSelectPositionInternal;
1659 if (startPos > endPos)
1661 int temp = startPos;
1672 return text.Substring(startPos, endPos - startPos);
1675 private int FindtNextWordBegin()
1677 if (stringSelectPositionInternal + 1 >=
text.Length)
1680 int spaceLoc =
text.IndexOfAny(kSeparators, stringSelectPositionInternal + 1);
1683 spaceLoc =
text.Length;
1690 private void MoveRight(
bool shift,
bool ctrl)
1692 if (hasSelection && !shift)
1696 stringPositionInternal = stringSelectPositionInternal = Mathf.Max(stringPositionInternal, stringSelectPositionInternal);
1697 caretPositionInternal = caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1700 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
1707 position = FindtNextWordBegin();
1710 if (m_isRichTextEditingAllowed)
1711 position = stringSelectPositionInternal + 1;
1713 position = GetStringIndexFromCaretPosition(caretSelectPositionInternal + 1);
1719 stringSelectPositionInternal = position;
1720 caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1724 stringSelectPositionInternal = stringPositionInternal = position;
1725 caretSelectPositionInternal =
caretPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1729 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
1733 private int FindtPrevWordBegin()
1735 if (stringSelectPositionInternal - 2 < 0)
1738 int spaceLoc =
text.LastIndexOfAny(kSeparators, stringSelectPositionInternal - 2);
1748 private void MoveLeft(
bool shift,
bool ctrl)
1750 if (hasSelection && !shift)
1754 stringPositionInternal = stringSelectPositionInternal = Mathf.Min(stringPositionInternal, stringSelectPositionInternal);
1755 caretPositionInternal = caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1758 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
1765 position = FindtPrevWordBegin();
1768 if (m_isRichTextEditingAllowed)
1769 position = stringSelectPositionInternal - 1;
1771 position = GetStringIndexFromCaretPosition(caretSelectPositionInternal - 1);
1776 stringSelectPositionInternal = position;
1777 caretSelectPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1782 stringSelectPositionInternal = stringPositionInternal = position;
1783 caretSelectPositionInternal =
caretPositionInternal = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
1787 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
1792 private int LineUpCharacterPosition(
int originalPos,
bool goToFirstChar)
1794 if (originalPos >= m_TextComponent.
textInfo.characterCount)
1797 TMP_CharacterInfo originChar = m_TextComponent.
textInfo.characterInfo[originalPos];
1798 int originLine = originChar.lineNumber;
1801 if (originLine - 1 < 0)
1802 return goToFirstChar ? 0 : originalPos;
1804 int endCharIdx = m_TextComponent.
textInfo.lineInfo[originLine].firstCharacterIndex - 1;
1807 float distance = TMP_Math.FLOAT_MAX;
1810 for (
int i = m_TextComponent.
textInfo.lineInfo[originLine - 1].firstCharacterIndex; i < endCharIdx; ++i)
1812 TMP_CharacterInfo currentChar = m_TextComponent.
textInfo.characterInfo[i];
1814 float d = originChar.origin - currentChar.origin;
1815 float r = d / (currentChar.xAdvance - currentChar.origin);
1817 if (r >= 0 && r <= 1)
1835 if (closest == -1)
return endCharIdx;
1846 private int LineDownCharacterPosition(
int originalPos,
bool goToLastChar)
1848 if (originalPos >= m_TextComponent.
textInfo.characterCount)
1849 return m_TextComponent.
textInfo.characterCount - 1;
1851 TMP_CharacterInfo originChar = m_TextComponent.
textInfo.characterInfo[originalPos];
1852 int originLine = originChar.lineNumber;
1855 if (originLine + 1 >= m_TextComponent.
textInfo.lineCount)
1856 return goToLastChar ? m_TextComponent.
textInfo.characterCount - 1 : originalPos;
1859 int endCharIdx = m_TextComponent.
textInfo.lineInfo[originLine + 1].lastCharacterIndex;
1862 float distance = TMP_Math.FLOAT_MAX;
1865 for (
int i = m_TextComponent.
textInfo.lineInfo[originLine + 1].firstCharacterIndex; i < endCharIdx; ++i)
1867 TMP_CharacterInfo currentChar = m_TextComponent.
textInfo.characterInfo[i];
1869 float d = originChar.origin - currentChar.origin;
1870 float r = d / (currentChar.xAdvance - currentChar.origin);
1872 if (r >= 0 && r <= 1)
1890 if (closest == -1)
return endCharIdx;
1901 private int PageUpCharacterPosition(
int originalPos,
bool goToFirstChar)
1903 if (originalPos >= m_TextComponent.
textInfo.characterCount)
1906 TMP_CharacterInfo originChar = m_TextComponent.
textInfo.characterInfo[originalPos];
1907 int originLine = originChar.lineNumber;
1910 if (originLine - 1 < 0)
1911 return goToFirstChar ? 0 : originalPos;
1915 int newLine = originLine - 1;
1917 for (; newLine > 0; newLine--)
1919 if (m_TextComponent.
textInfo.lineInfo[newLine].baseline > m_TextComponent.
textInfo.lineInfo[originLine].baseline + viewportHeight)
1923 int endCharIdx = m_TextComponent.
textInfo.lineInfo[newLine].lastCharacterIndex;
1926 float distance = TMP_Math.FLOAT_MAX;
1929 for (
int i = m_TextComponent.
textInfo.lineInfo[newLine].firstCharacterIndex; i < endCharIdx; ++i)
1931 TMP_CharacterInfo currentChar = m_TextComponent.
textInfo.characterInfo[i];
1933 float d = originChar.origin - currentChar.origin;
1934 float r = d / (currentChar.xAdvance - currentChar.origin);
1936 if (r >= 0 && r <= 1)
1954 if (closest == -1)
return endCharIdx;
1965 private int PageDownCharacterPosition(
int originalPos,
bool goToLastChar)
1967 if (originalPos >= m_TextComponent.
textInfo.characterCount)
1968 return m_TextComponent.
textInfo.characterCount - 1;
1970 TMP_CharacterInfo originChar = m_TextComponent.
textInfo.characterInfo[originalPos];
1971 int originLine = originChar.lineNumber;
1974 if (originLine + 1 >= m_TextComponent.
textInfo.lineCount)
1975 return goToLastChar ? m_TextComponent.
textInfo.characterCount - 1 : originalPos;
1979 int newLine = originLine + 1;
1981 for (; newLine < m_TextComponent.
textInfo.lineCount - 1; newLine++)
1983 if (m_TextComponent.
textInfo.lineInfo[newLine].baseline < m_TextComponent.
textInfo.lineInfo[originLine].baseline - viewportHeight)
1988 int endCharIdx = m_TextComponent.
textInfo.lineInfo[newLine].lastCharacterIndex;
1991 float distance = TMP_Math.FLOAT_MAX;
1994 for (
int i = m_TextComponent.
textInfo.lineInfo[newLine].firstCharacterIndex; i < endCharIdx; ++i)
1996 TMP_CharacterInfo currentChar = m_TextComponent.
textInfo.characterInfo[i];
1998 float d = originChar.origin - currentChar.origin;
1999 float r = d / (currentChar.xAdvance - currentChar.origin);
2001 if (r >= 0 && r <= 1)
2019 if (closest == -1)
return endCharIdx;
2028 private void MoveDown(
bool shift)
2030 MoveDown(shift,
true);
2034 private void MoveDown(
bool shift,
bool goToLastChar)
2036 if (hasSelection && !shift)
2043 int position = multiLine ? LineDownCharacterPosition(caretSelectPositionInternal, goToLastChar) : m_TextComponent.textInfo.characterCount - 1;
2047 caretSelectPositionInternal = position;
2048 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2053 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2057 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2061 private void MoveUp(
bool shift)
2063 MoveUp(shift,
true);
2067 private void MoveUp(
bool shift,
bool goToFirstChar)
2069 if (hasSelection && !shift)
2076 int position = multiLine ? LineUpCharacterPosition(caretSelectPositionInternal, goToFirstChar) : 0;
2080 caretSelectPositionInternal = position;
2081 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2086 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2090 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2095 private void MovePageUp(
bool shift)
2097 MovePageUp(shift,
true);
2100 private void MovePageUp(
bool shift,
bool goToFirstChar)
2102 if (hasSelection && !shift)
2109 int position = multiLine ? PageUpCharacterPosition(caretSelectPositionInternal, goToFirstChar) : 0;
2113 caretSelectPositionInternal = position;
2114 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2119 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2128 if (m_LineType != LineType.SingleLine)
2135 offset = topViewportBounds > topTextBounds + offset ? offset : topViewportBounds - topTextBounds;
2137 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(0, offset);
2139 m_IsScrollbarUpdateRequired =
true;
2143 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2149 private void MovePageDown(
bool shift)
2151 MovePageDown(shift,
true);
2154 private void MovePageDown(
bool shift,
bool goToLastChar)
2156 if (hasSelection && !shift)
2163 int position = multiLine ? PageDownCharacterPosition(caretSelectPositionInternal, goToLastChar) : m_TextComponent.textInfo.characterCount - 1;
2167 caretSelectPositionInternal = position;
2168 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2173 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2181 if (m_LineType != LineType.SingleLine)
2188 offset = bottomViewportBounds > bottomTextBounds + offset ? offset : bottomViewportBounds - bottomTextBounds;
2190 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(0, offset);
2192 m_IsScrollbarUpdateRequired =
true;
2196 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2201 private void Delete()
2206 if (stringPositionInternal == stringSelectPositionInternal)
2209 if (m_isRichTextEditingAllowed || m_isSelectAll)
2212 if (stringPositionInternal < stringSelectPositionInternal)
2214 m_Text =
text.Substring(0, stringPositionInternal) +
text.Substring(stringSelectPositionInternal,
text.Length - stringSelectPositionInternal);
2215 stringSelectPositionInternal = stringPositionInternal;
2219 m_Text =
text.Substring(0, stringSelectPositionInternal) +
text.Substring(stringPositionInternal,
text.Length - stringPositionInternal);
2220 stringPositionInternal = stringSelectPositionInternal;
2223 m_isSelectAll =
false;
2228 stringSelectPositionInternal = GetStringIndexFromCaretPosition(caretSelectPositionInternal);
2233 m_Text =
text.Substring(0, stringPositionInternal) +
text.Substring(stringSelectPositionInternal,
text.Length - stringSelectPositionInternal);
2235 stringSelectPositionInternal = stringPositionInternal;
2240 m_Text =
text.Substring(0, stringSelectPositionInternal) +
text.Substring(stringPositionInternal,
text.Length - stringPositionInternal);
2241 stringPositionInternal = stringSelectPositionInternal;
2243 stringPositionInternal = stringSelectPositionInternal;
2249 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2264 SendOnValueChangedAndUpdateLabel();
2268 if (m_isRichTextEditingAllowed)
2270 if (stringPositionInternal <
text.Length)
2272 m_Text =
text.Remove(stringPositionInternal, 1);
2274 SendOnValueChangedAndUpdateLabel();
2281 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(
caretPositionInternal);
2282 m_Text =
text.Remove(stringPositionInternal, 1);
2284 SendOnValueChangedAndUpdateLabel();
2290 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2305 SendOnValueChangedAndUpdateLabel();
2309 if (m_isRichTextEditingAllowed)
2311 if (stringPositionInternal > 0)
2313 m_Text =
text.Remove(stringPositionInternal - 1, 1);
2314 stringSelectPositionInternal = stringPositionInternal = stringPositionInternal - 1;
2316 m_isLastKeyBackspace =
true;
2318 SendOnValueChangedAndUpdateLabel();
2327 stringSelectPositionInternal = stringPositionInternal = GetStringIndexFromCaretPosition(
caretPositionInternal);
2330 m_isLastKeyBackspace =
true;
2332 SendOnValueChangedAndUpdateLabel();
2338 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2351 if (!InPlaceEditing())
2354 for (
int i = 0, imax = input.Length; i < imax; ++i)
2358 if (c >=
' ' || c ==
'\t' || c ==
'\r' || c == 10 || c ==
'\n')
2365 protected virtual void Append(
char input)
2370 if (!InPlaceEditing())
2374 if (onValidateInput !=
null)
2375 input = onValidateInput(
text, stringPositionInternal, input);
2376 else if (characterValidation == CharacterValidation.CustomValidator)
2380 if (input == 0)
return;
2382 SendOnValueChanged();
2387 else if (characterValidation != CharacterValidation.None)
2402 private void Insert(
char c)
2407 string replaceString = c.ToString();
2411 if (characterLimit > 0 &&
text.Length >= characterLimit)
2414 m_Text =
text.Insert(m_StringPosition, replaceString);
2415 stringSelectPositionInternal = stringPositionInternal += replaceString.Length;
2417 SendOnValueChanged();
2420 Debug.Log(
"Caret Position: " +
caretPositionInternal +
" Selection Position: " + caretSelectPositionInternal +
" String Position: " + stringPositionInternal +
" String Select Position: " + stringSelectPositionInternal);
2424 private void SendOnValueChangedAndUpdateLabel()
2426 SendOnValueChanged();
2430 private void SendOnValueChanged()
2432 if (onValueChanged !=
null)
2433 onValueChanged.Invoke(
text);
2442 if (onEndEdit !=
null)
2443 onEndEdit.Invoke(
m_Text);
2446 protected void SendOnSubmit()
2448 if (onSubmit !=
null)
2452 protected void SendOnFocus()
2454 if (onSelect !=
null)
2458 protected void SendOnFocusLost()
2460 if (onDeselect !=
null)
2461 onDeselect.Invoke(
m_Text);
2464 protected void SendOnTextSelection()
2466 m_isSelected =
true;
2468 if (onTextSelection !=
null)
2469 onTextSelection.Invoke(
m_Text, stringPositionInternal, stringSelectPositionInternal);
2472 protected void SendOnEndTextSelection()
2474 if (!m_isSelected)
return;
2476 if (onEndTextSelection !=
null)
2477 onEndTextSelection.Invoke(
m_Text, stringPositionInternal, stringSelectPositionInternal);
2479 m_isSelected =
false;
2489 if (m_TextComponent !=
null && m_TextComponent.
font !=
null)
2507 if (Input.compositionString.Length > 0)
2508 fullText =
text.Substring(0, m_StringPosition) + Input.compositionString +
text.Substring(m_StringPosition);
2513 if (inputType == InputType.Password)
2514 processed =
new string(asteriskChar, fullText.Length);
2516 processed = fullText;
2518 bool isEmpty =
string.IsNullOrEmpty(fullText);
2520 if (m_Placeholder !=
null)
2521 m_Placeholder.enabled = isEmpty;
2545 m_TextComponent.
text = processed +
"\u200B";
2546 MarkGeometryAsDirty();
2549 m_IsScrollbarUpdateRequired =
true;
2566 void UpdateScrollbar()
2569 if (m_VerticalScrollbar)
2573 m_IsUpdatingScrollbarValues =
true;
2575 m_VerticalScrollbar.size = size;
2592 if (m_IsUpdatingScrollbarValues) { m_IsUpdatingScrollbarValues =
false;
return; }
2594 if (value < 0 || value > 1)
return;
2614 if (textInfo ==
null || textInfo.lineInfo ==
null || textInfo.lineCount == 0 || textInfo.lineCount > textInfo.lineInfo.Length)
return;
2625 private int GetCaretPositionFromStringIndex(
int stringIndex)
2627 int count = m_TextComponent.
textInfo.characterCount;
2629 for (
int i = 0; i < count; i++)
2631 if (m_TextComponent.
textInfo.characterInfo[i].
index >= stringIndex)
2638 private int GetStringIndexFromCaretPosition(
int caretPosition)
2647 public void ForceLabelUpdate()
2652 private void MarkGeometryAsDirty()
2655 #if UNITY_2018_3_OR_NEWER 2656 if (!Application.isPlaying ||
UnityEditor.PrefabUtility.IsPartOfPrefabAsset(
this))
2659 if (!Application.isPlaying ||
UnityEditor.PrefabUtility.GetPrefabObject(gameObject) !=
null)
2664 CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(
this);
2667 public virtual void Rebuild(CanvasUpdate update)
2671 case CanvasUpdate.LatePreRender:
2677 public virtual void LayoutComplete()
2680 public virtual void GraphicUpdateComplete()
2683 private void UpdateGeometry()
2686 if (!Application.isPlaying)
2715 if (m_CachedInputRenderer ==
null)
2720 m_CachedInputRenderer.SetMesh(mesh);
2729 if (m_TextComponent !=
null && caretRectTrans !=
null &&
2730 (caretRectTrans.localPosition != m_TextComponent.
rectTransform.localPosition ||
2731 caretRectTrans.localRotation != m_TextComponent.
rectTransform.localRotation ||
2732 caretRectTrans.localScale != m_TextComponent.
rectTransform.localScale ||
2733 caretRectTrans.anchorMin != m_TextComponent.
rectTransform.anchorMin ||
2734 caretRectTrans.anchorMax != m_TextComponent.
rectTransform.anchorMax ||
2735 caretRectTrans.anchoredPosition != m_TextComponent.
rectTransform.anchoredPosition ||
2736 caretRectTrans.sizeDelta != m_TextComponent.
rectTransform.sizeDelta ||
2737 caretRectTrans.pivot != m_TextComponent.
rectTransform.pivot))
2739 caretRectTrans.localPosition = m_TextComponent.
rectTransform.localPosition;
2740 caretRectTrans.localRotation = m_TextComponent.
rectTransform.localRotation;
2741 caretRectTrans.localScale = m_TextComponent.
rectTransform.localScale;
2742 caretRectTrans.anchorMin = m_TextComponent.
rectTransform.anchorMin;
2743 caretRectTrans.anchorMax = m_TextComponent.
rectTransform.anchorMax;
2744 caretRectTrans.anchoredPosition = m_TextComponent.
rectTransform.anchoredPosition;
2745 caretRectTrans.sizeDelta = m_TextComponent.
rectTransform.sizeDelta;
2754 private void OnFillVBO(Mesh vbo)
2756 using (var helper =
new VertexHelper())
2758 if (!isFocused && m_ResetOnDeActivation)
2760 helper.FillMesh(vbo);
2764 if (isStringPositionDirty)
2766 stringPositionInternal = GetStringIndexFromCaretPosition(m_CaretPosition);
2767 stringSelectPositionInternal = GetStringIndexFromCaretPosition(m_CaretSelectPosition);
2768 isStringPositionDirty =
false;
2773 GenerateCaret(helper, Vector2.zero);
2774 SendOnEndTextSelection();
2778 GenerateHightlight(helper, Vector2.zero);
2779 SendOnTextSelection();
2782 helper.FillMesh(vbo);
2787 private void GenerateCaret(VertexHelper vbo, Vector2 roundingOffset)
2789 if (!m_CaretVisible)
2792 if (m_CursorVerts ==
null)
2794 CreateCursorVerts();
2797 float width = m_CaretWidth;
2803 int characterCount = m_TextComponent.
textInfo.characterCount;
2804 Vector2 startPosition = Vector2.zero;
2806 TMP_CharacterInfo currentCharacter;
2813 currentCharacter = m_TextComponent.
textInfo.characterInfo[0];
2814 startPosition =
new Vector2(currentCharacter.origin, currentCharacter.descender);
2815 height = currentCharacter.ascender - currentCharacter.descender;
2820 startPosition =
new Vector2(currentCharacter.origin, currentCharacter.descender);
2821 height = currentCharacter.ascender - currentCharacter.descender;
2825 currentCharacter = m_TextComponent.
textInfo.characterInfo[characterCount - 1];
2826 startPosition =
new Vector2(currentCharacter.xAdvance, currentCharacter.descender);
2827 height = currentCharacter.ascender - currentCharacter.descender;
2833 if (isFocused && startPosition != m_LastPosition || m_forceRectTransformAdjustment)
2836 m_LastPosition = startPosition;
2839 float top = startPosition.y + height;
2840 float bottom = top - height;
2842 m_CursorVerts[0].position =
new Vector3(startPosition.x, bottom, 0.0f);
2843 m_CursorVerts[1].position =
new Vector3(startPosition.x, top, 0.0f);
2844 m_CursorVerts[2].position =
new Vector3(startPosition.x + width, top, 0.0f);
2845 m_CursorVerts[3].position =
new Vector3(startPosition.x + width, bottom, 0.0f);
2848 m_CursorVerts[0].color = caretColor;
2849 m_CursorVerts[1].color = caretColor;
2850 m_CursorVerts[2].color = caretColor;
2851 m_CursorVerts[3].color = caretColor;
2853 vbo.AddUIVertexQuad(m_CursorVerts);
2855 int screenHeight = Screen.height;
2861 startPosition.y = screenHeight - startPosition.y;
2862 Input.compositionCursorPos = startPosition;
2868 private void CreateCursorVerts()
2870 m_CursorVerts =
new UIVertex[4];
2872 for (
int i = 0; i < m_CursorVerts.Length; i++)
2874 m_CursorVerts[i] = UIVertex.simpleVert;
2875 m_CursorVerts[i].uv0 = Vector2.zero;
2880 private void GenerateHightlight(VertexHelper vbo, Vector2 roundingOffset)
2882 TMP_TextInfo textInfo = m_TextComponent.
textInfo;
2885 caretSelectPositionInternal = m_CaretSelectPosition = GetCaretPositionFromStringIndex(stringSelectPositionInternal);
2892 if (caretSelectPositionInternal < textInfo.characterCount)
2894 caretPosition =
new Vector2(textInfo.characterInfo[caretSelectPositionInternal].origin, textInfo.characterInfo[caretSelectPositionInternal].descender);
2895 height = textInfo.characterInfo[caretSelectPositionInternal].ascender - textInfo.characterInfo[caretSelectPositionInternal].descender;
2899 caretPosition =
new Vector2(textInfo.characterInfo[caretSelectPositionInternal - 1].xAdvance, textInfo.characterInfo[caretSelectPositionInternal - 1].descender);
2900 height = textInfo.characterInfo[caretSelectPositionInternal - 1].ascender - textInfo.characterInfo[caretSelectPositionInternal - 1].descender;
2908 int endChar = Mathf.Max(0, caretSelectPositionInternal);
2911 if (startChar > endChar)
2913 int temp = startChar;
2914 startChar = endChar;
2923 int currentLineIndex = textInfo.characterInfo[startChar].lineNumber;
2924 int nextLineStartIdx = textInfo.lineInfo[currentLineIndex].lastCharacterIndex;
2926 UIVertex vert = UIVertex.simpleVert;
2927 vert.uv0 = Vector2.zero;
2928 vert.color = selectionColor;
2930 int currentChar = startChar;
2931 while (currentChar <= endChar && currentChar < textInfo.characterCount)
2933 if (currentChar == nextLineStartIdx || currentChar == endChar)
2935 TMP_CharacterInfo startCharInfo = textInfo.characterInfo[startChar];
2936 TMP_CharacterInfo endCharInfo = textInfo.characterInfo[currentChar];
2939 if (currentChar > 0 && endCharInfo.character == 10 && textInfo.characterInfo[currentChar - 1].character == 13)
2940 endCharInfo = textInfo.characterInfo[currentChar - 1];
2942 Vector2 startPosition =
new Vector2(startCharInfo.origin, textInfo.lineInfo[currentLineIndex].ascender);
2943 Vector2 endPosition =
new Vector2(endCharInfo.xAdvance, textInfo.lineInfo[currentLineIndex].descender);
2945 var startIndex = vbo.currentVertCount;
2946 vert.position =
new Vector3(startPosition.x, endPosition.y, 0.0f);
2949 vert.position =
new Vector3(endPosition.x, endPosition.y, 0.0f);
2952 vert.position =
new Vector3(endPosition.x, startPosition.y, 0.0f);
2955 vert.position =
new Vector3(startPosition.x, startPosition.y, 0.0f);
2958 vbo.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
2959 vbo.AddTriangle(startIndex + 2, startIndex + 3, startIndex + 0);
2961 startChar = currentChar + 1;
2964 if (currentLineIndex < textInfo.lineCount)
2965 nextLineStartIdx = textInfo.lineInfo[currentLineIndex].lastCharacterIndex;
2971 m_IsScrollbarUpdateRequired =
true;
2990 float rightOffset = viewportMax - (m_TextComponent.
rectTransform.anchoredPosition.x + startPosition.x + m_TextComponent.
margin.z + m_CaretWidth);
2991 if (rightOffset < 0f)
2993 if (!multiLine || (multiLine && isCharVisible))
2996 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(rightOffset, 0);
3002 float leftOffset = (m_TextComponent.
rectTransform.anchoredPosition.x + startPosition.x - m_TextComponent.
margin.x) - viewportMin;
3003 if (leftOffset < 0f)
3006 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(-leftOffset, 0);
3012 if (m_LineType != LineType.SingleLine)
3015 if (topOffset < -0.0001f)
3017 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(0, topOffset);
3019 m_IsScrollbarUpdateRequired =
true;
3023 if (bottomOffset < 0f)
3025 m_TextComponent.
rectTransform.anchoredPosition -=
new Vector2(0, bottomOffset);
3027 m_IsScrollbarUpdateRequired =
true;
3032 if (m_isLastKeyBackspace)
3034 float firstCharPosition = m_TextComponent.
rectTransform.anchoredPosition.x + m_TextComponent.
textInfo.characterInfo[0].origin - m_TextComponent.
margin.x;
3035 float lastCharPosition = m_TextComponent.
rectTransform.anchoredPosition.x + m_TextComponent.
textInfo.characterInfo[m_TextComponent.
textInfo.characterCount - 1].origin + m_TextComponent.
margin.z;
3038 if (m_TextComponent.
rectTransform.anchoredPosition.x + startPosition.x <= viewportMin + 0.0001f)
3040 if (firstCharPosition < viewportMin)
3042 float offset = Mathf.Min((viewportMax - viewportMin) / 2, viewportMin - firstCharPosition);
3043 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(offset, 0);
3047 else if (lastCharPosition < viewportMax && firstCharPosition < viewportMin)
3049 float offset = Mathf.Min(viewportMax - lastCharPosition, viewportMin - firstCharPosition);
3051 m_TextComponent.
rectTransform.anchoredPosition +=
new Vector2(offset, 0);
3055 m_isLastKeyBackspace =
false;
3058 m_forceRectTransformAdjustment =
false;
3067 if (characterValidation == CharacterValidation.None || !enabled)
3070 if (characterValidation == CharacterValidation.Integer || characterValidation == CharacterValidation.Decimal)
3073 bool cursorBeforeDash = (pos == 0 &&
text.Length > 0 &&
text[0] ==
'-');
3074 bool selectionAtStart = stringPositionInternal == 0 || stringSelectPositionInternal == 0;
3075 if (!cursorBeforeDash)
3077 if (ch >=
'0' && ch <=
'9')
return ch;
3078 if (ch ==
'-' && (pos == 0 || selectionAtStart))
return ch;
3079 if (ch ==
'.' && characterValidation == CharacterValidation.Decimal && !
text.Contains(
"."))
return ch;
3082 else if (characterValidation == CharacterValidation.Digit)
3084 if (ch >=
'0' && ch <=
'9')
return ch;
3086 else if (characterValidation == CharacterValidation.Alphanumeric)
3089 if (ch >=
'A' && ch <=
'Z')
return ch;
3090 if (ch >=
'a' && ch <=
'z')
return ch;
3091 if (ch >=
'0' && ch <=
'9')
return ch;
3093 else if (characterValidation == CharacterValidation.Name)
3095 char lastChar = (
text.Length > 0) ?
text[Mathf.Clamp(pos, 0,
text.Length - 1)] :
' ';
3096 char nextChar = (
text.Length > 0) ?
text[Mathf.Clamp(pos + 1, 0,
text.Length - 1)] :
'\n';
3098 if (
char.IsLetter(ch))
3101 if (
char.IsLower(ch) && lastChar ==
' ')
3102 return char.ToUpper(ch);
3105 if (
char.IsUpper(ch) && lastChar !=
' ' && lastChar !=
'\'')
3106 return char.ToLower(ch);
3112 else if (ch ==
'\'')
3115 if (lastChar !=
' ' && lastChar !=
'\'' && nextChar !=
'\'' && !
text.Contains(
"'"))
3121 if (lastChar !=
' ' && lastChar !=
'\'' && nextChar !=
' ' && nextChar !=
'\'')
3125 else if (characterValidation == CharacterValidation.EmailAddress)
3134 if (ch >=
'A' && ch <=
'Z')
return ch;
3135 if (ch >=
'a' && ch <=
'z')
return ch;
3136 if (ch >=
'0' && ch <=
'9')
return ch;
3137 if (ch ==
'@' &&
text.IndexOf(
'@') == -1)
return ch;
3138 if (kEmailSpecialCharacters.IndexOf(ch) != -1)
return ch;
3141 char lastChar = (
text.Length > 0) ?
text[Mathf.Clamp(pos, 0,
text.Length - 1)] :
' ';
3142 char nextChar = (
text.Length > 0) ?
text[Mathf.Clamp(pos + 1, 0,
text.Length - 1)] :
'\n';
3143 if (lastChar !=
'.' && nextChar !=
'.')
3147 else if (characterValidation == CharacterValidation.Regex)
3155 else if (characterValidation == CharacterValidation.CustomValidator)
3157 if (m_InputValidator !=
null)
3159 char c = m_InputValidator.Validate(ref
text, ref pos, ch);
3161 stringSelectPositionInternal = stringPositionInternal = pos;
3168 public void ActivateInputField()
3170 if (m_TextComponent ==
null || m_TextComponent.
font ==
null || !IsActive() || !IsInteractable())
3175 if (m_Keyboard !=
null && !m_Keyboard.active)
3177 m_Keyboard.active =
true;
3178 m_Keyboard.text =
m_Text;
3182 m_ShouldActivateNextUpdate =
true;
3185 private void ActivateInputFieldInternal()
3187 if (EventSystem.current ==
null)
3190 if (EventSystem.current.currentSelectedGameObject != gameObject)
3191 EventSystem.current.SetSelectedGameObject(gameObject);
3193 if (TouchScreenKeyboard.isSupported)
3195 if (Input.touchSupported)
3200 m_Keyboard = (inputType == InputType.Password) ?
3201 TouchScreenKeyboard.Open(
m_Text, keyboardType,
false, multiLine,
true) :
3202 TouchScreenKeyboard.Open(
m_Text, keyboardType, inputType == InputType.AutoCorrect, multiLine);
3210 Input.imeCompositionMode = IMECompositionMode.On;
3217 m_AllowInput =
true;
3218 m_OriginalText =
text;
3219 m_WasCanceled =
false;
3224 public override void OnSelect(BaseEventData eventData)
3228 base.OnSelect(eventData);
3231 ActivateInputField();
3234 public virtual void OnPointerClick(PointerEventData eventData)
3236 if (eventData.button != PointerEventData.InputButton.Left)
3239 ActivateInputField();
3242 public void OnControlClick()
3247 public void DeactivateInputField()
3255 m_HasDoneFocusTransition =
false;
3256 m_AllowInput =
false;
3258 if (m_Placeholder !=
null)
3259 m_Placeholder.enabled =
string.IsNullOrEmpty(
m_Text);
3261 if (m_TextComponent !=
null && IsInteractable())
3263 if (m_WasCanceled && m_RestoreOriginalTextOnEscape)
3264 text = m_OriginalText;
3266 if (m_Keyboard !=
null)
3268 m_Keyboard.active =
false;
3272 if (m_ResetOnDeActivation)
3274 m_StringPosition = m_StringSelectPosition = 0;
3275 m_CaretPosition = m_CaretSelectPosition = 0;
3276 m_TextComponent.
rectTransform.localPosition = m_DefaultTransformPosition;
3278 if (caretRectTrans !=
null)
3279 caretRectTrans.localPosition = Vector3.zero;
3285 SendOnEndTextSelection();
3287 Input.imeCompositionMode = IMECompositionMode.Auto;
3290 MarkGeometryAsDirty();
3293 m_IsScrollbarUpdateRequired =
true;
3296 public override void OnDeselect(BaseEventData eventData)
3300 DeactivateInputField();
3302 base.OnDeselect(eventData);
3306 public virtual void OnSubmit(BaseEventData eventData)
3310 if (!IsActive() || !IsInteractable())
3314 m_ShouldActivateNextUpdate =
true;
3325 private void EnforceContentType()
3327 switch (contentType)
3329 case ContentType.Standard:
3337 case ContentType.Autocorrected:
3345 case ContentType.IntegerNumber:
3347 m_LineType = LineType.SingleLine;
3354 case ContentType.DecimalNumber:
3356 m_LineType = LineType.SingleLine;
3363 case ContentType.Alphanumeric:
3365 m_LineType = LineType.SingleLine;
3372 case ContentType.Name:
3374 m_LineType = LineType.SingleLine;
3381 case ContentType.EmailAddress:
3383 m_LineType = LineType.SingleLine;
3390 case ContentType.Password:
3392 m_LineType = LineType.SingleLine;
3399 case ContentType.Pin:
3401 m_LineType = LineType.SingleLine;
3417 void SetTextComponentWrapMode()
3419 if (m_TextComponent ==
null)
3422 if (m_LineType == LineType.SingleLine)
3429 void SetTextComponentRichTextMode()
3431 if (m_TextComponent ==
null)
3434 m_TextComponent.
richText = m_RichText;
3437 void SetToCustomIfContentTypeIsNot(params ContentType[] allowedContentTypes)
3439 if (contentType == ContentType.Custom)
3442 for (
int i = 0; i < allowedContentTypes.Length; i++)
3443 if (contentType == allowedContentTypes[i])
3446 contentType = ContentType.Custom;
3451 if (contentType == ContentType.Custom)
3454 contentType = ContentType.Custom;
3457 void SetToCustom(CharacterValidation characterValidation)
3459 if (contentType == ContentType.Custom)
3461 characterValidation = CharacterValidation.CustomValidator;
3465 contentType = ContentType.Custom;
3466 characterValidation = CharacterValidation.CustomValidator;
3470 protected override void DoStateTransition(SelectionState state,
bool instant)
3472 if (m_HasDoneFocusTransition)
3473 state = SelectionState.Highlighted;
3474 else if (state == SelectionState.Pressed)
3475 m_HasDoneFocusTransition =
true;
3477 base.DoStateTransition(state, instant);
3488 if (placeholderTextComponent !=
null) placeholderTextComponent.
fontSize =
pointSize;
3500 if (placeholderTextComponent !=
null) placeholderTextComponent.
font =
fontAsset;
3509 static class SetPropertyUtility
3511 public static bool SetColor(ref Color currentValue, Color newValue)
3513 if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
3516 currentValue = newValue;
3520 public static bool SetEquatableStruct<T>(ref T currentValue, T newValue) where T : IEquatable<T>
3522 if (currentValue.Equals(newValue))
3525 currentValue = newValue;
3529 public static bool SetStruct<T>(ref T currentValue, T newValue) where T :
struct 3531 if (currentValue.Equals(newValue))
3534 currentValue = newValue;
3538 public static bool SetClass<T>(ref T currentValue, T newValue) where T :
class 3540 if ((currentValue ==
null && newValue ==
null) || (currentValue !=
null && currentValue.Equals(newValue)))
3543 currentValue = newValue;
virtual float preferredHeight
Computed preferred height of the text object.
int index
Index of the character in the raw string.
float fontSize
The point size of the font.
Class which contains information about every element contained within the text object.
bool HasCharacter(int character)
Function to check if a certain character exists in the font asset.
Bounds textBounds
Returns the bounds of the text of the text object.
Base class which contains common properties and functions shared between the TextMeshPro and TextMesh...
new Transform transform
Returns are reference to the Transform
new RectTransform rectTransform
Returns are reference to the RectTransform
virtual Vector4 margin
The margins of the text object.
TMP_FontAsset font
The Font Asset to be assigned to this text object.
bool enableWordWrapping
Controls whether or not word wrapping is applied. When disabled, the text will be displayed on a sing...
override Color color
This is the default vertex color assigned to each vertices. Color tags will override vertex colors un...
string text
A string containing the text to be displayed.
bool richText
Enables or Disables Rich Text Tags
bool ignoreRectMaskCulling
Controls whether or not the text object will be culled when using a 2D Rect Mask.
TMP_TextInfo textInfo
Returns data about the text object which includes information about each character,...