본문 바로가기
개발/Unity

Unity) TextMeshPro 특정단어 Click 이벤트 ( HyperText / Text Click)

by 테샤르 2024. 2. 5.

 TextMeshPro 특정단어 Click 이벤트

 ( HyperText / Text Click)

Text의 특정 단어를 클릭하면 처리하는 하이퍼텍스트(클릭시 링크) 하는 기능이 필요해서 

사용방법을 간단하게 포스팅한다.

Text에 다음과 같은 형태로 작업하면 된다.

<link="ID">Click Action</link>

 

반응형

 

여기서 "ID" 라고하는건 고유하게 식별이 가능하기 위한 텍스트로 가독성있는 단어로 하면 된다.

 

해당 스크립트를 추가하고 이벤트에 대한 설정을 하면 된다.

< TextMeshProTextLink 스크립트 >

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

/// <summary>
/// Text Link Tag Event Class
/// </summary>
[RequireComponent(typeof(TextMeshProUGUI))]
public class TextMeshProTextLink : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
    private bool Validtext = false;
    private bool IsClick = false;

    [SerializeField]
    private TextMeshProUGUI linkText;
    public TextMeshProUGUI LinkText
    {
        get
        {
            return linkText;
        }
        set
        {
            linkText = value;
        }
    }

    private int currenthoverID = -1;

    private Dictionary<int, Action> hoverAction = new Dictionary<int, Action>();
    private Dictionary<int, Action> leaveAction = new Dictionary<int, Action>();
    private Dictionary<int, Action> clickAction = new Dictionary<int, Action>();

    public void RegisterHoverOnID(string _id, Action _hoverAction, Action _leaveAction)
    {
        var index = TMP_TextUtilities.GetSimpleHashCode(_id);
        hoverAction[index] = _hoverAction;
        leaveAction[index] = _leaveAction;
    }

    public void RegisterClickAcion(string _id, Action _clickAction) => clickAction[TMP_TextUtilities.GetSimpleHashCode(_id)] = _clickAction;
    public void OnPointerEnter(PointerEventData eventData) => Validtext = true;
    public void OnPointerExit(PointerEventData eventData) => Validtext = false;
    public void OnPointerClick(PointerEventData eventData)
	{
    	int hoverdLinkIndex = TMP_TextUtilities.FindIntersectingLink(linkText, Input.mousePosition, Camera.main);
		if (hoverdLinkIndex == -1)
			return;
		IsClick = true;
	}

    private void ExecuteID(Dictionary<int, Action> dict, int id)
    {
        if (dict.TryGetValue(id, out Action action))
            action?.Invoke();
    }

    public void Clear()
    {
        Validtext = false;
        IsClick = false;
        currenthoverID = -1;

        hoverAction.Clear();
        leaveAction.Clear();
        clickAction.Clear();
    }

    void LateUpdate()
    {
        if (Validtext)
        {
            int hoverdLinkIndex = TMP_TextUtilities.FindIntersectingLink(linkText, Input.mousePosition, Camera.main);
            if (hoverdLinkIndex == -1)
            {
                if (currenthoverID != -1)
                    ExecuteID(leaveAction, currenthoverID);
                currenthoverID = -1;
                return;
            }

            int hoveredLinkHash = linkText.textInfo.linkInfo[hoverdLinkIndex].hashCode;
            if (hoveredLinkHash != currenthoverID) 
            {
                if (currenthoverID != -1)
                    ExecuteID(leaveAction, currenthoverID);

                ExecuteID(hoverAction, hoveredLinkHash);
                currenthoverID = hoveredLinkHash;
            }

            if (IsClick)
                ExecuteID(clickAction, hoveredLinkHash);

            IsClick = false;
        }
    }
}

 

< 테스트 코드 >

 

  내용
목표  `Simple Click Function Text Code in TextMehsPro`
Click 에 마우스를 올리면 컬러변경 (Red <> Blue), 클릭시 Google Home 으로 이동

기능은 Click 하는 기능과 Hover  / Leave 에 대한 UnityAction 을 등록하는 코드이다.

  [SerializeField]
 private TextMeshProTextLink  information = default;

 [Header("Link")]
 [SerializeField]
 private string linkID = default;

 [Header("치환할 단어")]
 [SerializeField]
 private string replaceWorld = default;

 [SerializeField]
 private UnityAction linkAction = default;
 
 private void initializeAction()
{
    if (IsVailed() == false)
        return;
    information.RegisterClickAcion(linkID, () => {
        Debug.Log($"Text Link Click : {linkID} !!");
        linkAction.Invoke();
    });

    information.RegisterHoverOnID(linkID, () =>
    {
        UpdateTextColor(Color.red);
    },
    () =>
    {
        UpdateTextColor(Color.blue);
    });
 private bool IsVailed()
 {
     if (information == null)
         return false;
     if (information.LinkText == null)
         return false;
     return true;
 }

 private void UpdateTextColor(Color _color)
 {
     if(IsVailed()==false)
         return;

     string contents = information.LinkText.text;
     var result = contents.Replace(replaceWorld,
         $"<color=#{ColorUtility.ToHtmlStringRGB(_color)}>{replaceWorld}</color>"
     );
     information.LinkText.text = result;
 }

 

 

 

TextMeshPro -Text Link : [링크]

 

Text Link | TextMeshPro | 4.0.0-pre.2

Text Link You can use my link to add link metadata to a text segment. The link ID should be unique to allow you to retrieve its ID and link text content when the user interacts with your text. You do not have to give each link a unique ID. You can reuse ID

docs.unity3d.com

 

★☆

 

반응형

댓글