Unity Version: 6.1 (6000.1.7f1)

테스트된 플랫폼: Windows, Web

 

Unity의 TMP_InputField의 텍스트를 선택했을 때 선택한 영역의 텍스트 색상을 변경하는 기능.

 

TMP_InputField Selectin Color

TMP_InputField에는 선택한 영역을 강조하는 기능이 있으며 인스펙터에서 Selection Color 라는 값으로 색상을 변경할 수 있다.

 

 

선택한 영역을 Selection Color로 강조

 

강조 효과는 Selection Color 색상의 직사각형으로 텍스트 뒤에 렌더링해서 선택한 영역을 강조한다.

이때, 텍스트 자체는 변화가 없어서 Selection Color의 값을 설정할 때 텍스트의 색상을 고려해야 된다는 단점이 있다.

 

선택한 영역의 텍스트를 하얀색으로 변경
웹에서 텍스트가 선택되었을 때의 텍스트 색상 변화

 

이러한 단점을 해결하기 위해 TMP_InputField의 Selection 관련 이벤트와 TMP_TextInfo를 활용하여 선택된 영역의 텍스트 색상을 원하는 색으로 변경하는 기능을 개발했다.

 

 

스크립트

using TMPro;
using UnityEngine;

[DisallowMultipleComponent]
public class TMPInputFieldSelectionTextColor : MonoBehaviour
{
    [SerializeField]
    private TMP_InputField inputField;

    [SerializeField]
    private Color selectionTextColor = Color.white;

    private void Awake()
    {
        inputField.onEndTextSelection.AddListener(OnEndTextSelection);
        inputField.onTextSelection.AddListener(OnTextSelection);
    }

    private void OnDestroy()
    {
        inputField.onEndTextSelection.RemoveListener(OnEndTextSelection);
        inputField.onTextSelection.RemoveListener(OnTextSelection);
    }

    private void OnEndTextSelection(string text, int start, int end)
    {
        var textInfo = inputField.textComponent.textInfo;
        for (int i = 0; i < textInfo.meshInfo.Length; i++)
        {
            for (int j = 0; j < textInfo.meshInfo[i].colors32.Length; j++)
            {
                if (!inputField.textComponent.enableVertexGradient)
                {
                    textInfo.meshInfo[i].colors32[j] = inputField.textComponent.color;
                }
            }
        }

        inputField.textComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    }

    private void OnTextSelection(string text, int start, int end)
    {
        int leftIndex = Mathf.Min(start, end);
        int rightIndex = Mathf.Max(start, end);

        var leftColorStartIndex = leftIndex * 4;
        var rightColorEndIndex = rightIndex * 4;

        var textInfo = inputField.textComponent.textInfo;
        var currentCharIndex = 0;
        var notVisibleCount = 0;

        while (currentCharIndex < text.Length)
        {
            if (!textInfo.characterInfo[currentCharIndex].isVisible)
            {
                currentCharIndex++;
                notVisibleCount++;
                continue;
            }
            else
            {
                var startIndex = currentCharIndex * 4;
                var endIndex = startIndex + 4;
                for (int i = startIndex; i < endIndex; i++)
                {
                    if (i >= leftColorStartIndex && i < rightColorEndIndex)
                    {
                        textInfo.meshInfo[0].colors32[i - (notVisibleCount * 4)] = selectionTextColor;
                    }
                    else
                    {
                        if (!inputField.textComponent.enableVertexGradient)
                        {
                            textInfo.meshInfo[0].colors32[i - (notVisibleCount * 4)] = inputField.textComponent.color;
                        }
                    }
                }

                currentCharIndex++;
            }
        }

        inputField.textComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    }

}

 

선택한 영역의 텍스트 색상 변경 컴포넌트

 

TMP_InputField를 연결하면 Awake에서 onEndTextSelection와 onTextSelection 이벤트를 초기화한다.

Selection 관련 이벤트를 받으면 현재 선택된 영역을 계산해서 TMP_TextInfo에서 색상 값을 Selection Text Color 값으로 변경한다.

Posted by Heon_Dev
,