Files
XRLib/Assets/Scripts/UVC/UIToolkit/Menu/UTKTopMenuItem.cs
2026-02-13 20:27:31 +09:00

182 lines
4.6 KiB
C#

#nullable enable
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// UIToolkit 기반 개별 메뉴 아이템 UI 컴포넌트입니다 (Label 기반).
/// 메뉴 아이템의 시각적 표현과 클릭 이벤트를 처리합니다.
/// </summary>
/// <example>
/// <code>
/// // 메뉴 아이템 생성
/// var menuItem = new UTKTopMenuItem();
/// menuItem.SetData(menuItemData);
///
/// // 클릭 이벤트 구독
/// menuItem.OnClicked += (data) => Debug.Log($"Clicked: {data.ItemId}");
///
/// // 사용 후 정리
/// menuItem.Dispose();
/// </code>
/// </example>
[UxmlElement]
public partial class UTKTopMenuItem : UTKMenuItemBase
{
#region Constants
private const string UXML_PATH = "UIToolkit/Menu/UTKMenuItem";
private const string USS_PATH = "UIToolkit/Menu/UTKMenuItemUss";
#endregion
#region Fields
private UTKLabel? _label;
#endregion
#region Constructor
/// <summary>
/// UTKTopMenuItem의 새 인스턴스를 초기화합니다.
/// </summary>
public UTKTopMenuItem() : base()
{
_ussPath = USS_PATH;
}
#endregion
#region Setup
/// <summary>
/// UI를 생성합니다.
/// </summary>
protected override void CreateUI()
{
AddToClassList("utk-menu-item");
var asset = Resources.Load<VisualTreeAsset>(UXML_PATH);
if (asset != null)
{
CreateUIFromUxml(asset);
}
else
{
CreateUIFallback();
}
}
/// <summary>
/// UXML에서 UI를 생성합니다.
/// </summary>
/// <param name="asset">UXML 에셋</param>
private void CreateUIFromUxml(VisualTreeAsset asset)
{
var root = asset.Instantiate();
// USS를 root에 추가
var uss = Resources.Load<StyleSheet>(USS_PATH);
if (uss != null)
{
root.styleSheets.Add(uss);
}
// UI 요소 참조 가져오기 (쿼리 캐싱)
_button = root.Q<Button>("menu-button");
_label = root.Q<UTKLabel>("label");
_arrow = root.Q<VisualElement>("arrow");
Add(root);
// 버튼 클릭 이벤트 등록
if (_button != null)
{
_onClickCallback = OnButtonClicked;
_button.RegisterCallback(_onClickCallback);
}
}
/// <summary>
/// Fallback UI를 생성합니다 (UXML 로드 실패 시).
/// </summary>
private void CreateUIFallback()
{
_button = new Button();
_button.name = "menu-button";
_button.AddToClassList("menu-item");
_label = new UTKLabel();
_label.name = "label";
_label.AddToClassList("menu-item__label");
_arrow = new VisualElement();
_arrow.name = "arrow";
_arrow.AddToClassList("menu-item__arrow");
_arrow.style.display = DisplayStyle.None;
_button.Add(_label);
_button.Add(_arrow);
Add(_button);
_onClickCallback = OnButtonClicked;
_button.RegisterCallback(_onClickCallback);
}
#endregion
#region Protected Methods
/// <summary>
/// UI를 업데이트합니다.
/// </summary>
protected override void UpdateUI()
{
if (_label != null && !string.IsNullOrEmpty(DisplayName))
{
// 다국어 적용
if (_locManager != null)
{
_label.Text = _locManager.GetString(DisplayName);
}
else
{
_label.Text = DisplayName;
}
}
UpdateOpacity();
}
/// <summary>
/// 활성화 상태에 따라 투명도를 업데이트합니다.
/// </summary>
protected override void UpdateOpacity()
{
if (_label != null)
{
_label.style.opacity = IsEnabled ? 1f : 0.5f;
}
}
#endregion
#region IDisposable
/// <summary>
/// 리소스를 정리합니다.
/// </summary>
public override void Dispose()
{
base.Dispose();
_label = null;
}
#endregion
}
}