ThreeKingdomsSlingshot/Assets/Scripts/OutGame/UI/UiWaveImage.cs

92 lines
4.2 KiB
C#
Raw Normal View History

using UnityEngine;
using UnityEngine.UI;
namespace TKS.OutGame
{
/// <summary>
/// 펄럭이는 천(로비 깃발 · PD 2026-11-11 「펄럭이는 깃발」) — 스프라이트를 격자로 나눠 줄마다 좌우로 민다(위 = 고정 · 아래로 갈수록 크게 · 물결이 아래로 흐름).
/// 배경 그림의 원래 깃발 위에 같은 자리로 덮어 그리므로, 줄마다 폭을 미는 양 이상 넓혀(flare) 원래 깃발이 옆으로 드러나지 않게 한다(배경 다시 그리기 없음).
/// 매 프레임 메시를 다시 만들므로 Frame 캔버스 안에 둔다(UiLayer.Isolate).
/// </summary>
[RequireComponent(typeof(CanvasRenderer))]
public class UiWaveImage : MaskableGraphic
{
public Sprite sprite;
public int cols = 4;
public int rows = 14;
/// <summary>아래끝 좌우 흔들림(스프라이트 px).</summary>
public float amp;
public float period = 2f;
/// <summary>위 → 아래 물결 수.</summary>
public float waves = 1f;
public float phase;
/// <summary>물결 골의 어두움(0 = 없음).</summary>
public float shade = 0.1f;
/// <summary>천이 바람을 받아 부푸는 폭(스프라이트 px · 넓어지는 쪽으로만 · 아래로 갈수록 크게) — 좁아지면 원래 깃발이 드러나므로 0 이상만.</summary>
public float billow;
내정 메뉴 개편(훈련·순찰·개발 배경 장면) + 「책사 → 승병」 게임 전체 - 3탭 배경 = 로비 화풍(연병장·저잣거리·규장각) · 장면 표 Resources/UI/domestic_scene.csv · 연출 LobbyAmbient(Frame 캔버스) - 훈련: 병종별 범용 병사 훈련 동작(UiDrillAnim · 뒷발 고정 · 병종별 박자 · 화면 배율) · 궁병 훈련 전용 클립 drill_ready/drill_action(대기 원화 리그) + 날아가는 화살 · 병종 탭 아이콘 · 카드 = 이름 +수치% - 순찰: 정보 판 1장(시계 + 쌓인 시간 · 게이지 · 시간당 골드·경험치·전리품 오른쪽 정렬 · 금테 안 획득 보상) · 버튼 수확/즉시 수확 · 광고 2배 = 수확 팝업 · 문 앞 순찰 영웅 + 창병 2 · 상인·주민 NPC 5(R22 대기 모션 · 길바닥) - 개발: 양피지 두루마리 위 성장 트리(노드 그림 아이콘 27) · 재화 칩 · 아래 두루마리 = 영웅 배치 + 트리 초기화 - 영웅 파견 3자리(훈련 병종 지휘관 · 순찰 · 개발 · 장면 표시만) · 세이브 필드 3 - 병사 5종 자세·타격 그림 색·크기 대기에 맞춤(전투 그림도 같은 파일) - 승병: UnitTypeInfo 이름/표시 글자 · heroes 병사 3 이름·한자 · 스킬·기믹 설명 · 튜토리얼 팁 + 임포트 자산(HeroDb·SkillInfoDb·GimmickDb·StageGimmickTable) - 테스트 DomesticSceneTests 4 · BattleFlowTests 표시 글자 PD 지시 2026-11-12(대화로그 공유/대화로그/삼국지슬링샷/2026-11-12_내정메뉴_개편.md · 레시피 R23) · QA r1~r12 · 마지막 r11·r12 PASS(B 0) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 13:41:33 +00:00
/// <summary>true = 아래끝 고정 · 위로 갈수록 크게 흔들림(풀·꽃 덤불 · PD 2026-11-12 「훈련장 주변 꽃이나 풀이 하늘거리는」) · 기본 false = 깃발(위 고정).</summary>
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++)
{
내정 메뉴 개편(훈련·순찰·개발 배경 장면) + 「책사 → 승병」 게임 전체 - 3탭 배경 = 로비 화풍(연병장·저잣거리·규장각) · 장면 표 Resources/UI/domestic_scene.csv · 연출 LobbyAmbient(Frame 캔버스) - 훈련: 병종별 범용 병사 훈련 동작(UiDrillAnim · 뒷발 고정 · 병종별 박자 · 화면 배율) · 궁병 훈련 전용 클립 drill_ready/drill_action(대기 원화 리그) + 날아가는 화살 · 병종 탭 아이콘 · 카드 = 이름 +수치% - 순찰: 정보 판 1장(시계 + 쌓인 시간 · 게이지 · 시간당 골드·경험치·전리품 오른쪽 정렬 · 금테 안 획득 보상) · 버튼 수확/즉시 수확 · 광고 2배 = 수확 팝업 · 문 앞 순찰 영웅 + 창병 2 · 상인·주민 NPC 5(R22 대기 모션 · 길바닥) - 개발: 양피지 두루마리 위 성장 트리(노드 그림 아이콘 27) · 재화 칩 · 아래 두루마리 = 영웅 배치 + 트리 초기화 - 영웅 파견 3자리(훈련 병종 지휘관 · 순찰 · 개발 · 장면 표시만) · 세이브 필드 3 - 병사 5종 자세·타격 그림 색·크기 대기에 맞춤(전투 그림도 같은 파일) - 승병: UnitTypeInfo 이름/표시 글자 · heroes 병사 3 이름·한자 · 스킬·기믹 설명 · 튜토리얼 팁 + 임포트 자산(HeroDb·SkillInfoDb·GimmickDb·StageGimmickTable) - 테스트 DomesticSceneTests 4 · BattleFlowTests 표시 글자 PD 지시 2026-11-12(대화로그 공유/대화로그/삼국지슬링샷/2026-11-12_내정메뉴_개편.md · 레시피 R23) · QA r1~r12 · 마지막 r11·r12 PASS(B 0) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 13:41:33 +00:00
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);
}
}
}
}