// ─────────────────────────────────────────────────────────────────────────────
// WLIslandUi.cs — 던전 입구의 이름표·「들어가기」 버튼 · 더미 머티리얼
//
// 발주서 WL-816d §1-② 「플레이어가 가까이 가면 『들어가기』가 뜨게 하라」
// 🔴 기존 UI 프리팹·Canvas 를 고치지 않는다 — 필요한 것만 런타임에 만들고, 떠날 때 지운다.
// 🔴 배경/캐릭터 머티리얼은 읽지도 고치지도 않는다(816a 소유). 더미용 머티리얼만 새로 만든다.
// ─────────────────────────────────────────────────────────────────────────────
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace WL.Island
{
/// 더미 전용 머티리얼 공장(기존 머티리얼은 건드리지 않는다).
public static class WLIslandLook
{
static readonly Dictionary s_cache = new Dictionary(8);
static Shader s_shader;
public static Shader LitShader
{
get
{
if (s_shader != null) return s_shader;
s_shader = Shader.Find("Universal Render Pipeline/Lit");
if (s_shader == null) s_shader = Shader.Find("Universal Render Pipeline/Simple Lit");
if (s_shader == null) s_shader = Shader.Find("Sprites/Default");
return s_shader;
}
}
public static Material GateMaterial(Color c)
{
int key = ((Color32)c).GetHashCode();
Material m;
if (s_cache.TryGetValue(key, out m) && m != null) return m;
if (LitShader == null) return null;
m = new Material(LitShader) { name = "WL_GateDummy", hideFlags = HideFlags.DontSave };
if (m.HasProperty("_BaseColor")) m.SetColor("_BaseColor", c);
if (m.HasProperty("_Color")) m.SetColor("_Color", c);
if (m.HasProperty("_Smoothness")) m.SetFloat("_Smoothness", 0.15f);
s_cache[key] = m;
return m;
}
}
/// 입구 위에 뜨는 3D 이름표.
public static class WLIslandLabel
{
public static void Attach(Transform parent, Vector3 localPos, string text)
{
var go = new GameObject("label");
go.transform.SetParent(parent, false);
go.transform.localPosition = localPos;
var tmp = go.AddComponent();
tmp.text = text;
tmp.fontSize = 3.2f;
tmp.alignment = TextAlignmentOptions.Center;
tmp.color = Color.white;
var rt = tmp.GetComponent();
if (rt != null) rt.sizeDelta = new Vector2(6f, 1.4f);
go.AddComponent();
}
}
/// 이름표가 항상 카메라를 본다.
public sealed class WLIslandBillboard : MonoBehaviour
{
void LateUpdate()
{
var cam = Camera.main;
if (cam == null) return;
transform.rotation = Quaternion.LookRotation(transform.position - cam.transform.position, Vector3.up);
}
}
/// 화면 아래 「들어가기」 — 런타임 생성 Canvas 1개(기존 UI 무변경).
public static class WLIslandPrompt
{
static GameObject s_root;
static TextMeshProUGUI s_text;
static WLDungeonGate s_target;
public static bool Visible { get { return s_root != null && s_root.activeSelf; } }
public static string LastText = "";
public static void Show(WLIslandSettings cfg, string text, WLDungeonGate gate)
{
Ensure(cfg);
s_target = gate;
LastText = text;
if (s_text != null) s_text.text = text;
if (s_root != null) s_root.SetActive(true);
}
public static void Hide()
{
s_target = null;
if (s_root != null) s_root.SetActive(false);
}
static void Ensure(WLIslandSettings cfg)
{
if (s_root != null) return;
s_root = new GameObject("~WL_IslandPrompt");
Object.DontDestroyOnLoad(s_root);
var canvas = s_root.AddComponent