装备系统做了很多
This commit is contained in:
@@ -0,0 +1,528 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user