EerieVillage/Assets/Scripts/MyUI/SkillCardSlot.cs

147 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using EerieVillage.Skills;
namespace EerieVillage.MyUI
{
/// <summary>
/// BT12-MVP-A 영역 단일 카드 슬롯 — PD 첨부 예시 ("기술 선택" 화면) 정합.
/// SkillSelectionUI 영역 3개 자식.
///
/// Phase 2-D 정정 (2026-05-09) — SkillCardPlaceholder → ActiveSkillData 전환.
/// SkillDataAsset base에 rarity 필드 부재 → 배너 고정 갈색 (BT12-MVP-A Phase 2-2 영역 정합).
///
/// PD 예시 카드 구성:
/// 1. 상단 색상 배너 (갈색 고정 — rarity 미지원)
/// 2. 카드 이름 (한글)
/// 3. 원형 아이콘 + 동심원 빛 효과
/// 4. "레벨 N" 표시
/// 5. 효과 설명 3~4 라인
/// </summary>
public class SkillCardSlot : MonoBehaviour
{
[Header("PD 예시 정합 — 카드 구성")]
[SerializeField] Image _topBanner; // 1. 상단 색상 배너 (갈색 고정)
[SerializeField] TMP_Text _nameText; // 2. 카드 이름 (한글)
[SerializeField] Image _icon; // 3. 원형 아이콘
[SerializeField] Image _glowEffect; // 3. 동심원 빛 효과
[SerializeField] TMP_Text _levelText; // 4. 레벨 표시
[SerializeField] TMP_Text _descriptionText; // 5. 효과 설명
[Header("인터랙션")]
[SerializeField] Button _clickArea; // 카드 전체 클릭 영역
[SerializeField] GameObject _highlightFrame; // 선택 시 활성
[Header("배너 고정 색상 (rarity 미지원 — 갈색 통일)")]
[SerializeField] Color _bannerColor = new Color(0.5f, 0.35f, 0.15f, 1f); // 갈색 고정
public ActiveSkillData Card { get; private set; }
public void Bind(ActiveSkillData card, System.Action onClick)
{
Card = card;
if (card == null)
{
gameObject.SetActive(false);
return;
}
gameObject.SetActive(true);
// 2. 카드 이름 (DisplayName — SkillDataAsset base PascalCase)
if (_nameText != null) _nameText.text = card.DisplayName;
// PD 지시 2026-05-13 — 3. 아이콘 (card.Icon null 시 속성별 색상 동적 원 sprite fallback)
if (_icon != null)
{
if (card.Icon != null)
{
_icon.sprite = card.Icon;
_icon.color = Color.white;
}
else
{
_icon.sprite = GetFallbackIconSprite();
_icon.color = GetColorByAttribute(card.AttributeTags);
}
_icon.enabled = true;
}
// PD 지시 2026-05-13 — 동심원 빛 효과 — fallback sprite·낮은 alpha (속성 색상 정합)
if (_glowEffect != null)
{
_glowEffect.sprite = GetFallbackIconSprite();
var glowCol = GetColorByAttribute(card.AttributeTags);
glowCol.a = 0.3f;
_glowEffect.color = glowCol;
_glowEffect.enabled = true;
}
// 5. 효과 설명
if (_descriptionText != null) _descriptionText.text = card.Description;
// 1. 상단 색상 배너 — rarity 필드 부재 → 갈색 고정
if (_topBanner != null) _topBanner.color = _bannerColor;
// 4. 레벨 표시 — SkillDataAsset base에 currentLevel 없음 → "레벨 1" 고정 표시
if (_levelText != null)
{
_levelText.text = "레벨 1";
_levelText.color = Color.white;
}
// 클릭 영역
if (_clickArea != null)
{
_clickArea.onClick.RemoveAllListeners();
_clickArea.onClick.AddListener(() => onClick?.Invoke());
}
SetHighlight(false);
}
public void SetHighlight(bool active)
{
if (_highlightFrame != null) _highlightFrame.SetActive(active);
}
// PD 지시 2026-05-13 — 아이콘 fallback (정적 캐싱·16×16 원 알파 sprite)
static Sprite _fallbackIconSprite;
static Sprite GetFallbackIconSprite()
{
if (_fallbackIconSprite != null) return _fallbackIconSprite;
const int size = 32;
var tex = new Texture2D(size, size, TextureFormat.RGBA32, false);
tex.wrapMode = TextureWrapMode.Clamp;
tex.filterMode = FilterMode.Bilinear;
float r = size * 0.5f;
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
{
float dx = x - r + 0.5f;
float dy = y - r + 0.5f;
float dist = Mathf.Sqrt(dx * dx + dy * dy);
float alpha = Mathf.Clamp01(1f - (dist - (r - 2.5f)));
tex.SetPixel(x, y, new Color(1f, 1f, 1f, alpha));
}
}
tex.Apply();
_fallbackIconSprite = Sprite.Create(tex, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f), size);
return _fallbackIconSprite;
}
// PD 지시 2026-05-13 — 속성별 색상 (Fire 주황·Frost 하늘·Dark 보라·Lightning 노랑·Physical 흰)
static Color GetColorByAttribute(AttributeTag attr)
{
if ((attr & AttributeTag.Fire) != 0) return new Color(1f, 0.5f, 0.2f);
if ((attr & AttributeTag.Frost) != 0) return new Color(0.5f, 0.85f, 1f);
if ((attr & AttributeTag.Dark) != 0) return new Color(0.6f, 0.3f, 0.85f);
if ((attr & AttributeTag.Lightning) != 0) return new Color(1f, 1f, 0.4f);
if ((attr & AttributeTag.Physical) != 0) return new Color(0.95f, 0.95f, 0.95f);
return Color.white;
}
}
}