装备系统做了很多

This commit is contained in:
FloatGaming
2026-03-27 08:02:55 +08:00
parent dd205b6cb4
commit 538085b64f
119 changed files with 27552 additions and 1672 deletions
+528
View File
@@ -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;
}
}