UIToolkit 기본 UI 개발 중
This commit is contained in:
104
Assets/Scripts/UVC/UIToolkit/Common/UTKFoldout.cs
Normal file
104
Assets/Scripts/UVC/UIToolkit/Common/UTKFoldout.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// 접을 수 있는 섹션 컴포넌트.
|
||||
/// Unity Foldout을 래핑하여 커스텀 스타일을 적용합니다.
|
||||
/// </summary>
|
||||
[UxmlElement]
|
||||
public partial class UTKFoldout : Foldout, IDisposable
|
||||
{
|
||||
#region Constants
|
||||
private const string USS_PATH = "UIToolkit/Common/UTKFoldout";
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private bool _disposed;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>펼침/접힘 상태 변경 이벤트</summary>
|
||||
public event Action<bool>? OnValueChanged;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>펼침 상태</summary>
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => value;
|
||||
set => this.value = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public UTKFoldout() : base()
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
|
||||
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
if (uss != null)
|
||||
{
|
||||
styleSheets.Add(uss);
|
||||
}
|
||||
|
||||
SetupStyles();
|
||||
SetupEvents();
|
||||
SubscribeToThemeChanges();
|
||||
}
|
||||
|
||||
public UTKFoldout(string title, bool expanded = true) : this()
|
||||
{
|
||||
text = title;
|
||||
value = expanded;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Setup
|
||||
private void SetupStyles()
|
||||
{
|
||||
AddToClassList("utk-foldout");
|
||||
}
|
||||
|
||||
private void SetupEvents()
|
||||
{
|
||||
this.RegisterValueChangedCallback(OnFoldoutValueChanged);
|
||||
}
|
||||
|
||||
private void SubscribeToThemeChanges()
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnThemeChanged(UTKTheme theme)
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
private void OnFoldoutValueChanged(ChangeEvent<bool> evt)
|
||||
{
|
||||
OnValueChanged?.Invoke(evt.newValue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
OnValueChanged = null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UVC/UIToolkit/Common/UTKFoldout.cs.meta
Normal file
2
Assets/Scripts/UVC/UIToolkit/Common/UTKFoldout.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91209cef71c1caa46abfbcd3fc625650
|
||||
114
Assets/Scripts/UVC/UIToolkit/Common/UTKHelpBox.cs
Normal file
114
Assets/Scripts/UVC/UIToolkit/Common/UTKHelpBox.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// 도움말 박스 컴포넌트.
|
||||
/// Unity HelpBox를 래핑하여 커스텀 스타일을 적용합니다.
|
||||
/// </summary>
|
||||
[UxmlElement]
|
||||
public partial class UTKHelpBox : HelpBox, IDisposable
|
||||
{
|
||||
#region Constants
|
||||
private const string USS_PATH = "UIToolkit/Common/UTKHelpBox";
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private bool _disposed;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>메시지 텍스트</summary>
|
||||
public string Message
|
||||
{
|
||||
get => text;
|
||||
set => text = value;
|
||||
}
|
||||
|
||||
/// <summary>메시지 타입</summary>
|
||||
public new HelpBoxMessageType messageType
|
||||
{
|
||||
get => base.messageType;
|
||||
set
|
||||
{
|
||||
base.messageType = value;
|
||||
UpdateMessageTypeClass();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public UTKHelpBox() : base()
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
|
||||
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
if (uss != null)
|
||||
{
|
||||
styleSheets.Add(uss);
|
||||
}
|
||||
|
||||
SetupStyles();
|
||||
SubscribeToThemeChanges();
|
||||
}
|
||||
|
||||
public UTKHelpBox(string message, HelpBoxMessageType type = HelpBoxMessageType.Info) : this()
|
||||
{
|
||||
text = message;
|
||||
messageType = type;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Setup
|
||||
private void SetupStyles()
|
||||
{
|
||||
AddToClassList("utk-helpbox");
|
||||
UpdateMessageTypeClass();
|
||||
}
|
||||
|
||||
private void UpdateMessageTypeClass()
|
||||
{
|
||||
RemoveFromClassList("utk-helpbox--info");
|
||||
RemoveFromClassList("utk-helpbox--warning");
|
||||
RemoveFromClassList("utk-helpbox--error");
|
||||
RemoveFromClassList("utk-helpbox--none");
|
||||
|
||||
var typeClass = messageType switch
|
||||
{
|
||||
HelpBoxMessageType.Warning => "utk-helpbox--warning",
|
||||
HelpBoxMessageType.Error => "utk-helpbox--error",
|
||||
HelpBoxMessageType.None => "utk-helpbox--none",
|
||||
_ => "utk-helpbox--info"
|
||||
};
|
||||
AddToClassList(typeClass);
|
||||
}
|
||||
|
||||
private void SubscribeToThemeChanges()
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnThemeChanged(UTKTheme theme)
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UVC/UIToolkit/Common/UTKHelpBox.cs.meta
Normal file
2
Assets/Scripts/UVC/UIToolkit/Common/UTKHelpBox.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c202715bb407dd64ab19c99f0e9674a0
|
||||
75
Assets/Scripts/UVC/UIToolkit/Common/UTKScrollView.cs
Normal file
75
Assets/Scripts/UVC/UIToolkit/Common/UTKScrollView.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// 스크롤 뷰 컴포넌트.
|
||||
/// Unity ScrollView를 래핑하여 커스텀 스타일을 적용합니다.
|
||||
/// </summary>
|
||||
[UxmlElement]
|
||||
public partial class UTKScrollView : ScrollView, IDisposable
|
||||
{
|
||||
#region Constants
|
||||
private const string USS_PATH = "UIToolkit/Common/UTKScrollView";
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private bool _disposed;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public UTKScrollView() : base()
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
|
||||
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
if (uss != null)
|
||||
{
|
||||
styleSheets.Add(uss);
|
||||
}
|
||||
|
||||
SetupStyles();
|
||||
SubscribeToThemeChanges();
|
||||
}
|
||||
|
||||
public UTKScrollView(ScrollViewMode mode) : this()
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Setup
|
||||
private void SetupStyles()
|
||||
{
|
||||
AddToClassList("utk-scrollview");
|
||||
}
|
||||
|
||||
private void SubscribeToThemeChanges()
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnThemeChanged(UTKTheme theme)
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d911858474fd4ae49a5306eb5366528c
|
||||
56
Assets/Scripts/UVC/UIToolkit/Common/UTKTooltipExtensions.cs
Normal file
56
Assets/Scripts/UVC/UIToolkit/Common/UTKTooltipExtensions.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
#nullable enable
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// VisualElement에 대한 툴팁 확장 메서드
|
||||
/// </summary>
|
||||
public static class UTKTooltipExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// VisualElement에 툴팁을 설정합니다.
|
||||
/// UTKTooltipManager가 초기화되어 있어야 합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <param name="tooltip">툴팁 텍스트 또는 다국어 키</param>
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T SetTooltip<T>(this T element, string tooltip) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.AttachTooltip(element, tooltip);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VisualElement에서 툴팁을 제거합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T ClearTooltip<T>(this T element) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.DetachTooltip(element);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VisualElement의 툴팁을 업데이트합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <param name="tooltip">새 툴팁 텍스트</param>
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T UpdateTooltip<T>(this T element, string tooltip) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.UpdateTooltip(element, tooltip);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67c6909173307404b849ffdc51eabae6
|
||||
413
Assets/Scripts/UVC/UIToolkit/Common/UTKTooltipManager.cs
Normal file
413
Assets/Scripts/UVC/UIToolkit/Common/UTKTooltipManager.cs
Normal file
@@ -0,0 +1,413 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UVC.Locale;
|
||||
|
||||
namespace UVC.UIToolkit.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// UIToolkit 기반 툴팁 매니저
|
||||
/// VisualElement에 마우스 오버 시 툴팁 표시
|
||||
/// </summary>
|
||||
public class UTKTooltipManager : IDisposable
|
||||
{
|
||||
#region Singleton
|
||||
private static UTKTooltipManager? _instance;
|
||||
public static UTKTooltipManager Instance => _instance ??= new UTKTooltipManager();
|
||||
|
||||
protected UTKTooltipManager() { }
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
private const string UXML_PATH = "UIToolkit/Common/UTKTooltip";
|
||||
private const string USS_PATH = "UIToolkit/Common/UTKTooltip";
|
||||
private const int SHOW_DELAY_MS = 500;
|
||||
private const int POSITION_OFFSET = 10;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private VisualElement? _root;
|
||||
private VisualElement? _tooltipContainer;
|
||||
private Label? _tooltipLabel;
|
||||
private bool _isInitialized;
|
||||
private bool _isVisible;
|
||||
private bool _disposed;
|
||||
|
||||
private CancellationTokenSource? _showDelayCts;
|
||||
private readonly Dictionary<VisualElement, string> _tooltipRegistry = new();
|
||||
private readonly Dictionary<VisualElement, EventCallback<PointerEnterEvent>> _enterCallbacks = new();
|
||||
private readonly Dictionary<VisualElement, EventCallback<PointerLeaveEvent>> _leaveCallbacks = new();
|
||||
private readonly Dictionary<VisualElement, EventCallback<PointerMoveEvent>> _moveCallbacks = new();
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool IsInitialized => _isInitialized;
|
||||
public bool IsVisible => _isVisible;
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
/// <summary>
|
||||
/// 툴팁 매니저를 초기화합니다.
|
||||
/// </summary>
|
||||
/// <param name="root">VisualElement 트리의 루트</param>
|
||||
public void Initialize(VisualElement root)
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
Debug.LogWarning("[UTKTooltipManager] Already initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
_root = root;
|
||||
|
||||
// UXML 로드 시도
|
||||
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
||||
if (visualTree != null)
|
||||
{
|
||||
_tooltipContainer = visualTree.Instantiate();
|
||||
_tooltipContainer.name = "utk-tooltip-container";
|
||||
_tooltipLabel = _tooltipContainer.Q<Label>("tooltip-label");
|
||||
}
|
||||
else
|
||||
{
|
||||
// UXML 없으면 코드로 생성
|
||||
CreateTooltipUI();
|
||||
}
|
||||
|
||||
if (_tooltipContainer != null)
|
||||
{
|
||||
_tooltipContainer.style.position = Position.Absolute;
|
||||
_tooltipContainer.style.display = DisplayStyle.None;
|
||||
_tooltipContainer.pickingMode = PickingMode.Ignore;
|
||||
_root.Add(_tooltipContainer);
|
||||
}
|
||||
|
||||
// 테마 변경 이벤트 구독
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 테마 변경 시 호출
|
||||
/// </summary>
|
||||
private void OnThemeChanged(UTKTheme theme)
|
||||
{
|
||||
if (_tooltipContainer != null)
|
||||
{
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(_tooltipContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 코드로 툴팁 UI 생성
|
||||
/// </summary>
|
||||
private void CreateTooltipUI()
|
||||
{
|
||||
_tooltipContainer = new VisualElement
|
||||
{
|
||||
name = "utk-tooltip-container",
|
||||
pickingMode = PickingMode.Ignore
|
||||
};
|
||||
|
||||
// 테마 적용
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(_tooltipContainer);
|
||||
|
||||
// USS 스타일시트 로드
|
||||
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
if (uss != null)
|
||||
{
|
||||
_tooltipContainer.styleSheets.Add(uss);
|
||||
}
|
||||
|
||||
// USS 클래스로 스타일 적용
|
||||
_tooltipContainer.AddToClassList("utk-tooltip-container");
|
||||
|
||||
_tooltipLabel = new Label
|
||||
{
|
||||
name = "tooltip-label",
|
||||
pickingMode = PickingMode.Ignore
|
||||
};
|
||||
_tooltipLabel.AddToClassList("utk-tooltip-label");
|
||||
|
||||
_tooltipContainer.Add(_tooltipLabel);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// 툴팁을 즉시 표시합니다.
|
||||
/// </summary>
|
||||
/// <param name="text">표시할 텍스트</param>
|
||||
/// <param name="position">화면 좌표</param>
|
||||
public void Show(string text, Vector2 position)
|
||||
{
|
||||
if (!_isInitialized || _tooltipContainer == null || _tooltipLabel == null)
|
||||
return;
|
||||
|
||||
// 다국어 처리
|
||||
string displayText = GetLocalizedText(text);
|
||||
if (string.IsNullOrEmpty(displayText))
|
||||
{
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
_tooltipLabel.text = displayText;
|
||||
_tooltipContainer.style.display = DisplayStyle.Flex;
|
||||
_isVisible = true;
|
||||
|
||||
// 다음 프레임에 위치 조정 (레이아웃 계산 후)
|
||||
_tooltipContainer.schedule.Execute(() => AdjustPosition(position));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지연 후 툴팁을 표시합니다.
|
||||
/// </summary>
|
||||
/// <param name="text">표시할 텍스트</param>
|
||||
/// <param name="position">화면 좌표</param>
|
||||
/// <param name="delayMs">지연 시간 (밀리초)</param>
|
||||
public async UniTaskVoid ShowDelayed(string text, Vector2 position, int delayMs = SHOW_DELAY_MS)
|
||||
{
|
||||
CancelShowDelay();
|
||||
_showDelayCts = new CancellationTokenSource();
|
||||
|
||||
try
|
||||
{
|
||||
await UniTask.Delay(delayMs, cancellationToken: _showDelayCts.Token);
|
||||
Show(text, position);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 취소됨 - 무시
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 툴팁을 숨깁니다.
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
CancelShowDelay();
|
||||
|
||||
if (_tooltipContainer != null)
|
||||
{
|
||||
_tooltipContainer.style.display = DisplayStyle.None;
|
||||
}
|
||||
_isVisible = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VisualElement에 툴팁을 연결합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <param name="tooltip">툴팁 텍스트 또는 다국어 키</param>
|
||||
public void AttachTooltip(VisualElement element, string tooltip)
|
||||
{
|
||||
if (element == null || string.IsNullOrEmpty(tooltip))
|
||||
return;
|
||||
|
||||
// 기존 등록 제거
|
||||
DetachTooltip(element);
|
||||
|
||||
_tooltipRegistry[element] = tooltip;
|
||||
|
||||
// 이벤트 콜백 생성 및 등록
|
||||
EventCallback<PointerEnterEvent> enterCallback = evt =>
|
||||
{
|
||||
if (_tooltipRegistry.TryGetValue(element, out var text))
|
||||
{
|
||||
ShowDelayed(text, evt.position).Forget();
|
||||
}
|
||||
};
|
||||
|
||||
EventCallback<PointerLeaveEvent> leaveCallback = _ => Hide();
|
||||
|
||||
EventCallback<PointerMoveEvent> moveCallback = evt =>
|
||||
{
|
||||
if (_isVisible)
|
||||
{
|
||||
AdjustPosition(evt.position);
|
||||
}
|
||||
};
|
||||
|
||||
element.RegisterCallback(enterCallback);
|
||||
element.RegisterCallback(leaveCallback);
|
||||
element.RegisterCallback(moveCallback);
|
||||
|
||||
_enterCallbacks[element] = enterCallback;
|
||||
_leaveCallbacks[element] = leaveCallback;
|
||||
_moveCallbacks[element] = moveCallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VisualElement에서 툴팁을 제거합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
public void DetachTooltip(VisualElement element)
|
||||
{
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
_tooltipRegistry.Remove(element);
|
||||
|
||||
if (_enterCallbacks.TryGetValue(element, out var enterCallback))
|
||||
{
|
||||
element.UnregisterCallback(enterCallback);
|
||||
_enterCallbacks.Remove(element);
|
||||
}
|
||||
|
||||
if (_leaveCallbacks.TryGetValue(element, out var leaveCallback))
|
||||
{
|
||||
element.UnregisterCallback(leaveCallback);
|
||||
_leaveCallbacks.Remove(element);
|
||||
}
|
||||
|
||||
if (_moveCallbacks.TryGetValue(element, out var moveCallback))
|
||||
{
|
||||
element.UnregisterCallback(moveCallback);
|
||||
_moveCallbacks.Remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 등록된 툴팁 텍스트를 업데이트합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <param name="tooltip">새 툴팁 텍스트</param>
|
||||
public void UpdateTooltip(VisualElement element, string tooltip)
|
||||
{
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(tooltip))
|
||||
{
|
||||
DetachTooltip(element);
|
||||
}
|
||||
else if (_tooltipRegistry.ContainsKey(element))
|
||||
{
|
||||
_tooltipRegistry[element] = tooltip;
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachTooltip(element, tooltip);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// 지연 표시 취소
|
||||
/// </summary>
|
||||
private void CancelShowDelay()
|
||||
{
|
||||
_showDelayCts?.Cancel();
|
||||
_showDelayCts?.Dispose();
|
||||
_showDelayCts = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 다국어 텍스트 가져오기
|
||||
/// </summary>
|
||||
private string GetLocalizedText(string keyOrText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyOrText))
|
||||
return string.Empty;
|
||||
|
||||
// LocalizationManager 연동
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
string localized = LocalizationManager.Instance.GetString(keyOrText);
|
||||
if (!string.IsNullOrEmpty(localized) && localized != keyOrText)
|
||||
{
|
||||
return localized;
|
||||
}
|
||||
}
|
||||
|
||||
return keyOrText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 화면 경계 내에서 위치 조정
|
||||
/// </summary>
|
||||
private void AdjustPosition(Vector2 mousePosition)
|
||||
{
|
||||
if (_tooltipContainer == null || _root == null)
|
||||
return;
|
||||
|
||||
var tooltipSize = new Vector2(
|
||||
_tooltipContainer.resolvedStyle.width,
|
||||
_tooltipContainer.resolvedStyle.height
|
||||
);
|
||||
|
||||
var rootSize = new Vector2(
|
||||
_root.resolvedStyle.width,
|
||||
_root.resolvedStyle.height
|
||||
);
|
||||
|
||||
// 기본 위치: 마우스 오른쪽 아래
|
||||
float x = mousePosition.x + POSITION_OFFSET;
|
||||
float y = mousePosition.y + POSITION_OFFSET;
|
||||
|
||||
// 오른쪽 경계 체크
|
||||
if (x + tooltipSize.x > rootSize.x)
|
||||
{
|
||||
x = mousePosition.x - tooltipSize.x - POSITION_OFFSET;
|
||||
}
|
||||
|
||||
// 아래쪽 경계 체크
|
||||
if (y + tooltipSize.y > rootSize.y)
|
||||
{
|
||||
y = mousePosition.y - tooltipSize.y - POSITION_OFFSET;
|
||||
}
|
||||
|
||||
// 왼쪽/위쪽 경계 체크
|
||||
x = Mathf.Max(0, x);
|
||||
y = Mathf.Max(0, y);
|
||||
|
||||
_tooltipContainer.style.left = x;
|
||||
_tooltipContainer.style.top = y;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
|
||||
// 테마 이벤트 구독 해제
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
|
||||
CancelShowDelay();
|
||||
|
||||
// 모든 등록된 요소에서 이벤트 해제
|
||||
foreach (var element in new List<VisualElement>(_tooltipRegistry.Keys))
|
||||
{
|
||||
DetachTooltip(element);
|
||||
}
|
||||
|
||||
_tooltipRegistry.Clear();
|
||||
_enterCallbacks.Clear();
|
||||
_leaveCallbacks.Clear();
|
||||
_moveCallbacks.Clear();
|
||||
|
||||
// UI 제거
|
||||
_tooltipContainer?.RemoveFromHierarchy();
|
||||
_tooltipContainer = null;
|
||||
_tooltipLabel = null;
|
||||
_root = null;
|
||||
|
||||
_isInitialized = false;
|
||||
_isVisible = false;
|
||||
_instance = null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e9f40c91d7a6e74286d1173edb7a120
|
||||
Reference in New Issue
Block a user