Files
bansonic_beta_main/Assets/_eqpmtSys/equipItemPrefab.cs
T

699 lines
22 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
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;
[Header("equipperProfile")]
public Image equipperProfileIcon;
private Action<equipmentSO> clickHandler;
private Func<equipmentSO, bool> rightClickHandler;
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, Func<equipmentSO, bool> onRightClick = null)
{
itemSO = so;
clickHandler = onClick;
rightClickHandler = onRightClick;
if (itemSO == null)
{
ApplyProfileSprite(null);
ApplyBottomColor(0);
ApplyEquipperProfile(null);
return;
}
equipmentSO.EquipmentTierPresentation presentation = itemSO.GetVisualTierPresentation();
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
ApplyProfileSprite(displaySprite);
ApplyBottomColor(itemSO.GetVisualQualityColorIndex());
ApplyEquipperProfile(FindEquipper(itemSO));
}
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;
eFinalDream matchedFinalDreamTarget = matchedUpdateTarget == null && matchedIllusionTarget == null ? FindMatchingFinalDreamTarget(eventData) : null;
equipTransfer matchedTransferTarget = matchedUpdateTarget == null && matchedIllusionTarget == null && matchedFinalDreamTarget == null ? FindMatchingTransferTarget(eventData) : null;
equipTransfer.TransferDropSlot matchedTransferSlot = matchedTransferTarget != null
? matchedTransferTarget.GetHoveredDropSlot(eventData != null ? eventData.position : (Vector2)Input.mousePosition, eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera)
: equipTransfer.TransferDropSlot.None;
equipSmelt matchedSmeltTarget = matchedUpdateTarget == null && matchedIllusionTarget == null && matchedFinalDreamTarget == null && matchedTransferTarget == 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 (matchedFinalDreamTarget != null)
{
matchedFinalDreamTarget.AcceptDraggedEquipment(itemSO);
return;
}
if (matchedTransferTarget != null)
{
if (matchedTransferSlot != equipTransfer.TransferDropSlot.None)
{
matchedTransferTarget.AcceptDraggedEquipment(itemSO, matchedTransferSlot);
return;
}
}
if (matchedSmeltTarget != null)
{
matchedSmeltTarget.AcceptDraggedEquipment(itemSO);
return;
}
if (cameFromSmeltPool)
{
equipSmelt.RemoveEquipmentFromSmeltPool(itemSO);
}
}
public void OnPointerClick(PointerEventData eventData)
{
if (eventData == null || itemSO == null)
{
return;
}
if (eventData.button == PointerEventData.InputButton.Right)
{
if (rightClickHandler != null && rightClickHandler.Invoke(itemSO))
{
isDraggingWithLeftButton = false;
SetAllDragTargetsVisible(false);
DestroyDragGhost();
suppressNextClick = true;
return;
}
if (!allowQuickTransfer)
{
return;
}
if (equipSmelt.TryHandleQuickTransfer(itemSO))
{
isDraggingWithLeftButton = false;
SetAllDragTargetsVisible(false);
DestroyDragGhost();
suppressNextClick = true;
}
return;
}
if (eventData.button != PointerEventData.InputButton.Left)
{
return;
}
}
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 equipTransfer FindMatchingTransferTarget(PointerEventData eventData)
{
equipTransfer[] targets = FindObjectsOfType<equipTransfer>(true);
if (targets == null || targets.Length == 0)
{
return null;
}
Vector2 pointerPosition = eventData != null ? eventData.position : (Vector2)Input.mousePosition;
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
for (int i = 0; i < targets.Length; i++)
{
equipTransfer target = targets[i];
if (target != null && target.gameObject.activeInHierarchy && target.GetHoveredDropSlot(pointerPosition, eventCamera) != equipTransfer.TransferDropSlot.None)
{
return target;
}
}
return null;
}
private eFinalDream FindMatchingFinalDreamTarget(PointerEventData eventData)
{
eFinalDream[] targets = FindObjectsOfType<eFinalDream>(true);
if (targets == null || targets.Length == 0)
{
return null;
}
Vector2 pointerPosition = eventData != null ? eventData.position : (Vector2)Input.mousePosition;
Camera eventCamera = eventData != null && eventData.pressEventCamera != null ? eventData.pressEventCamera : uiCamera;
for (int i = 0; i < targets.Length; i++)
{
eFinalDream 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);
}
}
}
eFinalDream[] finalDreamTargets = FindObjectsOfType<eFinalDream>(true);
if (finalDreamTargets != null)
{
for (int i = 0; i < finalDreamTargets.Length; i++)
{
if (finalDreamTargets[i] != null && finalDreamTargets[i].gameObject.activeInHierarchy)
{
finalDreamTargets[i].SetDragPreviewVisible(visible);
}
}
}
equipTransfer[] transferTargets = FindObjectsOfType<equipTransfer>(true);
if (transferTargets != null)
{
for (int i = 0; i < transferTargets.Length; i++)
{
if (transferTargets[i] != null && transferTargets[i].gameObject.activeInHierarchy)
{
transferTargets[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 void ApplyEquipperProfile(AllyHero_SO hero)
{
if (equipperProfileIcon == null)
{
return;
}
Sprite sprite = hero != null ? hero.ally_hero_squareProfile : null;
equipperProfileIcon.sprite = sprite;
equipperProfileIcon.color = sprite != null ? Color.white : new Color(1f, 1f, 1f, 0f);
equipperProfileIcon.enabled = true;
}
private AllyHero_SO FindEquipper(equipmentSO equipment)
{
if (equipment == null)
{
return null;
}
AllyHero_SO[] heroes = LoadHeroAssets();
for (int i = 0; i < heroes.Length; i++)
{
AllyHero_SO hero = heroes[i];
if (hero == null)
{
continue;
}
hero.LoadEquippedEquipmentFromLocal();
equipmentSO equipped = hero.GetEquippedEquipmentResolved();
if (equipped == equipment || (!string.IsNullOrWhiteSpace(equipped?.name) && equipped.name == equipment.name))
{
return hero;
}
}
return null;
}
private AllyHero_SO[] LoadHeroAssets()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
string[] guids = AssetDatabase.FindAssets("t:AllyHero_SO", new[] { "Assets/Resources/so/ally" });
var heroes = new AllyHero_SO[guids.Length];
int count = 0;
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
AllyHero_SO hero = AssetDatabase.LoadAssetAtPath<AllyHero_SO>(path);
if (hero != null)
{
heroes[count++] = hero;
}
}
if (count == heroes.Length)
{
return heroes;
}
Array.Resize(ref heroes, count);
return heroes;
}
#endif
return Resources.LoadAll<AllyHero_SO>("so/ally");
}
public void SetInteractionOptions(bool dragEnabled, bool quickTransferEnabled)
{
allowDrag = dragEnabled;
allowQuickTransfer = quickTransferEnabled;
}
}