using System.IO; using System.Text; using TKS.OutGame; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; namespace TKS.EditorTools { /// /// 아웃게임 표(Assets/Data/OutGame/*.csv · 기획 tables/ 사본 22장 = A 12 + C 10) → ScriptableObject 18개(Assets/Resources/OutGame/). /// 메뉴 TKS/Import OutGame Data 또는 CLI: Unity.exe -batchmode -nographics -projectPath <proj> -executeMethod TKS.EditorTools.DataImporter.Import -quit /// 형식·참조 오류가 하나라도 있으면 자산을 건드리지 않는다(콘솔 error 로 행 번호 보고). /// public static class DataImporter { public const string AssetFolder = "Assets/Resources/OutGame"; [MenuItem("TKS/Import OutGame Data (아웃게임 데이터 임포트)")] public static void Import() { ImportAll(); } public static string[] ReadFiles() { var dir = Path.Combine(Application.dataPath, OutGameTables.Folder); var texts = new string[OutGameTables.Files.Length]; for (int i = 0; i < texts.Length; i++) { var p = Path.Combine(dir, OutGameTables.Files[i]); texts[i] = File.Exists(p) ? File.ReadAllText(p, Encoding.UTF8) : null; } return texts; } public static bool ImportAll() { var r = OutGameTables.Parse(ReadFiles()); if (r.errors.Count > 0) { foreach (var e in r.errors) Debug.LogError("[TKS] 아웃게임 표 오류 · " + e); Debug.LogError("[TKS] 아웃게임 임포트 중단(오류 " + r.errors.Count + ") · 자산 변경 없음"); OutGameTables.Destroy(r); return false; } if (!AssetDatabase.IsValidFolder("Assets/Resources")) AssetDatabase.CreateFolder("Assets", "Resources"); if (!AssetDatabase.IsValidFolder(AssetFolder)) AssetDatabase.CreateFolder("Assets/Resources", "OutGame"); foreach (var so in r.data.All) { var name = so.GetType().Name; var path = AssetFolder + "/" + name + ".asset"; var existing = AssetDatabase.LoadAssetAtPath(path, so.GetType()) as ScriptableObject; so.name = name; if (existing == null) AssetDatabase.CreateAsset(so, path); else { EditorUtility.CopySerialized(so, existing); existing.name = name; if (existing is HeroDb) ((HeroDb)existing).InvalidateIndex(); if (existing is GearDb) ((GearDb)existing).InvalidateIndex(); EditorUtility.SetDirty(existing); Object.DestroyImmediate(so); } } AssetDatabase.SaveAssets(); var sb = new StringBuilder("[TKS] 아웃게임 임포트 완료 ·"); foreach (var kv in r.rowCounts) sb.Append(' ').Append(kv.Key).Append(' ').Append(kv.Value); Debug.Log(sb.Append(" · ").Append(AssetFolder).ToString()); return true; } /// /// 아웃게임 화면 검증 캡처(GUI 에디터 · 사본 프로젝트 권장 · 세이브 = 메모리 전용이라 실제 save.json 불변): /// Unity.exe -projectPath <copy> -executeMethod TKS.EditorTools.DataImporter.CaptureOutGame -outgameDir <dir> /// 로비 · 영웅 목록 · 영웅 상세 · 편성 · 뽑기 · 뽑기 결과 · 월드맵 팝업 · 전투 결과 PNG + log · 끝나면 스스로 종료. /// public static void CaptureOutGame() { string dir = GetArg("-outgameDir"); if (string.IsNullOrEmpty(dir)) dir = Path.Combine(Directory.GetCurrentDirectory(), "Logs", "outgame_capture"); ImportAll(); EditorSceneManager.OpenScene(ProjectSetup.ScenePath, OpenSceneMode.Single); SessionState.SetBool(SaveStore.MemoryFlagKey, true); SessionState.SetString(OutGameCaptureDriver.DirKey, dir); Debug.Log("[TKS] 아웃게임 캡처 시작 → " + dir); EditorApplication.EnterPlaymode(); } /// /// 스킬 화면 검증 캡처(GUI 에디터 · 사본 프로젝트 권장 · 세이브 = 메모리 전용 · PD #1093 B): /// Unity.exe -projectPath <copy> -executeMethod TKS.EditorTools.DataImporter.CaptureSkills -skillDir <dir> /// 스킬 레벨업 · 스킬 버튼 · 액티브 발동 · 패시브 표시 PNG 4장 + log · 끝나면 스스로 종료. /// public static void CaptureSkills() { string dir = GetArg("-skillDir"); if (string.IsNullOrEmpty(dir)) dir = Path.Combine(Directory.GetCurrentDirectory(), "Logs", "skill_capture"); ImportAll(); EditorSceneManager.OpenScene(ProjectSetup.ScenePath, OpenSceneMode.Single); SessionState.SetBool(SaveStore.MemoryFlagKey, true); SessionState.SetString(SkillCaptureDriver.DirKey, dir); Debug.Log("[TKS] 스킬 캡처 시작 → " + dir); EditorApplication.EnterPlaymode(); } /// /// 아웃게임 2차 화면 검증 캡처(GUI 에디터 · 사본 프로젝트 권장 · 세이브 = 메모리 전용 · PD #1093 C): /// Unity.exe -projectPath <copy> -executeMethod TKS.EditorTools.DataImporter.CaptureC -cDir <dir> /// 훈련 · 순찰 · 개발 · 보물 보유/세트/상자 · 탑 · 던전 · 투기장 · 도감 PNG 10장 + log · 끝나면 스스로 종료. /// public static void CaptureC() { string dir = GetArg("-cDir"); if (string.IsNullOrEmpty(dir)) dir = Path.Combine(Directory.GetCurrentDirectory(), "Logs", "outgame_c_capture"); ImportAll(); EditorSceneManager.OpenScene(ProjectSetup.ScenePath, OpenSceneMode.Single); SessionState.SetBool(SaveStore.MemoryFlagKey, true); SessionState.SetString(OutGameCaptureDriverC.DirKey, dir); Debug.Log("[TKS] 아웃게임 2차 캡처 시작 → " + dir); EditorApplication.EnterPlaymode(); } /// /// UI 리뉴얼 검증 캡처(GUI 에디터 · 사본 프로젝트 권장 · 세이브 = 메모리 전용 · PD #1100): /// Unity.exe -projectPath <copy> -executeMethod TKS.EditorTools.DataImporter.CaptureUI -uiDir <dir> /// 화면 10종 + 팝업(1080×1920) + 1536×2048 2장 PNG + log · 끝나면 스스로 종료. /// -uiOnly hero_list*,hero_detail = 그 화면만 찍고(정확한 이름 또는 「접두*」) 다 찍으면 바로 종료(PD 2026-11-09 「수정된 화면만 체크」 · 이름 = capture_log 의 shot 파일 이름에서 번호 뺀 것). /// public static void CaptureUI() { string dir = GetArg("-uiDir"); if (string.IsNullOrEmpty(dir)) dir = Path.Combine(Directory.GetCurrentDirectory(), "Logs", "ui_capture"); ImportAll(); UIThemeImporter.Import(); EditorSceneManager.OpenScene(ProjectSetup.ScenePath, OpenSceneMode.Single); SessionState.SetBool(SaveStore.MemoryFlagKey, true); SessionState.SetString(UICaptureDriver.DirKey, dir); SessionState.SetString(UICaptureDriver.OnlyKey, GetArg("-uiOnly") ?? ""); Debug.Log("[TKS] UI 캡처 시작 → " + dir); EditorApplication.EnterPlaymode(); } static string GetArg(string name) { var args = System.Environment.GetCommandLineArgs(); for (int i = 0; i < args.Length - 1; i++) if (args[i] == name) return args[i + 1]; return null; } } }