Files
Ipseity-Demo/Assets/_Content/Scripts/Features/DetectiveBoard/UI/ClueHandCard.cs
T

123 lines
3.9 KiB
C#

using UnityEngine;
using UnityEngine.EventSystems;
using Unheimlich.Features.DetectiveBoard.Data;
namespace Unheimlich.Features.DetectiveBoard.UI
{
/// <summary>
/// Wraps a PostItNode to behave as a card in the bottom-screen fan hand.
/// Handles hover pop animation and delegates click to ClueHandUI for board placement.
/// Add this component alongside PostItNode on the same GameObject.
/// </summary>
[RequireComponent(typeof(PostItNode))]
public class ClueHandCard : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
[Header("Hover Settings")]
[SerializeField] private float _hoverRiseAmount = 60f;
[SerializeField] private float _hoverAnimSpeed = 8f;
private PostItNode _node;
private ClueHandUI _handUI;
// Fan resting state assigned by ClueHandUI
private Vector2 _restAnchoredPosition;
private float _restRotation;
// Runtime animation state
private Vector2 _currentAnchoredPosition;
private float _currentRotation;
private bool _isHovered;
private bool _isPlaced;
public ClueData ClueData => _node != null ? _node.ClueData : null;
public PostItNode Node => _node;
public bool IsPlaced => _isPlaced;
private void Awake()
{
if (_node == null)
_node = GetComponent<PostItNode>();
}
/// <summary>
/// Binds this card to its parent hand manager.
/// </summary>
public void Initialize(PostItNode node, ClueHandUI handUI)
{
_node = node;
_handUI = handUI;
}
/// <summary>
/// Assigns the resting fan slot (position + rotation) for this card.
/// </summary>
public void SetFanSlot(Vector2 anchoredPosition, float rotationZ)
{
_restAnchoredPosition = anchoredPosition;
_restRotation = rotationZ;
_currentAnchoredPosition = anchoredPosition;
_currentRotation = rotationZ;
RectTransform rt = _node.RectTransform;
rt.anchoredPosition = anchoredPosition;
rt.localRotation = Quaternion.Euler(0f, 0f, rotationZ);
}
private void Update()
{
if (_isPlaced)
return;
RectTransform rt = _node.RectTransform;
Vector2 targetPos = _isHovered
? _restAnchoredPosition + Vector2.up * _hoverRiseAmount
: _restAnchoredPosition;
float targetRot = _isHovered ? 0f : _restRotation;
_currentAnchoredPosition = Vector2.Lerp(_currentAnchoredPosition, targetPos, Time.deltaTime * _hoverAnimSpeed);
_currentRotation = Mathf.LerpAngle(_currentRotation, targetRot, Time.deltaTime * _hoverAnimSpeed);
rt.anchoredPosition = _currentAnchoredPosition;
rt.localRotation = Quaternion.Euler(0f, 0f, _currentRotation);
}
public void OnPointerEnter(PointerEventData eventData)
{
if (_isPlaced)
return;
_isHovered = true;
_handUI?.OnCardHovered(this);
}
public void OnPointerExit(PointerEventData eventData)
{
if (_isPlaced)
return;
_isHovered = false;
_handUI?.OnCardUnhovered(this);
}
public void OnPointerClick(PointerEventData eventData)
{
if (_isPlaced || eventData.button != PointerEventData.InputButton.Left)
return;
_isHovered = false;
_handUI?.OnCardSelected(this);
}
/// <summary>
/// Hides this card from the hand after placement on the board.
/// </summary>
public void MarkAsPlaced()
{
_isPlaced = true;
gameObject.SetActive(false);
}
}
}