UTKImageListWindow 개발 중
This commit is contained in:
1063
Assets/Scripts/UVC/UIToolkit/List/UTKImageList.cs
Normal file
1063
Assets/Scripts/UVC/UIToolkit/List/UTKImageList.cs
Normal file
File diff suppressed because it is too large
Load Diff
2
Assets/Scripts/UVC/UIToolkit/List/UTKImageList.cs.meta
Normal file
2
Assets/Scripts/UVC/UIToolkit/List/UTKImageList.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 491e2649d8c32774ebe15cde9dabd6b8
|
||||
98
Assets/Scripts/UVC/UIToolkit/List/UTKImageListItemData.cs
Normal file
98
Assets/Scripts/UVC/UIToolkit/List/UTKImageListItemData.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace UVC.UIToolkit.List
|
||||
{
|
||||
/// <summary>
|
||||
/// UTKImageList의 아이템 데이터 클래스입니다.
|
||||
/// PrefabGridItemData를 UIToolkit용으로 변환한 클래스입니다.
|
||||
///
|
||||
/// <para><b>개요:</b></para>
|
||||
/// <para>
|
||||
/// 이미지와 텍스트를 포함하는 리스트 아이템의 데이터를 표현합니다.
|
||||
/// 드래그 앤 드롭, 검색 필터링 등의 기능을 지원합니다.
|
||||
/// </para>
|
||||
///
|
||||
/// <para><b>사용 예시:</b></para>
|
||||
/// <code>
|
||||
/// var itemData = new UTKImageListItemData
|
||||
/// {
|
||||
/// externalId = "item-001",
|
||||
/// itemName = "프리팹 이름",
|
||||
/// imagePath = "Prefabs/Thumbnails/item001",
|
||||
/// objectPrefabPath = "Prefabs/Objects/item001"
|
||||
/// };
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public sealed class UTKImageListItemData : IDisposable
|
||||
{
|
||||
#region 필드 (Fields)
|
||||
|
||||
/// <summary>
|
||||
/// ListView/TreeView에서 사용하는 내부 고유 ID입니다.
|
||||
/// UTKImageList.SetData() 호출 시 자동으로 할당됩니다.
|
||||
/// </summary>
|
||||
public int id;
|
||||
|
||||
/// <summary>
|
||||
/// 외부 시스템과의 연동을 위한 식별자입니다.
|
||||
/// 기존 PrefabGridItemData.Id에 해당합니다.
|
||||
/// </summary>
|
||||
public string externalId = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// UI에 표시될 아이템 이름입니다.
|
||||
/// 검색 필터링의 대상이 됩니다.
|
||||
/// </summary>
|
||||
public string itemName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 썸네일 이미지의 리소스 경로입니다.
|
||||
/// Resources 폴더 기준의 상대 경로를 사용합니다.
|
||||
/// </summary>
|
||||
public string imagePath = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 연결된 오브젝트 프리팹의 경로입니다.
|
||||
/// 드래그 앤 드롭 시 인스턴스화할 프리팹을 지정합니다.
|
||||
/// </summary>
|
||||
public string objectPrefabPath = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 사용자 정의 태그 또는 키 값입니다.
|
||||
/// 분류, 필터링 등의 용도로 활용할 수 있습니다.
|
||||
/// </summary>
|
||||
public string? tag;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 아이템의 선택 상태입니다.
|
||||
/// UI와의 동기화에 사용됩니다.
|
||||
/// </summary>
|
||||
public bool isSelected;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// 리소스를 해제합니다.
|
||||
/// 문자열 참조를 정리하여 GC가 수집할 수 있도록 합니다.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
// 문자열 참조 정리 (GC 힌트)
|
||||
externalId = string.Empty;
|
||||
itemName = string.Empty;
|
||||
imagePath = string.Empty;
|
||||
objectPrefabPath = string.Empty;
|
||||
tag = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c3b167a50d09d648a39e244242f3770
|
||||
318
Assets/Scripts/UVC/UIToolkit/Window/UTKImageListWindow.cs
Normal file
318
Assets/Scripts/UVC/UIToolkit/Window/UTKImageListWindow.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UVC.UIToolkit.List;
|
||||
|
||||
namespace UVC.UIToolkit.Window
|
||||
{
|
||||
/// <summary>
|
||||
/// UTKImageList를 래핑하여 윈도우 형태로 제공하는 컴포넌트입니다.
|
||||
/// LibraryWindow의 UIToolkit 버전입니다.
|
||||
///
|
||||
/// <para><b>개요:</b></para>
|
||||
/// <para>
|
||||
/// UTKImageListWindow는 UTKImageList를 내부에 포함하고 헤더(타이틀, 닫기 버튼)를 추가한
|
||||
/// 윈도우 형태의 컴포넌트입니다. 모든 리스트 관련 기능은 내부 UTKImageList에 위임됩니다.
|
||||
/// </para>
|
||||
///
|
||||
/// <para><b>주요 기능:</b></para>
|
||||
/// <list type="bullet">
|
||||
/// <item>윈도우 형태의 UI 제공 (헤더 + 닫기 버튼)</item>
|
||||
/// <item>내부 UTKImageList의 모든 기능 위임</item>
|
||||
/// <item>드래그 앤 드롭 이벤트 전달</item>
|
||||
/// </list>
|
||||
///
|
||||
/// <para><b>UXML에서 사용:</b></para>
|
||||
/// <code>
|
||||
/// <uvc:UTKImageListWindow name="library-window" />
|
||||
/// </code>
|
||||
///
|
||||
/// <para><b>코드에서 사용:</b></para>
|
||||
/// <code>
|
||||
/// var window = root.Q<UTKImageListWindow>();
|
||||
/// window.OnItemClick += (item) => Debug.Log($"클릭: {item.itemName}");
|
||||
/// window.SetData(imageItems);
|
||||
/// </code>
|
||||
///
|
||||
/// <para><b>관련 리소스:</b></para>
|
||||
/// <list type="bullet">
|
||||
/// <item>Resources/UIToolkit/Window/UTKImageListWindow.uxml - 윈도우 레이아웃</item>
|
||||
/// <item>Resources/UIToolkit/Window/UTKImageListWindow.uss - 윈도우 스타일</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[UxmlElement]
|
||||
public partial class UTKImageListWindow : VisualElement, IDisposable
|
||||
{
|
||||
#region 상수 (Constants)
|
||||
|
||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||
private const string UXML_PATH = "UIToolkit/Window/UTKImageListWindow";
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI 컴포넌트 참조 (UI Component References)
|
||||
|
||||
/// <summary>내부 UTKImageList 컴포넌트</summary>
|
||||
private UTKImageList? _imageList;
|
||||
|
||||
/// <summary>윈도우 닫기 버튼</summary>
|
||||
private Button? _closeButton;
|
||||
|
||||
/// <summary>윈도우 제목 라벨</summary>
|
||||
private Label? _titleLabel;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 공개 속성 (Public Properties)
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시 이미지가 커서를 따라다니도록 설정합니다.
|
||||
/// 내부 UTKImageList에 위임됩니다.
|
||||
/// </summary>
|
||||
public bool DragImageFollowCursor
|
||||
{
|
||||
get => _imageList?.DragImageFollowCursor ?? true;
|
||||
set { if (_imageList != null) _imageList.DragImageFollowCursor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 윈도우 제목을 가져오거나 설정합니다.
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get => _titleLabel?.text ?? string.Empty;
|
||||
set { if (_titleLabel != null) _titleLabel.text = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 닫기 버튼 표시 여부를 설정합니다.
|
||||
/// </summary>
|
||||
public bool ShowCloseButton
|
||||
{
|
||||
get => _closeButton?.style.display == DisplayStyle.Flex;
|
||||
set { if (_closeButton != null) _closeButton.style.display = value ? DisplayStyle.Flex : DisplayStyle.None; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 표시 중인 아이템 수를 반환합니다.
|
||||
/// </summary>
|
||||
public int ItemCount => _imageList?.ItemCount ?? 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 이벤트 위임 (Event Delegation)
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 클릭 이벤트입니다.
|
||||
/// 내부 UTKImageList에서 발생한 이벤트를 전달합니다.
|
||||
/// </summary>
|
||||
public Action<UTKImageListItemData>? OnItemClick
|
||||
{
|
||||
get => _imageList?.OnItemClick;
|
||||
set { if (_imageList != null) _imageList.OnItemClick = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드롭 이벤트입니다.
|
||||
/// </summary>
|
||||
public Action<UTKImageListItemData>? OnItemDrop
|
||||
{
|
||||
get => _imageList?.OnItemDrop;
|
||||
set { if (_imageList != null) _imageList.OnItemDrop = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시작 이벤트입니다.
|
||||
/// (아이템 데이터, 화면 좌표)
|
||||
/// </summary>
|
||||
public Action<UTKImageListItemData, Vector2>? OnItemBeginDrag
|
||||
{
|
||||
get => _imageList?.OnItemBeginDrag;
|
||||
set { if (_imageList != null) _imageList.OnItemBeginDrag = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중 이벤트입니다.
|
||||
/// (아이템 데이터, 화면 좌표)
|
||||
/// </summary>
|
||||
public Action<UTKImageListItemData, Vector2>? OnItemDrag
|
||||
{
|
||||
get => _imageList?.OnItemDrag;
|
||||
set { if (_imageList != null) _imageList.OnItemDrag = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 종료 이벤트입니다.
|
||||
/// (아이템 데이터, 화면 좌표)
|
||||
/// </summary>
|
||||
public Action<UTKImageListItemData, Vector2>? OnItemEndDrag
|
||||
{
|
||||
get => _imageList?.OnItemEndDrag;
|
||||
set { if (_imageList != null) _imageList.OnItemEndDrag = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 윈도우가 닫힐 때(숨겨질 때) 발생합니다.
|
||||
/// 닫기 버튼 클릭 또는 Close() 메서드 호출 시 트리거됩니다.
|
||||
/// </summary>
|
||||
public event Action? OnClosed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 생성자 (Constructor)
|
||||
|
||||
/// <summary>
|
||||
/// UTKImageListWindow 컴포넌트를 초기화합니다.
|
||||
/// UXML 템플릿을 로드하고 내부 UTKImageList를 설정합니다.
|
||||
/// </summary>
|
||||
public UTKImageListWindow()
|
||||
{
|
||||
// 1. 메인 UXML 로드 및 복제
|
||||
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
||||
if (visualTree == null)
|
||||
{
|
||||
Debug.LogError($"[UTKImageListWindow] UXML not found at: {UXML_PATH}");
|
||||
return;
|
||||
}
|
||||
visualTree.CloneTree(this);
|
||||
|
||||
// 2. 내부 UTKImageList 찾기 (UXML에서 생성된 컴포넌트)
|
||||
_imageList = this.Q<UTKImageList>();
|
||||
if (_imageList == null)
|
||||
{
|
||||
Debug.LogError("[UTKImageListWindow] UTKImageList not found in UXML");
|
||||
}
|
||||
|
||||
// 3. 헤더 요소 참조
|
||||
_titleLabel = this.Q<Label>("title");
|
||||
_closeButton = this.Q<Button>("close-btn");
|
||||
|
||||
// 4. 닫기 버튼 이벤트 연결
|
||||
if (_closeButton != null)
|
||||
{
|
||||
_closeButton.clicked += OnCloseButtonClicked;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 공개 메서드 (Public Methods)
|
||||
|
||||
/// <summary>
|
||||
/// 윈도우를 화면에 표시합니다.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
this.style.display = DisplayStyle.Flex;
|
||||
_imageList?.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 윈도우를 화면에서 숨깁니다.
|
||||
/// OnClosed 이벤트가 발생합니다.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
this.style.display = DisplayStyle.None;
|
||||
OnClosed?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 리스트 데이터를 설정합니다.
|
||||
/// 내부 UTKImageList에 위임됩니다.
|
||||
/// </summary>
|
||||
/// <param name="data">표시할 아이템 데이터 리스트</param>
|
||||
public void SetData(List<UTKImageListItemData> data)
|
||||
{
|
||||
_imageList?.SetData(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 리스트에 단일 아이템을 추가합니다.
|
||||
/// </summary>
|
||||
/// <param name="item">추가할 아이템 데이터</param>
|
||||
public void AddItem(UTKImageListItemData item)
|
||||
{
|
||||
_imageList?.AddItem(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 리스트에서 아이템을 제거합니다.
|
||||
/// </summary>
|
||||
/// <param name="item">제거할 아이템 데이터</param>
|
||||
/// <returns>제거 성공 여부</returns>
|
||||
public bool RemoveItem(UTKImageListItemData item)
|
||||
{
|
||||
return _imageList?.RemoveItem(item) ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 데이터를 제거합니다.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_imageList?.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 검색어로 검색을 실행합니다.
|
||||
/// </summary>
|
||||
/// <param name="query">검색어</param>
|
||||
public void ApplySearch(string query)
|
||||
{
|
||||
_imageList?.ApplySearch(query);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 이벤트 핸들러 (Event Handlers)
|
||||
|
||||
/// <summary>
|
||||
/// 닫기 버튼 클릭 이벤트를 처리합니다.
|
||||
/// </summary>
|
||||
private void OnCloseButtonClicked()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
// 내부 UTKImageList 정리
|
||||
_imageList?.Dispose();
|
||||
_imageList = null;
|
||||
|
||||
// 닫기 버튼 이벤트 해제
|
||||
if (_closeButton != null)
|
||||
{
|
||||
_closeButton.clicked -= OnCloseButtonClicked;
|
||||
}
|
||||
|
||||
// 외부 이벤트 구독자 정리
|
||||
OnClosed = null;
|
||||
|
||||
// UI 참조 정리
|
||||
_closeButton = null;
|
||||
_titleLabel = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a50040f6ea59514ab3a7a793a1b2dd8
|
||||
Reference in New Issue
Block a user