529 lines
15 KiB
C#
529 lines
15 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
public class equipItemPrefab : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
|
|
{
|
|
[Header("so")]
|
|
public equipmentSO itemSO;
|
|
|
|
[Header("info")]
|
|
public Image itemBtm;
|
|
public Color[] itemBtmColors;
|
|
public Image itemProfileIcon;
|
|
public string itemType;
|
|
public string itemName;
|
|
public Button itemButton;
|
|
|
|
[Header("description popup")]
|
|
public GameObject eqpmtDesPrefab;
|
|
public Transform popupParent;
|
|
public float popupHorizontalOffset = 40f;
|
|
|
|
[Header("events")]
|
|
public UnityEvent<equipmentSO> onItemClicked;
|
|
|
|
[Header("interaction")]
|
|
public bool allowDrag = true;
|
|
public bool allowQuickTransfer = true;
|
|
|
|
private Action<equipmentSO> clickHandler;
|
|
private GameObject spawnedDescription;
|
|
private bool suppressNextClick;
|
|
private Canvas rootCanvas;
|
|
private Camera uiCamera;
|
|
private GameObject dragGhost;
|
|
private RectTransform dragGhostRect;
|
|
private bool isDraggingWithLeftButton;
|
|
|
|
private void Awake()
|
|
{
|
|
if (itemButton == null)
|
|
{
|
|
itemButton = GetComponent<Button>();
|
|
}
|
|
|
|
if (itemButton != null)
|
|
{
|
|
itemButton.onClick.RemoveListener(HandleClicked);
|
|
itemButton.onClick.AddListener(HandleClicked);
|
|
}
|
|
|
|
rootCanvas = GetComponentInParent<Canvas>();
|
|
if (rootCanvas != null && rootCanvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
|
{
|
|
uiCamera = rootCanvas.worldCamera;
|
|
}
|
|
}
|
|
|
|
public void Bind(equipmentSO so, Action<equipmentSO> onClick = null)
|
|
{
|
|
itemSO = so;
|
|
clickHandler = onClick;
|
|
|
|
if (itemSO == null)
|
|
{
|
|
ApplyProfileSprite(null);
|
|
ApplyBottomColor(0);
|
|
return;
|
|
}
|
|
|
|
equipmentSO.EquipmentTierPresentation presentation = itemSO.GetCurrentTierPresentation();
|
|
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
|
|
ApplyProfileSprite(displaySprite);
|
|
ApplyBottomColor(GetQualityColorIndex(itemSO.level));
|
|
}
|
|
|
|
private void HandleClicked()
|
|
{
|
|
if (suppressNextClick)
|
|
{
|
|
suppressNextClick = false;
|
|
return;
|
|
}
|
|
|
|
if (itemSO == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ToggleDescriptionPopup();
|
|
clickHandler?.Invoke(itemSO);
|
|
onItemClicked?.Invoke(itemSO);
|
|
}
|
|
|
|
private void ToggleDescriptionPopup()
|
|
{
|
|
if (eqpmtDesPrefab == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (spawnedDescription != null)
|
|
{
|
|
Destroy(spawnedDescription);
|
|
spawnedDescription = null;
|
|
return;
|
|
}
|
|
|
|
Transform targetParent = ResolvePopupParent();
|
|
if (targetParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
spawnedDescription = Instantiate(eqpmtDesPrefab, targetParent);
|
|
spawnedDescription.name = $"{itemSO.name}_Description";
|
|
spawnedDescription.SetActive(true);
|
|
spawnedDescription.transform.SetAsLastSibling();
|
|
|
|
eqpmtDesPrefab description = spawnedDescription.GetComponent<eqpmtDesPrefab>();
|
|
if (description != null)
|
|
{
|
|
description.IgnoreCloseUntilClickReleased();
|
|
description.Bind(itemSO);
|
|
}
|
|
|
|
PositionPopup(spawnedDescription.transform as RectTransform, targetParent as RectTransform);
|
|
}
|
|
|
|
private Transform ResolvePopupParent()
|
|
{
|
|
if (popupParent != null && popupParent != transform && !popupParent.IsChildOf(transform))
|
|
{
|
|
return popupParent;
|
|
}
|
|
|
|
Canvas canvas = GetComponentInParent<Canvas>();
|
|
return canvas != null ? canvas.transform : transform.parent;
|
|
}
|
|
|
|
private void PositionPopup(RectTransform popupRect, RectTransform parentRect)
|
|
{
|
|
if (popupRect == null || parentRect == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(popupRect);
|
|
RectTransform itemRect = transform as RectTransform;
|
|
if (itemRect == null)
|
|
{
|
|
popupRect.anchoredPosition = Vector2.zero;
|
|
return;
|
|
}
|
|
|
|
Canvas canvas = GetComponentInParent<Canvas>();
|
|
Camera localUiCamera = null;
|
|
if (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
|
{
|
|
localUiCamera = canvas.worldCamera;
|
|
}
|
|
|
|
Vector3 worldCenter = itemRect.TransformPoint(itemRect.rect.center);
|
|
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(localUiCamera, worldCenter);
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRect, screenPoint, localUiCamera, out Vector2 localPoint);
|
|
|
|
float viewportX = localUiCamera != null
|
|
? localUiCamera.ScreenToViewportPoint(screenPoint).x
|
|
: screenPoint.x / Mathf.Max(1f, Screen.width);
|
|
|
|
bool placeLeft = viewportX > 0.5f;
|
|
float halfItemWidth = itemRect.rect.width * 0.5f;
|
|
float halfPopupWidth = popupRect.rect.width * 0.5f;
|
|
float xOffset = halfItemWidth + halfPopupWidth + popupHorizontalOffset;
|
|
popupRect.anchoredPosition = localPoint + new Vector2(placeLeft ? -xOffset : xOffset, 0f);
|
|
}
|
|
|
|
public void OnBeginDrag(PointerEventData eventData)
|
|
{
|
|
if (!allowDrag || itemSO == null || eventData == null || eventData.button != PointerEventData.InputButton.Left)
|
|
{
|
|
isDraggingWithLeftButton = false;
|
|
return;
|
|
}
|
|
|
|
isDraggingWithLeftButton = true;
|
|
suppressNextClick = true;
|
|
SetAllDragTargetsVisible(true);
|
|
CreateDragGhost();
|
|
UpdateDragGhostPosition(eventData);
|
|
}
|
|
|
|
public void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (!isDraggingWithLeftButton)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UpdateDragGhostPosition(eventData);
|
|
}
|
|
|
|
public void OnEndDrag(PointerEventData eventData)
|
|
{
|
|
if (!isDraggingWithLeftButton)
|
|
{
|
|
DestroyDragGhost();
|
|
SetAllDragTargetsVisible(false);
|
|
return;
|
|
}
|
|
|
|
isDraggingWithLeftButton = false;
|
|
equipUpdate matchedUpdateTarget = FindMatchingUpdateTarget(eventData);
|
|
equipIllusion matchedIllusionTarget = matchedUpdateTarget == null ? FindMatchingIllusionTarget(eventData) : null;
|
|
equipSmelt matchedSmeltTarget = matchedUpdateTarget == null && matchedIllusionTarget == null ? FindMatchingSmeltTarget(eventData) : null;
|
|
bool cameFromSmeltPool = equipSmelt.IsEquipmentAssignedToSmeltPool(itemSO);
|
|
|
|
SetAllDragTargetsVisible(false);
|
|
DestroyDragGhost();
|
|
|
|
if (matchedUpdateTarget != null)
|
|
{
|
|
matchedUpdateTarget.AcceptDraggedEquipment(itemSO);
|
|
return;
|
|
}
|
|
|
|
if (matchedIllusionTarget != null)
|
|
{
|
|
matchedIllusionTarget.AcceptDraggedEquipment(itemSO);
|
|
return;
|
|
}
|
|
|
|
if (matchedSmeltTarget != null)
|
|
{
|
|
matchedSmeltTarget.AcceptDraggedEquipment(itemSO);
|
|
return;
|
|
}
|
|
|
|
if (cameFromSmeltPool)
|
|
{
|
|
equipSmelt.RemoveEquipmentFromSmeltPool(itemSO);
|
|
}
|
|
}
|
|
|
|
public void OnPointerClick(PointerEventData eventData)
|
|
{
|
|
if (!allowQuickTransfer || eventData == null || eventData.button != PointerEventData.InputButton.Right || itemSO == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (equipSmelt.TryHandleQuickTransfer(itemSO))
|
|
{
|
|
isDraggingWithLeftButton = false;
|
|
SetAllDragTargetsVisible(false);
|
|
DestroyDragGhost();
|
|
suppressNextClick = true;
|
|
}
|
|
}
|
|
|
|
private equipUpdate FindMatchingUpdateTarget(PointerEventData eventData)
|
|
{
|
|
equipUpdate[] targets = FindObjectsOfType<equipUpdate>(true);
|
|
if (targets == null || targets.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Vector2 pointerPosition = eventData != null ? eventData.position : Input.mousePosition;
|
|
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
|
|
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
equipUpdate target = targets[i];
|
|
if (target != null && target.gameObject.activeInHierarchy && target.IsPointerOverDropArea(pointerPosition, eventCamera))
|
|
{
|
|
return target;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private equipSmelt FindMatchingSmeltTarget(PointerEventData eventData)
|
|
{
|
|
equipSmelt[] targets = FindObjectsOfType<equipSmelt>(true);
|
|
if (targets == null || targets.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Vector2 pointerPosition = eventData != null ? eventData.position : Input.mousePosition;
|
|
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
|
|
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
equipSmelt target = targets[i];
|
|
if (target != null && target.gameObject.activeInHierarchy && target.IsPointerOverDropArea(pointerPosition, eventCamera))
|
|
{
|
|
return target;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private equipIllusion FindMatchingIllusionTarget(PointerEventData eventData)
|
|
{
|
|
equipIllusion[] targets = FindObjectsOfType<equipIllusion>(true);
|
|
if (targets == null || targets.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Vector2 pointerPosition = eventData != null ? eventData.position : Input.mousePosition;
|
|
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
|
|
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
equipIllusion target = targets[i];
|
|
if (target != null && target.gameObject.activeInHierarchy && target.IsPointerOverDropArea(pointerPosition, eventCamera))
|
|
{
|
|
return target;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void CreateDragGhost()
|
|
{
|
|
DestroyDragGhost();
|
|
|
|
Transform ghostParent = rootCanvas != null ? rootCanvas.transform : transform.parent;
|
|
if (ghostParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dragGhost = Instantiate(gameObject, ghostParent);
|
|
dragGhost.name = $"{name}_DragGhost";
|
|
dragGhost.SetActive(true);
|
|
dragGhost.transform.SetAsLastSibling();
|
|
dragGhostRect = dragGhost.transform as RectTransform;
|
|
if (dragGhostRect != null)
|
|
{
|
|
dragGhostRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
dragGhostRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
dragGhostRect.pivot = new Vector2(0.5f, 0.5f);
|
|
dragGhostRect.localScale = Vector3.one;
|
|
dragGhostRect.localRotation = Quaternion.identity;
|
|
}
|
|
|
|
equipItemPrefab ghostItem = dragGhost.GetComponent<equipItemPrefab>();
|
|
if (ghostItem != null)
|
|
{
|
|
ghostItem.enabled = false;
|
|
if (ghostItem.itemButton != null)
|
|
{
|
|
ghostItem.itemButton.interactable = false;
|
|
}
|
|
}
|
|
|
|
Button[] buttons = dragGhost.GetComponentsInChildren<Button>(true);
|
|
for (int i = 0; i < buttons.Length; i++)
|
|
{
|
|
buttons[i].interactable = false;
|
|
}
|
|
|
|
Graphic[] graphics = dragGhost.GetComponentsInChildren<Graphic>(true);
|
|
for (int i = 0; i < graphics.Length; i++)
|
|
{
|
|
graphics[i].raycastTarget = false;
|
|
}
|
|
|
|
CanvasGroup canvasGroup = dragGhost.GetComponent<CanvasGroup>();
|
|
if (canvasGroup == null)
|
|
{
|
|
canvasGroup = dragGhost.AddComponent<CanvasGroup>();
|
|
}
|
|
|
|
canvasGroup.alpha = 0.55f;
|
|
canvasGroup.interactable = false;
|
|
canvasGroup.blocksRaycasts = false;
|
|
}
|
|
|
|
private void UpdateDragGhostPosition(PointerEventData eventData)
|
|
{
|
|
if (dragGhostRect == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RectTransform parentRect = dragGhostRect.parent as RectTransform;
|
|
if (parentRect == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Vector2 pointerPosition = eventData != null ? eventData.position : (Vector2)Input.mousePosition;
|
|
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
|
|
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRect, pointerPosition, eventCamera, out Vector2 localPoint))
|
|
{
|
|
dragGhostRect.anchoredPosition = localPoint;
|
|
}
|
|
}
|
|
|
|
private void DestroyDragGhost()
|
|
{
|
|
if (dragGhost == null)
|
|
{
|
|
dragGhostRect = null;
|
|
return;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
DestroyImmediate(dragGhost);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Destroy(dragGhost);
|
|
}
|
|
|
|
dragGhost = null;
|
|
dragGhostRect = null;
|
|
}
|
|
|
|
private static void SetAllDragTargetsVisible(bool visible)
|
|
{
|
|
equipUpdate[] updateTargets = FindObjectsOfType<equipUpdate>(true);
|
|
if (updateTargets != null)
|
|
{
|
|
for (int i = 0; i < updateTargets.Length; i++)
|
|
{
|
|
if (updateTargets[i] != null && updateTargets[i].gameObject.activeInHierarchy)
|
|
{
|
|
updateTargets[i].SetDragPreviewVisible(visible);
|
|
}
|
|
}
|
|
}
|
|
|
|
equipIllusion[] illusionTargets = FindObjectsOfType<equipIllusion>(true);
|
|
if (illusionTargets != null)
|
|
{
|
|
for (int i = 0; i < illusionTargets.Length; i++)
|
|
{
|
|
if (illusionTargets[i] != null && illusionTargets[i].gameObject.activeInHierarchy)
|
|
{
|
|
illusionTargets[i].SetDragPreviewVisible(visible);
|
|
}
|
|
}
|
|
}
|
|
|
|
equipSmelt[] smeltTargets = FindObjectsOfType<equipSmelt>(true);
|
|
if (smeltTargets != null)
|
|
{
|
|
for (int i = 0; i < smeltTargets.Length; i++)
|
|
{
|
|
if (smeltTargets[i] != null && smeltTargets[i].gameObject.activeInHierarchy)
|
|
{
|
|
smeltTargets[i].SetDragPreviewVisible(visible);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyProfileSprite(Sprite sprite)
|
|
{
|
|
if (itemProfileIcon != null)
|
|
{
|
|
itemProfileIcon.sprite = sprite;
|
|
itemProfileIcon.enabled = sprite != null;
|
|
}
|
|
}
|
|
|
|
private void ApplyBottomColor(int colorIndex)
|
|
{
|
|
if (itemBtm == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Color color = Color.white;
|
|
if (itemBtmColors != null && itemBtmColors.Length > 0)
|
|
{
|
|
int safeIndex = Mathf.Clamp(colorIndex, 0, itemBtmColors.Length - 1);
|
|
color = itemBtmColors[safeIndex];
|
|
}
|
|
|
|
itemBtm.color = color;
|
|
}
|
|
|
|
private static int GetQualityColorIndex(int level)
|
|
{
|
|
if (level >= 20)
|
|
{
|
|
return 5;
|
|
}
|
|
|
|
if (level >= 15)
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
if (level >= 10)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
if (level >= 5)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
public void SetInteractionOptions(bool dragEnabled, bool quickTransferEnabled)
|
|
{
|
|
allowDrag = dragEnabled;
|
|
allowQuickTransfer = quickTransferEnabled;
|
|
}
|
|
}
|