124 lines
5.7 KiB
C#
124 lines
5.7 KiB
C#
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace TKS.OutGame
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 타이틀 화면 검증 캡처(PD 2026-11-13 · 에디터 TKS.EditorTools.TitleCapture.Capture 가 SessionState 로 출력 폴더를 넘기면 생성 · 메모리 세이브).
|
|||
|
|
/// 등장 연출(연출 시계를 정해 찍음) · 끝 모습 1080×1920 · 화면비 1080×2400 · 1536×2048 · 대기 움직임 연속(실시간) · 누름 → 로비 확인 · 끝나면 스스로 종료.
|
|||
|
|
/// UICaptureDriver(다른 세션 작업 중)와 따로 둔다.
|
|||
|
|
/// </summary>
|
|||
|
|
public class TitleCaptureDriver : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public const string DirKey = "TKS_TITLE_CAPTURE_DIR";
|
|||
|
|
public string OutputDir;
|
|||
|
|
readonly List<string> log = new List<string>();
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|||
|
|
static void AutoSpawn()
|
|||
|
|
{
|
|||
|
|
string dir = UnityEditor.SessionState.GetString(DirKey, "");
|
|||
|
|
if (string.IsNullOrEmpty(dir)) return;
|
|||
|
|
UnityEditor.SessionState.EraseString(DirKey);
|
|||
|
|
new GameObject("TitleCaptureDriver").AddComponent<TitleCaptureDriver>().OutputDir = dir;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
IEnumerator Start()
|
|||
|
|
{
|
|||
|
|
Directory.CreateDirectory(OutputDir);
|
|||
|
|
yield return null;
|
|||
|
|
yield return null;
|
|||
|
|
var cam = Camera.main;
|
|||
|
|
if (cam == null)
|
|||
|
|
{
|
|||
|
|
Log("FAIL: 카메라 없음");
|
|||
|
|
Finish(1);
|
|||
|
|
yield break;
|
|||
|
|
}
|
|||
|
|
bool started = false;
|
|||
|
|
TitleScreen.ForceShow = true;
|
|||
|
|
var ts = TitleScreen.Show(cam, () => started = true);
|
|||
|
|
Log("heroes=" + ts.Heroes.Count + " introEnd=" + ts.IntroEnd.ToString("0.00") + " provider=" + (BootFlow.TitleProvider != null));
|
|||
|
|
// 등장 연출 — 연출 시계를 정해 한 장씩(캡처 시간에 흔들리지 않게)
|
|||
|
|
float[] at = { 0.15f, 0.35f, 0.55f, 0.75f, 0.95f, 1.15f, 1.35f, 1.42f, 1.50f, 1.60f, 1.75f }; // 로고 내려앉는 중간(1.30~1.72) 3장 = QA r1 U2
|
|||
|
|
int i = 1;
|
|||
|
|
foreach (var t in at)
|
|||
|
|
{
|
|||
|
|
ts.SetTime(t);
|
|||
|
|
yield return null;
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "intro_" + (i++).ToString("00") + "_" + t.ToString("0.00") + ".png"));
|
|||
|
|
}
|
|||
|
|
ts.SetTime(ts.IntroEnd + 1.2f);
|
|||
|
|
yield return null;
|
|||
|
|
yield return UiLayerProbe.Measure("title", Log, OutputDir);
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "title_1080x1920.png"));
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1080, 2400, Path.Combine(OutputDir, "title_1080x2400.png"));
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1536, 2048, Path.Combine(OutputDir, "title_1536x2048.png"));
|
|||
|
|
// 대기 움직임(실시간 · 약 0.12 초 간격) — 실제 간격을 로그에 남김
|
|||
|
|
float t0 = Time.unscaledTime;
|
|||
|
|
for (int k = 0; k < 24; k++)
|
|||
|
|
{
|
|||
|
|
yield return CaptureUtil.Capture(cam, 540, 960, Path.Combine(OutputDir, "idle_" + k.ToString("00") + ".png"));
|
|||
|
|
Log("idle " + k + " t=" + (Time.unscaledTime - t0).ToString("0.000"));
|
|||
|
|
float w = Time.unscaledTime + 0.12f;
|
|||
|
|
while (Time.unscaledTime < w) yield return null;
|
|||
|
|
}
|
|||
|
|
// 확인 영상용 실시간 연속(처음부터 다시 띄워 등장 → 대기 약 4 초 · 원본 크기 · 찍힌 실제 시각을 로그에 = 영상 프레임 길이)
|
|||
|
|
ts.Close();
|
|||
|
|
yield return null;
|
|||
|
|
ts = TitleScreen.Show(cam, () => started = true);
|
|||
|
|
string vdir = Path.Combine(OutputDir, "video");
|
|||
|
|
Directory.CreateDirectory(vdir);
|
|||
|
|
float v0 = Time.unscaledTime;
|
|||
|
|
var vlog = new List<string>();
|
|||
|
|
for (int k = 0; Time.unscaledTime - v0 < ts.IntroEnd + 4f && k < 400; k++)
|
|||
|
|
{
|
|||
|
|
float vt = Time.unscaledTime - v0;
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(vdir, "v" + k.ToString("000") + ".png"));
|
|||
|
|
vlog.Add(k + "," + vt.ToString("0.000", System.Globalization.CultureInfo.InvariantCulture));
|
|||
|
|
}
|
|||
|
|
File.WriteAllLines(Path.Combine(vdir, "times.csv"), vlog.ToArray());
|
|||
|
|
Log("video frames=" + vlog.Count + " seconds=" + (Time.unscaledTime - v0).ToString("0.00"));
|
|||
|
|
ts.SkipIntro();
|
|||
|
|
float ready = Time.unscaledTime + 2f;
|
|||
|
|
while (!ts.PressReady && Time.unscaledTime < ready) yield return null;
|
|||
|
|
// 누름 → 페이드 → 로비
|
|||
|
|
ts.Press();
|
|||
|
|
float until = Time.unscaledTime + 4f;
|
|||
|
|
while (!started && Time.unscaledTime < until) yield return null;
|
|||
|
|
Log("pressed → started=" + started + " titleGone=" + (TitleScreen.Current == null));
|
|||
|
|
yield return new WaitForSecondsRealtime(0.6f);
|
|||
|
|
yield return CaptureUtil.Capture(cam, 1080, 1920, Path.Combine(OutputDir, "after_press.png"));
|
|||
|
|
TitleScreen.ForceShow = false;
|
|||
|
|
Finish(started ? 0 : 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Log(string s)
|
|||
|
|
{
|
|||
|
|
log.Add(s);
|
|||
|
|
Debug.Log("[TitleCapture] " + s);
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
File.WriteAllLines(Path.Combine(OutputDir, "capture_log.txt"), log.ToArray());
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Finish(int code)
|
|||
|
|
{
|
|||
|
|
Log("finish code=" + code);
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
UnityEditor.EditorApplication.Exit(code);
|
|||
|
|
#else
|
|||
|
|
Application.Quit(code);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|