using UnityEngine; using UnityEngine.UI; namespace TKS.OutGame { /// /// 펄럭이는 천(로비 깃발 · PD 2026-11-11 「펄럭이는 깃발」) — 스프라이트를 격자로 나눠 줄마다 좌우로 민다(위 = 고정 · 아래로 갈수록 크게 · 물결이 아래로 흐름). /// 배경 그림의 원래 깃발 위에 같은 자리로 덮어 그리므로, 줄마다 폭을 미는 양 이상 넓혀(flare) 원래 깃발이 옆으로 드러나지 않게 한다(배경 다시 그리기 없음). /// 매 프레임 메시를 다시 만들므로 Frame 캔버스 안에 둔다(UiLayer.Isolate). /// [RequireComponent(typeof(CanvasRenderer))] public class UiWaveImage : MaskableGraphic { public Sprite sprite; public int cols = 4; public int rows = 14; /// 아래끝 좌우 흔들림(스프라이트 px). public float amp; public float period = 2f; /// 위 → 아래 물결 수. public float waves = 1f; public float phase; /// 물결 골의 어두움(0 = 없음). public float shade = 0.1f; /// 천이 바람을 받아 부푸는 폭(스프라이트 px · 넓어지는 쪽으로만 · 아래로 갈수록 크게) — 좁아지면 원래 깃발이 드러나므로 0 이상만. public float billow; /// true = 아래끝 고정 · 위로 갈수록 크게 흔들림(풀·꽃 덤불 · PD 2026-11-12 「훈련장 주변 꽃이나 풀이 하늘거리는」) · 기본 false = 깃발(위 고정). public bool fromBottom; public override Texture mainTexture { get { return sprite != null ? sprite.texture : s_WhiteTexture; } } protected override void Awake() { base.Awake(); if (Application.isPlaying) UiLayer.Isolate(gameObject); } void Update() { if (amp > 0f && period > 0f) SetVerticesDirty(); } protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); if (sprite == null || cols < 1 || rows < 1) return; var r = GetPixelAdjustedRect(); var uv = UnityEngine.Sprites.DataUtility.GetOuterUV(sprite); float unit = r.width / Mathf.Max(1f, sprite.rect.width); // 스프라이트 px → 이 그래픽 단위 float half = Mathf.Max(1f, sprite.rect.width * 0.5f); float t = Application.isPlaying ? Time.unscaledTime : 0f; float cx = r.center.x; const float Tau = Mathf.PI * 2f; for (int j = 0; j <= rows; j++) { float v = j / (float)rows; // 0 = 위 · 1 = 아래 float s = fromBottom ? 1f - v : v; // 고정 끝에서 잰 거리(0 = 고정) float env = s * s; float ph = (t / period - s * waves + phase) * Tau; float dx = amp * env * Mathf.Sin(ph); float puff = billow * env * (0.5f + 0.5f * Mathf.Sin(ph * 0.5f + 1.3f)); // 0 ~ billow(넓어지기만) float flare = (amp * env + env + puff) / half; // 미는 양 + 1 px(원래 깃발 가림) + 부풂 float dark = shade * env * (0.5f + 0.5f * Mathf.Cos(ph)); var c = color; c.r *= 1f - dark; c.g *= 1f - dark; c.b *= 1f - dark; float y = r.yMax - v * r.height; float uy = Mathf.Lerp(uv.w, uv.y, v); for (int i = 0; i <= cols; i++) { float u = i / (float)cols; float x = r.xMin + u * r.width; x = cx + (x - cx) * (1f + flare) + dx * unit; vh.AddVert(new Vector3(x, y), c, new Vector2(Mathf.Lerp(uv.x, uv.z, u), uy)); } } int w = cols + 1; for (int j = 0; j < rows; j++) for (int i = 0; i < cols; i++) { int a = j * w + i; vh.AddTriangle(a, a + 1, a + w + 1); vh.AddTriangle(a, a + w + 1, a + w); } } } }