탐색기, 라이브러리, 화면 객체 배치
This commit is contained in:
@@ -135,6 +135,7 @@ namespace UVC.UI.List.Accordion
|
||||
public int? CaptionSize;
|
||||
/// <summary>임의의 태그/키 값.</summary>
|
||||
public string? Tag;
|
||||
public object? Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace UVC.UI.List.Accordion
|
||||
private Image? _dragGhost;
|
||||
private AccordionGridItemData? _boundData;
|
||||
private AccordionList? _list;
|
||||
private RectTransform? _listRectTransform;
|
||||
|
||||
/// <summary>
|
||||
/// 에디터에서 컴포넌트를 추가할 때 기본 레이아웃을 보장합니다.
|
||||
@@ -99,8 +100,9 @@ namespace UVC.UI.List.Accordion
|
||||
{
|
||||
_boundData = data;
|
||||
_list = list;
|
||||
_listRectTransform = list != null ? list.GetComponent<RectTransform>() : null;
|
||||
caption.text = data.Caption;
|
||||
if (data.Image != null) image.sprite = await ResourceManager.LoadOnlyAsync<Sprite>(data.Image);
|
||||
if (data.Image != null) image.sprite = await ResourceManager.LoadSpriteAsync(data.Image);
|
||||
if (data.CaptionColor.HasValue) caption.color = data.CaptionColor.Value;
|
||||
if (data.CaptionSize.HasValue) caption.fontSize = data.CaptionSize.Value;
|
||||
button.onClick.RemoveAllListeners();
|
||||
@@ -119,23 +121,33 @@ namespace UVC.UI.List.Accordion
|
||||
{
|
||||
if (image == null || image.sprite == null || _canvas == null) return;
|
||||
|
||||
// 고스트 생성 (이미지 스프라이트 복사)
|
||||
var go = new GameObject("DragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
|
||||
go.transform.SetParent(_canvas.transform, false);
|
||||
go.transform.SetAsLastSibling();
|
||||
var ghostImg = go.GetComponent<Image>();
|
||||
ghostImg.sprite = image.sprite;
|
||||
ghostImg.preserveAspect = true;
|
||||
ghostImg.raycastTarget = false; // 드래그 중에는 이벤트 차단하지 않도록
|
||||
ghostImg.color = new Color(1f, 1f, 1f, 0.6f);
|
||||
// AccordionList의 이벤트를 통해 드래그 시작 처리
|
||||
if (_boundData != null && _list != null)
|
||||
{
|
||||
_list.HandleGridItemBeginDrag(_boundData, eventData.position);
|
||||
}
|
||||
|
||||
// 크기/위치 초기화
|
||||
var srcRT = image.rectTransform;
|
||||
var dstRT = (RectTransform)go.transform;
|
||||
dstRT.sizeDelta = srcRT.rect.size;
|
||||
SetGhostPosition(eventData, dstRT);
|
||||
// DragImageFollowCursor가 true일 때만 고스트 이미지 생성
|
||||
if (_list != null && _list.DragImageFollowCursor)
|
||||
{
|
||||
// 고스트 생성 (이미지 스프라이트 복사)
|
||||
var go = new GameObject("DragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
|
||||
go.transform.SetParent(_canvas.transform, false);
|
||||
go.transform.SetAsLastSibling();
|
||||
var ghostImg = go.GetComponent<Image>();
|
||||
ghostImg.sprite = image.sprite;
|
||||
ghostImg.preserveAspect = true;
|
||||
ghostImg.raycastTarget = false; // 드래그 중에는 이벤트 차단하지 않도록
|
||||
ghostImg.color = new Color(1f, 1f, 1f, 0.6f);
|
||||
|
||||
_dragGhost = ghostImg;
|
||||
// 크기/위치 초기화
|
||||
var srcRT = image.rectTransform;
|
||||
var dstRT = (RectTransform)go.transform;
|
||||
dstRT.sizeDelta = srcRT.rect.size;
|
||||
SetGhostPosition(eventData, dstRT);
|
||||
|
||||
_dragGhost = ghostImg;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -144,7 +156,25 @@ namespace UVC.UI.List.Accordion
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
// AccordionList의 이벤트를 통해 드래그 중 처리
|
||||
if (_boundData != null && _list != null)
|
||||
{
|
||||
_list.HandleGridItemDrag(_boundData, eventData.position);
|
||||
}
|
||||
|
||||
if (_dragGhost == null || _canvas == null) return;
|
||||
|
||||
// AccordionList 영역 체크하여 고스트 표시/숨김
|
||||
if (_listRectTransform != null)
|
||||
{
|
||||
bool isInsideList = RectTransformUtility.RectangleContainsScreenPoint(
|
||||
_listRectTransform,
|
||||
eventData.position,
|
||||
_canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : _canvas.worldCamera
|
||||
);
|
||||
_dragGhost.enabled = isInsideList;
|
||||
}
|
||||
|
||||
SetGhostPosition(eventData, (RectTransform)_dragGhost.transform);
|
||||
}
|
||||
|
||||
@@ -164,6 +194,7 @@ namespace UVC.UI.List.Accordion
|
||||
// AccordionList의 이벤트를 통해 드롭 처리
|
||||
if (_boundData != null && _list != null)
|
||||
{
|
||||
_list.HandleGridItemEndDrag(_boundData, eventData.position);
|
||||
_list.HandleGridItemDrop(_boundData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace UVC.UI.List.Accordion
|
||||
return;
|
||||
}
|
||||
headerImage.gameObject.SetActive(true);
|
||||
headerImage.sprite = await ResourceManager.LoadOnlyAsync<Sprite>(sprite);
|
||||
headerImage.sprite = await ResourceManager.LoadSpriteAsync(sprite);
|
||||
headerImage.color = color;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace UVC.UI.List.Accordion
|
||||
button.onClick.AddListener(() => _list.HandleHorizontalItemClick(_data, contentSpec));
|
||||
}
|
||||
var img = go.GetComponent<Image>();
|
||||
img.sprite = await ResourceManager.LoadOnlyAsync<Sprite>(icon);
|
||||
img.sprite = await ResourceManager.LoadSpriteAsync(icon);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
|
||||
@@ -37,6 +37,16 @@ namespace UVC.UI.List.Accordion
|
||||
[Header("Root")]
|
||||
[SerializeField] private RectTransform contentRoot = default!; // VerticalLayoutGroup 권장
|
||||
|
||||
[Header("Options")]
|
||||
[Tooltip("드래그 시 그리드 아이템 이미지가 커서를 따라다니도록 설정합니다.")]
|
||||
[SerializeField]
|
||||
public bool dragImageFollowCursor = true;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시 그리드 아이템 이미지가 커서를 따라다니도록 설정합니다.
|
||||
/// </summary>
|
||||
public bool DragImageFollowCursor => dragImageFollowCursor;
|
||||
|
||||
#region 이벤트 (Events)
|
||||
|
||||
/// <summary>
|
||||
@@ -55,6 +65,24 @@ namespace UVC.UI.List.Accordion
|
||||
/// </summary>
|
||||
public Action<AccordionGridItemData>? OnGridItemDrop;
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 시작 이벤트.
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<AccordionGridItemData, Vector2>? OnGridItemBeginDrag;
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 중 이벤트.
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<AccordionGridItemData, Vector2>? OnGridItemDrag;
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 종료 이벤트 (위치 포함).
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<AccordionGridItemData, Vector2>? OnGridItemEndDrag;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -144,6 +172,9 @@ namespace UVC.UI.List.Accordion
|
||||
OnHorizontalItemClick = null;
|
||||
OnGridItemClick = null;
|
||||
OnGridItemDrop = null;
|
||||
OnGridItemBeginDrag = null;
|
||||
OnGridItemDrag = null;
|
||||
OnGridItemEndDrag = null;
|
||||
}
|
||||
|
||||
#region 내부 이벤트 핸들러 (Internal Event Handlers)
|
||||
@@ -172,6 +203,30 @@ namespace UVC.UI.List.Accordion
|
||||
OnGridItemDrop?.Invoke(itemData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 시작 처리 (AccordionGridItemView에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleGridItemBeginDrag(AccordionGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnGridItemBeginDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 중 처리 (AccordionGridItemView에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleGridItemDrag(AccordionGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnGridItemDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 그리드 아이템 드래그 종료 처리 (AccordionGridItemView에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleGridItemEndDrag(AccordionGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnGridItemEndDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace UVC.UI.List.Accordion
|
||||
else
|
||||
{
|
||||
bg.color = expandColor;
|
||||
bg.enabled = false;
|
||||
// bg.enabled = false;
|
||||
}
|
||||
|
||||
if (titleText == null)
|
||||
@@ -112,7 +112,7 @@ namespace UVC.UI.List.Accordion
|
||||
expandButton.onClick.RemoveAllListeners();
|
||||
expandButton.onClick.AddListener(() => Toggle());
|
||||
|
||||
bg.enabled = _data.IsExpanded;
|
||||
// bg.enabled = _data.IsExpanded;
|
||||
expandButton.transform.DOKill(); // 이전 애니메이션이 있으면 종료
|
||||
expandButton.transform.DORotate(new Vector3(0, 0, !_data.IsExpanded ? 0 : 180), 0.0f);
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace UVC.UI.List.Accordion
|
||||
if (_data == null) return;
|
||||
_data.IsExpanded = !_data.IsExpanded;
|
||||
|
||||
bg.enabled = _data.IsExpanded;
|
||||
//bg.enabled = _data.IsExpanded;
|
||||
|
||||
expandButton.transform.DOKill(); // 이전 애니메이션이 있으면 종료
|
||||
expandButton.transform.DORotate(new Vector3(0, 0, !_data.IsExpanded ? 0 : 180), 0.0f);
|
||||
|
||||
@@ -23,6 +23,15 @@ namespace UVC.UI.List
|
||||
|
||||
[SerializeField]
|
||||
protected TextMeshProUGUI searchResultText;
|
||||
|
||||
[Tooltip("드래그 시 그리드 아이템 이미지가 커서를 따라다니도록 설정합니다.")]
|
||||
[SerializeField]
|
||||
public bool dragImageFollowCursor = true;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시 그리드 아이템 이미지가 커서를 따라다니도록 설정합니다.
|
||||
/// </summary>
|
||||
public bool DragImageFollowCursor => dragImageFollowCursor;
|
||||
|
||||
// InfiniteScroll에 표시될 원본 데이터 리스트입니다.
|
||||
protected List<PrefabGridItemData>? data;
|
||||
@@ -42,6 +51,24 @@ namespace UVC.UI.List
|
||||
/// </summary>
|
||||
public Action<PrefabGridItemData>? OnItemDrop;
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 시작 이벤트.
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<PrefabGridItemData, Vector2>? OnItemBeginDrag;
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 중 이벤트.
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<PrefabGridItemData, Vector2>? OnItemDrag;
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 종료 이벤트.
|
||||
/// (itemData, screenPosition)
|
||||
/// </summary>
|
||||
public Action<PrefabGridItemData, Vector2>? OnItemEndDrag;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -93,6 +120,9 @@ namespace UVC.UI.List
|
||||
// 이벤트 핸들러 정리
|
||||
OnItemClick = null;
|
||||
OnItemDrop = null;
|
||||
OnItemBeginDrag = null;
|
||||
OnItemDrag = null;
|
||||
OnItemEndDrag = null;
|
||||
|
||||
// 데이터 참조 정리
|
||||
data?.Clear();
|
||||
@@ -119,6 +149,30 @@ namespace UVC.UI.List
|
||||
OnItemDrop?.Invoke(itemData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 시작 처리 (PrefabGridItem에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleItemBeginDrag(PrefabGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnItemBeginDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 중 처리 (PrefabGridItem에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleItemDrag(PrefabGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnItemDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템 드래그 종료 처리 (PrefabGridItem에서 호출)
|
||||
/// </summary>
|
||||
internal void HandleItemEndDrag(PrefabGridItemData itemData, Vector2 screenPosition)
|
||||
{
|
||||
OnItemEndDrag?.Invoke(itemData, screenPosition);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace UVC.UI.List
|
||||
PrefabGridItemData data = (PrefabGridItemData)scrollData;
|
||||
|
||||
text.text = data.ItemName;
|
||||
image.sprite = await ResourceManager.LoadOnlyAsync<Sprite>(data.ImagePrefabPath);
|
||||
image.sprite = await ResourceManager.LoadSpriteAsync(data.ImagePrefabPath);
|
||||
|
||||
_boundData = data;
|
||||
}
|
||||
@@ -112,23 +112,33 @@ namespace UVC.UI.List
|
||||
{
|
||||
if (image == null || image.sprite == null || _canvas == null) return;
|
||||
|
||||
// 고스트 생성 (이미지 스프라이트 복사)
|
||||
var go = new GameObject("DragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
|
||||
go.transform.SetParent(_canvas.transform, false);
|
||||
go.transform.SetAsLastSibling();
|
||||
var ghostImg = go.GetComponent<Image>();
|
||||
ghostImg.sprite = image.sprite;
|
||||
ghostImg.preserveAspect = true;
|
||||
ghostImg.raycastTarget = false; // 드래그 중에는 이벤트 차단하지 않도록
|
||||
ghostImg.color = new Color(1f, 1f, 1f, 0.6f);
|
||||
// PrefabGrid의 이벤트를 통해 드래그 시작 처리
|
||||
if (_boundData != null && _prefabGrid != null)
|
||||
{
|
||||
_prefabGrid.HandleItemBeginDrag(_boundData, eventData.position);
|
||||
}
|
||||
|
||||
// 크기/위치 초기화
|
||||
var srcRT = image.rectTransform;
|
||||
var dstRT = (RectTransform)go.transform;
|
||||
dstRT.sizeDelta = srcRT.rect.size;
|
||||
SetGhostPosition(eventData, dstRT);
|
||||
// DragImageFollowCursor가 true일 때만 고스트 이미지 생성
|
||||
if (_prefabGrid != null && _prefabGrid.DragImageFollowCursor)
|
||||
{
|
||||
// 고스트 생성 (이미지 스프라이트 복사)
|
||||
var go = new GameObject("DragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
|
||||
go.transform.SetParent(_canvas.transform, false);
|
||||
go.transform.SetAsLastSibling();
|
||||
var ghostImg = go.GetComponent<Image>();
|
||||
ghostImg.sprite = image.sprite;
|
||||
ghostImg.preserveAspect = true;
|
||||
ghostImg.raycastTarget = false; // 드래그 중에는 이벤트 차단하지 않도록
|
||||
ghostImg.color = new Color(1f, 1f, 1f, 0.6f);
|
||||
|
||||
_dragGhost = ghostImg;
|
||||
// 크기/위치 초기화
|
||||
var srcRT = image.rectTransform;
|
||||
var dstRT = (RectTransform)go.transform;
|
||||
dstRT.sizeDelta = srcRT.rect.size;
|
||||
SetGhostPosition(eventData, dstRT);
|
||||
|
||||
_dragGhost = ghostImg;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -137,6 +147,12 @@ namespace UVC.UI.List
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
// PrefabGrid의 이벤트를 통해 드래그 중 처리
|
||||
if (_boundData != null && _prefabGrid != null)
|
||||
{
|
||||
_prefabGrid.HandleItemDrag(_boundData, eventData.position);
|
||||
}
|
||||
|
||||
if (_dragGhost == null || _canvas == null) return;
|
||||
SetGhostPosition(eventData, (RectTransform)_dragGhost.transform);
|
||||
}
|
||||
@@ -157,6 +173,7 @@ namespace UVC.UI.List
|
||||
// PrefabGrid의 이벤트를 통해 드롭 처리
|
||||
if (_boundData != null && _prefabGrid != null)
|
||||
{
|
||||
_prefabGrid.HandleItemEndDrag(_boundData, eventData.position);
|
||||
_prefabGrid.HandleItemDrop(_boundData);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user