183 lines
9.3 KiB
C#
183 lines
9.3 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems; // IPointerEnterHandler, IPointerExitHandler 인터페이스 사용
|
|
using UnityEngine.UI; // Selectable 컴포넌트 사용 (버튼 등의 상호작용 가능 여부 확인)
|
|
|
|
namespace UVC.UI.Tooltip
|
|
{
|
|
/// <summary>
|
|
/// UI 요소에 부착하여 마우스 오버 시 툴팁을 표시하고 마우스 아웃 시 툴팁을 숨기는 기능을 제공합니다.
|
|
/// TooltipManager와 함께 작동하며, 마우스 이벤트 감지 후 TooltipManager에 툴팁 관리를 위임합니다.
|
|
///
|
|
/// 사용 방법:
|
|
/// 1. 툴팁을 표시하고자 하는 UI 요소(예: Button, Image 등)에 이 컴포넌트를 추가합니다.
|
|
/// 2. Inspector 창이나 코드를 통해 'Tooltip' 프로퍼티에 표시할 텍스트 또는 다국어 키를 설정합니다.
|
|
/// 3. TooltipManager가 초기화되어 있어야 하며, 이 핸들러의 액션들을 TooltipManager의 메서드에 연결해야 합니다.
|
|
/// (일반적으로 다른 관리 클래스(예: ToolbarView)에서 이 연결을 수행합니다.)
|
|
///
|
|
/// 예시 (ToolbarView.cs에서의 설정 부분):
|
|
/// <code>
|
|
/// // ... ToolbarView.cs 내에서 버튼 생성 시 ...
|
|
/// GameObject buttonGameObject = Instantiate(buttonPrefab);
|
|
/// TooltipHandler tooltipHandler = buttonGameObject.AddComponent<TooltipHandler>();
|
|
/// tooltipHandler.Tooltip = "my_tooltip_key"; // 표시할 툴팁 내용 또는 다국어 키
|
|
///
|
|
/// // TooltipManager의 메서드와 연결
|
|
/// if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized)
|
|
/// {
|
|
/// tooltipHandler.OnPointerEnterAction = TooltipManager.Instance.HandlePointerEnter;
|
|
/// tooltipHandler.OnPointerExitAction = TooltipManager.Instance.HandlePointerExit;
|
|
/// }
|
|
/// </code>
|
|
/// </summary>
|
|
public class TooltipHandler : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
|
|
{
|
|
/// <summary>
|
|
/// 마우스 포인터가 UI 요소에 진입했을 때 호출될 액션입니다.
|
|
/// TooltipManager.Instance.HandlePointerEnter 메서드에 연결됩니다.
|
|
/// 첫 번째 string 매개변수는 툴팁 내용(또는 키), 두 번째 Vector3는 마우스 위치입니다.
|
|
/// </summary>
|
|
public System.Action<string, Vector3> OnPointerEnterAction;
|
|
|
|
/// <summary>
|
|
/// 마우스 포인터가 UI 요소에서 벗어났을 때 호출될 액션입니다.
|
|
/// TooltipManager.Instance.HandlePointerExit 메서드에 연결됩니다.
|
|
/// </summary>
|
|
public System.Action OnPointerExitAction;
|
|
|
|
/// <summary>
|
|
/// 이 UI 요소에 표시될 툴팁의 내용 또는 다국어 키입니다.
|
|
/// Inspector에서 직접 설정하거나 코드로 할당할 수 있습니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// TooltipHandler handler = myButton.GetComponent<TooltipHandler>();
|
|
/// if (handler != null)
|
|
/// {
|
|
/// handler.Tooltip = "버튼_설명_키"; // 다국어 키 사용
|
|
/// // 또는 handler.Tooltip = "이 버튼은 저장 기능을 수행합니다."; // 직접 텍스트 사용
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public string Tooltip { get; set; }
|
|
|
|
private Coroutine _showTooltipCoroutine; // 툴팁 표시 지연을 위한 코루틴 참조
|
|
private const float TooltipDelay = 0.5f; // 툴팁 표시까지의 지연 시간 (초 단위)
|
|
private const float MouseMoveThreshold = 5f; // 마우스 이동 감지 임계값 (픽셀 단위)
|
|
|
|
/// <summary>
|
|
/// 마우스 포인터가 이 UI 요소의 영역 안으로 들어왔을 때 호출됩니다. (IPointerEnterHandler 인터페이스 구현)
|
|
/// 설정된 Tooltip 내용이 있고, 연결된 Selectable 컴포넌트가 상호작용 가능 상태일 때만 작동합니다.
|
|
/// 지정된 지연 시간(TooltipDelay) 후에 OnPointerEnterAction을 호출하여 툴팁 표시를 요청합니다.
|
|
/// </summary>
|
|
/// <param name="eventData">포인터 이벤트 데이터입니다.</param>
|
|
public void OnPointerEnter(PointerEventData eventData)
|
|
{
|
|
// 툴팁 내용이 있고, 이 게임오브젝트에 Selectable 컴포넌트가 있거나 없거나, 있다면 interactable 상태일 때만
|
|
//Selectable selectable = gameObject.GetComponent<Selectable>();
|
|
if (!string.IsNullOrEmpty(Tooltip))// && (selectable == null || selectable.interactable))
|
|
{
|
|
// 이전에 실행 중이던 코루틴이 있다면 중지 (빠르게 들어왔다 나갔다 반복하는 경우 대비)
|
|
if (_showTooltipCoroutine != null)
|
|
{
|
|
StopCoroutine(_showTooltipCoroutine);
|
|
}
|
|
// 새 코루틴 시작하여 지연 후 툴팁 표시
|
|
_showTooltipCoroutine = StartCoroutine(ShowTooltipAfterDelayCoroutine(Tooltip, Input.mousePosition));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 지정된 시간(TooltipDelay)만큼 대기한 후, OnPointerEnterAction을 호출하여 툴팁 표시를 요청하는 코루틴입니다.
|
|
/// </summary>
|
|
/// <param name="tooltip">표시할 툴팁 내용 또는 다국어 키입니다.</param>
|
|
/// <param name="initialMousePosition">현재 마우스 포인터의 화면 좌표입니다.</param>
|
|
private IEnumerator ShowTooltipAfterDelayCoroutine(string tooltip, Vector3 initialMousePosition)
|
|
{
|
|
float stillTime = 0f; // 마우스가 움직이지 않은 시간
|
|
Vector3 lastMousePosition = initialMousePosition;
|
|
|
|
while (stillTime < TooltipDelay)
|
|
{
|
|
// 현재 마우스 위치와 마지막 기록된 위치 간의 거리 계산
|
|
float distance = Vector3.Distance(Input.mousePosition, lastMousePosition);
|
|
|
|
// 거리가 임계값을 초과하면 마우스가 움직인 것으로 간주
|
|
if (distance > MouseMoveThreshold)
|
|
{
|
|
// 마우스가 움직였으므로 정지 시간을 리셋
|
|
stillTime = 0f;
|
|
lastMousePosition = Input.mousePosition;
|
|
}
|
|
else
|
|
{
|
|
// 마우스가 거의 움직이지 않으면 정지 시간 증가
|
|
stillTime += Time.unscaledDeltaTime;
|
|
}
|
|
|
|
yield return null; // 다음 프레임까지 대기
|
|
}
|
|
|
|
// TooltipDelay 시간 동안 마우스가 거의 움직이지 않았으면 툴팁 표시
|
|
_showTooltipCoroutine = null; // 코루틴 완료 후 참조 null 처리
|
|
OnPointerEnterAction?.Invoke(tooltip, Input.mousePosition); // 현재 마우스 위치 사용
|
|
// TooltipManager의 메서드와 연결
|
|
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized)
|
|
{
|
|
TooltipManager.Instance.HandlePointerEnter(tooltip, Input.mousePosition);
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 마우스 포인터가 이 UI 요소의 영역 밖으로 나갔을 때 호출됩니다. (IPointerExitHandler 인터페이스 구현)
|
|
/// 실행 중인 툴팁 표시 코루틴이 있다면 중지하고, OnPointerExitAction을 호출하여 툴팁 숨김을 요청합니다.
|
|
/// </summary>
|
|
/// <param name="eventData">포인터 이벤트 데이터입니다.</param>
|
|
public void OnPointerExit(PointerEventData eventData)
|
|
{
|
|
// 실행 중인 툴팁 표시 코루틴이 있다면 중지 (마우스가 나가면 지연 중이던 툴팁 표시 취소)
|
|
if (_showTooltipCoroutine != null)
|
|
{
|
|
StopCoroutine(_showTooltipCoroutine);
|
|
_showTooltipCoroutine = null;
|
|
}
|
|
OnPointerExitAction?.Invoke(); // 연결된 액션 호출 (TooltipManager.HandlePointerExit)
|
|
if (TooltipManager.Instance != null && TooltipManager.Instance.IsInitialized)
|
|
{
|
|
TooltipManager.Instance.HandlePointerExit();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이 MonoBehaviour가 비활성화될 때 호출됩니다.
|
|
/// 실행 중인 코루틴이 있다면 정리합니다.
|
|
/// </summary>
|
|
private void OnDisable()
|
|
{
|
|
if (_showTooltipCoroutine != null)
|
|
{
|
|
StopCoroutine(_showTooltipCoroutine);
|
|
_showTooltipCoroutine = null;
|
|
}
|
|
// 만약 OnPointerExitAction이 즉시 호출되어야 한다면 아래 코드 추가
|
|
// OnPointerExitAction?.Invoke();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이 MonoBehaviour가 파괴될 때 호출됩니다.
|
|
/// 실행 중인 코루틴이 있다면 정리합니다.
|
|
/// </summary>
|
|
private void OnDestroy()
|
|
{
|
|
if (_showTooltipCoroutine != null)
|
|
{
|
|
StopCoroutine(_showTooltipCoroutine);
|
|
_showTooltipCoroutine = null;
|
|
}
|
|
// OnPointerEnterAction 및 OnPointerExitAction 참조 해제 (필요 시)
|
|
OnPointerEnterAction = null;
|
|
OnPointerExitAction = null;
|
|
}
|
|
}
|
|
} |