ThreeKingdomsSlingshot/Assets/Scripts/OutGame/ScenarioCaptureDriver.cs

137 lines
5.6 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace TKS.OutGame
{
/// <summary>
/// 시나리오 이벤트 검증 캡처(2026-11-12 · 개발 요청서 C1·C2) — 에디터 `TKS.EditorTools.ScenarioCapture.Run` 이 SessionState 로 넘기면 생성.
/// ① 스테이지 팝업(전장 설명 칸) ② 보스 스테이지마다 등장 연출을 정해진 시각에 찍고 아군 차례가 되면 1장 더 · 세이브 = 메모리 전용 신규 유저.
/// </summary>
public class ScenarioCaptureDriver : MonoBehaviour
{
public const string DirKey = "TKS_SC_CAPTURE_DIR";
public const string PopupKey = "TKS_SC_CAPTURE_POPUPS";
public const string StagesKey = "TKS_SC_CAPTURE_STAGES";
public const string TimesKey = "TKS_SC_CAPTURE_TIMES";
const int W = 1080, H = 1920;
string dir;
string[] popups = new string[0], stages = new string[0];
float[] times = new float[0];
readonly List<string> log = new List<string>();
#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void AutoSpawn()
{
string d = UnityEditor.SessionState.GetString(DirKey, "");
if (string.IsNullOrEmpty(d)) return;
UnityEditor.SessionState.EraseString(DirKey);
var drv = new GameObject("ScenarioCaptureDriver").AddComponent<ScenarioCaptureDriver>();
drv.dir = d;
drv.popups = Split(UnityEditor.SessionState.GetString(PopupKey, ""));
drv.stages = Split(UnityEditor.SessionState.GetString(StagesKey, ""));
var ts = new List<float>();
foreach (var t in Split(UnityEditor.SessionState.GetString(TimesKey, "")))
{
float v;
if (float.TryParse(t, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out v)) ts.Add(v);
}
drv.times = ts.ToArray();
}
#endif
static string[] Split(string s)
{
return s.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
}
static int Index(BattleManager b, string cs)
{
var p = cs.Split('-');
int c, s;
if (p.Length != 2 || !int.TryParse(p[0], out c) || !int.TryParse(p[1], out s)) return -1;
for (int i = 0; i < b.Config.stages.Length; i++)
if (b.Config.stages[i].chapter == c && b.Config.stages[i].stage == s) return i;
return -1;
}
IEnumerator Start()
{
Directory.CreateDirectory(dir);
yield return null;
yield return null;
var root = OutGameRoot.Instance;
var cam = Camera.main;
if (root == null || cam == null)
{
Log("FAIL: OutGameRoot 또는 카메라 없음");
Finish(1);
yield break;
}
var bm = root.Battle;
foreach (var cs in popups)
{
int si = Index(bm, cs.Trim());
if (si < 0) { Log("FAIL: 스테이지 없음 " + cs); continue; }
root.OpenWorldMap();
yield return new WaitForSecondsRealtime(0.4f);
root.Map.Show(bm.Config.stages[si].chapter - 1);
yield return new WaitForSecondsRealtime(0.3f);
root.Map.OpenPopup(bm.Config.stages[si].stage - 1);
yield return new WaitForSecondsRealtime(0.4f);
yield return Shot(cam, "popup_" + cs.Trim());
}
foreach (var cs in stages)
{
int si = Index(bm, cs.Trim());
if (si < 0) { Log("FAIL: 스테이지 없음 " + cs); continue; }
root.Map.EnterStage(bm.Config.stages[si].chapter - 1, bm.Config.stages[si].stage - 1);
float t0 = Time.realtimeSinceStartup;
foreach (var t in times)
{
while (Time.realtimeSinceStartup - t0 < t) yield return null;
yield return Shot(cam, "intro_" + cs.Trim() + "_" + t.ToString("0.0", System.Globalization.CultureInfo.InvariantCulture) + "s");
}
while (bm.Phase != BattlePhase.PlayerTurn && Time.realtimeSinceStartup - t0 < 20f) yield return null;
Log("intro " + cs + " → 아군 차례까지 " + (Time.realtimeSinceStartup - t0).ToString("0.00") + "초 · phase=" + bm.Phase);
yield return new WaitForSecondsRealtime(0.8f);
yield return Shot(cam, "intro_" + cs.Trim() + "_end");
bm.GoIdle();
root.OpenWorldMap();
yield return new WaitForSecondsRealtime(0.5f);
}
Log("scenario errors=" + ScenarioData.Errors.Count);
foreach (var e in ScenarioData.Errors) Log(" " + e);
Finish(0);
}
IEnumerator Shot(Camera cam, string name)
{
string file = Path.Combine(dir, name + ".png");
yield return CaptureUtil.Capture(cam, W, H, file);
Log("shot " + file);
}
void Log(string s)
{
log.Add(s);
Debug.Log("[TKS-SC] " + s);
try { File.WriteAllLines(Path.Combine(dir, "scenario_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
}
}
}