203 lines
7.4 KiB
C#
203 lines
7.4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
using XED.UI;
|
|
|
|
namespace XED.Hierarchy
|
|
{
|
|
public class CustomScrollRect : ScrollRect, IPointerDownHandler, IPointerUpHandler
|
|
{
|
|
public bool passDragToChildren = true;
|
|
public UnityEvent<HierarchyItem, HierarchyItem> setToChildItem;
|
|
public UnityEvent<HierarchyItem, HierarchyItem> setToPriorSiblingItem;
|
|
public UnityEvent<HierarchyItem, HierarchyItem> setToNextSiblingItem;
|
|
//public UnityEvent onSelect;
|
|
public UnityEvent<HierarchyItem> onDragBegin;
|
|
public UnityEvent<HierarchyItem> onDragAndDrop;
|
|
public GameObject itemPopup;
|
|
public GameObject menuPopup;
|
|
public HierarchyItem sourceItem;
|
|
private ScrollItemUI hoverItemUI;
|
|
private Coroutine coroutinePendPopup;
|
|
public override void OnBeginDrag(PointerEventData eventData)
|
|
{
|
|
onDragBegin?.Invoke(sourceItem);
|
|
if (!passDragToChildren)
|
|
{
|
|
base.OnBeginDrag(eventData); // Allow default scrolling if needed
|
|
}
|
|
}
|
|
public override void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
{
|
|
if (hoverItemUI != null) hoverItemUI.DeactivateAllHighlights();
|
|
ScrollItemUI itemUI = GetTargetItemUI(eventData);
|
|
if (itemUI != null)
|
|
{
|
|
RectTransform itemRect = itemUI.GetComponent<RectTransform>();
|
|
Vector2 localPoint;
|
|
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
|
itemRect,
|
|
eventData.position,
|
|
eventData.pressEventCamera,
|
|
out localPoint
|
|
);
|
|
|
|
float rectHeight = itemRect.rect.height;
|
|
float normalizedY = (localPoint.y + rectHeight / 2) / rectHeight;
|
|
|
|
if (normalizedY >= 0.8f) // Upper 20%
|
|
{
|
|
itemUI.ActivateUpperHighlight();
|
|
}
|
|
else if (normalizedY <= 0.2f) // Lower 20%
|
|
{
|
|
itemUI.ActivateLowerHighlight();
|
|
}
|
|
else // Middle 60%
|
|
{
|
|
itemUI.ActivateMidHighlight();
|
|
}
|
|
hoverItemUI = itemUI;
|
|
}
|
|
}
|
|
if (!passDragToChildren)
|
|
{
|
|
base.OnDrag(eventData);
|
|
}
|
|
}
|
|
|
|
public override void OnEndDrag(PointerEventData eventData)
|
|
{
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
{
|
|
if (hoverItemUI != null) hoverItemUI.DeactivateAllHighlights();
|
|
if (coroutinePendPopup != null)
|
|
{
|
|
StopCoroutine(coroutinePendPopup);
|
|
coroutinePendPopup = null;
|
|
}
|
|
itemPopup.SetActive(false);
|
|
//Add to Other Item Hierarchy
|
|
ScrollItemUI itemUI = GetTargetItemUI(eventData);
|
|
if (itemUI != null && sourceItem != null)
|
|
{
|
|
RectTransform itemRect = itemUI.GetComponent<RectTransform>(); // Get RectTransform of the item
|
|
Vector2 localPoint;
|
|
|
|
// Convert screen position to local position within the item
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
|
itemRect,
|
|
eventData.position,
|
|
eventData.pressEventCamera,
|
|
out localPoint
|
|
);
|
|
|
|
float rectHeight = itemRect.rect.height; // Height of the item's RectTransform
|
|
float normalizedY = (localPoint.y + rectHeight / 2) / rectHeight; // Normalize to 0 (bottom) to 1 (top)
|
|
|
|
hoverItemUI = itemUI;
|
|
HierarchyItem destItem = itemUI.currentItem;
|
|
|
|
if (destItem == null)
|
|
return;
|
|
|
|
if (normalizedY >= 0.8f)
|
|
{
|
|
setToPriorSiblingItem?.Invoke(sourceItem, destItem);
|
|
}
|
|
else if (normalizedY <= 0.2f)
|
|
{
|
|
setToNextSiblingItem?.Invoke(sourceItem, destItem);
|
|
}
|
|
else
|
|
{
|
|
setToChildItem?.Invoke(sourceItem, destItem);
|
|
}
|
|
sourceItem = null;
|
|
}
|
|
onDragAndDrop?.Invoke(sourceItem);
|
|
sourceItem = null;
|
|
}
|
|
if (!passDragToChildren)
|
|
{
|
|
base.OnEndDrag(eventData);
|
|
}
|
|
}
|
|
public void OnPointerDown(PointerEventData eventData)
|
|
{
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
{
|
|
ScrollItemUI itemUI = GetTargetItemUI(eventData);
|
|
if (itemUI != null)
|
|
{
|
|
sourceItem = itemUI.currentItem;
|
|
}
|
|
if (sourceItem != null)
|
|
{
|
|
coroutinePendPopup = StartCoroutine(CoroutinePendPopup());
|
|
}
|
|
}
|
|
}
|
|
public void OnPointerUp(PointerEventData eventData)
|
|
{
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
{
|
|
if (coroutinePendPopup != null)
|
|
{
|
|
StopCoroutine(coroutinePendPopup);
|
|
coroutinePendPopup = null;
|
|
}
|
|
itemPopup.SetActive(false);
|
|
}
|
|
else if (eventData.button == PointerEventData.InputButton.Right)
|
|
{
|
|
if (menuPopup != null)
|
|
{
|
|
menuPopup.SetActive(true);
|
|
}
|
|
}
|
|
}
|
|
private ScrollItemUI GetTargetItemUI(PointerEventData eventData)
|
|
{
|
|
PointerEventData pointerData = new PointerEventData(EventSystem.current)
|
|
{
|
|
position = eventData.position // Get mouse position at drag end
|
|
};
|
|
|
|
var results = new List<RaycastResult>();
|
|
EventSystem.current.RaycastAll(pointerData, results); // Raycast against UI elements
|
|
|
|
ScrollItemUI itemUI = null;
|
|
foreach (var result in results)
|
|
{
|
|
itemUI = result.gameObject.GetComponent<ScrollItemUI>();
|
|
if (itemUI != null) // Exclude the dragged item itself
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (itemUI != null && itemUI.GetComponentInParent<CustomScrollRect>() == this)
|
|
return itemUI;
|
|
|
|
return null;
|
|
}
|
|
public bool IsPointerOverScrollRect()
|
|
{
|
|
return RectTransformUtility.RectangleContainsScreenPoint(
|
|
GetComponent<RectTransform>(), Input.mousePosition);
|
|
}
|
|
IEnumerator CoroutinePendPopup()
|
|
{
|
|
yield return new WaitForSeconds(0.1f);
|
|
itemPopup.SetActive(true);
|
|
yield return null;
|
|
}
|
|
}
|
|
}
|